Hi All,

I really need to be able to do a silent install of the pywin32 package for 
python2.7, so I started looking at the distutils bdist_msi option, to see if I 
could get that working for pywin32.  Although I *was eventually able to do so,* 
I ran into several problems that I had to work around in the process:

1) I couldn't build from the latest source version (218).  This is because the 
downloadable pywin32-218.zip file is either incomplete or inconsistent, because 
the win32\src\PerfMon directory no longer includes perfutil.h, but the code 
therein attempts to include it.  (See bug 
https://sourceforge.net/p/pywin32/bugs/647/.)

2) I was able to successfully build the source tree for pywin32-217, but when I 
ran with the bdist_msi option, it complained:

Executing post install script...
creating dist
Traceback (most recent call last):
File "setup.py", line 2435, in
[...]
File "c:\Python27\lib\distutils\command\bdist_msi.py", line 232, in run
sversion = "%d.%d.%d" % StrictVersion(version).version
File "c:\Python27\lib\distutils\version.py", line 40, in init
self.parse(vstring)
File "c:\Python27\lib\distutils\version.py", line 107, in parse
raise ValueError, "invalid version number '%s'" % vstring
ValueError: invalid version number '217'

(Bug https://sourceforge.net/p/pywin32/bugs/648/.)

It turns out that this error is thrown because the msi installer mechanism 
requires the use of the 'StrictVersion' class in the distutils package, and 
that disallows a single integer version number.  Similarly, the pywin32_version 
string used to compile the sources (eg. 2.7.217.0) is also illegal, because it 
only allows an Major.Minor[.build][abN] structure.  Since the dist object 
specified in the setup.py just uses the build_id (eg. '217') as the version, 
this makes the distutils stuff choke when trying to use the bdist_msi option.

To work around this, I modified the setup.py script to add a 
pywin32_msi_version string, which I set to:
   build_id_patch = build_id
   if not "." in build_id_patch:
       build_id_patch = build_id_patch + ".0"
   pywin32_version="%d.%d.%s" % (sys.version_info[0], sys.version_info[1], 
build_id_patch)
+ pywin32_msi_version = "%d.%d.%s" % (sys.version_info[0], sys.version_info[1], 
build_id)

(That is, exclude the .0 from the string, so that it was just '2.7.217'. This 
seemed a reasonable thing to do, as I've never seen a "patch" number on any 
pywin32 version, and the rest seemed appropriate, but I don't know if Mark 
Hammond would agree, and if there ever was a patch number, this would not work.)

I then also modified the dist object's setup construction, thusly:

   dist = setup(name="pywin32",
<       version=str(build_id),
---
>       version=str(pywin32_msi_version),
         description="Python for Window Extensions",

With these minor changes, I was then able to successfully build the msi.  
However, I have no idea of the possible other consequences of this 
modification, vis-à-vis the other distutils bdist methods, and so am not sure 
if this would be an appropriate general fix.

However, there was yet another problem: 
3) On actually trying to use the resulting .msi, the postinstall script failed.

It turns out that there is a bug in the distutils build_msi.py file;  although 
the documentation claims that it supplies the -install and -remove arguments to 
any postinstall scripts for their respective invocation, it does not, in fact, 
currently do this.  As a result, the pywin32_postinstall.py just generated a 
usage message because it was run without arguments, and thus didn't work 
properly, either for install or remove.

It turns out that this distutils bug was reported back in August of 2012, and a 
patch has even been supplied (see http://bugs.python.org/issue15797.)  When I 
applied the supplied patch, and rebuilt my msi, it properly ran the postinstall 
script, and (as far as I can tell) the resulting install works perfectly!  

(And there was much rejoicing...  yea...)

So:  The reasons for my post to this forum:

1)  Is the change I made to the version string used in the dist construction 
appropriate? If not, what would be the appropriate version to use?

2) Can this version be used for both the .exe and the .msi build methods, or, 
if not, is there a way to conditionally set this based on which type of build 
is being attempted?

3) The patch for distutils was submitted in August of 2012, but, AFAICT, has 
not been incorporated into the 2.7.x distutils source; is there a way to 
expedite that?

4) Would it be possible to take all of this into account, verify that I'm not 
missing anything subtle, and generate "official" .msi files for pywin32, since 
this is all targeted *for Microsoft systems,* after all...  ;)

Thanks in advance,
/Will Sadkin
_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to