[Distutils] More minor issues

Rene Liebscher R.Liebscher@gmx.de
Thu Sep 14 05:19:01 2000

This is a multi-part message in MIME format.
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Greg Ward wrote:
> On 12 September 2000, Rene Liebscher said:
> > 1) If the install command had a '--force' option,
> >    which lets install ignore file dates, you could
> >    overwrite manipulated installations with the
> >    original files.
> Good idea, especially since the "install" command needs to get *more*
> paranoid about overwriting old files.
> ...OK, I've just made that change to install*.py.  Boy, we need a better
> way to add an option to a whole family of commands.  ;-(
> Anyways, it works for me when installing the Distutils.  Please give it
> a try on something that includes data, scripts, etc.  Hmmm, maybe I'll
> give it a shot on my Distutil-ized IDLE... that's got modules, data
> files, and a script!
> ...OK, it works, but it revealed a subtle bug in my IDLE setup script.
> D'ohh!  Oh well, this is an excuse to repost said setup script to
> python-dev and prod Guido about distutil-izing IDLE.  ;-)  Good demo of
> packaging a real Python app, if nothing else.
> > 2) If you are using two or more different python versions
> >    on your computer, and you want to install a package
> >    which contains C-compiled extensions, then you have
> >    to delete the build directory before you can install
> >    the package with another version of python or you
> >    use build with the '--force' option.
> >    In any case you have to force distutils to rebuild
> >    all extensions because they were compiled using a wrong
> >    version of python.
> Hmmm, good point.  I'm always wary of over-differentiation leading to
> unworkably long directory names, but I think this one is worthy.
> However, I don't like the idea of having multiple top-level "build"
> directories; I'd rather the sub-directories of "build" incorporated the
> Python version along with the platform info that they already include.
> This means there should probably be a function somewhere to take a plain
> vanilla directory name and "differentiate" it -- eg. build/lib ->
> build/lib-1.6 or build/temp -> build/temp.linux-i586-1.6.  Or something
> like that.  Can you rework your patch to do this?  I think the commads
> to hit are build_* and bdist_*.
It is only build.py, all other command get their paths from build.
I changed only the platform specific directories.

lib.linux2 -> lib-1.5.linux2
temp.linux2 -> temp-1.5.linux2

If you try this with distutils, you will not see any changes, 
because distutils is a pure-python package.
(file: lib-x.x.patch)

In the CVS are the source files for the windows installer.
So everyone can create his own, I think most people 
would like to change the bitmap (PythonPowered) and use
a more specific bitmap for their package.
Creating the installer executable is not the problem, but
to use it you have to change bdist_wininst.py.
(If you only maintain one package this is not a problem
but if there are more, you had to change it everytime
you want to create an installer for the other package.)

So I added an 'install-exe' option to bdist_wininst, which
can be used to specify the executable which is used as base
for the installer.
Using this you can have own installers for every package.
(You could set it in setup.cfg.)
This should also help to test new installers, 
I'm right, Thomas?

(file: wininst.patch)

Another problem:

python setup.py bdist --formats=zip,gztar

doesn't work. It deletes the build tree after
creating the first archive.

There is a simple solution for that.
First find out all commands to run.
Then execute all commands, check for every command
if it has to be run later again (eg. bdist_dumb
with other format), if it has, check if there
is a keep_tree option and set it.

This way you keep the tree for following runs,
only the last one will remove the tree because
there is no following command and the keep_tree
will not be set.

(file: bdist.patch)

After this you could even run this command:

python setup.py bdist --formats=rpm,gztar,bztar,ztar,tar,wininst,zip 

All, except rpm and wininst, would use the same tree.

Kind regards

Rene Liebscher
Content-Type: text/plain; charset=us-ascii;
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;

diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build.py distutils.patched/distutils/command/build.py
--- distutils.orig/distutils/command/build.py	Sat Jun 24 03:23:37 2000
+++ distutils.patched/distutils/command/build.py	Wed Sep 13 13:58:56 2000
@@ -74,7 +74,7 @@
             self.build_purelib = os.path.join (self.build_base, 'lib')
         if self.build_platlib is None:
             self.build_platlib = os.path.join (self.build_base,
-                                               'lib.' + self.plat)
+                                'lib-' + sys.version[0:3] + '.' + self.plat)
         # 'build_lib' is the actual directory that we will use for this
         # particular module distribution -- if user didn't supply it, pick
@@ -89,7 +89,7 @@
         # "build/temp.<plat>"
         if self.build_temp is None:
             self.build_temp = os.path.join (self.build_base,
-                                            'temp.' + self.plat)
+                                'temp-' + sys.version[0:3] + '.' + self.plat)
         if self.build_scripts is None:
             self.build_scripts = os.path.join (self.build_base, 'scripts')
     # finalize_options ()

Content-Type: text/plain; charset=us-ascii;
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;

diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/bdist_wininst.py distutils.patched/distutils/command/bdist_wininst.py
--- distutils.orig/distutils/command/bdist_wininst.py	Tue Sep 12 11:50:01 2000
+++ distutils.patched/distutils/command/bdist_wininst.py	Wed Sep 13 18:05:13 2000
@@ -31,6 +31,8 @@
                      "do not compile .py to .pyo (optimized) on the target system"),
                     ('dist-dir=', 'd',
                      "directory to put final built distributions in"),
+                    ('install-exe=', None,
+                     "executable used as base for installer"),
     def initialize_options (self):
@@ -40,6 +42,7 @@
         self.no_target_optimize = 0
         self.target_version = None
         self.dist_dir = None
+        self.install_exe = None
     # initialize_options()
@@ -59,6 +62,10 @@
         self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
+        if self.install_exe:
+            if not os.path.isfile(self.install_exe):
+                raise DistutilsFileError, "%s not found." % self.install_exe    
     # finalize_options()
@@ -193,8 +200,11 @@
     # create_exe()
     def get_exe_bytes (self):
-        import base64
-        return base64.decodestring (EXEDATA)
+        if self.install_exe:
+            return open(self.install_exe,"rb").read()
+        else:                
+            import base64
+            return base64.decodestring (EXEDATA)
 # class bdist_wininst

Content-Type: text/plain; charset=us-ascii;
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;

diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/bdist.py distutils.patched/distutils/command/bdist.py
--- distutils.orig/distutils/command/bdist.py	Tue Sep 12 11:50:01 2000
+++ distutils.patched/distutils/command/bdist.py	Wed Sep 13 15:39:08 2000
@@ -109,16 +109,25 @@
     def run (self):
+        commands = []
+        # which commands do we need
         for format in self.formats:
-                cmd_name = self.format_command[format][0]
+                commands.append(self.format_command[format][0])
             except KeyError:
                 raise DistutilsOptionError, \
                       "invalid format '%s'" % format
+        # execute commands
+        for i in range(len(self.formats)):
+            cmd_name = commands[i]
             sub_cmd = self.reinitialize_command(cmd_name)
             if cmd_name not in self.no_format_option:
-                sub_cmd.format = format
+                sub_cmd.format = self.formats[i]
+            # Do we need this command later again? Does it have a keep_tree
+            # option? If it has, keep the tree for next run of this command.
+            if hasattr(sub_cmd,"keep_tree") and (cmd_name in commands[i+1:]):
+                sub_cmd.keep_tree = 1
             self.run_command (cmd_name)
     # run()