classification
Title: bdist_msi does not deal with pre-release version
Type: enhancement Stage:
Components: Distutils Versions: Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: cdavid, eric.araujo, exarkun, loewis, rogerbinns, tarek, techtonik, tim.golden
Priority: normal Keywords:

Created on 2009-05-16 11:08 by cdavid, last changed 2014-03-14 01:41 by loewis.

Messages (15)
msg87877 - (view) Author: Cournapeau David (cdavid) Date: 2009-05-16 11:08
If bdist_msi is used on a package which has a non released version
(defined from StrictVersion), it refuses to build the package. The code
for the bdist_msi mentions that pre-release is not supported. Knowing
nothing about msi, I don't know what shall be done for it to work.
msg90145 - (view) Author: Roger Binns (rogerbinns) Date: 2009-07-05 07:25
This issue is highly annoying.  The ultimate cause is the msi code using
the StrictVersion class to get the version number.  StrictVersion is
documented to be constrained to numerical dot separated versions, and
there doesn't appear to be a way of providing that.  My extension has a
human readable version and I'm happy to also provide a different mangled
version to keep this command working.  I suspect the strictversion
doesn't actually matter than much and is only used to identify an
identical version of the installer so there is no reason why it can't be
automatically derived from the human readable version.
msg99517 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-02-18 18:04
The problem is that the version number goes into the MSI ProductVersion property, which MUST be numeric, or else Windows will refuse to install the package. So this is not just an arbitrary choice (at least not by bdist_msi).

I'm not sure how a strictly numeric version could be determined from the metadata for a prerelease.
msg132964 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-04 20:12
Is there any workaround we can use in setup.py to set correct version for build_msi subcommand only?
msg133035 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-05 14:45
Metadata can be automatically figured out using regexp matching like ^\d+(\.\d+){2,3}, but for explicit handling there should be should some callback or msi-specific version property in metadata. In the end it is pretty logical if binary distribution process can be configured using distribution specific (bdist_* specific) properties.

In the meanwhile here is the workaround:
{{{

from distutils.command.bdist_msi import bdist_msi

class bdist_msi_version_hack(bdist_msi):
    """ bdist_msi requires version to be in x.x.x format
        because it is embedded into MSI
    """
    def run(self):
        # strip suffix from version, i.e. from 11.0.0+r3443
        saved = self.distribution.metadata.version
        self.distribution.metadata.version = saved.split('+')[0]
        bdist_msi.run(self)
        saved_version = self.distribution.metadata.version

setup(
    ...
    cmdclass={'bdist_msi': bdist_msi_version_hack},
)
}}}
msg133036 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-05 14:52
Wrong code. The last line in the bdist_msi_version_hack override should be:

  self.distribution.metadata.version = saved
msg133049 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-05 16:26
The above workaround still doesn't isolate version modification to bdist_msi command, because bdist_msi is calling `build` and `install` targets before doing its own stuff.

Any ideas how to override version for MSI without copying while `bdist_msi` contents?

Definitely something to think about in distutils2.
msg133050 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-05 16:27
s/while/whole/

Sorry.
msg133094 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-05 21:39
All right. The ultimate solution:

{{{
# Imports for converting version to MSI format for bdist_msi
from distutils.command.bdist_msi import bdist_msi
import inspect
import types
 
...

class bdist_msi_patch_version(bdist_msi):
    """ MSI builder requires version to be in the x.x.x format """
    def run(self):
        def monkey_get_version(self):
            """ monkey patch replacement for metadata.get_version() that
                returns MSI compatible version string for bdist_msi
            """
            # get filename of the calling function
            if inspect.stack()[1][1].endswith('bdist_msi.py'):
                # strip revision from version (if any), e.g. 11.0.0-r31546
                return self.version.split('-')[0]
            else:
                return self.version

        # monkeypatching get_version() call for DistributionMetadata
        self.distribution.metadata.get_version = \
            types.MethodType(monkey_get_version, self.distribution.metadata)
        bdist_msi.run(self)


...
setup(
    ...
    cmdclass={'bdist_msi': bdist_msi_version_hack},
)
}}}
msg133244 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2011-04-07 18:20
To keep this focused, we should first try to make a test and patch for the stdlib, then discuss a recipe to work around the bug in unfixed versions.
msg133375 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-09 06:51
What for? IIUC, it won't be fixed in distutils anyway.
msg133387 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2011-04-09 13:53
Well, this is the bug tracker for the stdlib.  We have first to define clearly what the bug is, then find how to fix it in packaging (the name of distutils2 merged into 3.3), then decide whether to backport it to distutils.  Half-tested recipes to work-around the bug on unpatched versions divert attention and are out of place.
msg133400 - (view) Author: anatoly techtonik (techtonik) Date: 2011-04-09 16:34
Feel free to copy this report for a clear user story - http://twistedmatrix.com/trac/ticket/5024
msg213470 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2014-03-13 21:16
The issue is that projects want to generate MSIs for pre- and post-release versions.  As Martin said, there is an MSI limitation here (that should be documented in distutils doc).

I see two issues with munging the version number:

1) Both Twisted 2.0+r42 and Twisted 2.0 generate twisted-2.0.msi (filename simplified for the discussion), which will surely be confusing for humans and programs.

2) Does the MSI system allow people to go from 2.0+r42 to 2.0 if each of them is in a file named twisted-2.0.msi?
msg213508 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2014-03-14 01:41
As for 2): I believe that bdist_msi doesn't support upgrade installations currently, anyway. To support this, the UpgradeCode property would have to be specified. As it stands, multiple versions of the same PyPI package result in multiple separate installations (potentially overwriting each other's files).

It would be possible to automatically derive an UpgradeCode from the metadata, however, we would then still need to define what versions replace each other, and what versions can be installed side-by-side.

In any case, the name of the MSI file is irrelevant (AFAIK). They could be named the same or differently - what matters to Windows is the package code, the product code, and the upgrade code. The ProductVersion matters for the UI, and to determine whether something is an upgrade. See

http://msdn.microsoft.com/en-us/library/aa370859(v=vs.85).aspx
History
Date User Action Args
2014-03-14 01:41:31loewissetmessages: + msg213508
2014-03-13 21:16:12eric.araujosetversions: + Python 3.5, - 3rd party
nosy: + exarkun

messages: + msg213470

assignee: tarek ->
components: + Distutils, - Distutils2
2011-04-09 16:34:14techtoniksetmessages: + msg133400
2011-04-09 13:53:07eric.araujosetmessages: + msg133387
2011-04-09 06:51:03techtoniksetmessages: + msg133375
2011-04-07 18:20:13eric.araujosetmessages: + msg133244
2011-04-05 21:39:38techtoniksetmessages: + msg133094
2011-04-05 16:27:24techtoniksetmessages: + msg133050
2011-04-05 16:26:24techtoniksetmessages: + msg133049
2011-04-05 14:52:57techtoniksetmessages: + msg133036
2011-04-05 14:45:39techtoniksetmessages: + msg133035
2011-04-04 20:12:59techtoniksetnosy: + techtonik
messages: + msg132964
2010-11-26 02:10:31eric.araujosetnosy: + eric.araujo

components: + Distutils2, - Distutils
versions: + 3rd party, - Python 3.2
2010-08-04 07:31:19tim.goldensetnosy: + tim.golden
2010-08-04 04:05:19terry.reedysetversions: + Python 3.2, - Python 2.6, Python 2.5, Python 2.4
nosy: + tarek

assignee: tarek
components: + Distutils
type: enhancement
2010-02-18 18:04:04loewissetnosy: + loewis
messages: + msg99517
2009-07-05 07:25:24rogerbinnssetnosy: + rogerbinns
messages: + msg90145
2009-05-16 11:08:24cdavidcreate