build version handling

Hi All,

This is not an issue with wxpython but i am posting this hoping to get
some tips /suggestions.

I am using wxpython py2exe and inno to create build and distribute
the application as an exe.

I need to handle the version and build information. Currently i am
storing it in an xml file and bundled with the app.

What i found that when i do a new build with py2exe in most cases the
files that changes is exe file and library.zip .

so if i manage to save the build and version info in the exe i figure
i will have an easier upgrade process.

Any suggestion what the best practice to follow when there is frequent
updates to the application and major releases every 2 months.

Thanks
Thomas

Hi All,

I found this in wxpython demo app

# This file was generated by setup.py...

VERSION_STRING = '2.8.10.1'

I think i could use similar can anyone has the source for this
setup.py

Thanks
Thomas

···

On Sep 17, 10:36 am, thomas <tctho...@gmail.com> wrote:

Hi All,

This is not an issue with wxpython but i am posting this hoping to get
some tips /suggestions.

I am using wxpython py2exe and inno to create build and distribute
the application as an exe.

I need to handle the version and build information. Currently i am
storing it in an xml file and bundled with the app.

What i found that when i do a new build with py2exe in most cases the
files that changes is exe file and library.zip .

so if i manage to save the build and version info in the exe i figure
i will have an easier upgrade process.

Any suggestion what the best practice to follow when there is frequent
updates to the application and major releases every 2 months.

Thanks
Thomas

Hi Thomas,

thomas wrote:

Hi All,

I found this in wxpython demo app

# This file was generated by setup.py...

VERSION_STRING = '2.8.10.1'

I think i could use similar can anyone has the source for this
setup.py
  

I use this type of approach too, i.e. I have a __version__.py which is generated/updated by setup.py with the following information.

# This file was generated by setup.py...

twcbVERSION_STRING = "3.0.515.9"
twcbVERSION_NUMBER = "3.0.515"
twcbMAJOR_VERSION = 3
twcbMINOR_VERSION = 1
twcbBUILD_NUMBER = 515
twcbSTATUS = "9"
twcbDB_STRUCT = 3.1
twcbDB_DATA = 3.1
twcbVersionType = 10

When the application starts it checks as one of the first things the content of this file and compares it with e.g. some values in the database (twcbDB_STRUCT and twcbDB_DATA) have an equivalent column in the database), if they are higher then a database upgrade is automatically started, if they are the same nothing happens and if they are lower then what is in the database then the program stops with an error message.

FYI, above is out of my dev folder and it shows that I never built version 3.1 as the two first values are still for 3.0.

Hope this helps
Werner

Hi Werner,

Thanks for that I was planning to follow similar structure .

I have couple of queries here. Do you use a separate application for
upgrade process.
Windows wont let you replace the application when it is running right.

what is the status parameter used for.

Do you mind sending a sample setup.py with version generating code.

Thanks
Thomas

···

On Sep 17, 7:13 pm, werner <wbru...@free.fr> wrote:

Hi Thomas,

thomas wrote:
> Hi All,

> I found this in wxpython demo app

> # This file was generated by setup.py...

> VERSION_STRING = '2.8.10.1'

> I think i could use similar can anyone has the source for this
> setup.py

I use this type of approach too, i.e. I have a __version__.py which is
generated/updated by setup.py with the following information.

# This file was generated by setup.py...

twcbVERSION_STRING = "3.0.515.9"
twcbVERSION_NUMBER = "3.0.515"
twcbMAJOR_VERSION = 3
twcbMINOR_VERSION = 1
twcbBUILD_NUMBER = 515
twcbSTATUS = "9"
twcbDB_STRUCT = 3.1
twcbDB_DATA = 3.1
twcbVersionType = 10

When the application starts it checks as one of the first things the
content of this file and compares it with e.g. some values in the
database (twcbDB_STRUCT and twcbDB_DATA) have an equivalent column in
the database), if they are higher then a database upgrade is
automatically started, if they are the same nothing happens and if they
are lower then what is in the database then the program stops with an
error message.

FYI, above is out of my dev folder and it shows that I never built
version 3.1 as the two first values are still for 3.0.

Hope this helps
Werner

Hi

My upgrade scenario is different i think . We dont have a repository
of updates . We planning to send out to the client's latest exe and
library file and have some method of replacing (i need to figure out)
the ones already in the install directory.

I am thinking also sending out the version string file and once exe
replaced do a check with version on exe to confirm the upgrade.

I have found the code below to obtain the version info on an exe in
windows.

Thanks
Thomas

filename="fullpath to my exe"
import win32api

lo = win32api.LOWORD
hi = win32api.HIWORD

def get_version_number (filename):
  info = win32api.GetFileVersionInfo (filename, "\\")
  print info
  ms = info['FileVersionMS']
  ls = info['FileVersionLS']
  print ms
  return hi (ms), lo (ms), hi (ls), lo (ls)

currentVersion=".".join ([str (i) for i in get_version_number
(filename)])

Thanks
Thomas

···

On Sep 18, 9:43 am, thomas <tctho...@gmail.com> wrote:

Hi Werner,

Thanks for that I was planning to follow similar structure .

I have couple of queries here. Do you use a separate application for
upgrade process.
Windows wont let you replace the application when it is running right.

what is the status parameter used for.

Do you mind sending a sample setup.py with version generating code.

Thanks
Thomas

On Sep 17, 7:13 pm, werner <wbru...@free.fr> wrote:

> Hi Thomas,

> thomas wrote:
> > Hi All,

> > I found this in wxpython demo app

> > # This file was generated by setup.py...

> > VERSION_STRING = '2.8.10.1'

> > I think i could use similar can anyone has the source for this
> > setup.py

> I use this type of approach too, i.e. I have a __version__.py which is
> generated/updated by setup.py with the following information.

> # This file was generated by setup.py...

> twcbVERSION_STRING = "3.0.515.9"
> twcbVERSION_NUMBER = "3.0.515"
> twcbMAJOR_VERSION = 3
> twcbMINOR_VERSION = 1
> twcbBUILD_NUMBER = 515
> twcbSTATUS = "9"
> twcbDB_STRUCT = 3.1
> twcbDB_DATA = 3.1
> twcbVersionType = 10

> When the application starts it checks as one of the first things the
> content of this file and compares it with e.g. some values in the
> database (twcbDB_STRUCT and twcbDB_DATA) have an equivalent column in
> the database), if they are higher then a database upgrade is
> automatically started, if they are the same nothing happens and if they
> are lower then what is in the database then the program stops with an
> error message.

> FYI, above is out of my dev folder and it shows that I never built
> version 3.1 as the two first values are still for 3.0.

> Hope this helps
> Werner

Correct. The typical implementation for a self-updater would be to do a version check, and if an update is needed then launch a different executable that does the download and install and then relaunches the new version of the original executable. Keep in mind that on Windows active DLLs (PYD files are DLLs) also can't be replaced, so you may have to get a little creative to make sure that the updater program is not using anything that you may want to replace in a future update.

···

On 9/17/09 2:43 PM, thomas wrote:

Hi Werner,

Thanks for that I was planning to follow similar structure .

I have couple of queries here. Do you use a separate application for
upgrade process.
Windows wont let you replace the application when it is running right.

--
Robin Dunn
Software Craftsman

Hi Robin,

I tried to develop the bare minimum app but exe generated has
library.zip file which need to replaced. How can i get around this.

Below a sample code of what i am trying to achieve.

Thanks
Thomas

import wx
import os
import sys
import zipfile

wildcard = "*.zip"

#modules ={}

class Frame1(wx.Frame):
    def _init_ctrls(self, prnt):
        wx.Frame.__init__(self, style=wx.DEFAULT_FRAME_STYLE, name='',
parent=prnt, title='Frame1', pos=wx.Point(-1, -1), id=wxID_FRAME1,
size=wx.Size(-1, -1))

class BoaApp(wx.App):
    def processUpgradeProcess(self,filename,upgarde_dir):
        self.unzipFileIntoDir(filename,upgarde_dir)
        print filename
    def OnInit(self):
        upgarde_dir=os.path.dirname(os.path.abspath(sys.argv[0]))
        frame=Frame1(None)
        dlg = wx.FileDialog(frame, message="Choose the file upgrade",
defaultDir=os.getcwd(),
                defaultFile="", wildcard=wildcard, style=wx.OPEN |
wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
           filenames = dlg.GetPaths()
           print filenames
           self.processUpgradeProcess(filenames[0],upgarde_dir)
        frame.Destroy()
        return True

    def unzipFileIntoDir(self,file, dir):
        zfobj = zipfile.ZipFile(file)
        for name in zfobj.namelist():
            if name.endswith('/'):
                #os.mkdir(os.path.join(dir, name))
                print "no directories at this stage"
            else:
                outfile = open(os.path.join(dir, name), 'wb')
                outfile.write(zfobj.read(name))
                outfile.close()

def main():
    application = BoaApp(0)
    application.MainLoop()

if __name__ == '__main__':
    main()

Also the setup.py

from distutils.core import setup
from glob import glob
import py2exe

setup(name="DxBxClientUpgrade",
      windows=["../dxbxUpgradeApp.py"],
      version='1.0.001',
     )

and the command i am using python setup.py py2exe

cheers
Thomas

···

On Sep 18, 10:49 am, Robin Dunn <ro...@alldunn.com> wrote:

On 9/17/09 2:43 PM, thomas wrote:

> Hi Werner,

> Thanks for that I was planning to follow similar structure .

> I have couple of queries here. Do you use a separate application for
> upgrade process.
> Windows wont let you replace the application when it is running right.

Correct. The typical implementation for a self-updater would be to do a
version check, and if an update is needed then launch a different
executable that does the download and install and then relaunches the
new version of the original executable. Keep in mind that on Windows
active DLLs (PYD files are DLLs) also can't be replaced, so you may have
to get a little creative to make sure that the updater program is not
using anything that you may want to replace in a future update.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org

Thomas,

thomas wrote:

Hi Werner,

Thanks for that I was planning to follow similar structure .

I have couple of queries here. Do you use a separate application for
upgrade process.
Windows wont let you replace the application when it is running right.
  

Please keep in mind that I am hobby programmer, so I am sure there are lots of things one could do better and/or more efficient - but so far this approach has worked for me, I have gone through 2 major upgrades of my shareware and many minor ones without ever having a problem with the upgrade process.

I do this pretty early on in OnInit within my wx.App.

I.e.:
        # Get the minimal preferences from the DB
        self.prefMinimal = self.ds.query(dbmin.Prefminimal).get(1)

        # lets see if we need to update the db
        self.UpdateDB()
        # delete minimal stuff and reload prefs after update
        del self.prefMinimal
               self.GetPrefs()

I use SQLAlchemy for the db access, so the above query uses a minimal model with only one table (preferences) with only the two columns dbstructure and dbdata, then in self.UpdateDB() I check the content of these two columns with the values in __version__.py, if the later are higher then an upgrade is done (e.g. if user is on 2.1 and __version__ is 2.4 I then do a database backup and then do the upgrade to 2.2, then 2.3 and last to 2.4 and when that is done I do a database optimize).

When UpdateDB is done I load the real preference table in self.GetPrefs, this is done as the preference table might also be changed during an upgrade.

what is the status parameter used for.

Do you mind sending a sample setup.py with version generating code.
  

Here is the relevant code for the version stuff in my setup.py (if like to see the full one let me know), which also answers the status parameter question above.

# generate the build number

···

#
# Minor, major or status change need to be updated manually!!!!!
#
import __version__

versionfile = file(r'__version__.py', 'w+')

twcbMAJOR_VERSION = 3 # major functionality change
twcbMINOR_VERSION = 1 # minor functionality change
twcbDB_STRUCT = 3.1 # database structure
twcbDB_DATA = 3.1 # database structure
twcbBUILD_NUMBERnew = __version__.twcbBUILD_NUMBER + 1 # problem/bug fix
twcbSTATUS = u'9' # 1 = alpha, 2 = beta, 3 = release candidate, 9 = final stable
twcbVERSION_STRING = u'%s.%s.%s.%s' % (twcbMAJOR_VERSION,
                                       twcbMINOR_VERSION,
                                       twcbBUILD_NUMBERnew,
                                       twcbSTATUS)

twcbVERSION_NUMBER = u'%s.%s.%s' % (twcbMAJOR_VERSION,
                                    twcbMINOR_VERSION,
                                    twcbBUILD_NUMBERnew)

versionfile.write('# This file was generated by setup.py...\n')
versionfile.write('\n')
versionfile.write('twcbVERSION_STRING = "%s"\n' % twcbVERSION_STRING)
versionfile.write('twcbVERSION_NUMBER = "%s"\n' % twcbVERSION_NUMBER)
versionfile.write('twcbMAJOR_VERSION = %i\n' % twcbMAJOR_VERSION)
versionfile.write('twcbMINOR_VERSION = %i\n' % twcbMINOR_VERSION)
versionfile.write('twcbBUILD_NUMBER = %i\n' % twcbBUILD_NUMBERnew)
versionfile.write('twcbSTATUS = "%s"\n' % twcbSTATUS)
versionfile.write('twcbDB_STRUCT = %g\n' % twcbDB_STRUCT)
versionfile.write('twcbDB_DATA = %g\n' % twcbDB_DATA)
versionfile.write('twcbVersionType = %i\n' % versionType)

versionfile.close()

print 'Generating type: %s, version: %s' % (distVer, twcbVERSION_NUMBER)

Werner

thomas wrote:

Hi Robin,

I tried to develop the bare minimum app but exe generated has
library.zip file which need to replaced. How can i get around this.
  

In my case the installer (InnoSetup) installs the new version and gets rid of anything out dated, it never touches the database if it already exists.

Below a sample code of what i am trying to achieve.

Thanks
Thomas

import wx
import os
import sys
import zipfile

wildcard = "*.zip"

#modules ={}

class Frame1(wx.Frame):
    def _init_ctrls(self, prnt):
        wx.Frame.__init__(self, style=wx.DEFAULT_FRAME_STYLE, name='',
parent=prnt, title='Frame1', pos=wx.Point(-1, -1), id=wxID_FRAME1,
size=wx.Size(-1, -1))

class BoaApp(wx.App):
    def processUpgradeProcess(self,filename,upgarde_dir):
        self.unzipFileIntoDir(filename,upgarde_dir)
        print filename
  

My upgrade process is a "normal" python module I import and then run/execute the appropriate methods/functions (backup db, update db structure, update/add data, optimize db) and it is run at the beginning of OnInit (see other response for a bit more detail).

Werner

You need to design it such that the program doing the updating (at least the part that "installs" the new files) does not itself use any of the files that will be updated. For example, if the updater program is a Python app then it can not update the Python DLL that it is using, but if it is running in its own dir and has its own copy of the Python DLL, then it could update the Python DLL of your main app in another dir (if it's not in use.)

Another possibility is to not use a Python app for the actual "install" of the new version, but to make a sell-installing exe with InnoSetup or some similar tool. Then your main app can do the downloading of the update, launch the installer and terminate itself, and the installer should then be able to update any of the files installed for the main app.

···

On 9/17/09 5:11 PM, thomas wrote:

Hi Robin,

I tried to develop the bare minimum app but exe generated has
library.zip file which need to replaced. How can i get around this.

--
Robin Dunn
Software Craftsman