From hgebel@inet.net Tue May 2 08:55:00 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Tue, 2 May 2000 03:55:00 -0400 Subject: [Distutils] New bdist_rpm patch Message-ID: <20000502035500.M13333@inet.net> --ItroYk2LVxvwOvi/ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is the bdist_rpm patch again, a small bug has been removed. This week, (I am hoping on Thursday) I will be sending a patch adding post- and pre- install and uninstall scripts, plus allowing the build and install rpm sections to be customized (I think this last will have to be used only very rarely with Distutils.) I still haven't heard from anyone about their opinion on how to handle CFLAGS. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.net --ItroYk2LVxvwOvi/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.patch" ? redhat ? rpm.patch ? dry_run.patch ? MANIFEST ? package_data ? install_options.patch ? long_description.patch ? exeception_error.patch ? bdist_rpm.patch ? Distutils-0.8.2.tar.gz ? distutils/command/bdist_rpm.py Index: MANIFEST.in =================================================================== RCS file: /projects/cvsroot/distutils/MANIFEST.in,v retrieving revision 1.4 diff -u -r1.4 MANIFEST.in --- MANIFEST.in 2000/04/21 04:38:11 1.4 +++ MANIFEST.in 2000/05/02 07:52:16 @@ -9,7 +9,9 @@ # include *.txt +include package_data include MANIFEST.in +include redhat/*.spec recursive-include examples *.txt *.py prune examples/sample?/build recursive-include doc *.sty *.tex Index: distutils/command/__init__.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/__init__.py,v retrieving revision 1.8 diff -u -r1.8 __init__.py --- __init__.py 2000/03/31 03:14:51 1.8 +++ __init__.py 2000/05/02 07:52:16 @@ -15,4 +15,5 @@ 'sdist', 'bdist', 'bdist_dumb', + 'bdist_rpm', ] Index: distutils/command/bdist.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/bdist.py,v retrieving revision 1.5 diff -u -r1.5 bdist.py --- bdist.py 2000/04/25 01:38:19 1.5 +++ bdist.py 2000/05/02 07:52:17 @@ -31,8 +31,12 @@ 'bztar': 'bdist_dumb', 'ztar': 'bdist_dumb', 'tar': 'bdist_dumb', - 'zip': 'bdist_dumb', } + 'zip': 'bdist_dumb', + 'rpm': 'bdist_rpm', + } + # The following commands do not take a format option from bdist + no_format_option = ( 'bdist_rpm', ) def initialize_options (self): self.format = None @@ -63,8 +67,9 @@ raise DistutilsOptionError, \ "invalid archive format '%s'" % self.format - sub_cmd = self.find_peer (cmd_name) - sub_cmd.set_option ('format', self.format) + if cmd_name not in self.no_format_option: + sub_cmd = self.find_peer (cmd_name) + sub_cmd.set_option ('format', self.format) self.run_peer (cmd_name) # run() Index: distutils/command/install.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/install.py,v retrieving revision 1.23 diff -u -r1.23 install.py --- install.py 2000/04/27 01:56:38 1.23 +++ install.py 2000/05/02 07:52:20 @@ -12,6 +12,7 @@ from distutils import sysconfig from distutils.util import write_file, native_path, subst_vars, change_root from distutils.errors import DistutilsOptionError +from glob import glob INSTALL_SCHEMES = { 'unix_prefix': { @@ -82,9 +83,11 @@ #('install-man=', None, "directory for Unix man pages"), #('install-html=', None, "directory for HTML documentation"), #('install-info=', None, "directory for GNU info files"), - ] + ('record', None, + "make a record of installation")] + # 'sub_commands': a list of commands this command might have to run # to get its work done. Each command is represented as a tuple # (func, command) where 'func' is a function to call that returns @@ -141,6 +144,7 @@ #self.install_html = None #self.install_info = None + self.record = None def finalize_options (self): @@ -267,7 +271,8 @@ from distutils.fancy_getopt import longopt_xlate print msg + ":" for opt in self.user_options: - opt_name = string.translate (opt[0][0:-1], longopt_xlate) + if opt[0][-1] == '=': + opt_name = string.translate (opt[0][0:-1], longopt_xlate) val = getattr (self, opt_name) print " %s: %s" % (opt_name, val) @@ -424,6 +429,24 @@ "Python's module search path (sys.path) -- " + "you'll have to change the search path yourself") % self.install_lib) + + + # write list of installed files, if requested. + if self.record: + outputs = self.get_outputs() + for counter in xrange (len (outputs)): # include ".pyc" and ".pyo" + if outputs[counter][-3:] == ".py": + byte_code = glob(outputs[counter] + '[co]') + outputs.extend(byte_code) + outputs.sort() # just makes it look nicer + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in xrange (len (outputs)): + outputs[counter] = outputs[counter][root_len:] + self.execute(write_file, + ("INSTALLED_FILES", outputs), + "Writing list of installed files") + # run () --ItroYk2LVxvwOvi/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=package_data release = '1' group = 'Development/Libraries' vendor = 'Distutils-SIG' packager = 'Harry Henry Gebel ' doc = ['CHANGES.txt', 'README.txt', 'USAGE.txt', 'doc/', 'examples/', ] changelog = '''\ * Wed Apr 26 2000 Harry Henry Gebel 0.8.2-1 - First test of bdist_rpm''' --ItroYk2LVxvwOvi/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.py" """distutils.command.bdist_rpm Implements the Distutils 'bdist_rpm' command (create RPM source and binary distributions.""" # created 2000/04/25, by Harry Henry Gebel __revision__ = "$Id: bdist_dumb.py,v 1.3 2000/04/22 02:51:25 gward Exp $" import os.path import os from distutils.core import Command from distutils.util import mkpath, write_file, remove_tree from distutils.errors import * from string import join class bdist_rpm (Command): description = "create an RPM distribution" user_options = [ ('spec-only', None, "Only regenerate spec file"), ('tar-only', None, "Only generate spec file and tarball"), ('no-remove', None, "Do not remove root owned files"), ('arch=', None, "Build for a specific architecture"), ] def initialize_options (self): self.spec_only = None self.tar_only = None self.no_remove = None self.arch = None # initialize_options() def finalize_options (self): if os.name != 'posix': raise DistutilsPlatformError, \ ("don't know how to create RPM " "distributions on platform %s") % os.name if self.spec_only and self.tar_only: raise DistutilsOptionsError, \ 'Cannot specify both spec-only and tar-only' if os.getuid(): # if not root if self.no_remove: self.warn('no-remove has no effect when not root') self.remove = None else: # if root if self.no_remove: self.remove = None else: self.remove = 1 # finalize_options() def run (self): self._getPackageData() # get packaging info # place spec file in ./redhat directory self.execute(mkpath, ('./redhat',), "Created ./redhat directory") spec_path = './redhat/%s.spec' % self.name self.execute(write_file, (spec_path, self._makeSpecFile()), 'Writing .spec file') if self.spec_only: # stop if requested return # make a .gz distribution sdist = self.find_peer ('sdist') sdist.set_option ('formats', ['gztar']) self.run_peer('sdist') if self.tar_only: # stop if requested return # build package self.announce('Building RPMs') rpm_args = ['rpm', '-ta', '--clean'] if self.arch and self.distribution.has_ext_modules(): rpm_args.append['--target=' + arch] rpm_args.append(self.distribution.get_fullname() + '.tar.gz') self.spawn(rpm_args) if self.remove: # remove generated files self.execute(self._remove_root, (), 'Removing generated files') def _remove_root(self): ''' Remove files generated to support rpm ''' os.unlink('MANIFEST') os.unlink(self.distribution.get_fullname() + '.tar.gz') remove_tree('redhat') def _getPackageData(self): ''' Get data needed to generate spec file, first from the DistributionMetadata class, then from the package_data file, which is Python code read with execfile() ''' package_type = 'rpm' # read in package data, if any if os.path.exists('package_data'): try: exec(open('package_data')) except: raise DistutilsOptionError, 'Error in package data file' # set instance variables, supplying default value if not provided in # package data file vars = locals().keys() if 'name' in vars: self.name = name else: self.name = self.distribution.get_name() if 'version' in vars: self.version = version else: self.version = self.distribution.get_version() if 'summary' in vars: self.summary = summary else: self.summary = self.distribution.get_description() if 'description' in vars: self.description = description else: self.description = self.distribution.get_long_description() if 'summaries' in vars: self.summaries = summaries else: self.summaries = {} if 'descriptions' in vars: self.descriptions = descriptions else: self.descriptions = {} if 'copyright' in vars: self.copyright = copyright else: self.copyright = self.distribution.get_licence() if 'release' in vars: self.release = release else: self.release = '1' if 'group' in vars: self.group = group else: self.group = 'Applications' if 'vendor' in vars: self.vendor = vendor else: self.vendor = None if 'packager' in vars: self.packager = packager else: self.packager = None if 'url' in vars: self.url = url else: self.url = self.distribution.get_url() if 'doc' in vars: self.doc = join(doc, ' ') else: self.doc = None if 'changelog' in vars: self.changelog = changelog else: self.changelog = None def _makeSpecFile(self): ''' Generate an RPM spec file ''' spec_file = [ '%define name ' + self.name, '%define version ' + self.version, '%define release ' + self.release, '', 'Summary: ' + self.summary, ] # put locale summaries into spec file for locale in self.summaries.keys(): spec_file.append('Summary(%s): %s' % (locale, self.summaries[locale])) spec_file.extend([ 'Name: %{name}', 'Version: %{version}', 'Release: %{release}', 'Source0: %{name}-%{version}.tar.gz', 'Copyright: ' + self.copyright, 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-buildroot', 'Prefix: %{_prefix}', ]) if not self.distribution.has_ext_modules(): spec_file.append('BuildArchitectures: noarch') if self.vendor: spec_file.append('Vendor: ' + self.vendor) if self.packager: spec_file.append('Packager: ' + self.packager) if self.url: spec_file.append('Url: ' + self.url) spec_file.extend([ '', '%description', self.description]) # put locale descriptions into spec file for locale in self.descriptions.keys(): spec_file.extend([ '', '%description -l ' + locale, self.descriptions[locale], ]) spec_file.extend([ '', '%prep', '%setup', '', '%build', 'python setup.py build', '', '%install', 'python setup.py install --root=$RPM_BUILD_ROOT --record', '', '%clean', 'rm -rf $RPM_BUILD_ROOT', 'rm -f INSTALLED_FILES', '', '%files -f INSTALLED_FILES', '%defattr(-,root,root)', ]) if self.doc: spec_file.append('%doc ' + self.doc) if self.changelog: spec_file.extend([ '', '%changelog', self.changelog ]) return spec_file # run() --ItroYk2LVxvwOvi/-- From gward@ase.com Wed May 3 01:57:27 2000 From: gward@ase.com (Greg Ward) Date: Tue, 2 May 2000 20:57:27 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000427014305.H32467@inet.net>; from Harry Henry Gebel on Thu, Apr 27, 2000 at 01:43:05AM -0400 References: <20000427014305.H32467@inet.net> Message-ID: <20000502205727.A1562@beelzebub> On 27 April 2000, Harry Henry Gebel said: > Will build an RPM using DistributionMetaData to get package > information. Additional information can be put in the file > 'package_data'. 'package_data' contains python code setting the following > variables (variables marked with * are by default set from > DistributionMetaData and do not be need assigned in package_data unless > you need to override the values in .setup.py): Yuck. I like the idea that all meta-data is supplied in the setup script, but some of this stuff is obviously RPM-specific so really shouldn't clutter up the main DistributionMetadata class/object. I think the answer is to put it in the mythical setup.cfg -- one more thing prodding me to go off and finish thinking through Distutils config files, argg! I'll let the 'package_data' file slide for now since I haven't supplied a viable alternative, but its days are numbered... > *name - name of package > *version - package version > *summary - short summary of package > *description - long summary of package Another yuck: description in setup.py -> summary in the .spec file, and long_description in setup.py -> description in the .spec file. Oh well: name conflicts happen, that's just life. I think the confusion can be localized to bdist_rpm.py, so it's not too bad. > doc - a list of string containing names of files and directories to put in > the system's documentation directory. This should be initialized to ["README"] or ["README.txt"] (whichever one happens to be supplied). The "sdist" command ought to make that information available, but there isn't really a clean way to get it now. Hmmm again. > Unless otherwise noted these must all be strings. There is no type > checking yet, I would like people's opinion: should they be cast to > strings or should an exception be raised if they are not strings? I would say definitely do type-checking, and do it in the logical way: require that everything be a string except: * 'summaries' and 'descriptions' must be {string:string} dictionaries * 'release' can be a number or a string > 'package_data's local namespace includes the variable 'package_type' which > is set to 'rpm', this variable will hopefully allow 'package_data' to be > used for all bdist_* commands . I think the right way to do this is to put these "not-quite-fundamental" meta-data bits in the config file, in a "bdist" section (rather than a "bdist_rpm" section). But that points back to me getting back to the config file stuff.... > bdist_rpm works by making a spec file and saving it into the 'redhat/' > directory (making the directory if necessary), it then produces a gzipped > source tarball and runs `rpm -ta --clean` on the tarball. bdist_rpm leaves > the spec file and tarball around since they would probably be wanted > anyway. Why does the .spec file need a directory of its own? The .spec is tiny and essential; I think it belongs right in the distribution root, like a setup script or a makefile. Any temporary by-products of "bdist_rpm" belong somewhere in the build tree: build/rpm, perhaps? I haven't looked at the code yet, but I certainly hope that "bdist_rpm" uses "sdist" to create the source tarball -- if not, that should be fixed. > Here are the caveats I mentioned. If you have not configured rpm to allow > you to build RPMs without being root you will have a directory and three > files (the redhat/ directory and spec file, the MANIFEST file, and the > tarball) saying around owned by root. The other caution is that the spec > file must be included in MANIFEST.in, otherwise it will not be included in > the tarball and therefore the tarball will not be buildable with rpm. If you're talking about the standard source distribution tarball, I don't think it *has* to include the .spec file: after all, the point of the "bdist_rpm" command is to 1) generate a spec file, and 2) optionally run some "rpm -b" commands on it. Anyone who downloads the source distribution should be able to reconstruct the .spec file themselves using the "bdist_rpm" command. Of course, then the module developer has to be sure to include "package_data" in MANIFEST.in, but that file should go away to be replaced by setup.cfg, which *will* be one of the default files like README.txt and setup.py. > The first will be solved with an option I am adding tonight which will > just generate the spec file and tarball, the user can then su and run > 'rpm -ta' on the tarball. How about another option to generate a source RPM? Not essential, but it just seems complete. Plus it's generally considered nice to provide source RPMs when you provide binary RPMs. I think it should be accessible like this: setup.py bdist --format=srpm or setup.py bdist_rpm --srpm Maybe --source-rpm or --source-only on that last one; not sure. Also, should the normal output of "bdist_rpm" be just a binary RPM, or both binary and source RPMs? If both by default, "--source-only" makes sense. > The MANIFEST problem I don't know what is the best way to solve, should > the spec file be automatically added like setup.py, should bdist_rpm add > it to the MANIFEST itself, or should it remain the user's > responsibility? If it is automatically included should package_data also > be automatically included?, if a user alters the package in some way they > will want to change the 'release' variable and regenerate the spec file, > this will be easier if they have 'package_data' The default files that are included in MANIFEST are entirely up to the "sdist" command, which knows nothing about RPMs or other platform-specific distribution mechanisms. I maintain, though, that it's not necessary to include the .spec file in source distributions, so the issue is moot. I could be wrong... Off to actually read the code... Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ One man's theology is another man's belly laugh. From gward@ase.com Wed May 3 02:18:11 2000 From: gward@ase.com (Greg Ward) Date: Tue, 2 May 2000 21:18:11 -0400 Subject: [Distutils] install_scripts and install_data commands In-Reply-To: ; from Bastian Kleineidam on Thu, Apr 27, 2000 at 04:30:33PM +0200 References: Message-ID: <20000502211811.B1562@beelzebub> On 27 April 2000, Bastian Kleineidam said: > I wrote a patch for the above commands. > Both commands derive from install_misc, which copies some files to a > given directory and is defined in cmd.py. > With the attached patch you can now have "scripts=[...]" and > "data=[...]" attributes in setup.py. Cool, thanks! Been meaning to get around to those... > By the way: I was not able to TeX the documentation because I found > no howto.cls file (the files are using \documentclass{howto}). There > should be a make file to compile all the various .tex files. Rather than answering you directly, here's the doc/README.txt I just wrote to answer everyone who looks in that directory... ------------------------------------------------------------------------ The Distutils documentation is supplied as two manuals: Installing Python Modules (aimed at system administrators, end-users, and Python programmers who need to add new goodies to their Python installation) Distributing Python Modules (aimed at module developers who want to share their goodies with the rest of the world in the standard way) These manuals will be a standard part of the Python 1.6 documentation set, and are tightly integrated with the standard Python documentation tools. That means that you won't be able to process the LaTeX files here without 1) downloading the latest Python documentation tools, and 2) setting up a fearsome forest of symbolic links to make it all work. Since these two manuals are now included with the Python documentation (CVS version as of 28 April 2000), there's really not much point in trying to process the manuals provided here. You're better off checking out the latest Python documentation -- which is included in the Python source, when you access it via CVS -- and starting from there. For information on getting access to the Python source and documentation via CVS, see http://www.python.org/download/cvs.html If all you really want to do is *read* the documentation, you don't need to process it yourself: see http://www.python.org/sigs/distutils-sig/doc/ for access to the (roughly) current Distutils documentation, in PDF, PostScript, and HTML. ------------------------------------------------------------------------ Hope that clarifies matters... Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ Any priest or shaman must be presumed guilty until proven innocent. From gward@ase.com Wed May 3 02:27:45 2000 From: gward@ase.com (Greg Ward) Date: Tue, 2 May 2000 21:27:45 -0400 Subject: [Distutils] HTML manuals available Message-ID: <20000502212745.C1562@beelzebub> Hi all -- the Distutils manuals are now available in HTML at http://www.python.org/sigs/distutils-sig/doc/ Thanks to Fred Drake for doing the LaTeX2HTML magic to make this happen! Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ Secrecy is the beginning of tyranny. From hoel@germanlloyd.org Wed May 3 08:15:05 2000 From: hoel@germanlloyd.org (Berthold Hoellmann) Date: Wed, 03 May 2000 09:15:05 +0200 Subject: [Distutils] HTML manuals available References: <20000502212745.C1562@beelzebub> Message-ID: <390FD1F9.D6DE71F8@GermanLloyd.org> Greg Ward wrote: > > Hi all -- > > the Distutils manuals are now available in HTML at > > http://www.python.org/sigs/distutils-sig/doc/ > > Thanks to Fred Drake for doing the LaTeX2HTML magic to make this happen! Haven't have more than a first look it seems, the navigation buttons are missing, at least from the top document. Greetings Berthold -- email: hoel@GermanLloyd.org ) ( C[_] These opinions might be mine, but never those of my employer. From hgebel@inet.net Wed May 3 10:25:27 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Wed, 3 May 2000 05:25:27 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000502205727.A1562@beelzebub>; from gward@ase.com on Tue, May 02, 2000 at 08:57:27PM -0400 References: <20000427014305.H32467@inet.net> <20000502205727.A1562@beelzebub> Message-ID: <20000503052527.E20099@inet.net> On Tue, May 02, 2000 at 08:57:27PM -0400, Greg Ward wrote: > On 27 April 2000, Harry Henry Gebel said: > > Will build an RPM using DistributionMetaData to get package > > information. Additional information can be put in the file > > 'package_data'. 'package_data' contains python code setting the following > > variables (variables marked with * are by default set from > > DistributionMetaData and do not be need assigned in package_data unless > > you need to override the values in .setup.py): > > Yuck. I like the idea that all meta-data is supplied in the setup > script, but some of this stuff is obviously RPM-specific so really > shouldn't clutter up the main DistributionMetadata class/object. I > think the answer is to put it in the mythical setup.cfg -- one more > thing prodding me to go off and finish thinking through Distutils config > files, argg! I put it into a separate file to keep from putting RPM specific data in setup.py, I just picked package_data as the name because I did not know for sure what the current status of external configuration files in Distutils. > > *name - name of package > > *version - package version > > *summary - short summary of package > > *description - long summary of package > > Another yuck: description in setup.py -> summary in the .spec file, and > long_description in setup.py -> description in the .spec file. Oh well: > name conflicts happen, that's just life. I think the confusion can be > localized to bdist_rpm.py, so it's not too bad. Yea, I know. Unfortunately I didn't pick the names of the sections in a spec file. I wasn't sure whether to pick names that matched the Distutils meta-data or to pick names that matched spec file sections. I also thought about not allowing the packager to override the values that are already set in setup.py, if I disallowed this the whole issue would be moot. I am leaning more towards taking those variables out since, for example, overriding name or version would screw up the whole process (or at least the automation of the process). In the next patch all the variables that don't supply new data will probably be gone. > > doc - a list of string containing names of files and directories to put in > > the system's documentation directory. > > This should be initialized to ["README"] or ["README.txt"] (whichever > one happens to be supplied). The "sdist" command ought to make that > information available, but there isn't really a clean way to get it now. > Hmmm again. Will do. > > Unless otherwise noted these must all be strings. There is no type > > checking yet, I would like people's opinion: should they be cast to > > strings or should an exception be raised if they are not strings? > > I would say definitely do type-checking, and do it in the logical way: > require that everything be a string except: > * 'summaries' and 'descriptions' must be {string:string} dictionaries > * 'release' can be a number or a string Okay, I only left it out pending a decision on what form it should take, this will be in the next patch also. > > 'package_data's local namespace includes the variable 'package_type' which > > is set to 'rpm', this variable will hopefully allow 'package_data' to be > > used for all bdist_* commands . > > I think the right way to do this is to put these "not-quite-fundamental" > meta-data bits in the config file, in a "bdist" section (rather than a > "bdist_rpm" section). But that points back to me getting back to the > config file stuff.... > > > bdist_rpm works by making a spec file and saving it into the 'redhat/' > > directory (making the directory if necessary), it then produces a gzipped > > source tarball and runs `rpm -ta --clean` on the tarball. bdist_rpm leaves > > the spec file and tarball around since they would probably be wanted > > anyway. > > Why does the .spec file need a directory of its own? The .spec is tiny > and essential; I think it belongs right in the distribution root, like a > setup script or a makefile. Any temporary by-products of "bdist_rpm" I am not familiar with any packaging systems other than rpm and debian (and with regards to debian I am only familiar with it to the extent that is possible from browsing through the PyNcurses 'debian/' directory (which was contributed by someone else)). Not being familiar with other packaging systems I was a little afraid that another packaging system might have the same spec file naming convention as rpm and I didn't want them setting on each other. If this is not a concern I can change it to use the distribution root instead. I also thought it would fit in with the 'debian/' directory that the debian packaging system seems to use. > > tarball) saying around owned by root. The other caution is that the spec > > file must be included in MANIFEST.in, otherwise it will not be included in > > the tarball and therefore the tarball will not be buildable with rpm. > If you're talking about the standard source distribution tarball, I > don't think it *has* to include the .spec file: after all, the point of > the "bdist_rpm" command is to 1) generate a spec file, and 2) optionally > run some "rpm -b" commands on it. Anyone who downloads the source > distribution should be able to reconstruct the .spec file themselves > using the "bdist_rpm" command. Of course, then the module developer has The problem with not including the spec file is that I am using `rpm -ta` command rather than `rpm -ba` command. I am using this to get around the fact that the different distributions put rpm related files by default in different directories from each other, plus many users don't like to build RPMs as root and so set up their own directories for use with rpm. To use `rpm -ba` I would have to determine the location of the 'SOURCES/' directory and the only way I could figure out to do this was parsing the rpmrc, and this I did not want to do. Maybe I am missing an rpm command that spits this information out or allows you to define a specific source directory on the command line. `rpm -ta` takes a tarball containing a spec file and builds the RPM from that tarball and spec file. When the source RPM is produced the original tarball is placed in as the source file. Therefore, any source RPM produced with `rpm -ta` will contain a spec file in it's source tarball. The convention in rpm (and this is repeatedly stressed in rpm development materials) is to use pristine sources ie. the exact source distribution you would get if you went and downloaded it from the author's site. If the spec file is not included in the standard source distribution then any source RPM produced with `rpm -ta` will by definition be in violation of this convention. > How about another option to generate a source RPM? Not essential, but > it just seems complete. Plus it's generally considered nice to provide > source RPMs when you provide binary RPMs. I think it should be > accessible like this: > > setup.py bdist --format=srpm > or > setup.py bdist_rpm --srpm > > Maybe --source-rpm or --source-only on that last one; not sure. > > Also, should the normal output of "bdist_rpm" be just a binary RPM, or > both binary and source RPMs? If both by default, "--source-only" makes > sense. At the moment the default is to build both binary and source. rpm goes through the whole process whether you are building a binary or source rpm or both so I figured it would be better to just do both. Of course if there is a desire out there to only build one or the other I could easily add '--source-only' and '--binary-only' options that just call `rpm -ts` and `rpm -tb` instead of `rpm -ta`. Did you read my post regarding CFLAGS, and what do you feel is the best way to go on that issue? -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.ne From mwa@gate.net Wed May 3 22:59:32 2000 From: mwa@gate.net (Mark W. Alexander) Date: Wed, 3 May 2000 17:59:32 -0400 (EDT) Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000503052527.E20099@inet.net> Message-ID: On Wed, 3 May 2000, Harry Henry Gebel wrote: > Subject: Re: [Distutils] Instructions for bdist_rpm > [snipping and probably losing who said what....] > > > bdist_rpm works by making a spec file and saving it into the 'redhat/' > > > directory (making the directory if necessary), it then produces a gzipped > > > source tarball and runs `rpm -ta --clean` on the tarball. bdist_rpm leaves > > > the spec file and tarball around since they would probably be wanted > > > anyway. A couple of concerns: Redhat uses the /usr/src/redhat convention, Mandrake uses /usr/src/RPM so it's even worse than you noted. You could use rpm --showrc, but you'd probably end up (re)writing a parser to handle RPM macros, which would be just as bad as parsing the rpmrc (once you fond it). The -ta option is interesting. How does it handle patches? (see later on...) > > > > Why does the .spec file need a directory of its own? The .spec is tiny > > and essential; I think it belongs right in the distribution root, like a > > setup script or a makefile. Any temporary by-products of "bdist_rpm" > > I am not familiar with any packaging systems other than rpm and debian > (and with regards to debian I am only familiar with it to the extent that > is possible from browsing through the PyNcurses 'debian/' directory (which > was contributed by someone else)). Not being familiar with other packaging > systems I was a little afraid that another packaging system might have the > same spec file naming convention as rpm and I didn't want them setting on > each other. If this is not a concern I can change it to use the > distribution root instead. I also thought it would fit in with the > 'debian/' directory that the debian packaging system seems to use. I don't know debian well, but pkgtool (Solaris and others) includes the spec file type info in the files pkginfo and pkgproto, with other script files also allowed. They are annoyingly ALWAYS THOSE NAMES so they CANNOT go into the same directory. By convention, they are not usually even included in the packages. HP-UX uses .psf files, but I think that's a convention, not a requirement. > > The problem with not including the spec file is that I am using `rpm -ta` > command rather than `rpm -ba` command. I am using this to get around the > fact that the different distributions put rpm related files by default in > different directories from each other, plus many users don't like to build > RPMs as root and so set up their own directories for use with rpm. To use > `rpm -ba` I would have to determine the location of the 'SOURCES/' > directory and the only way I could figure out to do this was parsing the > rpmrc, and this I did not want to do. Maybe I am missing an rpm command > that spits this information out or allows you to define a specific source > directory on the command line. But still, don't you build the spec file from the distutil information anyway? That's going to be true of whatever package format the user requires, which, if it's not RPM the spec file is extraneous. I agree that figuring out the where's and what's of which rpm is going to be a nightmare...BUT, you can create a spec file with internal definitions for RPM_BUILD_ROOT, RPM_SOURCE_DIR, RPM_BUILD_DIR, etc, that does all the dirty work in /tmp, /var/tmp, or wherever, leaving only the final binary and/or source RPMS in the user's home directory. (That's my theory and I'm sticking to it untill someone points out an obvious error ;-). Anywhat, I strongly agree with supporting the creation of RPM's by non-root users. I just consider it safer, since it's pretty much impossible to step on a functioning installation. > > `rpm -ta` takes a tarball containing a spec file and builds the RPM from > that tarball and spec file. When the source RPM is produced the original > tarball is placed in as the source file. Therefore, any source RPM > produced with `rpm -ta` will contain a spec file in it's source tarball. > > The convention in rpm (and this is repeatedly stressed in rpm development > materials) is to use pristine sources ie. the exact source distribution > you would get if you went and downloaded it from the author's site. If the > spec file is not included in the standard source distribution then any > source RPM produced with `rpm -ta` will by definition be in violation of > this convention. BUT, they also support inclusion and application of patches with the "pristine" sources in order to support the inevitable modifications of dealing with multiple distributions and platforms. (By the way, for those that don't know, RPM does run on non-Linux UNIX'es. It's not pretty trying to get dependency interaction with stuff already installed, 'though...) So the big question is does the -ta option support the inclusion of patch sets? > > At the moment the default is to build both binary and source. rpm goes > through the whole process whether you are building a binary or source rpm > or both so I figured it would be better to just do both. Of course if > there is a desire out there to only build one or the other I could easily > add '--source-only' and '--binary-only' options that just call `rpm -ts` > and `rpm -tb` instead of `rpm -ta`. I positively vote either-or-whatever! The only consideration I see is if someone is extremely space tight. It takes moments longer to produce the source rpm. mwa From gward@ase.com Thu May 4 02:31:03 2000 From: gward@ase.com (Greg Ward) Date: Wed, 3 May 2000 21:31:03 -0400 Subject: [Distutils] HTML manuals available In-Reply-To: <390FD1F9.D6DE71F8@GermanLloyd.org>; from Berthold Hoellmann on Wed, May 03, 2000 at 09:15:05AM +0200 References: <20000502212745.C1562@beelzebub> <390FD1F9.D6DE71F8@GermanLloyd.org> Message-ID: <20000503213103.B531@beelzebub> On 03 May 2000, Berthold Hoellmann said: > Haven't have more than a first look it seems, the navigation buttons are > missing, at least from the top document. Yeah, I noticed that too, and I'm not going to worry about it. This is just a temporary measure until Fred starts putting out pre-release copies of the 1.6 documentation "for real". I'm more interested in hearing about mangled HTML, bad writing, code/documentation mismatches, etc. Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ I just forgot my whole philosophy of life!!! From hgebel@inet.net Thu May 4 08:53:54 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Thu, 4 May 2000 03:53:54 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: ; from mwa@gate.net on Wed, May 03, 2000 at 05:59:32PM -0400 References: <20000503052527.E20099@inet.net> Message-ID: <20000504035354.E21388@inet.net> On Wed, May 03, 2000 at 05:59:32PM -0400, Mark W. Alexander wrote: > A couple of concerns: Redhat uses the /usr/src/redhat convention, > Mandrake uses /usr/src/RPM so it's even worse than you noted. > You could use rpm --showrc, but you'd probably end up (re)writing > a parser to handle RPM macros, which would be just as bad as > parsing the rpmrc (once you fond it). The -ta option is interesting. This was exactly my point. > But still, don't you build the spec file from the distutil information > anyway? That's going to be true of whatever package format the user > requires, which, if it's not RPM the spec file is extraneous. I agree > that figuring out the where's and what's of which rpm is going to > be a nightmare...BUT, you can create a spec file with internal > definitions for RPM_BUILD_ROOT, RPM_SOURCE_DIR, RPM_BUILD_DIR, etc, > that does all the dirty work in /tmp, /var/tmp, or wherever, > leaving only the final binary and/or source RPMS in the user's > home directory. (That's my theory and I'm sticking to it untill > someone points out an obvious error ;-). I did not specify them in the spec file because I do not want them being hard-coded as going places that the user does not expect. What I am going to try is to dump the rc with `rpm --showrc` and then tag new definitions to the end of the a temporory file and use that file as an rc file, hopefully that will work. Believe me, I would rather use `rpm -ba` rather than `rpm -ta` for a lot of reasons, if I could figure out a way to make it work without stepping on source RPM user's expectations. > BUT, they also support inclusion and application of patches with the > "pristine" sources in order to support the inevitable modifications > of dealing with multiple distributions and platforms. (By the way, > for those that don't know, RPM does run on non-Linux UNIX'es. It's > not pretty trying to get dependency interaction with stuff already > installed, 'though...) So the big question is does the -ta option > support the inclusion of patch sets? `rpm -ta` does not support patches, but I do not think that is a problem because I don't plan to put patch support into bdist_rpm. People who are producing patched RPMs will have to add the patches to the spec file by hand, this is a simple process that involves adding two lines to the spec file per patch and is one of the reasons I tried to keep the spec file as clean as possible. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.net From mwa@gate.net Thu May 4 14:44:38 2000 From: mwa@gate.net (Mark W. Alexander) Date: Thu, 4 May 2000 09:44:38 -0400 (EDT) Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000504035354.E21388@inet.net> Message-ID: On Thu, 4 May 2000, Harry Henry Gebel wrote: > `rpm -ta` does not support patches, but I do not think that is a problem > because I don't plan to put patch support into bdist_rpm. People who are > producing patched RPMs will have to add the patches to the spec file by > hand, this is a simple process that involves adding two lines to the spec > file per patch and is one of the reasons I tried to keep the spec file as > clean as possible. Sold. Upon reflection, given the context of Distutils, patch support does seem kinda silly. That pretty much eradicates the other issues of using -t? vs. -b?. I'll step out of your way now... mwa From hgebel@inet.net Thu May 4 16:14:05 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Thu, 4 May 2000 11:14:05 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: ; from mwa@gate.net on Thu, May 04, 2000 at 09:44:38AM -0400 References: <20000504035354.E21388@inet.net> Message-ID: <20000504111405.A23465@inet.net> On Thu, May 04, 2000 at 09:44:38AM -0400, Mark W. Alexander wrote: > On Thu, 4 May 2000, Harry Henry Gebel wrote: > > `rpm -ta` does not support patches, but I do not think that is a problem > > because I don't plan to put patch support into bdist_rpm. People who are > > producing patched RPMs will have to add the patches to the spec file by > > hand, this is a simple process that involves adding two lines to the spec > > file per patch and is one of the reasons I tried to keep the spec file as > > clean as possible. > Sold. Upon reflection, given the context of Distutils, patch support does > seem kinda silly. That pretty much eradicates the other issues of > using -t? vs. -b?. I'll step out of your way now... My own personal reason is so I can add an option to use bztar for the source code; rpm supports bzip2 with `rpm -ba` but not `rpm -ta`. And I think Greg is right that they shouldn't have to include the spec file in the RPM, it's just a requirement as long as I am using `rpm -ta`, switching to `rpm -ba` would eliminate that to. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.ne From gward@ase.com Fri May 5 02:46:22 2000 From: gward@ase.com (Greg Ward) Date: Thu, 4 May 2000 21:46:22 -0400 Subject: [Distutils] Update bdist_rpm patch In-Reply-To: <20000427055048.J32467@inet.net>; from Harry Henry Gebel on Thu, Apr 27, 2000 at 05:50:48AM -0400 References: <20000427055048.J32467@inet.net> Message-ID: <20000504214622.A487@beelzebub> On 27 April 2000, Harry Henry Gebel said: > One important consideration for --arch : Unless ./setup.py can be made to > recognize the rpm's CFLAGS it will generate the same object code no matter > what architecture you specify. That's a feature. No way do I plan to support cross-compiling in the Distutils. Quick, when was the last time anybody cared about cross-compiling? ;-) My original reasoning for wanting the --arch option to "bdist_rpm" was to set the "build arch" string for binary RPMs. My thinking was that "bdist_rpm" wouldn't have anything better than the value returned by 'distutils.util.get_platform()' to go by, meaning it would use (eg.) "linux2-i586" when it should really use "i386". (At least, those are the values returned by 'get_platform()' and used by RPM on my system.) However, I may have been wrong -- ie. it looks as though RPM is smart enough to put in the "right" build arch string itself. The only thing Distutils would have to do, then, is set it to "noarch" if there are no extensions -- ie. if this is a pure Python module distribution. Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ "I came, I saw, she conquered." (The original Latin seems to have been garbled.) From gward@ase.com Fri May 5 03:22:22 2000 From: gward@ase.com (Greg Ward) Date: Thu, 4 May 2000 22:22:22 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000504111405.A23465@inet.net>; from Harry Henry Gebel on Thu, May 04, 2000 at 11:14:05AM -0400 References: <20000504035354.E21388@inet.net> <20000504111405.A23465@inet.net> Message-ID: <20000504222222.B487@beelzebub> On 04 May 2000, Harry Henry Gebel said: > My own personal reason is so I can add an option to use bztar for the > source code; rpm supports bzip2 with `rpm -ba` but not `rpm -ta`. And I > think Greg is right that they shouldn't have to include the spec file in > the RPM, it's just a requirement as long as I am using `rpm -ta`, > switching to `rpm -ba` would eliminate that to. Sounds like you're moving in the right direction to me, so I assume another version of the patch is forthcoming. For the record, I think all are agreed here: no need to support patches in Distutils-generated RPMs, better to use -b than -t, and preferable not to require including the .spec file in the source distribution. I don't see a burning need for bzip2 support, but if you can work it in cleanly (like with the "sdist" command) go ahead. Before you do send another version of the patch, though, I have one small request: lowercase_method_names please, not camelCase! It's the convention I've used throughout the Distutils (and in pretty much every line of C, Python, and Perl I've written in the last 4 or 5 years), and I'd rather keep the code consistent. Thanks! Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ Sure, I'm paranoid... but am I paranoid ENOUGH? From hgebel@inet.net Fri May 5 05:44:45 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Fri, 5 May 2000 00:44:45 -0400 Subject: [Distutils] Update bdist_rpm patch In-Reply-To: <20000504214622.A487@beelzebub>; from gward@ase.com on Thu, May 04, 2000 at 09:46:22PM -0400 References: <20000427055048.J32467@inet.net> <20000504214622.A487@beelzebub> Message-ID: <20000505004445.A24970@inet.net> On Thu, May 04, 2000 at 09:46:22PM -0400, Greg Ward wrote: > On 27 April 2000, Harry Henry Gebel said: > > One important consideration for --arch : Unless ./setup.py can be made to > > recognize the rpm's CFLAGS it will generate the same object code no matter > > what architecture you specify. > That's a feature. No way do I plan to support cross-compiling in the > Distutils. Quick, when was the last time anybody cared about > cross-compiling? ;-) > However, I may have been wrong -- ie. it looks as though RPM is smart > enough to put in the "right" build arch string itself. The only thing > Distutils would have to do, then, is set it to "noarch" if there are no > extensions -- ie. if this is a pure Python module distribution. I wasn't looking at --arch and CFLAGS to support cross-compiling, rather it is to support different versions of the same processor family. If I compile 'module-1.0-1.src.rpm' on an i386 or with '--target=i386' it will generate 'module-1.0-1.i386.rpm' but if I compile the same source RPM on a Pentium II or with '--target=i686' it will generate 'module-1.0-1.i686.rpm' even though it is really an i386 binary because ./setup.py does not pass any '--mcpu' or '--march' options to gcc. RPM sets a variable containing the appropriate '--mcpu' and '--march' (and other) options, but in does not appear that there is any way to use this variable in ./setup.py at this time. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.ne From hgebel@inet.net Fri May 5 05:54:51 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Fri, 5 May 2000 00:54:51 -0400 Subject: [Distutils] Instructions for bdist_rpm In-Reply-To: <20000504222222.B487@beelzebub>; from gward@ase.com on Thu, May 04, 2000 at 10:22:22PM -0400 References: <20000504035354.E21388@inet.net> <20000504111405.A23465@inet.net> <20000504222222.B487@beelzebub> Message-ID: <20000505005451.C24970@inet.net> On Thu, May 04, 2000 at 10:22:22PM -0400, Greg Ward wrote: > On 04 May 2000, Harry Henry Gebel said: > > My own personal reason is so I can add an option to use bztar for the > > source code; rpm supports bzip2 with `rpm -ba` but not `rpm -ta`. And I > the .spec file in the source distribution. I don't see a burning need > for bzip2 support, but if you can work it in cleanly (like with the > "sdist" command) go ahead. Yes I am planning on using sdist to generate the bzipped tarball, and it is going to be an option, leaving gzip as the default. The main reason is to shrink the size of the source RPM (it will have no effect on the binary RPM since rpm has no options (yet) supporting changing compression methods in binary RPMs). > Before you do send another version of the patch, though, I have one > small request: lowercase_method_names please, not camelCase! It's the > convention I've used throughout the Distutils (and in pretty much every > line of C, Python, and Perl I've written in the last 4 or 5 years), and > I'd rather keep the code consistent. Thanks! Sorry, force of habit. I noticed the convention used in Distutils and made a note to use it, but forgot the note! The names will be changed in the next patch. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python: http://pyncurses.sourceforge.ne From hgebel@inet.net Fri May 5 07:21:55 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Fri, 5 May 2000 02:21:55 -0400 Subject: [Distutils] Latest bdist_rpm Message-ID: <20000505022154.D24970@inet.net> --JYK4vJDZwFMowpUq Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I have added type checking to bdist_rpm, eliminated the ability to override meta-data supplied in './setup.py', and changed the function names to the standard Distutils style. Tomorrow I hope to be building with `rpm -ba` instead of `rpm -ta` and I have some options I will add. The patch to existing files and the 'package_data' file have not changed. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --JYK4vJDZwFMowpUq Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.py" """distutils.command.bdist_rpm Implements the Distutils 'bdist_rpm' command (create RPM source and binary distributions.""" # created 2000/04/25, by Harry Henry Gebel __revision__ = "$Id: bdist_dumb.py,v 1.3 2000/04/22 02:51:25 gward Exp $" from os.path import exists import os from distutils.core import Command from distutils.util import mkpath, write_file, remove_tree from distutils.errors import * from string import join from types import StringType, DictType, LongType, FloatType, IntType class bdist_rpm (Command): description = "create an RPM distribution" user_options = [ ('spec-only', None, "Only regenerate spec file"), ('tar-only', None, "Only generate spec file and tarball"), ('no-remove', None, "Do not remove root owned files"), ('arch=', None, "Build for a specific architecture"), ] def initialize_options (self): self.spec_only = None self.tar_only = None self.no_remove = None self.arch = None # initialize_options() def finalize_options (self): if os.name != 'posix': raise DistutilsPlatformError, \ ("don't know how to create RPM " "distributions on platform %s") % os.name if self.spec_only and self.tar_only: raise DistutilsOptionsError, \ 'Cannot specify both spec-only and tar-only' if os.getuid(): # if not root if self.no_remove: self.warn('no-remove has no effect when not root') self.remove = None else: # if root if self.no_remove: self.remove = None else: self.remove = 1 # finalize_options() def run (self): self._get_package_data() # get packaging info # place spec file in ./redhat directory self.execute(mkpath, ('./redhat',), "Created ./redhat directory") spec_path = './redhat/%s.spec' % self.distribution.get_name() self.execute(write_file, (spec_path, self._make_spec_file()), 'Writing .spec file') if self.spec_only: # stop if requested return # make a .gz distribution sdist = self.find_peer ('sdist') sdist.set_option ('formats', ['gztar']) self.run_peer('sdist') if self.tar_only: # stop if requested return # build package self.announce('Building RPMs') rpm_args = ['rpm', '-ta', '--clean'] if self.arch and self.distribution.has_ext_modules(): rpm_args.append['--target=' + arch] rpm_args.append(self.distribution.get_fullname() + '.tar.gz') self.spawn(rpm_args) if self.remove: # remove generated files self.execute(self._remove_root, (), 'Removing generated files') # run() def _remove_root(self): ''' Remove files generated to support rpm ''' os.unlink('MANIFEST') os.unlink(self.distribution.get_fullname() + '.tar.gz') remove_tree('redhat') def _get_package_data(self): ''' Get data needed to generate spec file, first from the DistributionMetadata class, then from the package_data file, which is Python code read with execfile() ''' package_type = 'rpm' # read in package data, if any if exists('package_data'): try: exec(open('package_data')) except: raise DistutilsOptionError, 'Unable to parse package data file' # set instance variables, supplying default value if not provided in # package data file vars = locals().keys() # the following variables must be {string (len() = 2): string} if 'summaries' in vars: self.summaries = self._check_locale(summaries, 'summaries') else: self.summaries = {} if 'descriptions' in vars: self.descriptions = self._check_locale(descriptions, 'descriptions') else: self.descriptions = {} # The following variable must be an ordinary number or a string if 'release' in vars: if type(release) in (StringType, LongType, IntType, FloatType): self.release = str(release) else: raise DistutilsOptionError, \ ("Error in package_data: 'release' must be a number or " 'a string') else: self.release = '1' # The following variables must be strings if 'group' in vars: self.group = self._check_string(group, 'group') else: self.group = 'Applications' if 'vendor' in vars: self.vendor = self._check_string(vendor, 'vendor') else: self.vendor = None if 'packager' in vars: self.packager = self._check_string(packager, 'vendor') else: self.packager = None if 'changelog' in vars: self.changelog = self._check_string(changelog, 'vendor') else: self.changelog = None # doc must be a list (or tuple) of strings, or a string if 'doc' not in vars: doc = [] for readme in ('README', 'README.txt'): if exists(readme): doc.append(readme) try: self.doc = join(doc) except: raise DistutilsOptionError, \ "Error in package_data: 'doc' must be a sequence of strings" if 'changelog' in vars: self.changelog = changelog else: self.changelog = None def _make_spec_file(self): ''' Generate an RPM spec file ''' spec_file = [ '%define name ' + self.distribution.get_name(), '%define version ' + self.distribution.get_version(), '%define release ' + self.release, '', 'Summary: ' + self.distribution.get_description(), ] # put locale summaries into spec file for locale in self.summaries.keys(): spec_file.append('Summary(%s): %s' % (locale, self.summaries[locale])) spec_file.extend([ 'Name: %{name}', 'Version: %{version}', 'Release: %{release}', 'Source0: %{name}-%{version}.tar.gz', 'Copyright: ' + self.distribution.get_licence(), 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-buildroot', 'Prefix: %{_prefix}', ]) if not self.distribution.has_ext_modules(): spec_file.append('BuildArchitectures: noarch') if self.vendor: spec_file.append('Vendor: ' + self.vendor) if self.packager: spec_file.append('Packager: ' + self.packager) if self.distribution.get_url() != 'UNKNOWN': spec_file.append('Url: ' + self.distribution.get_url()) spec_file.extend([ '', '%description', self.distribution.get_long_description()]) # put locale descriptions into spec file for locale in self.descriptions.keys(): spec_file.extend([ '', '%description -l ' + locale, self.descriptions[locale], ]) spec_file.extend([ '', '%prep', '%setup', '', '%build', 'python setup.py build', '', '%install', 'python setup.py install --root=$RPM_BUILD_ROOT --record', '', '%clean', 'rm -rf $RPM_BUILD_ROOT', 'rm -f INSTALLED_FILES', '', '%files -f INSTALLED_FILES', '%defattr(-,root,root)', ]) if self.doc: spec_file.append('%doc ' + self.doc) if self.changelog: spec_file.extend([ '', '%changelog', self.changelog ]) return spec_file def _check_locale(self, test_me, name): ''' Tests a wariable to determine if it is {string: string} ''' pass_test = 1 # set to 0 if fails test if type(test_me) == DictType: for locale in test_me.keys(): if (type(locale) != StringType) or (type(test_me[locale]) != StringType): pass_test = 0 break if pass_test: return test_me raise DistutilsOptionError, \ ("Error in package_data: '%s' must be dictionary: " '{string: string}' % name) def _check_string(self, test_me, name): ''' Tests a variable to determino if it is a string ''' if type(test_me) == StringType: return test_me else: raise DistutilsOptionError, \ "Error in package_data: '%s' must be a string" % name --JYK4vJDZwFMowpUq-- From hgebel@inet.net Fri May 5 16:38:41 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Fri, 5 May 2000 11:38:41 -0400 Subject: [Distutils] Nem bdist_rpm Message-ID: <20000505113841.A25756@inet.net> --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is a new version of bdist_rpm. bdist_rpm now builds in build/rpm using `rpm -ba` so it no longer requires the spec file to be in the source distribution and can be completely built by non-root users. Here are the current options: --spec-only - only generates a spec file --source-only - only build a source RPM --binary-only - only build a binary RPW --use-bzip2 - makes source distribution using bzip2 --no-clean - does not clean build/rpm/BUILD after building RPM --arch has been temporarily disabled since 'rpm -ba --target=' does not seem to work with 'rpm -ba --define'. I will be trying to find out why on the RPM list. `./setup.py clean` does not yet take care of 'build/rpm'. When used with the --spec-only option the spec file is placed in redhat/, otherwise it is placed in /build/rpm/SPECS. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.py" """distutils.command.bdist_rpm Implements the Distutils 'bdist_rpm' command (create RPM source and binary distributions.""" # created 2000/04/25, by Harry Henry Gebel __revision__ = "$Id: bdist_dumb.py,v 1.3 2000/04/22 02:51:25 gward Exp $" from os.path import exists import os from distutils.core import Command from distutils.util import mkpath, write_file, copy_file from distutils.errors import * from string import join from types import StringType, DictType, LongType, FloatType, IntType class bdist_rpm (Command): description = "create an RPM distribution" user_options = [ ('spec-only', None, "Only regenerate spec file"), # ('arch=', None, # "Build for a specific architecture"), ('source-only', None, "Only generate source RPM"), ('binary-only', None, "Only generate binary RPM"), ('use-bzip2', None, "Use bzip2 instead of gzip to create source distribution"), ('no-clean', None, "Do not clean RPM build directory") ] def initialize_options (self): self.spec_only = None # self.arch = None self.binary_only = None self.source_only = None self.use_bzip2 = None self.no_clean = None # initialize_options() def finalize_options (self): if os.name != 'posix': raise DistutilsPlatformError, \ ("don't know how to create RPM " "distributions on platform %s" % os.name) if self.binary_only and self.source_only: raise DistutilsOptionsError, \ "Cannot supply both '--source-only' and '--binary-only'" # finalize_options() def run (self): self._get_package_data() # get packaging info # make directories if self.spec_only: self.execute(mkpath, ('redhat',), "Created './redhat' directory") else: self.execute(mkpath, ('build/rpm/SOURCES',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SPECS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/BUILD',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/RPMS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SRPMS',), "Created RPM source directory") # spec file goes into .redhat directory if '--spec-only specified', # into build/rpm/spec otherwisu if self.spec_only: spec_path = './redhat/%s.spec' % self.distribution.get_name() else: spec_path = ('build/rpm/SPECS/%s.spec' % self.distribution.get_name()) self.execute(write_file, (spec_path, self._make_spec_file()), 'Writing .spec file') if self.spec_only: # stop if requested return # make a source distribution and copy to SOURCES directory sdist = self.find_peer ('sdist') if self.use_bzip2: sdist.set_option ('formats', ['bztar']) else: sdist.set_option ('formats', ['gztar']) self.run_peer('sdist') if self.use_bzip2: source = self.distribution.get_fullname() + '.tar.bz2' else: source = self.distribution.get_fullname() + '.tar.gz' self.execute(copy_file, (source, 'build/rpm/SOURCES'), 'Copying source distribution to SOURCES') # build package self.announce('Building RPMs') rpm_args = ['rpm',] if self.source_only: # what kind of RPMs? rpm_args.append('-bs') elif self.binary_only: rpm_args.append('-bb') else: rpm_args.append('-ba') topdir = os.getcwd() + 'build/rpm' rpm_args.extend(['--define', '_topdir ' + os.getcwd() + '/build/rpm',]) if not self.no_clean: rpm_args.append('--clean') # if self.arch and self.distribution.has_ext_modules(): # rpm_args.extend('define', '_target_cpu ' + self.arch) rpm_args.append(spec_path) self.spawn(rpm_args) # run() def _get_package_data(self): ''' Get data needed to generate spec file, first from the DistributionMetadata class, then from the package_data file, which is Python code read with execfile() ''' package_type = 'rpm' # read in package data, if any if exists('package_data'): try: exec(open('package_data')) except: raise DistutilsOptionError, 'Unable to parse package data file' # set instance variables, supplying default value if not provided in # package data file vars = locals().keys() # the following variables must be {string (len() = 2): string} if 'summaries' in vars: self.summaries = self._check_locale(summaries, 'summaries') else: self.summaries = {} if 'descriptions' in vars: self.descriptions = self._check_locale(descriptions, 'descriptions') else: self.descriptions = {} # The following variable must be an ordinary number or a string if 'release' in vars: if type(release) in (StringType, LongType, IntType, FloatType): self.release = str(release) else: raise DistutilsOptionError, \ ("Error in package_data: 'release' must be a number or " 'a string') else: self.release = '1' # The following variables must be strings if 'group' in vars: self.group = self._check_string(group, 'group') else: self.group = 'Applications' if 'vendor' in vars: self.vendor = self._check_string(vendor, 'vendor') else: self.vendor = None if 'packager' in vars: self.packager = self._check_string(packager, 'vendor') else: self.packager = None if 'changelog' in vars: self.changelog = self._check_string(changelog, 'vendor') else: self.changelog = None # doc must be a list (or tuple) of strings, or a string if 'doc' not in vars: doc = [] for readme in ('README', 'README.txt'): if exists(readme): doc.append(readme) try: self.doc = join(doc) except: raise DistutilsOptionError, \ "Error in package_data: 'doc' must be a sequence of strings" if 'changelog' in vars: self.changelog = changelog else: self.changelog = None def _make_spec_file(self): ''' Generate an RPM spec file ''' spec_file = [ '%define name ' + self.distribution.get_name(), '%define version ' + self.distribution.get_version(), '%define release ' + self.release, '', 'Summary: ' + self.distribution.get_description(), ] # put locale summaries into spec file for locale in self.summaries.keys(): spec_file.append('Summary(%s): %s' % (locale, self.summaries[locale])) spec_file.extend([ 'Name: %{name}', 'Version: %{version}', 'Release: %{release}',]) if self.use_bzip2: spec_file.append('Source0: %{name}-%{version}.tar.bz2') else: spec_file.append('Source0: %{name}-%{version}.tar.gz') spec_file.extend([ 'Copyright: ' + self.distribution.get_licence(), 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-buildroot', 'Prefix: %{_prefix}', ]) if not self.distribution.has_ext_modules(): spec_file.append('BuildArchitectures: noarch') if self.vendor: spec_file.append('Vendor: ' + self.vendor) if self.packager: spec_file.append('Packager: ' + self.packager) if self.distribution.get_url() != 'UNKNOWN': spec_file.append('Url: ' + self.distribution.get_url()) spec_file.extend([ '', '%description', self.distribution.get_long_description()]) # put locale descriptions into spec file for locale in self.descriptions.keys(): spec_file.extend([ '', '%description -l ' + locale, self.descriptions[locale], ]) spec_file.extend([ '', '%prep', '%setup', '', '%build', 'python setup.py build', '', '%install', 'python setup.py install --root=$RPM_BUILD_ROOT --record', '', '%clean', 'rm -rf $RPM_BUILD_ROOT', 'rm -f INSTALLED_FILES', '', '%files -f INSTALLED_FILES', '%defattr(-,root,root)', ]) if self.doc: spec_file.append('%doc ' + self.doc) if self.changelog: spec_file.extend([ '', '%changelog', self.changelog ]) return spec_file def _check_locale(self, test_me, name): ''' Tests a wariable to determine if it is {string: string} ''' pass_test = 1 # set to 0 if fails test if type(test_me) == DictType: for locale in test_me.keys(): if (type(locale) != StringType) or (type(test_me[locale]) != StringType): pass_test = 0 break if pass_test: return test_me raise DistutilsOptionError, \ ("Error in package_data: '%s' must be dictionary: " '{string: string}' % name) def _check_string(self, test_me, name): ''' Tests a variable to determino if it is a string ''' if type(test_me) == StringType: return test_me else: raise DistutilsOptionError, \ "Error in package_data: '%s' must be a string" % name --n8g4imXOkfNTN/H1-- From jlj@cfdrc.com Fri May 5 21:00:50 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 05 May 2000 15:00:50 -0500 Subject: [Distutils] distutils & Borland's free compiler Message-ID: <39132872.9ADEE7A7@cfdrc.com> Gordon, First of all, thanks very much for posting your paper about compiling Python extensions with Borland's free compiler. I haven't tried it out yet but am looking forward to experimenting with this next week. I also wanted to check to see if you are familiar with the work going on in the Distutils-SIG (which will become part of the standard Python library in Python 1.6): http://www.python.org/sigs/distutils-sig Their support for building Python extensions under Windows is currently limited to Microsoft Visual C++. I'd like to work-up a new module for the distutils which would also the support use of Borland's C++ compiler, based on your instructions (and with all appropriate credits, of course). Had you planned to look at that, or do you know if anyone else is? I obviously don't want to duplicate anyone else's efforts... Lyle From gward@ase.com Sat May 6 14:17:20 2000 From: gward@ase.com (Greg Ward) Date: Sat, 6 May 2000 09:17:20 -0400 Subject: [Distutils] Update bdist_rpm patch In-Reply-To: <20000505004445.A24970@inet.net>; from Harry Henry Gebel on Fri, May 05, 2000 at 12:44:45AM -0400 References: <20000427055048.J32467@inet.net> <20000504214622.A487@beelzebub> <20000505004445.A24970@inet.net> Message-ID: <20000506091720.A456@beelzebub> On 05 May 2000, Harry Henry Gebel said: > I wasn't looking at --arch and CFLAGS to support cross-compiling, rather > it is to support different versions of the same processor family. If I > compile 'module-1.0-1.src.rpm' on an i386 or with '--target=i386' it will > generate 'module-1.0-1.i386.rpm' but if I compile the same source RPM on a > Pentium II or with '--target=i686' it will generate > 'module-1.0-1.i686.rpm' even though it is really an i386 binary because > ./setup.py does not pass any '--mcpu' or '--march' options to gcc. RPM > sets a variable containing the appropriate '--mcpu' and '--march' (and > other) options, but in does not appear that there is any way to use this > variable in ./setup.py at this time. Aahhh! I get it now, thanks. Anyways, I've just checked in a change that should enable this. It was already possible to sneak extra arguments into the link command line; now it can be done with the compile command line to boot. Start in the 'build_extensions()' method of distutils/command/build_ext.py; you'll note that it now looks for an 'extra_compile_args' element in the 'build_info' dictionary. FYI: 'build_info' is the dictionary of info that's included with each extension and contains all the information required to build the extension on "any" platform. For example, here's a snippet from the NumPy setup script: ext_modules = [('_numpy', { 'sources' : ['Src/_numpymodule.c', 'Src/arrayobject.c', 'Src/ufuncobject.c'], } ), If I want to sneak, say, "-m486", onto the compiler command line for each of the three source files in *this* extensions, I would change the build_info dict shown here to: { 'sources' : ['Src/_numpymodule.c', 'Src/arrayobject.c', 'Src/ufuncobject.c'], 'extra_compile_afgs' : ['-m486'] } Of course, you'll be invoking "build_ext" programmatically, rather than through the command line and setup script, so it'll be slightly different for you. This should give you the idea, though; just read through the 'build_extensions()' method and you should see what's going on. Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ Speak softly and carry a +6 two-handed sword. From gward@ase.com Sat May 6 14:19:55 2000 From: gward@ase.com (Greg Ward) Date: Sat, 6 May 2000 09:19:55 -0400 Subject: [Distutils] distutils & Borland's free compiler In-Reply-To: <39132872.9ADEE7A7@cfdrc.com>; from Lyle Johnson on Fri, May 05, 2000 at 03:00:50PM -0500 References: <39132872.9ADEE7A7@cfdrc.com> Message-ID: <20000506091955.B456@beelzebub> On 05 May 2000, Lyle Johnson said: > Their support for building Python extensions under Windows is currently > limited to Microsoft Visual C++. I'd like to work-up a new module for > the distutils which would also the support use of Borland's C++ > compiler, based on your instructions (and with all appropriate credits, > of course). Had you planned to look at that, or do you know if anyone > else is? I obviously don't want to duplicate anyone else's efforts... Excellent! Please do it! I assume you are aware that the starting point is msvccompiler.py; let me just *strongly* encourage you to refactor common code out of the MSVCCompiler class and whatever-you-write (BorlandCCompiler?) rather than submitting a patch with lots of overlapping code. Thanks in advance! Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ I appoint you ambassador to Fantasy Island!!! From hgebel@inet.net Sat May 6 15:07:02 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Sat, 6 May 2000 10:07:02 -0400 Subject: [Distutils] Update bdist_rpm patch In-Reply-To: <20000506091720.A456@beelzebub>; from gward@ase.com on Sat, May 06, 2000 at 09:17:20AM -0400 References: <20000427055048.J32467@inet.net> <20000504214622.A487@beelzebub> <20000505004445.A24970@inet.net> <20000506091720.A456@beelzebub> Message-ID: <20000506100701.A582@inet.net> On Sat, May 06, 2000 at 09:17:20AM -0400, Greg Ward wrote: > On 05 May 2000, Harry Henry Gebel said: > > I wasn't looking at --arch and CFLAGS to support cross-compiling, rather > > it is to support different versions of the same processor family. If I > note that it now looks for an 'extra_compile_args' element in the > 'build_info' dictionary. Thanks, I have a post on rpm-list asking about the '--target' problem, as soon as that is figured out I will put this in. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.ne From gward@ase.com Sun May 7 16:49:51 2000 From: gward@ase.com (Greg Ward) Date: Sun, 7 May 2000 11:49:51 -0400 Subject: [Distutils] Where to find config files Message-ID: <20000507114951.A1336@beelzebub> Hi all -- I've finally started coding the Distutils config file stuff, now that I actually have a design of sorts on paper. Anyways, one little procedural issue: how many config files should there be, and where to find them? Here's my initial stab at a policy: def find_config_files (self): """Find as many configuration files as should be processed for this platform, and return a list of filenames in the order in which they should be parsed. The filenames returned are guaranteed to exist and be readable (modulo nasty race conditions). On Unix, there are three possible config files: pydistutils.cfg in the Distutils installation directory (ie. where the top-level Distutils __inst__.py file lives), .pydistutils.cfg in the user's home directory, and setup.cfg in the current directory. On Windows and Mac OS, there are two possible config files: pydistutils.cfg in the Python installation directory (sys.prefix) and setup.cfg in the current directory.""" Code forthcoming... Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ Are we THERE yet? From jlj@cfdrc.com Mon May 8 16:24:15 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Mon, 8 May 2000 10:24:15 -0500 Subject: [Distutils] distutils & Borland's free compiler In-Reply-To: <20000506160019.C70561CDE8@dinsdale.python.org> Message-ID: <000501bfb901$788f0d10$4e574dc0@cfdrc.com> > Excellent! Please do it! I assume you are aware that the starting > point is msvccompiler.py; let me just *strongly* encourage you to > refactor common code out of the MSVCCompiler class and > whatever-you-write (BorlandCCompiler?) rather than submitting a patch > with lots of overlapping code. Maybe I need to double-check the architecture of the distutils with you. It appeared that I (basically) needed to do two things: 1. Create a new class (I was calling it BCPPCompiler, but I'm not too attached to that name ;) which is derived from CCompiler. This class lives in its own module file "bcppcompiler.py" so that it is on the same footing as "msvccompiler.py" (which supports that other company's compiler). 2. Patch distutils/ccompiler.py to add this new compiler into the compiler_class dictionary. 3. Ask Greg about how to let the end-user actually override the default compiler choice for platform "nt". This could be done by passing the keyword argument compiler=bcpp to the new_compiler() factory function, if we had some kind of commmand-line option to let the user do that... Three! Three things! Lyle From jlj@cfdrc.com Mon May 8 23:31:57 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Mon, 8 May 2000 17:31:57 -0500 Subject: [Distutils] More questions on distutils... Message-ID: <000001bfb93d$37e59680$4e574dc0@cfdrc.com> Greg, While working out the stuff for supporting Borland's C/C++ compiler under the Distutils, I've gotten a little confused about the division of responsbilities for the various command and compiler classes. The specific case I'm studying right now is the "built_ext" command (implemented in distutils/command/built_ext.py). If you take a look at the build_extensions() function defined in this class, it appears that he "knows" some things about the "msvc" compiler. It seems like you'd want to avoid letting the various commands know these kinds of details about specific implementations of the CCompiler class. Ideally, they would stick to the basic CCompiler interface, no? I'm not attacking the current implementation -- I know that the primary goal to this point is to get things working. But now I'm faced with the decision about where to put certain Borland-specific flags and so forth -- do they come in solely through the new BCPPCompiler class, or do some of them also filter in through the build_ext command (and his siblings)? Please clue me in ;) I've got the Borland stuff basically working now but I'd like to get it a little cleaner before submitting my proposed patches, etc. Thanks, Lyle From mmuller@enduden.com Sat May 6 01:25:27 2000 From: mmuller@enduden.com (Michael Muller) Date: Mon, 05 May 2000 20:25:27 -0400 Subject: [Distutils] Where to find config files Message-ID: <200005090034.UAA09560@bogus.com> Greg Ward wrote: [snip] > On Unix, there are three possible config files: pydistutils.cfg in > the Distutils installation directory (ie. where the top-level > Distutils __inst__.py file lives), .pydistutils.cfg in the user's > home directory, and setup.cfg in the current directory. [snip] I totally agree with the site-home-currentdir structure, but shouldn't the site level file live someplace apart from the code? If you customize the site file, you probably don't want your changes clobbered by a subsequent distutils install. sys.prefix + '/etc', perhaps? ============================================================================= michaelMuller = mmuller@enduden.com | http://www.cloud9.net/~proteus ----------------------------------------------------------------------------- Mantra for the 60's: Tune in, turn on, drop out Mantra for the 90's: Turn on, jack in, jerk off ============================================================================= From gward@ase.com Tue May 9 02:22:09 2000 From: gward@ase.com (Greg Ward) Date: Mon, 8 May 2000 21:22:09 -0400 Subject: [Distutils] Where to find config files In-Reply-To: <200005090034.UAA09560@bogus.com>; from Michael Muller on Fri, May 05, 2000 at 08:25:27PM -0400 References: <200005090034.UAA09560@bogus.com> Message-ID: <20000508212209.A456@beelzebub> On 05 May 2000, Michael Muller said: > I totally agree with the site-home-currentdir structure, but shouldn't the > site level file live someplace apart from the code? If you customize the > site file, you probably don't want your changes clobbered by a subsequent > distutils install. sys.prefix + '/etc', perhaps? That's the nice thing about how sys.prefix "belongs" to Python on Windows and Mac OS. I'm not super-keen on /usr/local/etc; I'd rather keep the Distutils config file somewhere in the Python library tree. Thus, the distutils (or site-packages/distutils, for pre-1.6) directory makes sense. I'm open to other ideas. Clobbering on subsequent installations can be prevented by not installing a config file; that'll make it a little harder for people to find out that they have the option of customizing via a config file, but that doesn't bother me excessively. (Awww, the poor babies will have to read a manual... *sniff* *sniff*) Anyone else give a hoot? Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ Any priest or shaman must be presumed guilty until proven innocent. From gward@ase.com Tue May 9 02:33:21 2000 From: gward@ase.com (Greg Ward) Date: Mon, 8 May 2000 21:33:21 -0400 Subject: [Distutils] distutils & Borland's free compiler In-Reply-To: <000501bfb901$788f0d10$4e574dc0@cfdrc.com>; from Lyle Johnson on Mon, May 08, 2000 at 10:24:15AM -0500 References: <20000506160019.C70561CDE8@dinsdale.python.org> <000501bfb901$788f0d10$4e574dc0@cfdrc.com> Message-ID: <20000508213321.B456@beelzebub> On 08 May 2000, Lyle Johnson said: > 1. Create a new class (I was calling it BCPPCompiler, but I'm not too > attached to that name ;) which is derived from CCompiler. This class > lives in its own module file "bcppcompiler.py" so that it is on the > same footing as "msvccompiler.py" (which supports that other company's > compiler). Yeah, you've got the basic idea right. I just suspect that there will be overlapping functionality between the two DOS/Windows compilers, and I would like to see that factored out into a common base class. I went to a lot of trouble a month or two back to factor out the commonality between DOS/Windows (MSVCCompiler) and Unix into the CCompiler base class, and I want others to share the pain. ;-) Err, no, that's not it -- I want to avoid excessive code bloat, and refactoring common functionality is one good way to do that. The BCPPCompiler name is at least consistent with MSVCCompiler. I guess I didn't spell out MicrosoftCCompiler because I didn't want to utter the vile name in public -- a common superstition among primitive peoples, you know, the strong fear of uttering the enemy's name... ;-) > 2. Patch distutils/ccompiler.py to add this new compiler into the > compiler_class dictionary. Yup. > 3. Ask Greg about how to let the end-user actually override the default > compiler choice for platform "nt". This could be done by passing the > keyword argument compiler=bcpp to the new_compiler() factory function, > if we had some kind of commmand-line option to let the user do that... Hmmm. Good question. This'll be relevant for Mac OS too, as there will -- I hope! -- be two compilers support there. I think your keyword argument is half the solution; the other half would be a "--compiler=bcpp" command-line option to "build_ext". Go ahead and add that if you feel comfortable doing so. I will have to hang my head in shame, though, when I see "default: msvc" in the help string. Ahh well, at least it won't say "default: microsoft". (Auugh! my soul was just stolen!) > Three! Three things! ...and a FANATICAL devotion to the pope! Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ I invented skydiving in 1989! From gward@ase.com Tue May 9 02:40:07 2000 From: gward@ase.com (Greg Ward) Date: Mon, 8 May 2000 21:40:07 -0400 Subject: [Distutils] More questions on distutils... In-Reply-To: <000001bfb93d$37e59680$4e574dc0@cfdrc.com>; from Lyle Johnson on Mon, May 08, 2000 at 05:31:57PM -0500 References: <000001bfb93d$37e59680$4e574dc0@cfdrc.com> Message-ID: <20000508214007.C456@beelzebub> On 08 May 2000, Lyle Johnson said: > Greg, > > While working out the stuff for supporting Borland's C/C++ compiler under > the Distutils, I've gotten a little confused about the division of > responsbilities for the various command and compiler classes. The specific > case I'm studying right now is the "built_ext" command (implemented in > distutils/command/built_ext.py). > > If you take a look at the build_extensions() function defined in this class, > it appears that he "knows" some things about the "msvc" compiler. It seems > like you'd want to avoid letting the various commands know these kinds of > details about specific implementations of the CCompiler class. Ideally, they > would stick to the basic CCompiler interface, no? You are absolutely correct. This was discussed on the list a few months back, but my admonishments never made it into the code. So I've just added this comment to build_ext.py: # XXX this is a kludge! Knowledge of specific compilers or # platforms really doesn't belong here; in an ideal world, the # CCompiler interface would provide access to everything in a # compiler/linker system needs to build Python extensions, and # we would just do everything nicely and cleanly through that # interface. However, this is a not an ideal world and the # CCompiler interface doesn't handle absolutely everything. # Thus, kludges like this slip in occasionally. (This is no # excuse for committing more platform- and compiler-specific # kludges; they are to be avoided if possible!) if self.compiler.compiler_type == 'msvc': [...] Does that answer your question? If not, please let us know what Borland-specific kludges you need. Perhaps the CCompiler interface could/should be expanded. I have a hunch that the notion of "exported symbols" belongs, but that the notion of "file listing symbols to export" does not. Unfortunately, this hunch directly contradicts the present kludge in build_ext.py, as it supports both the abstract (good) list-of-exported-symbols and concrete (not-so-good) name-of-file-with-list-of-exported-symbols. Yuck. The other reason for that kludge, "temp directory for compiler/linker turds", could probably also be squeezed into the CCompiler abstraction. Hmmm. > I'm not attacking the current implementation -- I know that the primary goal > to this point is to get things working. But now I'm faced with the decision > about where to put certain Borland-specific flags and so forth -- do they > come in solely through the new BCPPCompiler class, or do some of them also > filter in through the build_ext command (and his siblings)? If the flags are related to compiling code, or linking code into a shared object (DLL), then they belong in BCPPCompiler. If they are specific to building Python extensions, and cannot be accomodated by the CCompiler interface, we may have to hold our noses and put another kludge in build_ext.py. I'd prefer to avoid that, obviously. Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ Predestination was doomed from the start. From fdrake@acm.org Tue May 9 05:55:52 2000 From: fdrake@acm.org (Fred L. Drake, Jr.) Date: Tue, 9 May 2000 00:55:52 -0400 (EDT) Subject: [Distutils] Where to find config files In-Reply-To: <20000508212209.A456@beelzebub> References: <200005090034.UAA09560@bogus.com> <20000508212209.A456@beelzebub> Message-ID: <14615.39512.537226.556956@newcnri.cnri.reston.va.us> Greg Ward writes: > Anyone else give a hoot? Another possibility is to only install the file if it doesn't already exist, which would be my preference. The $prefix/lib/python1.X/ directory doesn't currently contain much in the way of data files; it can contain .pth files, but those are normally in $prefix/lib/python1.5/site-packages/. That may not be a bad location for it, but I'm not really comfortable with using that for misc. configuration files. Placing it there would also imply that the file is site-specific, which isn't a bad thing in this case. It could be called distutils.conf. -Fred -- Fred L. Drake, Jr. Corporation for National Research Initiatives From hgebel@inet.net Tue May 9 14:14:36 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Tue, 9 May 2000 09:14:36 -0400 Subject: [Distutils] bdist_rpm and --arch Message-ID: <20000509091436.A17190@inet.net> The response from the rpm list seems to indicate that the problem I am having is an rpm bug in versions < 3.04, and the response on how to get around the bug was "upgrade to 3.04". Rather than require that rpm be a certain version, I am going to remove this option. Anyone who wishes to build under a different architecture than the default can still make a source RPM with Distutils and then run `rpm -bb` from the command line. I am currently adding CFLAGS support so that the i686 and i586 RPMs generated by default on Pentium-class machines will really be i686 and i586 RPMs -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.ne From gregor@hoffleit.de Tue May 9 15:21:13 2000 From: gregor@hoffleit.de (Gregor Hoffleit) Date: Tue, 9 May 2000 16:21:13 +0200 Subject: [Distutils] Where to find config files In-Reply-To: <20000508212209.A456@beelzebub>; from gward@ase.com on Mon, May 08, 2000 at 09:22:09PM -0400 References: <200005090034.UAA09560@bogus.com> <20000508212209.A456@beelzebub> Message-ID: <20000509162113.A9662@53b.hoffleit.de> --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable On Mon, May 08, 2000 at 09:22:09PM -0400, Greg Ward wrote: > On 05 May 2000, Michael Muller said: > > I totally agree with the site-home-currentdir structure, but shouldn't = the > > site level file live someplace apart from the code? If you customize t= he > > site file, you probably don't want your changes clobbered by a subseque= nt > > distutils install. sys.prefix + '/etc', perhaps? >=20 > That's the nice thing about how sys.prefix "belongs" to Python on > Windows and Mac OS. I'm not super-keen on /usr/local/etc; I'd rather > keep the Distutils config file somewhere in the Python library tree. > Thus, the distutils (or site-packages/distutils, for pre-1.6) directory > makes sense. I'm open to other ideas. Au contraire for Debian and the like. ;-) Think about installations where Distutils live in a read-only tree (e.g. mounted read-only per NFS), or a tree that's shared across many different systems and platforms. In Debian's case, the directive is to keep *all* system-wide configuration files in /etc. The /usr tree (less /usr/local) should potentially be mountable read-only. Variable data goes into /var. That's also the sketch of the Linux Filesystem Standard (now FHS). Btw, I think as a consequence even site.py should be moved from lib/python1.X to /etc. In the end, I guess this is a philosophical question, and the answer will be different depending on your viewpoint (standalone Windoid/Macoid machines or homo/heterogeneous networked systems potentially sharing a common filespace= ). Gregor =20 --LZvS9be/3tNcYl/X Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.1 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE5GB7Z3eVfDf25G40RAd8yAJ0XvoANzyW7WdI8kY/Qq14pF/07VgCgp1L0 NcWgKrvTr7Rt0Z3Lz5LdhjA= =MIBE -----END PGP SIGNATURE----- --LZvS9be/3tNcYl/X-- From fdrake@acm.org Tue May 9 16:15:05 2000 From: fdrake@acm.org (Fred L. Drake, Jr.) Date: Tue, 9 May 2000 11:15:05 -0400 (EDT) Subject: [Distutils] Where to find config files In-Reply-To: <20000509162113.A9662@53b.hoffleit.de> References: <200005090034.UAA09560@bogus.com> <20000508212209.A456@beelzebub> <20000509162113.A9662@53b.hoffleit.de> Message-ID: <14616.11129.747374.141087@seahag.cnri.reston.va.us> Gregor Hoffleit writes: > In Debian's case, the directive is to keep *all* system-wide configuration > files in /etc. The /usr tree (less /usr/local) should potentially be > mountable read-only. Variable data goes into /var. That's also the sketch of > the Linux Filesystem Standard (now FHS). > > Btw, I think as a consequence even site.py should be moved from > lib/python1.X to /etc. Not site.py, but sitecustomize.py, which is where local modifications should go. This is *not* included in the distribution, so it not an installation problem, but the site-admin would need to create a .pth in the shared area that added some directory to sys.path (say, /etc/python/site-packages) so that individual host-admins could add packages locally. But this begs the question: in such an environment, would it generally make sense to support host-specific additions? > In the end, I guess this is a philosophical question, and the answer will be > different depending on your viewpoint (standalone Windoid/Macoid machines or > homo/heterogeneous networked systems potentially sharing a common filespace). And depending on how you think that shared filespace should be managed; we use shared spaces here for all the "extras" (but not the base installations), but we all of us that use that shared space can update it. -Fred -- Fred L. Drake, Jr. Corporation for National Research Initiatives From hgebel@inet.net Wed May 10 04:35:10 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Tue, 9 May 2000 23:35:10 -0400 Subject: [Distutils] Latest bdist_rpm patch Message-ID: <20000509233509.E17190@inet.net> --6zdv2QT/q3FMhpsV Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is the latest bdist_rpm patch. It gives build_ext the ability to recognize and use the CFLAGS environment variable, it then sets CFLAGS to RPM_OPT_FLAGS in the spec file. It adds an option '--no-rpm-opt-flags' which will cause a spec file to be generated that does not set CFLAGS, this option is turned on automatically for pure python distributions. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --6zdv2QT/q3FMhpsV Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=package_data release = '2' group = 'Development/Libraries' vendor = 'Distutils-SIG' packager = 'Harry Henry Gebel ' doc = ['CHANGES.txt', 'README.txt', 'USAGE.txt', 'doc/', 'examples/', ] changelog = '''\ * Tue May 09 2000 Harry Henry Gebel 0.8.2-2 - Include RPM_OPT_FLAGS * Wed Apr 26 2000 Harry Henry Gebel 0.8.2-1 - First test of bdist_rpm''' --6zdv2QT/q3FMhpsV Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.py" """distutils.command.bdist_rpm Implements the Distutils 'bdist_rpm' command (create RPM source and binary distributions.""" # created 2000/04/25, by Harry Henry Gebel __revision__ = "$Id: bdist_dumb.py,v 1.3 2000/04/22 02:51:25 gward Exp $" from os.path import exists import os from distutils.core import Command from distutils.util import mkpath, write_file, copy_file from distutils.errors import * from string import join from types import StringType, DictType, LongType, FloatType, IntType class bdist_rpm (Command): description = "create an RPM distribution" user_options = [ ('spec-only', None, "Only regenerate spec file"), ('source-only', None, "Only generate source RPM"), ('binary-only', None, "Only generate binary RPM"), ('use-bzip2', None, "Use bzip2 instead of gzip to create source distribution"), ('no-clean', None, "Do not clean RPM build directory"), ('no-rpm-opt-flags', None, "Do not pass any RPM CFLAGS to compiler") ] def initialize_options (self): self.spec_only = None self.binary_only = None self.source_only = None self.use_bzip2 = None self.no_clean = None self.no_rpm_opt_flags = None # initialize_options() def finalize_options (self): if os.name != 'posix': raise DistutilsPlatformError, \ ("don't know how to create RPM " "distributions on platform %s" % os.name) if self.binary_only and self.source_only: raise DistutilsOptionsError, \ "Cannot supply both '--source-only' and '--binary-only'" # don't pass CFLAGS to pure python distributions if not self.distribution.has_ext_modules(): self.no_rpm_opt_flags = 1 # finalize_options() def run (self): self._get_package_data() # get packaging info # make directories if self.spec_only: self.execute(mkpath, ('redhat',), "Created './redhat' directory") else: self.execute(mkpath, ('build/rpm/SOURCES',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SPECS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/BUILD',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/RPMS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SRPMS',), "Created RPM source directory") # spec file goes into .redhat directory if '--spec-only specified', # into build/rpm/spec otherwisu if self.spec_only: spec_path = './redhat/%s.spec' % self.distribution.get_name() else: spec_path = ('build/rpm/SPECS/%s.spec' % self.distribution.get_name()) self.execute(write_file, (spec_path, self._make_spec_file()), 'Writing .spec file') if self.spec_only: # stop if requested return # make a source distribution and copy to SOURCES directory sdist = self.find_peer ('sdist') if self.use_bzip2: sdist.formats = ['bztar'] else: sdist.formats = ['gztar'] self.run_peer('sdist') if self.use_bzip2: source = self.distribution.get_fullname() + '.tar.bz2' else: source = self.distribution.get_fullname() + '.tar.gz' self.execute(copy_file, (source, 'build/rpm/SOURCES'), 'Copying source distribution to SOURCES') # build package self.announce('Building RPMs') rpm_args = ['rpm',] if self.source_only: # what kind of RPMs? rpm_args.append('-bs') elif self.binary_only: rpm_args.append('-bb') else: rpm_args.append('-ba') topdir = os.getcwd() + 'build/rpm' rpm_args.extend(['--define', '_topdir ' + os.getcwd() + '/build/rpm',]) if not self.no_clean: rpm_args.append('--clean') rpm_args.append(spec_path) self.spawn(rpm_args) # run() def _get_package_data(self): ''' Get data needed to generate spec file, first from the DistributionMetadata class, then from the package_data file, which is Python code read with execfile() ''' package_type = 'rpm' # read in package data, if any if exists('package_data'): try: exec(open('package_data')) except: raise DistutilsOptionError, 'Unable to parse package data file' # set instance variables, supplying default value if not provided in # package data file vars = locals().keys() # the following variables must be {string (len() = 2): string} if 'summaries' in vars: self.summaries = self._check_locale(summaries, 'summaries') else: self.summaries = {} if 'descriptions' in vars: self.descriptions = self._check_locale(descriptions, 'descriptions') else: self.descriptions = {} # The following variable must be an ordinary number or a string if 'release' in vars: if type(release) in (StringType, LongType, IntType, FloatType): self.release = str(release) else: raise DistutilsOptionError, \ ("Error in package_data: 'release' must be a number or " 'a string') else: self.release = '1' # The following variables must be strings if 'group' in vars: self.group = self._check_string(group, 'group') else: self.group = 'Applications' if 'vendor' in vars: self.vendor = self._check_string(vendor, 'vendor') else: self.vendor = None if 'packager' in vars: self.packager = self._check_string(packager, 'vendor') else: self.packager = None if 'changelog' in vars: self.changelog = self._check_string(changelog, 'vendor') else: self.changelog = None # doc must be a list (or tuple) of strings, or a string if 'doc' not in vars: doc = [] for readme in ('README', 'README.txt'): if exists(readme): doc.append(readme) try: self.doc = join(doc) except: raise DistutilsOptionError, \ "Error in package_data: 'doc' must be a sequence of strings" if 'changelog' in vars: self.changelog = changelog else: self.changelog = None def _make_spec_file(self): ''' Generate an RPM spec file ''' spec_file = [ '%define name ' + self.distribution.get_name(), '%define version ' + self.distribution.get_version(), '%define release ' + self.release, '', 'Summary: ' + self.distribution.get_description(), ] # put locale summaries into spec file for locale in self.summaries.keys(): spec_file.append('Summary(%s): %s' % (locale, self.summaries[locale])) spec_file.extend([ 'Name: %{name}', 'Version: %{version}', 'Release: %{release}',]) if self.use_bzip2: spec_file.append('Source0: %{name}-%{version}.tar.bz2') else: spec_file.append('Source0: %{name}-%{version}.tar.gz') spec_file.extend([ 'Copyright: ' + self.distribution.get_licence(), 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-buildroot', 'Prefix: %{_prefix}', ]) if not self.distribution.has_ext_modules(): spec_file.append('BuildArchitectures: noarch') if self.vendor: spec_file.append('Vendor: ' + self.vendor) if self.packager: spec_file.append('Packager: ' + self.packager) if self.distribution.get_url() != 'UNKNOWN': spec_file.append('Url: ' + self.distribution.get_url()) spec_file.extend([ '', '%description', self.distribution.get_long_description()]) # put locale descriptions into spec file for locale in self.descriptions.keys(): spec_file.extend([ '', '%description -l ' + locale, self.descriptions[locale], ]) spec_file.extend([ '', '%prep', '%setup', '', '%build',]) # pass CFLAGS if building a binary module and '--no-rpm-opt-flags' is # not set if not self.no_rpm_opt_flags: spec_file.append( 'env CFLAGS="$RPM_OPT_FLAGS" python setup.py build') else: spec_file.append('python setup.py build') spec_file.extend([ '', '%install', 'python setup.py install --root=$RPM_BUILD_ROOT --record', '', '%clean', 'rm -rf $RPM_BUILD_ROOT', 'rm -f INSTALLED_FILES', '', '%files -f INSTALLED_FILES', '%defattr(-,root,root)', ]) if self.doc: spec_file.append('%doc ' + self.doc) if self.changelog: spec_file.extend([ '', '%changelog', self.changelog ]) return spec_file def _check_locale(self, test_me, name): ''' Tests a wariable to determine if it is {string: string} ''' pass_test = 1 # set to 0 if fails test if type(test_me) == DictType: for locale in test_me.keys(): if (type(locale) != StringType) or (type(test_me[locale]) != StringType): pass_test = 0 break if pass_test: return test_me raise DistutilsOptionError, \ ("Error in package_data: '%s' must be dictionary: " '{string: string}' % name) def _check_string(self, test_me, name): ''' Tests a variable to determino if it is a string ''' if type(test_me) == StringType: return test_me else: raise DistutilsOptionError, \ "Error in package_data: '%s' must be a string" % name --6zdv2QT/q3FMhpsV Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.patch" ? redhat ? temp.rc ? rpm.patch ? dry_run.patch ? MANIFEST ? package_data ? build ? install_options.patch ? long_description.patch ? exeception_error.patch ? bdist_rpm.patch ? Distutils-0.8.2.tar.gz ? Distutils-0.8.2+cvs+bdist_rpm.tar.gz ? Distutils-0.8.2.tar.bz2 ? distutils/command/bdist_rpm.py Index: MANIFEST.in =================================================================== RCS file: /projects/cvsroot/distutils/MANIFEST.in,v retrieving revision 1.4 diff -u -r1.4 MANIFEST.in --- MANIFEST.in 2000/04/21 04:38:11 1.4 +++ MANIFEST.in 2000/05/10 03:33:56 @@ -9,6 +9,7 @@ # include *.txt +include package_data include MANIFEST.in recursive-include examples *.txt *.py prune examples/sample?/build Index: distutils/command/__init__.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/__init__.py,v retrieving revision 1.8 diff -u -r1.8 __init__.py --- __init__.py 2000/03/31 03:14:51 1.8 +++ __init__.py 2000/05/10 03:33:56 @@ -15,4 +15,5 @@ 'sdist', 'bdist', 'bdist_dumb', + 'bdist_rpm', ] Index: distutils/command/bdist.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/bdist.py,v retrieving revision 1.6 diff -u -r1.6 bdist.py --- bdist.py 2000/05/07 15:32:12 1.6 +++ bdist.py 2000/05/10 03:33:57 @@ -22,6 +22,9 @@ "(tar, ztar, gztar, bztar, zip, ... )"), ] + # The following commands do not take a format option from bdist + no_format_option = ( 'bdist_rpm', ) + # This won't do in reality: will need to distinguish RPM-ish Linux, # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS. default_format = { 'posix': 'gztar', @@ -31,6 +34,7 @@ 'bztar': 'bdist_dumb', 'ztar': 'bdist_dumb', 'tar': 'bdist_dumb', + 'rpm': 'bdist_rpm', 'zip': 'bdist_dumb', } @@ -63,8 +67,9 @@ raise DistutilsOptionError, \ "invalid archive format '%s'" % self.format - sub_cmd = self.find_peer (cmd_name) - sub_cmd.format = self.format + if cmd_name not in self.no_format_option: + sub_cmd = self.find_peer (cmd_name) + sub_cmd.format = self.format self.run_peer (cmd_name) # run() Index: distutils/command/build_ext.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/build_ext.py,v retrieving revision 1.34 diff -u -r1.34 build_ext.py --- build_ext.py 2000/05/09 01:50:41 1.34 +++ build_ext.py 2000/05/10 03:34:00 @@ -9,6 +9,7 @@ __revision__ = "$Id: build_ext.py,v 1.34 2000/05/09 01:50:41 gward Exp $" import sys, os, string, re +from string import split from types import * from distutils.core import Command from distutils.errors import * @@ -290,6 +291,11 @@ macros = build_info.get ('macros') include_dirs = build_info.get ('include_dirs') extra_args = build_info.get ('extra_compile_args') + # honor CFLAGS enviroment variable + if os.environ.has_key('CFLAGS'): + if not extra_args: + extra_args = [] + extra_args = split(os.environ['CFLAGS']) + extra_args objects = self.compiler.compile (sources, output_dir=self.build_temp, macros=macros, Index: distutils/command/install.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/install.py,v retrieving revision 1.23 diff -u -r1.23 install.py --- install.py 2000/04/27 01:56:38 1.23 +++ install.py 2000/05/10 03:34:03 @@ -12,6 +12,7 @@ from distutils import sysconfig from distutils.util import write_file, native_path, subst_vars, change_root from distutils.errors import DistutilsOptionError +from glob import glob INSTALL_SCHEMES = { 'unix_prefix': { @@ -82,8 +83,9 @@ #('install-man=', None, "directory for Unix man pages"), #('install-html=', None, "directory for HTML documentation"), #('install-info=', None, "directory for GNU info files"), - ] + ('record', None, + "make a record of installation")] # 'sub_commands': a list of commands this command might have to run # to get its work done. Each command is represented as a tuple @@ -141,6 +143,7 @@ #self.install_html = None #self.install_info = None + self.record = None def finalize_options (self): @@ -267,7 +270,8 @@ from distutils.fancy_getopt import longopt_xlate print msg + ":" for opt in self.user_options: - opt_name = string.translate (opt[0][0:-1], longopt_xlate) + if opt[0][-1] == '=': + opt_name = string.translate (opt[0][0:-1], longopt_xlate) val = getattr (self, opt_name) print " %s: %s" % (opt_name, val) @@ -424,6 +428,24 @@ "Python's module search path (sys.path) -- " + "you'll have to change the search path yourself") % self.install_lib) + + + # write list of installed files, if requested. + if self.record: + outputs = self.get_outputs() + for counter in xrange (len (outputs)): # include ".pyc" and ".pyo" + if outputs[counter][-3:] == ".py": + byte_code = glob(outputs[counter] + '[co]') + outputs.extend(byte_code) + outputs.sort() # just makes it look nicer + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in xrange (len (outputs)): + outputs[counter] = outputs[counter][root_len:] + self.execute(write_file, + ("INSTALLED_FILES", outputs), + "Writing list of installed files") + # run () Index: distutils/command/sdist.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/sdist.py,v retrieving revision 1.18 diff -u -r1.18 sdist.py --- sdist.py 2000/04/26 01:14:33 1.18 +++ sdist.py 2000/05/10 03:34:07 @@ -196,7 +196,7 @@ def find_defaults (self): - standards = [('README', 'README.txt'), 'setup.py'] + standards = [('README', 'README.txt'), 'setup.py', 'package_data'] for fn in standards: if type (fn) is TupleType: alts = fn --6zdv2QT/q3FMhpsV-- From flight@hoffleit.de Wed May 10 19:28:15 2000 From: flight@hoffleit.de (Gregor Hoffleit) Date: Wed, 10 May 2000 20:28:15 +0200 Subject: [Distutils] Where to find config files In-Reply-To: <14616.11129.747374.141087@seahag.cnri.reston.va.us>; from fdrake@acm.org on Tue, May 09, 2000 at 11:15:05AM -0400 References: <200005090034.UAA09560@bogus.com> <20000508212209.A456@beelzebub> <20000509162113.A9662@53b.hoffleit.de> <14616.11129.747374.141087@seahag.cnri.reston.va.us> Message-ID: <20000510202815.F24783@53b.hoffleit.de> --ChQOR20MqfxkMJg9 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable On Tue, May 09, 2000 at 11:15:05AM -0400, Fred L. Drake, Jr. wrote: > Gregor Hoffleit writes: > > Btw, I think as a consequence even site.py should be moved from > > lib/python1.X to /etc. >=20 > Not site.py, but sitecustomize.py, which is where local > modifications should go. This is *not* included in the distribution, > so it not an installation problem, but the site-admin would need to > create a .pth in the shared area that added some directory to sys.path > (say, /etc/python/site-packages) so that individual host-admins could > add packages locally. > But this begs the question: in such an environment, would it > generally make sense to support host-specific additions? I think so. Currently the Debian package adds /usr/local/ directories to sys.path in site.py: "FOR DEBIAN, this sys.path is augmented with directories in /usr/local. Local addons go into /usr/local/lib/python/site-packages (resp. /usr/local/lib/site-python), Debian addons install into /usr/lib/python/site-packages." It's a question of Debian policy that things in /usr/local should override things in /usr, therefore I need to add these /usr/local/lib directories in front of their /usr/lib equivalents, e.g. >>> sys.path ['', '/usr/lib/python1.5/', '/usr/lib/python1.5/plat-linux2', '/usr/lib/python1.5/lib-tk', '/usr/lib/python1.5/lib-dynload', '/usr/local/lib/python1.5/site-packages', '/usr/local/lib/python1.5/site-packages/GMatH', '/usr/local/lib/site-python', '/usr/lib/python1.5/site-packages', '/usr/lib/site-python'] I think this is not possible using .pth files, nor with sitecustomize.py, therefore this was done in site.py. Now I guess I should include a .pth file in the Debian package so that something like /etc/python is appended to sys.path, and then the sysadmin should be educated to use /etc/python/sitecustomize.py to further modify the path.=20 Or does anybody have a better solution here ? Gregor =20 --ChQOR20MqfxkMJg9 Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.1 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE5Gao/3eVfDf25G40RAWudAJ9yHPxtCO6Ggtysp8Om9AryftZ86gCdFw64 7qw+LyTPucXKVERlSnRQcBM= =mlhx -----END PGP SIGNATURE----- --ChQOR20MqfxkMJg9-- From hgebel@inet.net Thu May 11 06:46:01 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Thu, 11 May 2000 01:46:01 -0400 Subject: [Distutils] bdist_rpm patch: new package_data Message-ID: <20000511014601.B24292@inet.net> --GZVR6ND4mMseVXL/ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is a new bdist_rpm patch that adds the following variables to package_data: Strings: icon - path (relative to setup.py) to an icon which will be used for the package in graphical rpm front-ends distribution_name - placed in spec file 'Distribution' field pre, post, preun, postun, prep, build, install, clean - spec file scripts (defaults are still provided for prep, build, clean, and install that should work 99% of the time) String or number: serial - placed in spec file 'Serial' field Lists of strings or strings: provides, requires, build_requires, conflicts, obsoletes - placed in appropriate fields in spec file The default value of 'group' in package_data has been changed from 'Applications' to 'Development/Libraries'. Type checking has been cleaned up a little. The default addition of 'README' and 'README.txt' to the doc files can be overridden by defining doc as a string rather than as a list of strings. Defining doc as '' will prevent any files including 'README' and 'README.txt' from being include in the doc files. I modified clean.py so that 'clean -a' removes the 'build/rpm' directory. (The rpm program handles cleaning of the 'build/rpm/BUILD' directory, unless 'bdist_rpm --no-clean' is specified. (Or should --no-clean be the default for bdist_rpm?)) -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --GZVR6ND4mMseVXL/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=package_data release = '3' vendor = 'Distutils-SIG' packager = 'Harry Henry Gebel ' doc = ['CHANGES.txt', 'README.txt', 'USAGE.txt', 'doc/', 'examples/', ] changelog = '''\ * Thu May 10 2000 Harry Henry Gebel 0.8.2-3 - Added new options to package_data * Tue May 09 2000 Harry Henry Gebel 0.8.2-2 - Include RPM_OPT_FLAGS in distutils * Wed Apr 26 2000 Harry Henry Gebel 0.8.2-1 - First test of bdist_rpm''' --GZVR6ND4mMseVXL/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.py" """distutils.command.bdist_rpm Implements the Distutils 'bdist_rpm' command (create RPM source and binary distributions.""" # created 2000/04/25, by Harry Henry Gebel __revision__ = "$Id: bdist_dumb.py,v 1.3 2000/04/22 02:51:25 gward Exp $" from os.path import exists, basename import os from distutils.core import Command from distutils.util import mkpath, write_file, copy_file from distutils.errors import * from string import join, lower from types import StringType, DictType, LongType, FloatType, IntType, \ ListType, TupleType class bdist_rpm (Command): description = "create an RPM distribution" user_options = [ ('spec-only', None, "Only regenerate spec file"), ('source-only', None, "Only generate source RPM"), ('binary-only', None, "Only generate binary RPM"), ('use-bzip2', None, "Use bzip2 instead of gzip to create source distribution"), ('no-clean', None, "Do not clean RPM build directory"), ('no-rpm-opt-flags', None, "Do not pass any RPM CFLAGS to compiler") ] def initialize_options (self): self.spec_only = None self.binary_only = None self.source_only = None self.use_bzip2 = None self.no_clean = None self.no_rpm_opt_flags = None # initialize_options() def finalize_options (self): if os.name != 'posix': raise DistutilsPlatformError, \ ("don't know how to create RPM " "distributions on platform %s" % os.name) if self.binary_only and self.source_only: raise DistutilsOptionsError, \ "Cannot supply both '--source-only' and '--binary-only'" # don't pass CFLAGS to pure python distributions if not self.distribution.has_ext_modules(): self.no_rpm_opt_flags = 1 # finalize_options() def run (self): self._get_package_data() # get packaging info # make directories if self.spec_only: self.execute(mkpath, ('redhat',), "Created './redhat' directory") else: self.execute(mkpath, ('build/rpm/SOURCES',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SPECS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/BUILD',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/RPMS',), "Created RPM source directory") self.execute(mkpath, ('build/rpm/SRPMS',), "Created RPM source directory") # spec file goes into .redhat directory if '--spec-only specified', # into build/rpm/spec otherwisu if self.spec_only: spec_path = './redhat/%s.spec' % self.distribution.get_name() else: spec_path = ('build/rpm/SPECS/%s.spec' % self.distribution.get_name()) self.execute(write_file, (spec_path, self._make_spec_file()), 'Writing .spec file') if self.spec_only: # stop if requested return # make a source distribution and copy to SOURCES directory with # optional icon sdist = self.find_peer ('sdist') if self.use_bzip2: sdist.formats = ['bztar'] else: sdist.formats = ['gztar'] self.run_peer('sdist') if self.use_bzip2: source = self.distribution.get_fullname() + '.tar.bz2' else: source = self.distribution.get_fullname() + '.tar.gz' self.execute(copy_file, (source, 'build/rpm/SOURCES'), 'Copying source distribution to SOURCES') if self.icon: if exists(self.icon): self.execute(copy_file, (self.icon, 'build/rpm/SOURCES'), 'Copying icon to SOURCES') else: raise DistutilsFileError, \ "Unable to find icon file '%s'" % self.icon # build package self.announce('Building RPMs') rpm_args = ['rpm',] if self.source_only: # what kind of RPMs? rpm_args.append('-bs') elif self.binary_only: rpm_args.append('-bb') else: rpm_args.append('-ba') topdir = os.getcwd() + 'build/rpm' rpm_args.extend(['--define', '_topdir ' + os.getcwd() + '/build/rpm',]) if not self.no_clean: rpm_args.append('--clean') rpm_args.append(spec_path) self.spawn(rpm_args) # run() def _get_package_data(self): ''' Get data needed to generate spec file, first from the DistributionMetadata class, then from the package_data file, which is Python code read with execfile() ''' package_type = 'rpm' # read in package data, if any if exists('package_data'): try: exec(open('package_data')) except: raise DistutilsOptionError, 'Unable to parse package data file' # set instance variables, supplying default value if not provided in # package data file self.package_data = locals() # the following variables must be {string (len() = 2): string} self.summaries = self._check_string_dict('summaries') self.descriptions = self._check_string_dict('descriptions') # The following variable must be an ordinary number or a string self.release = self._check_number_or_string('release', '1') self.serial = self._check_number_or_string('serial') # The following variables must be strings self.group = self._check_string('group', 'Development/Libraries') self.vendor = self._check_string('vendor') self.packager = self._check_string('packager') self.changelog = self._check_string('changelog') self.icon = self._check_string('icon') self.distribution_name = self._check_string('distribution_name') self.pre = self._check_string('pre') self.post = self._check_string('post') self.preun = self._check_string('preun') self.postun = self._check_string('postun') self.prep = self._check_string('prep', '%setup') if not self.no_rpm_opt_flags: self.build = (self._check_string( 'build', 'env CFLAGS="$RPM_OPT_FLAGS" python setup.py build')) else: self.build = (self._check_string('build', 'python setup.py build')) self.install = self._check_string( 'install', 'python setup.py install --root=$RPM_BUILD_ROOT --record') self.clean = self._check_string( 'clean', 'rm -rf $RPM_BUILD_ROOT') # The following variables must be a list or tuple of strings, or a # string self.doc = self._check_string_list('doc') if type(self.doc) == ListType: for readme in ('README', 'README.txt'): if exists(readme) and readme not in self.doc: self.doc.append(readme) self.doc = join(self.doc) self.provides = join(self._check_string_list('provides')) self.requires = join(self._check_string_list('requires')) self.conflicts = join(self._check_string_list('conflicts')) self.build_requires = join(self._check_string_list('build_requires')) self.obsoletes = join(self._check_string_list('obsoletes')) def _make_spec_file(self): ''' Generate an RPM spec file ''' # definitons and headers spec_file = [ '%define name ' + self.distribution.get_name(), '%define version ' + self.distribution.get_version(), '%define release ' + self.release, '', 'Summary: ' + self.distribution.get_description(), ] # put locale summaries into spec file for locale in self.summaries.keys(): spec_file.append('Summary(%s): %s' % (locale, self.summaries[locale])) spec_file.extend([ 'Name: %{name}', 'Version: %{version}', 'Release: %{release}',]) if self.use_bzip2: spec_file.append('Source0: %{name}-%{version}.tar.bz2') else: spec_file.append('Source0: %{name}-%{version}.tar.gz') spec_file.extend([ 'Copyright: ' + self.distribution.get_licence(), 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-buildroot', 'Prefix: %{_prefix}', ]) # noarch if no extension modules if not self.distribution.has_ext_modules(): spec_file.append('BuildArchitectures: noarch') for field in ('Vendor', 'Packager', 'Provides', 'Requires', 'Conflicts', 'Obsoletes', ): if getattr(self, lower(field)): spec_file.append('%s: %s' % (field, getattr(self, lower(field)))) if self.distribution.get_url() != 'UNKNOWN': spec_file.append('Url: ' + self.distribution.get_url()) if self.distribution_name: spec_file.append('Distribution: ' + self.distribution_name) if self.build_requires: spec_file.append('BuildRequires: ' + self.build_requires) if self.icon: spec_file.append('Icon: ' + basename(self.icon)) spec_file.extend([ '', '%description', self.distribution.get_long_description() ]) # put locale descriptions into spec file for locale in self.descriptions.keys(): spec_file.extend([ '', '%description -l ' + locale, self.descriptions[locale], ]) # rpm scripts for script in ('prep', 'build', 'install', 'clean', 'pre', 'post', 'preun', 'postun', ): if getattr(self, script): spec_file.extend([ '', '%' + script, getattr(self, script), ]) # files section spec_file.extend([ '', '%files -f INSTALLED_FILES', '%defattr(-,root,root)', ]) if self.doc: spec_file.append('%doc ' + self.doc) if self.changelog: spec_file.extend([ '', '%changelog', self.changelog ]) return spec_file def _check_string_dict(self, var_name, default_value = {}): ''' Tests a wariable to determine if it is {string: string}, var_name is the name of the wariable. Return the value if it is valid, returns default_value if the variable does not exist, raises DistutilsOptionError if the variable is not valid''' if self.package_data.has_key(var_name): pass_test = 1 # set to 0 if fails test value = self.package_data[var_name] if type(value) == DictType: for locale in value.keys(): if (type(locale) != StringType) or (type(value[locale]) != StringType): pass_test = 0 break if pass_test: return test_me raise DistutilsOptionError, \ ("Error in package_data: '%s' must be dictionary: " '{string: string}' % var_name) else: return default_value def _check_string(self, var_name, default_value = None): ''' Tests a variable in package_data to determine if it is a string, var_name is the name of the wariable. Return the value if it is a string, returns default_value if the variable does not exist, raises DistutilsOptionError if the variable is not a string''' if self.package_data.has_key(var_name): if type(self.package_data[var_name]) == StringType: return self.package_data[var_name] else: raise DistutilsOptionError, \ "Error in package_data: '%s' must be a string" % var_name else: return default_value def _check_number_or_string(self, var_name, default_value = None): ''' Tests a variable in package_data to determine if it is a number or a string, var_name is the name of the wariable. Return the value if it is valid, returns default_value if the variable does not exist, raises DistutilsOptionError if the variable is not valid''' if self.package_data.has_key(var_name): if type(self.package_data[var_name]) in (StringType, LongType, IntType, FloatType): return str(self.package_data[var_name]) else: raise DistutilsOptionError, \ ("Error in package_data: '%s' must be a string or a " 'number' % var_name) else: return default_value def _check_string_list(self, var_name, default_value = []): ''' Tests a variable in package_data to determine if it is a string or a list or tuple of strings, var_name is the name of the wariable. Return the value as a string or a list if it is valid, returns default_value if the variable does not exist, raises DistutilsOptionError if the variable is not valid''' if self.package_data.has_key(var_name): value = self.package_data[var_name] pass_test = 1 if type(value) == StringType: return value elif type(value) in (ListType, TupleType): for item in value: if type(item) != StringType: pass_test = 0 break if pass_test: return list(value) raise DistutilsOptionError, \ ("Error in package_data: '%s' must be a string or a " 'list or tuple of strings' % var_name) else: return default_value --GZVR6ND4mMseVXL/ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bdist_rpm.patch" Index: MANIFEST.in =================================================================== RCS file: /projects/cvsroot/distutils/MANIFEST.in,v retrieving revision 1.4 diff -u -r1.4 MANIFEST.in --- MANIFEST.in 2000/04/21 04:38:11 1.4 +++ MANIFEST.in 2000/05/11 05:41:52 @@ -9,6 +9,7 @@ # include *.txt +include package_data include MANIFEST.in recursive-include examples *.txt *.py prune examples/sample?/build Index: distutils/command/__init__.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/__init__.py,v retrieving revision 1.8 diff -u -r1.8 __init__.py --- __init__.py 2000/03/31 03:14:51 1.8 +++ __init__.py 2000/05/11 05:41:52 @@ -15,4 +15,5 @@ 'sdist', 'bdist', 'bdist_dumb', + 'bdist_rpm', ] Index: distutils/command/bdist.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/bdist.py,v retrieving revision 1.6 diff -u -r1.6 bdist.py --- bdist.py 2000/05/07 15:32:12 1.6 +++ bdist.py 2000/05/11 05:41:53 @@ -22,6 +22,9 @@ "(tar, ztar, gztar, bztar, zip, ... )"), ] + # The following commands do not take a format option from bdist + no_format_option = ( 'bdist_rpm', ) + # This won't do in reality: will need to distinguish RPM-ish Linux, # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS. default_format = { 'posix': 'gztar', @@ -31,6 +34,7 @@ 'bztar': 'bdist_dumb', 'ztar': 'bdist_dumb', 'tar': 'bdist_dumb', + 'rpm': 'bdist_rpm', 'zip': 'bdist_dumb', } @@ -63,8 +67,9 @@ raise DistutilsOptionError, \ "invalid archive format '%s'" % self.format - sub_cmd = self.find_peer (cmd_name) - sub_cmd.format = self.format + if cmd_name not in self.no_format_option: + sub_cmd = self.find_peer (cmd_name) + sub_cmd.format = self.format self.run_peer (cmd_name) # run() Index: distutils/command/build_ext.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/build_ext.py,v retrieving revision 1.34 diff -u -r1.34 build_ext.py --- build_ext.py 2000/05/09 01:50:41 1.34 +++ build_ext.py 2000/05/11 05:41:56 @@ -9,6 +9,7 @@ __revision__ = "$Id: build_ext.py,v 1.34 2000/05/09 01:50:41 gward Exp $" import sys, os, string, re +from string import split from types import * from distutils.core import Command from distutils.errors import * @@ -290,6 +291,11 @@ macros = build_info.get ('macros') include_dirs = build_info.get ('include_dirs') extra_args = build_info.get ('extra_compile_args') + # honor CFLAGS enviroment variable + if os.environ.has_key('CFLAGS'): + if not extra_args: + extra_args = [] + extra_args = split(os.environ['CFLAGS']) + extra_args objects = self.compiler.compile (sources, output_dir=self.build_temp, macros=macros, Index: distutils/command/clean.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/clean.py,v retrieving revision 1.2 diff -u -r1.2 clean.py --- clean.py 2000/03/18 17:33:18 1.2 +++ clean.py 2000/05/11 05:41:56 @@ -53,6 +53,10 @@ # remove the module build directory (unless already gone) if os.path.exists (self.build_lib): remove_tree (self.build_lib, self.verbose, self.dry_run) + # remove build/rpm (note: RPM handles cleaning up of temporary + # builds itself + if os.path.exists ('build/rpm'): + remove_tree ('build/rpm', self.verbose, self.dry_run) # just for the heck of it, try to remove the base build directory: # we might have emptied it right now, but if not we don't care Index: distutils/command/install.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/install.py,v retrieving revision 1.23 diff -u -r1.23 install.py --- install.py 2000/04/27 01:56:38 1.23 +++ install.py 2000/05/11 05:42:01 @@ -12,6 +12,7 @@ from distutils import sysconfig from distutils.util import write_file, native_path, subst_vars, change_root from distutils.errors import DistutilsOptionError +from glob import glob INSTALL_SCHEMES = { 'unix_prefix': { @@ -82,8 +83,10 @@ #('install-man=', None, "directory for Unix man pages"), #('install-html=', None, "directory for HTML documentation"), #('install-info=', None, "directory for GNU info files"), - ] + ('record', None, + "make a record of installation"), + ] # 'sub_commands': a list of commands this command might have to run # to get its work done. Each command is represented as a tuple @@ -141,6 +144,7 @@ #self.install_html = None #self.install_info = None + self.record = None def finalize_options (self): @@ -267,7 +271,8 @@ from distutils.fancy_getopt import longopt_xlate print msg + ":" for opt in self.user_options: - opt_name = string.translate (opt[0][0:-1], longopt_xlate) + if opt[0][-1] == '=': + opt_name = string.translate (opt[0][0:-1], longopt_xlate) val = getattr (self, opt_name) print " %s: %s" % (opt_name, val) @@ -424,6 +429,22 @@ "Python's module search path (sys.path) -- " + "you'll have to change the search path yourself") % self.install_lib) + + # write list of installed files, if requested. + if self.record: + outputs = self.get_outputs() + for counter in xrange (len (outputs)): # include ".pyc" and ".pyo" + if outputs[counter][-3:] == ".py": + byte_code = glob(outputs[counter] + '[co]') + outputs.extend(byte_code) + outputs.sort() # just makes it look nicer + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in xrange (len (outputs)): + outputs[counter] = outputs[counter][root_len:] + self.execute(write_file, + ("INSTALLED_FILES", outputs), + "Writing list of installed files") # run () Index: distutils/command/sdist.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/sdist.py,v retrieving revision 1.18 diff -u -r1.18 sdist.py --- sdist.py 2000/04/26 01:14:33 1.18 +++ sdist.py 2000/05/11 05:42:06 @@ -196,7 +196,7 @@ def find_defaults (self): - standards = [('README', 'README.txt'), 'setup.py'] + standards = [('README', 'README.txt'), 'setup.py', 'package_data'] for fn in standards: if type (fn) is TupleType: alts = fn --GZVR6ND4mMseVXL/-- From flight@hoffleit.de Thu May 11 07:46:38 2000 From: flight@hoffleit.de (Gregor Hoffleit) Date: Thu, 11 May 2000 08:46:38 +0200 Subject: [Distutils] Thoughts about Distutils and Debian Message-ID: <20000511084637.A25803@53b.hoffleit.de> --y0ulUmNC+osPPQO6 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Hi, I'm currently trying to make up my mind how Distutils and building Debian packages fit together. I have to impression we're faced with something like a chicken and egg problem. ... Since not everybody knows the Debian package format, I'll give a short introduction: A short story of .deb's and Debian packages ------------------------------------------- A .deb package is in fact really, really simple: freefly;158> ar tv python-ldap_1.8-1_i386.deb=20 rw-r--r-- 0/0 4 Nov 30 15:58 1999 debian-binary rw-r--r-- 0/0 1078 Nov 30 15:58 1999 control.tar.gz rw-r--r-- 0/0 52562 Nov 30 15:58 1999 data.tar.gz freefly;159> ar x python-ldap_1.8-1_i386.deb=20 freefly;160> cat debian-binary=20 2.0 freefly;161> tar tvpzf control.tar.gz=20 drwxr-xr-x root/root 0 1999-11-30 15:58:41 ./ -rwxr-xr-x root/root 553 1999-11-30 15:58:05 ./postinst -rwxr-xr-x root/root 461 1999-11-30 15:58:05 ./prerm -rw-r--r-- root/root 660 1999-11-30 15:58:41 ./md5sums -rw-r--r-- root/root 392 1999-11-30 15:58:41 ./control freefly;162> tar tvpzf data.tar.gz=20 drwxr-xr-x root/root 0 1999-11-30 15:58:04 ./ drwxr-xr-x root/root 0 1999-11-30 15:58:01 ./usr/ drwxr-xr-x root/root 0 1999-11-30 15:58:01 ./usr/lib/ drwxr-xr-x root/root 0 1999-11-30 15:58:01 ./usr/lib/python1.5/ ... -rw-r--r-- root/root 228 1999-11-30 15:48:07 ./usr/share/doc-base/p= ython-ldap The nice thing is that you can simply unpack the file with standard Unix tools. The same is true for the reverse: You can build a .deb with ar and tar only. What's the stuff in control.tar.gz ? postinst and prerm (and preinst and postrm) are optional scripts that are called at various points of the installation/deinstallation of a package; control is a text file describing the package: freefly;163> cat control Package: python-ldap Version: 1.8-1 Section: net Priority: optional Architecture: i386 Depends: libc6 (>=3D 2.1), libopenldap1 Installed-Size: 99 Maintainer: Gregor Hoffleit Description: An LDAP module for Python. This module provides an Python interface to the LDAP client library (LDAP is the Lightweight Directory Access Protocol). It has been compiled with OpenLDAP. Building a valid .deb package is as simple as echo 2.0 >debian-binary vi control tar -c -z -f control.tar.gz ./control tar -c -z -f data.tar.gz -C build . ar cv my1stdeb-0.0.deb debian-binary control.tar.gz data.tar.gz Now while this is a valid .deb file, there's more to a valid Debian package than this: Packages have to follow some rules in order to (a) not to hose the system were they're unpacked (b) fit into the Debian archive scheme (c) support building from source (d) support auto-building from source These rules are put together in the Debian Policy manual (http://www.debian.org/doc/debian-policy/) and the Debian Packaging manual. The most interesting things in our context are certainly (c) and (d). A valid Debian package should be built from a source package. A source package consists of a tarball of the upstream version (xyz_1.2.orig.tar.gz), a diff file with Debian's changes to the package (xyz_1.2-5.diff.gz) and a text file with a description of the package (xyz_1.2-5.dsc) including things like md5sums of the source files and GPG signed by the maintainer of the package. (If you have these three files, you can unpack the source tree with "dpkg-source -x xyz_1.2-5.dsc", or with tar -xzpf xyz_1.2.orig.tar.gz zcat xyz_1.2-5.diff.gz | patch -p1 Debian's equivalent to an RPM spec file is a ./debian directory in the source tree. Typically, this directory looks like this: freefly;193> cd python-ldap-1.8/ freefly;194> ls -ld debian/* -rw-r--r-- 1 flight flight 323 Mai 10 21:28 debian/README.Deb= ian -rw-r--r-- 1 flight flight 203 Mai 10 21:28 debian/TODO.Debian -rw-r--r-- 1 flight flight 1644 Mai 10 21:28 debian/changelog -rw-r--r-- 1 flight flight 392 Mai 10 21:28 debian/control -rw-r--r-- 1 flight flight 799 Mai 10 21:28 debian/copyright -rw-r--r-- 1 flight flight 228 Mai 10 21:28 debian/doc-base -rw-r--r-- 1 flight flight 133 Mai 10 21:28 debian/postinst -rw-r--r-- 1 flight flight 130 Mai 10 21:28 debian/prerm -rwxr-xr-x 1 flight flight 1576 Mai 10 21:28 debian/rules* The most important thing is debian/rules (note the connotation ;-), which is in fact an (executable) Makefile with targets "build", "clean", "binary-indep", "binary-arch" and "binary". Provided the tools used in this rules Makefile are installed, building all packages from a source tree is done by calling debian/rules binary "debian/rules binary-indep" would build only the packages that are flagged architecture-independent (like a 100% pure Python package); "debian/rules binary-arch" would build the architecture-dependent packages for the architecture of the system we're running on (e.g. i386, m68k, sparc, hurd-i386 or perhaps bsd-i386 or cygwin-i386). For a normal package, "rules build" calls "./configure; make", "rules clean" calls "make clean", "rules binary" calls "make DESTDIR=3D'pwd'/debian/tmp install" and "dh_builddeb" (from a simplified view). Needless to say that Debian's build tools (and autobuild daemon's) rely on the presence of ./debian/rules to build binary packages for every architecture from their source packages. Enters Distutils ---------------- So where exactly does Distutils fit into this picture, how much sense makes bdist_deb, and what should it do ? =46rom the theory above, you see that it's possible and even quite easy to write a bdist_deb target that builds a valid .deb file (using ar and tar) for any Distutil'ed package. The problem is that that's still only a third-class Debian package: Fine for rapid-prototyping of .deb packages, but without support for Debian's infrastructure. If we'd like to do better, we have to support debian/rules somehow. I'm still not sure what's the best way to do this, and how bdist's "source distributions" fit into this. Possible ideas: bdist_deb could create a source archive with a debian/rules skeleton that just works(tm). The debian/rules skeleton would just call up setup.py in different places. I.e. bdist_deb source distribution command creates a source package; this source package uses (in debian/rules) simple setup.py targets like "clean", "build" and "install" and finally builds the .deb file using standard Debian tools. In an ideal world (any Distutil'ed package maps perfectly in a Debian package) this would be fine. In our world, Debian maintainers still would have to merge their changes with new upstream versions, therefore providing a debian/rules skeleton is perhaps not enough. Maybe the bdist_deb binary distribution command then could simply call up "debian/rules binary" to build the binary packages. A little bit more elaborated thoughts to come, I hope. Gregor --y0ulUmNC+osPPQO6 Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.1 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE5GldN3eVfDf25G40RAfgjAJ9qaSpoKL+9MooHnUGIMWUuO29u6QCgps+e XWl1RmcmlvyPlxvpq5S06hU= =lJLD -----END PGP SIGNATURE----- --y0ulUmNC+osPPQO6-- From Brad Chapman Thu May 11 15:29:19 2000 From: Brad Chapman (Brad Chapman) Date: Thu, 11 May 2000 10:29:19 -0400 Subject: [Distutils] Parsing config files + passing options Message-ID: <200005111431.KAA35604@archa10.cc.uga.edu> Hello all! I've been playing around with Distutils-0.8.2 and just have a few questions. Before I start though, thanks for all your work on this so far, it is *very* nice and much needed! I just have two questions: 1. I'm working on writing a setup.py for an extension that uses gnome and glib libraries, and was curious if there was a general way anyone has already thought of to handle getting information from gnome-config and glib-config calls into a form that you can input into Distutils. For instance, if I do something like the following: >>> import commands >>> gthread_cflags = commands.getoutput("glib-config --cflags gthread") >>> print gthread_cflags -I/usr/local/include/glib12 -D_THREAD_SAFE I can get the options you would pass. It would be useful to have something to process this like: def parse_cflag_config(configure_script, library) which would then return two lists, the include dirs and the macros. So they you could do something in your setup.py like: gthread_includes, gthread_macros = parse_cflag_config("glib-config", "gthread") Of course, this would only work on UNIX, but that is where the config calls are anyways :-) Is this something that would be generally useful to anyone? Does this approach seem like a good idea? Is there already a better plan in place to handle this? 2. Going along with this first problem, I was also wondering how to pass specific compiler flags. The issue I have is that on FreeBSD, there is a FreeBSD specific option for linking the thread libraries: '-pthread' (what this option does is link in libc_r and not libc, if anyone cares. I'm afraid I'm not smart enough to more about it than that :-). Anyways, is there a way to pass a flag like '-pthread'? Apologies if I missed it! Thanks much for listening and thanks again for the wonderful tool. Brad From hgebel@inet.net Thu May 11 17:27:03 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Thu, 11 May 2000 12:27:03 -0400 Subject: [Distutils] Parsing config files + passing options In-Reply-To: <200005111431.KAA35604@archa10.cc.uga.edu>; from chapmanb@arches.uga.edu on Thu, May 11, 2000 at 10:29:19AM -0400 References: <200005111431.KAA35604@archa10.cc.uga.edu> Message-ID: <20000511122703.A26371@inet.net> On Thu, May 11, 2000 at 10:29:19AM -0400, Brad Chapman wrote: > 2. Going along with this first problem, I was also wondering how to > pass specific compiler flags. The issue I have is that on FreeBSD, > there is a FreeBSD specific option for linking the thread libraries: > '-pthread' (what this option does is link in libc_r and not libc, if > anyone cares. I'm afraid I'm not smart enough to more about it than > that :-). If you look through recent bdist_rpm related messages, the last bdist_rpm patch contains a patch to build_ext.py that allows it to recognize the CFLAGS environment variable, and one of Greg's messages contains a way to specify compiler flags in setup.py . -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.ne From jlj@cfdrc.com Thu May 11 21:46:38 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Thu, 11 May 2000 15:46:38 -0500 Subject: [Distutils] Patches for --compiler option Message-ID: <001301bfbb8a$00d8c370$4e574dc0@cfdrc.com> All, Listed below are patches for the build, build_clib and build_ext commands to support a new option "--compiler=compiler_type". This is a prerequisite for supporting compiler types other than the default (and specifically, supporting Borland's compiler on Windows). These patches are against the latest CVS version of the distutils. Lyle Index: distutils/command/build.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/build.py,v retrieving revision 1.17 diff -a -u -r1.17 build.py --- build.py 2000/04/10 01:31:58 1.17 +++ build.py 2000/05/11 20:43:38 @@ -26,10 +26,12 @@ "build-purelib or build-platlib"), ('build-temp=', 't', "temporary build directory"), + ('compiler=', 'c', + "specify the compiler type"), ('debug', 'g', "compile extensions and libraries with debugging information"), ('force', 'f', - "forcibly build everything (ignore file timestamps"), + "forcibly build everything (ignore file timestamps)"), ] def initialize_options (self): @@ -40,6 +42,7 @@ self.build_platlib = None self.build_lib = None self.build_temp = None + self.compiler = None self.debug = None self.force = 0 Index: distutils/command/build_clib.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/build_clib.py,v retrieving revision 1.13 diff -a -u -r1.13 build_clib.py --- build_clib.py 2000/04/15 22:15:07 1.13 +++ build_clib.py 2000/05/11 20:43:39 @@ -38,7 +38,9 @@ ('debug', 'g', "compile with debugging information"), ('force', 'f', - "forcibly build everything (ignore file timestamps"), + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), ] def initialize_options (self): @@ -54,6 +56,7 @@ self.undef = None self.debug = None self.force = 0 + self.compiler = None # initialize_options() @@ -68,6 +71,7 @@ self.set_undefined_options ('build', ('build_temp', 'build_clib'), ('build_temp', 'build_temp'), + ('compiler', 'compiler'), ('debug', 'debug'), ('force', 'force')) @@ -93,9 +97,11 @@ return # Yech -- this is cut 'n pasted from build_ext.py! - self.compiler = new_compiler (verbose=self.verbose, + self.compiler = new_compiler (compiler=self.compiler, + verbose=self.verbose, dry_run=self.dry_run, force=self.force) + if self.include_dirs is not None: self.compiler.set_include_dirs (self.include_dirs) if self.define is not None: Index: distutils/command/build_ext.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/command/build_ext.py,v retrieving revision 1.34 diff -a -u -r1.34 build_ext.py --- build_ext.py 2000/05/09 01:50:41 1.34 +++ build_ext.py 2000/05/11 20:43:39 @@ -67,7 +67,9 @@ ('debug', 'g', "compile/link with debugging information"), ('force', 'f', - "forcibly build everything (ignore file timestamps"), + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), ] @@ -87,6 +89,7 @@ self.link_objects = None self.debug = None self.force = None + self.compiler = None def finalize_options (self): @@ -95,6 +98,7 @@ self.set_undefined_options ('build', ('build_lib', 'build_lib'), ('build_temp', 'build_temp'), + ('compiler', 'compiler'), ('debug', 'debug'), ('force', 'force')) @@ -169,7 +173,8 @@ # Setup the CCompiler object that we'll use to do all the # compiling and linking - self.compiler = new_compiler (verbose=self.verbose, + self.compiler = new_compiler (compiler=self.compiler, + verbose=self.verbose, dry_run=self.dry_run, force=self.force) @@ -340,6 +345,7 @@ implib_dir = os.path.join(self.build_temp,\ self.get_ext_libname(extension_name)) extra_args.append ('/IMPLIB:' + implib_dir) + self.mkpath (os.path.dirname(implib_dir)) # if MSVC fullname = self.get_ext_fullname (extension_name) From jlj@cfdrc.com Thu May 11 22:06:41 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Thu, 11 May 2000 16:06:41 -0500 Subject: [Distutils] Function stubs for CCompiler class? Message-ID: <001401bfbb8c$ce137360$4e574dc0@cfdrc.com> It appears that in addition to the "worker" functions like compile(), link_shared_object(), etc. there are four functions which *must* be implemented by subclasses of CCompiler: library_dir_option() runtime_library_dir_option() library_option() find_library_file() I submit the following patch (against the current CVS version of ccompiler.py) to make future compiler implementors aware of this requirement. Lyle Index: distutils/ccompiler.py =================================================================== RCS file: /projects/cvsroot/distutils/distutils/ccompiler.py,v retrieving revision 1.17 diff -a -u -r1.17 ccompiler.py --- ccompiler.py 2000/03/26 21:37:09 1.17 +++ ccompiler.py 2000/05/11 20:59:16 @@ -566,7 +566,38 @@ pass + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function; there is + # no appropriate default implementation so subclasses should + # implement all of these. + + + def library_dir_option (self, dir): + """Return the compiler option to add 'dir' to the list of directories + searched for libraries.""" + raise NotImplementedError + + + def runtime_library_dir_option (self, dir): + """Return the compiler option to add 'dir' to the list of directories + searched for runtime libraries.""" + raise NotImplementedError + + + def library_option (self, lib): + """Return the compiler option to add 'dir' to the list of libraries + linked into the shared library or executable.""" + raise NotImplementedError + + + def find_library_file (self, dirs, lib): + """Search the specified list of directories for a static or shared + library file 'lib' and return the full path to that file. Return + None if it wasn't found in any of the specified directories.""" + raise NotImplementedError + + # -- Filename generation methods ----------------------------------- # The default implementation of the filename generating methods are From gward@ase.com Fri May 12 01:08:13 2000 From: gward@ase.com (Greg Ward) Date: Thu, 11 May 2000 20:08:13 -0400 Subject: [Distutils] Re: using distutils for compiling PyXML0.5.4 In-Reply-To: <391B18B7.6C140267@cri-inc.com>; from F. Oliver Gathmann on Thu, May 11, 2000 at 08:31:51PM +0000 References: <391B18B7.6C140267@cri-inc.com> Message-ID: <20000511200813.A984@beelzebub> On 11 May 2000, F. Oliver Gathmann said: > I was trying to get the new PyXML (v. 0.5.4) compiled with distutils v. > 0.8.1, and besides some tweaking of pyexpat.c I had to make sure the > directory path for the > temporary import library was generated, as shown in the attached patch > to build_ext.py (BTW, this was on a Win98 machine). Hmmm, I thought someone else had reported this, and I thought it had been fixed. Can you try Distutils 0.8.2 and see if if it works any better? From looking at the code, though, it looks like this bug is still there. Can anyone on the SIG enlighten me about this bug? It looks like an easy fix, so I'll do it now. BTW, Oliver -- thanks for the patch, but it's *much* better to submit full context diffs! Your patch was against out-of-date code, so the line numbers were wrong; plus, it didn't contain any filename; finally, it was a plain vanilla diff, which is much less useful than a context or unified diff. (Use "diff -c" for context diffs, or "diff -u" for unified. Either one is fine by me.) Greg -- Greg Ward - programmer-at-large gward@python.net http://starship.python.net/~gward/ I want to read my new poem about pork brains and outer space ... From gward@ase.com Fri May 12 02:08:46 2000 From: gward@ase.com (Greg Ward) Date: Thu, 11 May 2000 21:08:46 -0400 Subject: [Distutils] install_scripts and install_data commands In-Reply-To: ; from Bastian Kleineidam on Thu, Apr 27, 2000 at 04:30:33PM +0200 References: Message-ID: <20000511210846.A1076@beelzebub> On 27 April 2000, Bastian Kleineidam said: > I wrote a patch for the above commands. > Both commands derive from install_misc, which copies some files to a > given directory and is defined in cmd.py. > With the attached patch you can now have "scripts=[...]" and > "data=[...]" attributes in setup.py. Finally got around to looking over this patch and checking it in: thanks again! However, I just realized a problem: we probably should have a "build_scripts" command, to ensure that the proper "#!" line is in the installed scripts. If someone distributes scripts with "#!/usr/local/bin/python" or however Python happens to be installed on their system, there's no guarantee it'll work on the installation system. But I don't think we should rely on everyone using the "#!/usr/bin/env" hack, either: the first python on the path isn't necessarily the right one. I think the python used to run the setup script is what should go on the #! line. Opinions? Bastien, can you whip up a "build_scripts" command? Should be pretty easy -- just copy the scripts to "build/scripts" and tweak the first line as appropriate. Thanks -- Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ Everybody is going somewhere!! It's probably a garage sale or a disaster Movie!! From gward@ase.com Fri May 12 03:11:27 2000 From: gward@ase.com (Greg Ward) Date: Thu, 11 May 2000 22:11:27 -0400 Subject: [Distutils] New snapshot available Message-ID: <20000511221127.A1403@beelzebub> Hi all -- I've just released a new code snapshot, available at http://www.python.org/sigs/distutils-sig/download.html#snapshot The major change is the addition of Bastian Kleineidam's "install_scripts" and "install_data" commands. I'll let you figure out what type of files these two install. ;-) I also fixed a little bug in the "install" command that appeared when testing Bastian's two commands. Also, there an initial stab at finding and parsing config files has been added. It doesn't have any actual effect yet, though. Oh yeah, Lyle Johnson's --compiler switch went in tonight too. Thanks to Bastian and Lyle for the patches! (And also to Harry Gebel, whose bdist_rpm did *not* make it in tonight ... that was the original plan, but I got distracted by Bastian's stuff. Ahh well, one patch at a time...) Greg PS. there's some CVS reshuffling going on at python.org, the upshot of which is that these changes are *not* available by CVS (unless you happen to have a login on my home PC, which you do not unless you are me). I'm afraid everyone will have to use code snapshots for the next couple of days. ;-( -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ Be wary of strong drink. It can make you shoot at tax collectors--and miss. From calvin@cs.uni-sb.de Fri May 12 12:15:54 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Fri, 12 May 2000 13:15:54 +0200 (CEST) Subject: [Distutils] install_scripts and install_data commands In-Reply-To: <20000511210846.A1076@beelzebub> Message-ID: Hello, >However, I just realized a problem: we probably should have a >"build_scripts" command, to ensure that the proper "#!" line is in the >installed scripts. Do we have always Python scripts? What about shell scripts, and specifically Windows Batch scripts? See below for my current "Windows" hack in setup.py. >But I don't think we should rely on everyone using the >"#!/usr/bin/env" hack, either: the first python on the path isn't >necessarily the right one. The "first python on the path" is the correct thing for the user, otherwise the path is wrong. So "/usr/bin/env pyton" yields the correct interpreter to execute. Bastian PS. Here is my Distribution class form setup.py for LinkChecker: # Autodetect the existence of an SSL library (this is pretty shitty) # Autodetect Windows platforms to include the linkchecker.bat script class LCDistribution(Distribution): default_include_dirs = ['/usr/include/openssl', '/usr/local/include/openssl'] def run_commands (self): self.check_ssl() self.check_windows() for cmd in self.commands: self.run_command (cmd) def check_ssl(self): incldir = self.has_ssl() if incldir: self.announce("SSL header file ssl.h found, " "enabling SSL compilation.") self.ext_modules = [('ssl', {'sources': ['ssl.c'], 'include_dirs': [incldir], 'library_dirs': ['/usr/lib'], 'libs': ['ssl']})] else: self.announce("SSL header file ssl.h missing, " "disabling SSL compilation.\n" "Use the -I option for the build_ext command.") def check_windows(self): if sys.platform=='win32': inst = self.find_command_obj("install") inst.ensure_ready() t = Template("linkchecker.bat.tmpl") f = open("linkchecker.bat","w") # replace "path_to_linkchecker" with install path f.write(t.fill_in({"path_to_linkchecker": inst.install_scripts})) f.close() self.scripts.append('linkchecker.bat') def has_ssl(self): incls = self.find_command_obj("build_ext").include_dirs incls = (incls and string.split(incls, os.pathsep)) or [] for d in incls + self.default_include_dirs: if os.path.exists(os.path.join(d, "ssl.h")): return d return 0 From tony@lsl.co.uk Fri May 12 12:57:47 2000 From: tony@lsl.co.uk (Tony J Ibbs (Tibs)) Date: Fri, 12 May 2000 12:57:47 +0100 Subject: [Distutils] install_scripts and install_data commands In-Reply-To: Message-ID: <000501bfbc09$49f5b430$f0c809c0@lslp7o.lsl.co.uk> I'm only following this with half a mind at best (sorry), but Bastian had an email that contained: > >But I don't think we should rely on everyone using the > >"#!/usr/bin/env" hack, either: the first python on the path isn't > >necessarily the right one. > The "first python on the path" is the correct thing for the user, > otherwise the path is wrong. So "/usr/bin/env pyton" yields the correct > interpreter to execute. Do please remember the problem on Dec Unixes (which appears to be) that if the environment is large (i.e., many environment variables) then /usr/bin/env falls back to *printing* the environment variables, instead of executing the given program (gods know why, but this is Dec). So, for instance, on the Dec Alpha Unix boxes at work here, the #!/usr/bin/env" hack is a consistent failure! (not that I have any *better* suggestion - just don't assume it's a full solution). Tibs -- Tony J Ibbs (Tibs) http://www.tibsnjoan.demon.co.uk/ Give a pedant an inch and they'll take 25.4mm (once they've established you're talking a post-1959 inch, of course) My views! Mine! Mine! (Unless Laser-Scan ask nicely to borrow them.) From jlj@cfdrc.com Fri May 12 15:59:15 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 09:59:15 -0500 Subject: [Distutils] Patches for --compiler option In-Reply-To: <20000511203138.A1021@beelzebub> Message-ID: <000401bfbc22$a40145c0$4e574dc0@cfdrc.com> > Thanks -- I'll check it in shortly. One problem: > > > extra_args.append ('/IMPLIB:' + implib_dir) > > + self.mkpath (os.path.dirname(implib_dir)) > > # if MSVC > > I fixed this bug just before seeing your patch with > > self.mkpath(implib_dir) > > One of us misunderstands what 'implib_dir' is, and since you're the one > using Windows, it could well be me. Can you test to see which fix is > the right one? The /IMPLIB:name switch to the linker is used to specify the name of an import library. The variable name "implib_dir" should probably be changed to "implib_file" because it is the file name of the import library and not a directory name. Having said that, the correct code snippet is: implib_file = os.path.join (self.build_temp, \ self.get_ext_libname (extension_name)) extra_args.append ('/IMPLIB:' + implib_file) self.mkpath (os.path.dirname (implib_file)) I just tested this on two of my projects plus PyXML-0.5.4 and it works properly. Lyle From jlj@cfdrc.com Fri May 12 17:19:22 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 11:19:22 -0500 Subject: [Distutils] Suggested additions to function argument list Message-ID: <000601bfbc2d$d4e28b30$4e574dc0@cfdrc.com> All, In trying to implement the compiler class for Borland's C++ compiler I've run up against a minor snag or two. First, some background. For extension modules on Windows, we want to support the specification of an optional module definition file (a.k.a. a .DEF file). On Unix I believe it's true that all of the symbols in a shared library are "exported" so this is a non-issue. On Windows, however, you must specify in one way or another which symbols in a DLL are to be exported. One way to do this is to provide the exported symbols' names in a .DEF file which you must write (it's a specially-formatted ASCII text file). Another way to do this is list each of the exported symbols' names on the linker command line using a linker-specific switch. Currently, a module developer can tell the Distutils which DEF file to use for each extension module with the "def_file" key, e.g.: setup (..., ext_modules = [ ('module1', { 'sources' : ['module1.c'], 'def_file' : ['module1.def'] } ), ('module2', { 'sources' : ['module2.c'], 'def_file' : ['module2.def'] } ), ] ) If the "def_file" information for an extension module is not explicitly specified, there is code in the build_ext command which guesses a likely name for the .DEF file (basically module_name + ".def") and sees if that file exists. If so, it uses that file. Otherwise, we adopt a reasonable fallback position and guess the initialization function's name to be "init" + module_name and ask the linker to export that symbol for us. OK, we have now arrived at the problem part ;) The way to specify either the .DEF file name or the exported symbol name(s) is linker-specific. For Microsoft's linker they are passed along as straightforward arguments, either: /DEF:module1.def or /EXPORTS:initmodule1 but for Borland's linker this information comes in very differently -- not as simple arguments which you can just append to the linker's argument list. Since only the compiler class knows for sure how to specify the .DEF file name (or alternatively the exported symbols list) it seems that we should pass this information directly to the compiler through the link_shared_object() function's argument list, instead of cooking up those arguments in the build_ext command. I'd propose adding an additional argument to the function's signature (its default could be None and could be ignored by non-Windows compilers). Changing the subject, it might also be appropriate to pass down the temporary files directory for the current extension's build, unless this kind of code: build_ext = self.find_peer ('build_ext') build_temp = build_ext.build_temp is considered safe. If this doesn't violate encapsulation (for the compiler object to know that the build_ext object has an attribute named "build_temp") then I'll just do this and sleep soundly ;) Sorry for the rambling e-mail! Lyle From thomas.heller@ion-tof.com Fri May 12 17:37:57 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Fri, 12 May 2000 18:37:57 +0200 Subject: [Distutils] Suggested additions to function argument list References: <000601bfbc2d$d4e28b30$4e574dc0@cfdrc.com> Message-ID: <00a801bfbc30$6e439c40$4500a8c0@thomasnb> From: "Lyle Johnson" To: Sent: Friday, May 12, 2000 6:19 PM Subject: [Distutils] Suggested additions to function argument list > > The way to specify either the .DEF file name or the exported symbol name(s) > is linker-specific. For Microsoft's linker they are passed along as > straightforward arguments, either: > > /DEF:module1.def > > or > > /EXPORTS:initmodule1 > > but for Borland's linker this information comes in very differently -- not > as simple arguments which you can just append to the linker's argument list. How ? Thomas From thomas.heller@ion-tof.com Fri May 12 17:42:04 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Fri, 12 May 2000 18:42:04 +0200 Subject: [Distutils] Suggested additions to function argument list References: <000601bfbc2d$d4e28b30$4e574dc0@cfdrc.com> Message-ID: <00b201bfbc31$00d56e30$4500a8c0@thomasnb> > Changing the subject, it might also be appropriate to pass down the > temporary files directory for the current extension's build, unless this > kind of code: > > build_ext = self.find_peer ('build_ext') > build_temp = build_ext.build_temp > > is considered safe. If this doesn't violate encapsulation (for the compiler > object to know that the build_ext object has an attribute named > "build_temp") then I'll just do this and sleep soundly ;) As far as I understood distutils design philosophie (sp?) Greg will not like this. The CCompiler classes should remain usable outside distutils. Thomas From jlj@cfdrc.com Fri May 12 17:59:27 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 11:59:27 -0500 Subject: [Distutils] Suggested additions to function argument list In-Reply-To: <00a801bfbc30$6e439c40$4500a8c0@thomasnb> Message-ID: <000b01bfbc33$6eeb4690$4e574dc0@cfdrc.com> > > but for Borland's linker this information comes in very > differently -- not > > as simple arguments which you can just append to the linker's argument > list. > > How ? The command-line syntax for Borland's linker (called ILINK32) is: ILINK32 [options] objects, [exe], [mapfile], [libs], [deffile] The name of the module definition file, if specified, must appear in exactly the position shown. It's not considered one of the "options" which can appear in any order at the beginning of the command line. And after a second look at the documentation for ILINK32 it doesn't appear that they have anything analogous to the /EXPORTS switch for naming the exported symbol(s) directly on the command line. Lyle From jlj@cfdrc.com Fri May 12 18:08:00 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 12:08:00 -0500 Subject: [Distutils] Suggested additions to function argument list In-Reply-To: <00b201bfbc31$00d56e30$4500a8c0@thomasnb> Message-ID: <000c01bfbc34$a054da60$4e574dc0@cfdrc.com> > As far as I understood distutils design philosophie (sp?) Greg > will not like > this. > > The CCompiler classes should remain usable outside distutils. Yes, as I indicated I'm not too comfortable with the CCompiler classes knowing that much about the internals of the "build_ext" command either. The issue of knowing a "safe" place to dump temporary files is again somewhat compiler (and linker) specific. We know that for Microsoft's linker, it's going to automatically create an import library when it creates the DLL. Currently, the decision about where to dump that DLL is made in the build_ext command, thereby making "build_ext" aware of the MSVCCompiler class details. If we could instead just tell the (abstract) compiler where the build_temp directory is, it could do the right thing without build_ext's intervention. Similarly, Borland's linker wants to create a lot of temporary files during the link process. I've found linker options to suppress the creation of most of these files but at least one (the "TDS" file) I don't seem to be able to kill off. But I can tell the linker *where* to put it -- and that's where it would again be useful for my subclass of CCompiler to know where the temporary files should go. From thomas.heller@ion-tof.com Fri May 12 18:23:34 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Fri, 12 May 2000 19:23:34 +0200 Subject: [Distutils] Suggested additions to function argument list References: <000b01bfbc33$6eeb4690$4e574dc0@cfdrc.com> Message-ID: <00f001bfbc36$cd114460$4500a8c0@thomasnb> > The command-line syntax for Borland's linker (called ILINK32) is: > > ILINK32 [options] objects, [exe], [mapfile], [libs], [deffile] > > The name of the module definition file, if specified, must appear in exactly > the position shown. It's not considered one of the "options" which can > appear in any order at the beginning of the command line. And after a second > look at the documentation for ILINK32 it doesn't appear that they have > anything analogous to the /EXPORTS switch for naming the exported symbol(s) > directly on the command line. Looks much like the MSVC 1.5 (the 16-bit compiler) linker command line. [Just curious (and unrelated to python extensions): What about resources? How are they built into the executable?] So what to do? - REQUIRE a def file? (Extension writers on unix would like not to have to care about this) - Trust the extension writer to use the (compiler specific?) pragmas? (Same as above) - Dynamically build a def-file and delete it after the build? Maybe the (distutils-generated) temporary def-file would be the best.(?) Greg? Thomas From jlj@cfdrc.com Fri May 12 19:36:43 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 13:36:43 -0500 Subject: [Distutils] Suggested additions to function argument list In-Reply-To: <00f001bfbc36$cd114460$4500a8c0@thomasnb> Message-ID: <000201bfbc41$0513c0e0$4e574dc0@cfdrc.com> > [Just curious (and unrelated to python extensions): What about > resources? > How are they built into the executable?] Sorry, left that off by accident; the resources file is the last argument. The full command line would be: ILINK32 [options] objects, [exe], [mapfile], [libs], [deffile], [resfile] > > So what to do? > > - REQUIRE a def file? (Extension writers on unix would like not to have to > care > about this) > - Trust the extension writer to use the (compiler specific?) pragmas? > (Same as above) > - Dynamically build a def-file and delete it after the build? > > Maybe the (distutils-generated) temporary def-file would be the best.(?) > I'd prefer not to *require* a .DEF file, since by convention most people will name their module initialization function "init" + modulename. The compiler class can then generate the def-file on the fly (if needed) and use it appropriately. The terminally clever developer who wants the (private) name of his module initialization function to be something else would be required to provide a .DEF file which exports that function as "init" + module, though -- there's obviously no way for distutils to guess that. By the way: again unlike Microsoft, Borland's linker prepends an underscore to exported functions' names, so the automatically-generated .DEF file for BorlandCCompiler will need to look something like this: EXPORTS initmodule=_initmodule --Lyle From thomas.heller@ion-tof.com Fri May 12 19:58:25 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Fri, 12 May 2000 20:58:25 +0200 Subject: [Distutils] Suggested additions to function argument list References: <000201bfbc41$0513c0e0$4e574dc0@cfdrc.com> Message-ID: <015b01bfbc44$0d684b00$4500a8c0@thomasnb> > > I'd prefer not to *require* a .DEF file, since by convention most people > will name their module initialization function "init" + modulename. The > compiler class can then generate the def-file on the fly (if needed) and use > it appropriately. The terminally clever developer who wants the (private) > name of his module initialization function to be something else would be > required to provide a .DEF file which exports that function as "init" + > module, though -- there's obviously no way for distutils to guess that. Is this possible? I think when you 'import extension' python looks for extension.dll or extension.pyd, then tries to locate and call 'void initextension (void)' and will fail if this is not found. > > By the way: again unlike Microsoft, Borland's linker prepends an underscore > to exported functions' names, so the automatically-generated .DEF file for > BorlandCCompiler will need to look something like this: > > EXPORTS > initmodule=_initmodule More reason to generate the def-file. BTW: If you change the CCompiler (and derived classes) function signatures I'm willing to test this for the MS case. Another reason to update my distutils... Thomas From jlj@cfdrc.com Fri May 12 21:00:14 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 12 May 2000 15:00:14 -0500 Subject: [Distutils] Suggested additions to function argument list In-Reply-To: <015b01bfbc44$0d684b00$4500a8c0@thomasnb> Message-ID: <000701bfbc4c$affb94a0$4e574dc0@cfdrc.com> > BTW: If you change the CCompiler (and derived classes) function signatures > I'm willing to test this for the MS case. Another reason to update my > distutils... Sounds good to me. I would like to wait until the CVS link to python.org is working again so that I can be sure I'm up-to-date (see Greg's e-mail from Thursday). I also want to hear back from Greg himself and anyone else who might have an opinion on the subject before I make too many changes. From mmuller@enduden.com Sat May 13 00:36:15 2000 From: mmuller@enduden.com (Michael Muller) Date: Fri, 12 May 2000 19:36:15 -0400 Subject: [Distutils] install_scripts and install_data commands Message-ID: <200005122342.TAA11866@bogus.com> Tony J Ibbs (Tibs) wrote: > I'm only following this with half a mind at best (sorry), but Bastian had an > email that contained: > > > >But I don't think we should rely on everyone using the > > >"#!/usr/bin/env" hack, either: the first python on the path isn't > > >necessarily the right one. > > The "first python on the path" is the correct thing for the user, > > otherwise the path is wrong. So "/usr/bin/env pyton" yields the correct > > interpreter to execute. > > Do please remember the problem on Dec Unixes (which appears to be) that if > the environment is large (i.e., many environment variables) then > /usr/bin/env falls back to *printing* the environment variables, instead of > executing the given program (gods know why, but this is Dec). [snip] That's not the only problem, apparently different systems are undecided as to whether "env" belongs in "/usr/bin" or in "/bin". Also, considering that other operating systems have their own ways of implementing the spirit of the "#!" hack (and they're usually pretty bad at it), I think the final script really needs to be generated during installation. See this URL for the complete discussion on #!/bin/env: http://x29.deja.com/dnquery.xp?search=next&DBS=1&IS=%22/bin/env%20python%22&ST=QS&offsets=db99p8%021%01db99p1%021%01db2000p1%022%01db99p2%026%01db98p3%024%01db98p4%022%01db99p4%021%01db98p5%021%01db2000p4%021%01db99p5%021%01db99p6%021%01db99p7%024&svcclass=dnserver&CONTEXT=958173312.1618477065 ============================================================================= michaelMuller = mmuller@enduden.com | http://www.cloud9.net/~proteus ----------------------------------------------------------------------------- The natural progress of things is for liberty to yield and government to gain control. - Thomas Jefferson ============================================================================= From gward@ase.com Sat May 13 02:37:10 2000 From: gward@ase.com (Greg Ward) Date: Fri, 12 May 2000 21:37:10 -0400 Subject: [Distutils] Patches for --compiler option In-Reply-To: <000401bfbc22$a40145c0$4e574dc0@cfdrc.com>; from Lyle Johnson on Fri, May 12, 2000 at 09:59:15AM -0500 References: <20000511203138.A1021@beelzebub> <000401bfbc22$a40145c0$4e574dc0@cfdrc.com> Message-ID: <20000512213710.A478@beelzebub> On 12 May 2000, Lyle Johnson said: > The /IMPLIB:name switch to the linker is used to specify the name of an > import library. The variable name "implib_dir" should probably be changed to > "implib_file" because it is the file name of the import library and not a > directory name. Having said that, the correct code snippet is: Ahh, I see. I thought that looked like a funny way to generate a directory name. I've checked in your code. Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ A committee is a life form with six or more legs and no brain. From gward@ase.com Sat May 13 05:12:24 2000 From: gward@ase.com (Greg Ward) Date: Sat, 13 May 2000 00:12:24 -0400 Subject: [Distutils] install_scripts and install_data commands In-Reply-To: ; from Bastian Kleineidam on Fri, May 12, 2000 at 01:15:54PM +0200 References: <20000511210846.A1076@beelzebub> Message-ID: <20000513001223.A1013@beelzebub> On 12 May 2000, Bastian Kleineidam said: > Do we have always Python scripts? What about shell scripts, and > specifically Windows Batch scripts? > See below for my current "Windows" hack in setup.py. Good point -- it would be nice to use 'scripts' for shell scripts, MS-DOG batch files, and Python scripts. But I bet you can do a fair job of distinguishing those three by looking at a mix of extensions and #! line; and if you can't figure something out, assume it's a Python script. > The "first python on the path" is the correct thing for the user, > otherwise the path is wrong. So "/usr/bin/env pyton" yields the correct > interpreter to execute. Not at all! Two possible scenarios come to mind: * I live life on the edge, so Python 1.6a2 is my "default" Python, but I'm installing something for a bunch of other users -- so it should use Python 1.5.2. Then I would run (eg.) python-1.5.2 setup.py install ...and I would damn well expect that any scripts installed by that distribution would (by default) be run by the Python 1.5.2 interpreter that I used to build/install the application. * I don't live life on the edge, so Python 1.5.2 is my default Python. But I've just downloaded some cutting-edge toy that requires 1.6 Then I would run (eg.) python-1.6a2 setup.py install ...and again, I would certainly expect any scripts installed by this distribution to be run by my Python 1.6 interpreter. And the arguments against always relying on #!/usr/bin/env are compelling -- I have long suspected it's a bit dodgy to rely on that across Unices, and the other posts in this thread confirm my paranoia. (With Unix, things are never as bad as they seem -- they're worse.) (Oh yeah, that's true for all operating systems...) Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ I want you to MEMORIZE the collected poems of EDNA ST VINCENT MILLAY ... BACKWARDS!! From hgebel@inet.net Mon May 15 02:30:46 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Sun, 14 May 2000 21:30:46 -0400 Subject: [Distutils] Optimized bytecode patch Message-ID: <20000514213046.D6308@inet.net> --vni90+aGYgRvsTuO Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I have to go out, when I get back I will send explanations -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --vni90+aGYgRvsTuO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="distutils.optimized.patch" diff -ur distutils-orig/distutils/command/install.py distutils/distutils/command/install.py --- distutils-orig/distutils/command/install.py Fri May 12 22:16:45 2000 +++ distutils/distutils/command/install.py Sun May 14 21:15:50 2000 @@ -12,7 +12,6 @@ from distutils import sysconfig from distutils.util import write_file, native_path, subst_vars, change_root from distutils.errors import DistutilsOptionError -from glob import glob INSTALL_SCHEMES = { 'unix_prefix': { @@ -423,13 +422,7 @@ def run (self): - - # Obviously have to build before we can install - if not self.skip_build: - self.run_peer ('build') - - # Run all sub-commands: currently this just means install all - # Python modules using 'install_lib'. + # Run all sub-commands. for (func, cmd_name) in self.sub_commands: if func is None or func(): self.run_peer (cmd_name) diff -ur distutils-orig/distutils/command/install_lib.py distutils/distutils/command/install_lib.py --- distutils-orig/distutils/command/install_lib.py Fri May 12 22:11:10 2000 +++ distutils/distutils/command/install_lib.py Sun May 14 21:23:58 2000 @@ -13,11 +13,17 @@ user_options = [ ('install-dir=', 'd', "directory to install to"), ('build-dir=','b', "build directory (where to install from)"), - ('compile', 'c', "compile .py to .pyc"), - ('optimize', 'o', "compile .py to .pyo (optimized)"), + ('compile', 'c', "compile .py to .pyc (default)"), + ('no-compile', None, "do not compile .py to .pyc"), + ('optimize', 'o', + "generate both optimized and non-optimized byte code (default)"), + ('no-optimize', None, + "do not generate both optimized and non-optimized byte code"), ('skip-build', None, "skip the build steps"), ] - + + negative_opt = {'no-compile': 'compile', + 'no-optimize': 'optimize'} def initialize_options (self): # let the 'install' command dictate our installation directory @@ -35,11 +41,13 @@ self.set_undefined_options ('install', ('build_lib', 'build_dir'), ('install_lib', 'install_dir'), - ('compile_py', 'compile'), - ('optimize_py', 'optimize'), ('skip_build', 'skip_build'), ) + # 'optimize implies 'compile' + if self.optimize: + self.compile = 1 + def run (self): @@ -47,6 +55,8 @@ if not self.skip_build: if self.distribution.has_pure_modules(): self.run_peer ('build_py') + if self.distribution.has_c_libraries(): + self.run_peer ('build_clib') if self.distribution.has_ext_modules(): self.run_peer ('build_ext') @@ -72,9 +82,42 @@ skip_msg = "byte-compilation of %s skipped" % f self.make_file (f, out_fn, compile, (f,), compile_msg, skip_msg) + + # run child script to generate optimized bytecode if requested + if self.optimize: + self._make_optimized() + # run () + def _make_optimized (self): + ''' Runs a child script with the opposite optimization of the current + script ''' + + # generate child command and arguments + child = ['python',] + + # if we are not optimized, run an optimizod version + if __debug__: + child.append('-O') + + # build has already been performed so we skip it, '-c' and'no-optimize' + # are passed in order to override any configuration options to the + # contrary. install-dir and build-dir are passed for essentially the + # same reason + child.extend(['setup.py', + 'install_lib', + '--no-optimize', + '-c', + '--skip-build', + '-d' + self.install_dir, + '-b' + self.build_dir]) + + self.spawn(child) + + # _make_optimized () + + def _mutate_outputs (self, has_any, build_cmd, cmd_option, output_dir): if not has_any: @@ -99,6 +142,9 @@ bytecode = py_file + (__debug__ and "c" or "o") bytecode_files.append(bytecode) + if self.optimize: # add optimize bytecode if applicable + bytecode = py_file + (__debug__ and "o" or "c") + bytecode_files.append(bytecode) return bytecode_files def get_outputs (self): --vni90+aGYgRvsTuO-- From hgebel@inet.net Mon May 15 03:44:23 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Sun, 14 May 2000 22:44:23 -0400 Subject: [Distutils] Optimized bytecode patch (explanation) In-Reply-To: <20000514213046.D6308@inet.net>; from hgebel@inet.net on Sun, May 14, 2000 at 09:30:46PM -0400 References: <20000514213046.D6308@inet.net> Message-ID: <20000514224423.E6308@inet.net> Hi here are the changes made by the patch: In install_lib.py: Puts --optimize option to work (see below) Adds two negative options --no-compile and --no-optimize which turn off --compile and --optimize . No longer attempts to set compile and optimize from --compile-py and --optimize-py in 'install' (there are no such options). Runs 'build_clib', eliminating the need for 'install' to run 'build' In install.py: Removes import of glob.glob (a leftover of my --record implementation) No longer runs 'build' (see above) Comment in beginning of run() brought up to date The new --optimize option really means 'both optimized and non-optimized', but the --optimize option already existed (and is alot quicker to type :) ). It works by running a child script with the opposite optimization setting of the current script. I just realized that if a user turns --compile off this patch will turn it back on unless the user also turns off --optimize, I will fix and send an update. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.ne From hgebel@inet.net Mon May 15 04:06:58 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Sun, 14 May 2000 23:06:58 -0400 Subject: [Distutils] Patch to patch In-Reply-To: <20000514224423.E6308@inet.net>; from hgebel@inet.net on Sun, May 14, 2000 at 10:44:23PM -0400 References: <20000514213046.D6308@inet.net> <20000514224423.E6308@inet.net> Message-ID: <20000514230658.F6308@inet.net> --ey/N+yb7u/X9mFhi Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Okay here is a patch against the last patch that fixes the problem I mentioned. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --ey/N+yb7u/X9mFhi Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="distutils.optimized.options.patch" --- install_lib.py.old Sun May 14 22:44:08 2000 +++ install_lib.py Sun May 14 23:00:13 2000 @@ -5,6 +5,7 @@ import sys, os, string from distutils.core import Command from distutils.util import copy_tree +from distutils.errors import DistutilsOptionError class install_lib (Command): @@ -29,8 +30,8 @@ # let the 'install' command dictate our installation directory self.install_dir = None self.build_dir = None - self.compile = 1 - self.optimize = 1 + self.compile = None + self.optimize = None self.skip_build = None def finalize_options (self): @@ -44,9 +45,17 @@ ('skip_build', 'skip_build'), ) - # 'optimize implies 'compile' - if self.optimize: - self.compile = 1 + # make sure --optimize agrees with --compile, set defaults + if self.optimize == 1 and self.compile == 0: + raise DistutilsOptionError, \ + "Incompatible options: '--no-compile' and '--optimize'" + if self.compile == 0: + self.optimize = 0 + else: + if self.compile == None: + self.compile = 1 + if self.optimize == None: + self.optimize = 1 def run (self): --ey/N+yb7u/X9mFhi-- From thomas.heller@ion-tof.com Mon May 15 11:00:19 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Mon, 15 May 2000 12:00:19 +0200 Subject: [Distutils] Small bug in distutils 2000-05-11 snapshot Message-ID: <027e01bfbe54$60a6aed0$4500a8c0@thomasnb> It seems the line 'from distutils import sysconfig' is missing on top of file dist.py in the recent distutils snapshot 2000-05-11. Thomas Heller From calvin@cs.uni-sb.de Mon May 15 19:40:59 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Mon, 15 May 2000 20:40:59 +0200 (CEST) Subject: [Distutils] install_scripts and install_data commands In-Reply-To: <20000513001223.A1013@beelzebub> Message-ID: I will work on the build_scripts command. Strange is that the CVS repository does not have the install_scripts.py command. The code snapshot has this file. I am using cvs update -PAd. CVS Root is :pserver:distutilscvs@cvs.python.org:/projects/cvsroot Good point -- it would be nice to use 'scripts' for shell scripts, >MS-DOG batch files, and Python scripts. But I bet you can do a fair job >of distinguishing those three by looking at a mix of extensions and #! >line; and if you can't figure something out, assume it's a Python >script. I assume we will install the DOS batch files only on Windows systems. So after all the build_scripts command will also affect the install_scripts command. Bastian -- Bastian Kleineidam -- Time to close your windows: Storm Linux .~. http://fsinfo.cs.uni-sb.de/~calvin/official/ /V\ // \\ /( )\ ^`~'^ From R.Liebscher@gmx.de Wed May 17 11:45:48 2000 From: R.Liebscher@gmx.de (Rene Liebscher (Rene.Liebscher@htw-dresden.de)) Date: Wed, 17 May 2000 12:45:48 +0200 Subject: [Distutils] distutils & Cygwin compiler on Win32 Message-ID: <3922785C.8DBF72CC@gmx.de> Hi, did anyone ever try to use the Cygwin compiler on Win32 with distutils? If not, then I'm the first. You can find a compiler class for this purpose at http://www.informatik.htw-dresden.de/~htw7192/distutils-cygwin/ there is also some additional information about some problem it still has. It is not completly tested, so if anyone want to test, use or debug it, she is free to do so. (I used it to build some dll's, the complete rest was not tested.) (PS: It works probably with mingw32, too. I used cygwin in no-cygwin mode, which is same as mingw32, I think.) Kind regards Rene Liebscher From thomas.heller@ion-tof.com Wed May 17 17:18:39 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Wed, 17 May 2000 18:18:39 +0200 Subject: [Distutils] Thinking about a Windows Installer Message-ID: <010901bfc01b$8fedf590$4500a8c0@thomasnb> Hi, I'm currently thinking about a bdist_winexe command for distutils. (Is there a better name?) This command will create a single executable file similar to those created with Wise or Installshield installers (except that you don't need to have these _commercial_ programs installed). This exe-File consists of a C-program embedding python, appended is a zip-compatible archive of the modules to distribute, the setup.py script, as well as an ini-file "setup.ini" or something like that which contains the distribution meta-data in a format easily readable by the C-program. This exe-File, when run, simply unpacks the archive into a temporary directory, displays a nice GUI, runs the setup.py script, and cleans up the temp-dir. (The design is inspired by previous work: Gordons installer, squeeze and whatever) Comments? Thomas Heller From dubois@users.sourceforge.net Thu May 18 15:53:37 2000 From: dubois@users.sourceforge.net (Paul F. Dubois) Date: Thu, 18 May 2000 07:53:37 -0700 Subject: [Distutils] do-nothing fails Message-ID: Allow me to confess that the following low-priority bug actually bit me: You can't have packages be an empty list. The build directory does not get created and the installer complains it can't copy the tree. Why might I be running distutils to install "nothing"? The CXX package consists of header files and some C and C++ source files; no python files or extension modules at the moment. I propose to put the source files (needed by a builder of a CXX extension) into PYTHON/etc/CXX. The include files get treated like Numeric's. I can obviously work around this but it is a generally nice idea that end cases work. From calvin@cs.uni-sb.de Fri May 19 23:27:14 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Sat, 20 May 2000 00:27:14 +0200 (CEST) Subject: [Distutils] util.copy_file and --dry-run Message-ID: I found a misleading behaviour with the --dry-run option. Suppose you create a directory and then you copy a file in this directory. With --dry-run the directory is not created and this makes the copy_file function to announce the renaming of the file rather than copying it into the new directory. code snippet: ./setup.py --dry-run build [...] creating build/scripts copying linkchecker -> build should be: creating build/scripts copying linkchecker -> build/scripts I do not have a fix for this. I think this is a feature, not a bug. Bastian -- Bastian Kleineidam -- Just do it. Use Linux. .~. http://fsinfo.cs.uni-sb.de/~calvin/official/ /V\ // \\ /( )\ ^`~'^ From gward@python.net Sat May 20 13:48:06 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 08:48:06 -0400 Subject: [Distutils] Supporting Borland's compiler Message-ID: <20000520084806.A322@beelzebub> Hi all -- this is a followup to Lyle and Thomas' exchange earlier in the week; sorry for the delay. 1. First topic: list of symbols to export. [Lyle] > Since only the compiler class knows for sure how to specify the .DEF file > name (or alternatively the exported symbols list) it seems that we should > pass this information directly to the compiler through the > link_shared_object() function's argument list, instead of cooking up those > arguments in the build_ext command. I'd propose adding an additional > argument to the function's signature (its default could be None and could be > ignored by non-Windows compilers). Yep, I've been thinking this was needed for a while. Here's a proposed new signature for the 'link_shared_lib()' method: def link_shared_lib (self, objects, output_libname, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, exported_symbols=None, debug=0, extra_preargs=None, extra_postargs=None): 'exported_symbols' would be a list of strings; it's up to the compiler class to translate that into command-line options, a file (in the appropriate format for that compiler) listing the names, or whatever. For MSVCCompiler, we would add "/EXPORT:" options to the command line, one for each string in 'exported_symbols'. For BorlandCCompiler (or whatever Lyle's calling it -- I suppose I should have veto power on the name, but I still can't make up my mind), the class would have to generate a .def file (in Borland style with underscores added/removed as appropriate) and pass that in just the right place on the compiler command-line. 'link_shared_object()', of course, would be adjusted similarly (since 'link_shared_lib()' is just a wrapper around 'link_shared_object()' on both Unix and Windows.) 2. Variation on first topic: allowing sneaky symbol aliasing [Lyle] > The terminally clever developer who wants the (private) > name of his module initialization function to be something else would be > required to provide a .DEF file which exports that function as "init" + > module, though -- there's obviously no way for distutils to guess that. [Thomas echoes my sentiments] > Is this possible? I think when you 'import extension' python looks > for extension.dll or extension.pyd, then tries to locate and call > 'void initextension (void)' and will fail if this is not found. More importantly, is this *desirable* or *useful*? This doesn't sound like a useful thing to support; in fact, it sounds like a downright *bad* idea to let developers name their module initializer anything other than "init" + extension_name. (Assuming that it even works -- if the symbols exported from a DLL really can be aliased in the way that Lyle's "initmodule = _initmodule" example implies, then that demolishes Thomas' argument... but it doesn't make this kind of trickery a good idea!) 3. Second topic: temporary files [Lyle] > Changing the subject, it might also be appropriate to pass down the > temporary files directory for the current extension's build, unless this > kind of code: > > build_ext = self.find_peer ('build_ext') > build_temp = build_ext.build_temp > > is considered safe. If this doesn't violate encapsulation (for the compiler > object to know that the build_ext object has an attribute named > "build_temp") then I'll just do this and sleep soundly ;) If you're talking about putting this code in one (or more) of the CCompiler classes, then Thomas was right: I don't like this. Furthermore, it won't work -- 'find_peer()' is a method of Command, and CCompiler is independent of that class hierarchy. I think the right thing to do is add a 'temp_dir' attribute to CCompiler. (I see no reason to allow overriding this in every method.) Currently this would not gain much, just the ability to move a bit of the MSVC-specific code out of build_ext.py (specifically, the stuff that generates the /IMPLIB: option). But if it's necessary to support Borland's compiler cleanly, I'm willing to do it. Here are proposed semantics for 'temp_dir': * files that are obviously compiler/linker turds (like the stuff Lyle is talking about, and the MSVC turds that Thomas took care of several months ago by generating that /IMPLIB: option) would unconditionally go in 'temp_dir' * intermediate products, specifically object files, would go under 'temp_dir' unless you pass 'output_dir' to 'compile()' * 'temp_dir' would really be the root of a temporary tree, to avoid possible name collisions. Eg. if you compile "src/foo/a.c" and "src/bar/a.c", you'd get "/src/foo/a.o" and "/src/bar/a.o" * in the distutils context (ie. the "build_ext" command), temp_dir would be build/temp. -- ie. build_ext would do something like self.compiler.temp_dir = self.build_temp and that's the only use it would have for 'self.build_temp' * the compiler classes would be responsible for making sure any output directories (temp_dir or otherwise) exist before writing to them * the compiler classes are *not* responsible for cleaning up the temp dir -- that way, we can reuse .o files across builds. In the Distutils context, the user is responsible for cleaning via the "clean" command Sound reasonable? Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ "Passionate hatred can give meaning and purpose to an empty life." -- Eric Hoffer From gward@python.net Sat May 20 14:01:52 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 09:01:52 -0400 Subject: [Distutils] Patch to MSVCCompiler: 'export_symbols' Message-ID: <20000520090152.A517@beelzebub> OK, all your Windows experts: tell me if I got this right. Here's a patch to msvccompiler.py to add support for the 'export_symbol' keyword argument to 'link_shared_lib()' and 'link_shared_object()'. Right now it turns a list of ['foo', 'bar', 'baz'] into additional arguments to the linker: /EXPORT:foo /EXPORT:bar /EXPORT:baz Is this the correct and/or optimal way to do it? Here's the patch... diff -c -r1.27 msvccompiler.py *** msvccompiler.py 2000/04/19 02:16:49 1.27 --- msvccompiler.py 2000/05/20 12:59:04 *************** *** 304,309 **** --- 304,310 ---- libraries=None, library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None): *************** *** 313,318 **** --- 314,321 ---- output_dir=output_dir, libraries=libraries, library_dirs=library_dirs, + runtime_library_dirs=runtime_library_dirs, + export_symbols=export_symbols, debug=debug, extra_preargs=extra_preargs, extra_postargs=extra_postargs) *************** *** 325,330 **** --- 328,334 ---- libraries=None, library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None): *************** *** 350,357 **** else: ldflags = self.ldflags_shared ! ld_args = ldflags + lib_opts + \ ! objects + ['/OUT:' + output_filename] if extra_preargs: ld_args[:0] = extra_preargs --- 354,365 ---- else: ldflags = self.ldflags_shared ! export_opts = [] ! for sym in (export_symbols or []): ! export_opts.append("/EXPORT:" + sym) ! ! ld_args = (ldflags + lib_opts + export_opts + ! objects + ['/OUT:' + output_filename]) if extra_preargs: ld_args[:0] = extra_preargs -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ Disclaimer: All rights reserved. Void where prohibited. Limit 1 per customer. From gward@python.net Sat May 20 14:28:01 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 09:28:01 -0400 Subject: [Distutils] Function stubs for CCompiler class? In-Reply-To: <001401bfbb8c$ce137360$4e574dc0@cfdrc.com>; from Lyle Johnson on Thu, May 11, 2000 at 04:06:41PM -0500 References: <001401bfbb8c$ce137360$4e574dc0@cfdrc.com> Message-ID: <20000520092801.A318@beelzebub> On 11 May 2000, Lyle Johnson said: > It appears that in addition to the "worker" functions like compile(), > link_shared_object(), etc. there are four functions which *must* be > implemented by subclasses of CCompiler: > > library_dir_option() > runtime_library_dir_option() > library_option() > find_library_file() > > I submit the following patch (against the current CVS version of > ccompiler.py) to make future compiler implementors aware of this > requirement. Thanks -- just checked it in. Greg -- Greg Ward - programmer-at-large gward@python.net http://starship.python.net/~gward/ I haven't lost my mind; I know exactly where I left it. From gward@python.net Sat May 20 15:05:26 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 10:05:26 -0400 Subject: [Distutils] Optimized bytecode patch (explanation) In-Reply-To: <20000514224423.E6308@inet.net>; from Harry Henry Gebel on Sun, May 14, 2000 at 10:44:23PM -0400 References: <20000514213046.D6308@inet.net> <20000514224423.E6308@inet.net> Message-ID: <20000520100526.B318@beelzebub> [Harry Henry Gebel, regarding his patch for doing both optimized and non-optimized bytecode compilation at install-time] > Hi here are the changes made by the patch: > > In install_lib.py: > > Puts --optimize option to work (see below) > Adds two negative options --no-compile and --no-optimize which turn off > --compile and --optimize . > No longer attempts to set compile and optimize from --compile-py and > --optimize-py in 'install' (there are no such options). > Runs 'build_clib', eliminating the need for 'install' to run 'build' [...] I like the spirit of the patch, but I'm not sure if this is the right way to do it. I'm inclined more towards this: generate a little script, and run it twice: "python compile.py" and "python -O compile.py". I see three options: 1) generate a script that explicitly lists all the .py modules to be compiled, does the necessary timestamp-checking, and calls 'py_compile.compile()' to do the compilation. PRO: gives us exact control over what's compiled CON: largely reimplements the standard compileall module (the difference is that this one would take a list of files rather than a directory) 2) run python /compileall.py -d PRO: not much code to write CON: not the right thing to do if installing new modules into a package (eg. the root package) that already has modules in it 3) same as #2, but invoke "compileall" as a "-c" script -- eg. python -c "from compileall import compile_dir ; compile_dir() ...I don't think this is any different from #2 I'm leaning towards #1, but with a new Distutils module to handle most of the work (ie. the near-reimplementation-of-compileall). Thus, the generated script would be mainly a list of modules. Perhaps we could even get away with generating just a data file (list of modules to compile) and passing it to the new "distutils.bytecompile" (?) module. Opinions? I'm really not keen on the Distutils recursively invoking the setup script just to do bytecode compilation. *Really* not keen. And it seem more symmetric to not care what the current interpreter's optimization state is, but just spawn two separate interpreters to take care of the two optimization case. Also, as I mentioned in private email to Harry, I don't think it's the business of the "install" command to know what the subcommands of "build" are, so I'd prefer if you left out the "don't run 'build', just run its subcommands" tweak. Harry, d'you want to rework and resubmit your patch? If not, I'll tackle this task. Greg -- Greg Ward - just another Python hacker gward@python.net http://starship.python.net/~gward/ A day for firm decisions!!!!! Or is it? From gward@python.net Sat May 20 15:08:03 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 10:08:03 -0400 Subject: [Distutils] Small bug in distutils 2000-05-11 snapshot In-Reply-To: <027e01bfbe54$60a6aed0$4500a8c0@thomasnb>; from Thomas Heller on Mon, May 15, 2000 at 12:00:19PM +0200 References: <027e01bfbe54$60a6aed0$4500a8c0@thomasnb> Message-ID: <20000520100803.C318@beelzebub> On 15 May 2000, Thomas Heller said: > It seems the line > > 'from distutils import sysconfig' > > is missing on top of file dist.py in the recent distutils snapshot > 2000-05-11. Thanks -- fixed and checked in. Should probably get a new snapshot out in a couple of days... Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ Think honk if you're a telepath. From gward@python.net Sat May 20 15:21:49 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 10:21:49 -0400 Subject: [Distutils] distutils & Cygwin compiler on Win32 In-Reply-To: <3922785C.8DBF72CC@gmx.de>; from Rene Liebscher (Rene.Liebscher@htw-dresden.de) on Wed, May 17, 2000 at 12:45:48PM +0200 References: <3922785C.8DBF72CC@gmx.de> Message-ID: <20000520102149.D318@beelzebub> On 17 May 2000, Rene Liebscher (Rene.Liebscher@htw-dresden.de) said: > did anyone ever try to use the Cygwin compiler on Win32 > with distutils? > > If not, then I'm the first. Cool! Looks like a good start, but it needs work. First, I will never in a million years accept a patch that is mostly cut 'n pasted from existing source code. Please, *please* take advantage of OO techniques and *subclass* UnixCCompiler rather than copy it! If you're not sure how to do this, I'd be happy to help. But it looks as though a number of methods are straight copies of UnixCCompiler methods... ie. they should just be inherited from UnixCCompiler. Changing the compiler-selection code in ccompiler.py should not be necessary; users can use the "--compiler" option to "build_ext" to select an alternate compiler. (That was added to support Borland's compiler.) I spotted an instance of spawning bash to do some sed and grep trickery. Ugh! Please recode this as a Python function. I wouldn't even do this on Unix, much less Windows. Why are large chunks of code wrapped in ''' ? Is that a weird way of commenting stuff out? Please don't do that -- Python has a perfectly good comment character. Finally, has anyone submitted the config.h that works with Cygwin to Guido? I'm not sure how many people will be inclined to change Python's config.h. Send patches to patches@python.org. I for one think it would be great if Python 1.6 could build on Windows with something other than MSVC, although I have no idea if this is a priority for Guido. Oh, could someone explain to me the differences between cygwin and mingw32? I gather they both have something to do with using GCC and/or other GNU tools on Windows, but that's all I know. Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ Do I have a lifestyle yet? From gward@python.net Sat May 20 15:41:14 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 10:41:14 -0400 Subject: [Distutils] Thinking about a Windows Installer In-Reply-To: <010901bfc01b$8fedf590$4500a8c0@thomasnb>; from Thomas Heller on Wed, May 17, 2000 at 06:18:39PM +0200 References: <010901bfc01b$8fedf590$4500a8c0@thomasnb> Message-ID: <20000520104114.E318@beelzebub> On 17 May 2000, Thomas Heller said: > I'm currently thinking about a bdist_winexe command for distutils. > (Is there a better name?) How about "bdist_wininst"? > This command will create a single executable file similar to those > created with Wise or Installshield installers (except that you don't > need to have these _commercial_ programs installed). There is some sort of informal arrangement that lets Python developers use Wise to create installers of free Python extensions for free. I think the same arrangement lets Guido create Python installers for free. So we probably shouldn't toss Wise out the window just because it's commercial; it might be a good (and zero-cost, if not entirely free) option for Python-on-Windows developers. > This exe-File consists of a C-program embedding python, appended > is a zip-compatible archive of the modules to distribute, the setup.py > script, as well as an ini-file "setup.ini" or something like that which > contains the distribution meta-data in a format easily readable by > the C-program. Whether you want to embed Python really depends on your audience. Let's face it, installing Python on Windows is not that hard. If a programmer wants to use some collection of modules, it's not too bad to say, "Download and install Python, then download and install the module distribution". Painless * 2 is not too bad. For end-user applications, though, embedding a Python interpreter (and however much of the standard library as is needed) is probably the right thing to do. I think it should be up to the module developer/packager to decide he distributes a "Python-less" installer or a big fat one (or both). Now, if you *do* end up writing your own installer GUI (instead of using Wise), how much of it can be written in Python rather than C? I assume doing this would require the presence of the Win32 extensions, so "painless * 2" might become "painless * 3". Hmmm... I'd be reluctant to make someone install Python *and* the Win32 stuff just to run an installer. > This exe-File, when run, simply unpacks the archive into a temporary > directory, displays a nice GUI, runs the setup.py script, and cleans > up the temp-dir. I think the mode of operation should be as close to the other bdist commands as possible: distribute a pseudo-installation tree and just copy it in place. That is, the setup script shouldn't enter into it here, *unless* you need it to extract package meta-data. (Unless that's put into another file when you run "bdist_wininst".) Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ All programmers are playwrights and all computers are lousy actors. From gward@python.net Sat May 20 16:18:56 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 11:18:56 -0400 Subject: [Distutils] do-nothing fails In-Reply-To: ; from Paul F. Dubois on Thu, May 18, 2000 at 07:53:37AM -0700 References: Message-ID: <20000520111856.F318@beelzebub> On 18 May 2000, Paul F. Dubois said: > You can't have packages be an empty list. The build directory does not get > created and the installer complains it can't copy the tree. Ahh, oops -- I've fixed this. Now "install" won't even run "install_lib" if there are no Python modules or extensions to build, *and* "install_lib" warns (rather than blows up) if the build directory doesn't exist. (Necessary in case some agent other than the "install" command runs "install_lib" -- eg. the user.) This will get into the next release or snapshot or whatever it turns out to be. Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ I'm on a strict vegetarian diet -- I only eat vegetarians. From gward@python.net Sat May 20 16:54:31 2000 From: gward@python.net (Greg Ward) Date: Sat, 20 May 2000 11:54:31 -0400 Subject: [Distutils] util.copy_file and --dry-run In-Reply-To: ; from Bastian Kleineidam on Sat, May 20, 2000 at 12:27:14AM +0200 References: Message-ID: <20000520115431.G318@beelzebub> On 20 May 2000, Bastian Kleineidam said: > I found a misleading behaviour with the --dry-run option. Suppose you > create a directory and then you copy a file in this directory. With > --dry-run the directory is not created and this makes the copy_file > function to announce the renaming of the file rather than copying it > into the new directory. > > code snippet: > ./setup.py --dry-run build > [...] > creating build/scripts > copying linkchecker -> build > > should be: > creating build/scripts > copying linkchecker -> build/scripts Ooh, sneaky sneaky! This is both a feature and a bug, if you'll buy that. I've just changed how 'copy_file()' does its verbose output so that the feature part outweighs the bug part. ('copy_file()' still misunderstands what it's doing in dry-run mode when you try to copy to a directory that doesn't exist. But it now prints output that makes it *look* like it knows what it's doing. Since this only affects the verbose output in dry-run mode, I think that *looking* good is good enough.) Greg -- Greg Ward - geek gward@python.net http://starship.python.net/~gward/ I appoint you ambassador to Fantasy Island!!! From hgebel@inet.net Sat May 20 19:26:55 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Sat, 20 May 2000 14:26:55 -0400 Subject: [Distutils] Optimized bytecode patch (explanation) In-Reply-To: <20000520100526.B318@beelzebub>; from gward@python.net on Sat, May 20, 2000 at 10:05:26AM -0400 References: <20000514213046.D6308@inet.net> <20000514224423.E6308@inet.net> <20000520100526.B318@beelzebub> Message-ID: <20000520142655.A1986@inet.net> --17pEHd4RhPHOinZp Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sat, May 20, 2000 at 10:05:26AM -0400, Greg Ward wrote: > Harry, d'you want to rework and resubmit your patch? If not, I'll > tackle this task. I'm still interested in working on the patch, I probably won't get a chance to work on anything till next weekend as a client just called me up and wants me to convert some things from ncurses to GTK, and he is the source of most of my referrals so I have to give him quick response. Actually I've been meaning to convert them to GTK for awhile so this is just putting a burr under my saddle, so to speak. --=20 Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net --17pEHd4RhPHOinZp Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.0 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE5JtjvgAlRceSu4ygRAvUTAJ9ZFvMlwFD6xhMrd90CqbYfXP/yIgCbB8EB BBTrfEENJJx0eJnd7WBEQM4= =srdA -----END PGP SIGNATURE----- --17pEHd4RhPHOinZp-- From calvin@cs.uni-sb.de Mon May 22 12:31:05 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Mon, 22 May 2000 13:31:05 +0200 (CEST) Subject: [Distutils] the build_scripts patch Message-ID: I submitted a patch to Greg against the latest Snapshot release. It is too big to include it here, but a list of changes follows: - new command build_scripts: copy all scripts in build/scripts. If the first line of a script begins with "#!" and ends with "python", write the path to the current Python interpreter in this line. - bug fixed in dist.py: import sysconfig for win32 platforms. - new function Command.create_tree which calls util.create_tree. - install_misc is now the base class for all install commands - install_data now creates leading directories of the files you supply and copies the files in these directories. So for example pixmaps/open.xpm gets installed in /pixmaps/open.xpm and not in /open.xpm I think the last point is a convenient way to install data in different directories. Another way (like in automake) is to supply for each set of filenames a different directory in which the files are going to be installed, but I like my solution better. Bastian Kleineidam From jlj@cfdrc.com Mon May 22 15:47:25 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Mon, 22 May 2000 09:47:25 -0500 Subject: [Distutils] distutils & Cygwin compiler on Win32 In-Reply-To: <20000520102149.D318@beelzebub> Message-ID: <001601bfc3fc$a4c8ef30$4e574dc0@cfdrc.com> > Oh, could someone explain to me the differences between cygwin and > mingw32? I gather they both have something to do with using GCC and/or > other GNU tools on Windows, but that's all I know. The long answers can be found on the two projects' respective home pages: http://sourceware.cygnus.com/cygwin http://www.mingw.org The short answer goes something like this: MinGWin32 stands for "minimalist GNU-Win32" and the purpose of that project is to allow you to use GNU development tools to create native Win32 applications that don't rely on any 3rd party DLLs. In other words, if you've got yer basic Win32 program that would compile under one of the commercial compilers like Visual C++ or Borland C++, you can now use gcc to do the same. This is in contrast to the Cygwin project, which provides a kind of Unix emulation layer through the Cygwin API. Programs built on Cygwin obviously depend on the Cygwin runtime library (cygwin1.dll) and I'm not entirely clear on the licensing issues there. But the upshot is that a majority of the free software available for Unix compiles out-of-the-box under Cygwin. Several of the links from the Cygwin page are impressive lists of all the stuff that works under Cygwin with minimal or no patches to the source. From thomas.heller@ion-tof.com Mon May 22 16:51:21 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Mon, 22 May 2000 17:51:21 +0200 Subject: [Distutils] CVS access Message-ID: <009901bfc405$936566c0$4500a8c0@thomasnb> I have successfully accessed the python source on sourceforge, including the lib/distutils subtree. How would I access the distutils (complete) tree? Thomas Heller From fdrake@acm.org Mon May 22 16:53:12 2000 From: fdrake@acm.org (Fred L. Drake) Date: Mon, 22 May 2000 08:53:12 -0700 (PDT) Subject: [Distutils] CVS access In-Reply-To: <009901bfc405$936566c0$4500a8c0@thomasnb> Message-ID: On Mon, 22 May 2000, Thomas Heller wrote: > I have successfully accessed the python source on sourceforge, > including the lib/distutils subtree. > > How would I access the distutils (complete) tree? Instead of checking out the "python" product, get the "distutils" product. The last word of the checkout command should simply be changed to "distutils" to do this. -Fred -- Fred L. Drake, Jr. From jlj@cfdrc.com Mon May 22 16:59:40 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Mon, 22 May 2000 10:59:40 -0500 Subject: [Distutils] CVS access In-Reply-To: <009901bfc405$936566c0$4500a8c0@thomasnb> Message-ID: <000201bfc406$bceab710$4e574dc0@cfdrc.com> If your CVSROOT is :pserver:anonymous@cvs.python.sourceforge.net:/cvsroot/python you should be able to do a checkout of the distutils like so: cvs checkout distutils This worked for me... > -----Original Message----- > From: distutils-sig-admin@python.org > [mailto:distutils-sig-admin@python.org]On Behalf Of Thomas Heller > Sent: Monday, May 22, 2000 10:51 AM > To: Distutils-SIG@python.org > Subject: [Distutils] CVS access > > > I have successfully accessed the python source on sourceforge, > including the lib/distutils subtree. > > How would I access the distutils (complete) tree? > > Thomas Heller > > > > _______________________________________________ > Distutils-SIG maillist - Distutils-SIG@python.org > http://www.python.org/mailman/listinfo/distutils-sig > From jlj@cfdrc.com Mon May 22 22:32:21 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Mon, 22 May 2000 16:32:21 -0500 Subject: [Distutils] Supporting Borland's compiler In-Reply-To: <20000520084806.A322@beelzebub> Message-ID: <000101bfc435$367ce9d0$4e574dc0@cfdrc.com> > Yep, I've been thinking this was needed for a while. Here's a proposed > new signature for the 'link_shared_lib()' method: > > def link_shared_lib (self, > objects, > output_libname, > output_dir=None, > libraries=None, > library_dirs=None, > runtime_library_dirs=None, > exported_symbols=None, > debug=0, > extra_preargs=None, > extra_postargs=None): > This works for me. I'm also not attached to the "BorlandCCompiler" name, I promise! > 2. Variation on first topic: allowing sneaky symbol aliasing > > More importantly, is this *desirable* or *useful*? This doesn't sound > like a useful thing to support; in fact, it sounds like a downright > *bad* idea to let developers name their module initializer anything > other than "init" + extension_name. (Assuming that it even works -- if > the symbols exported from a DLL really can be aliased in the way that > Lyle's "initmodule = _initmodule" example implies, then that demolishes > Thomas' argument... but it doesn't make this kind of trickery a good > idea!) You can definitely alias exported symbol names; look up the MSDN documentation for the /EXPORT switch if you are still a doubter! But I meant for my use of the phrase "terminally clever" to indicate that developers who do this for Python extensions should be, um, terminated ;) So I agree with both you and Thomas that we shouldn't give them this hook. > > 3. Second topic: temporary files > > I think the right thing to do is add a 'temp_dir' attribute to > CCompiler. (I see no reason to allow overriding this in every method.) > Currently this would not gain much, just the ability to move a bit of > the MSVC-specific code out of build_ext.py (specifically, the stuff that > generates the /IMPLIB: option). But if it's necessary to support > Borland's compiler cleanly, I'm willing to do it. > > Here are proposed semantics for 'temp_dir': > * files that are obviously compiler/linker turds (like the stuff > Lyle is talking about, and the MSVC turds that Thomas took care > of several months ago by generating that /IMPLIB: option) > would unconditionally go in 'temp_dir' > * intermediate products, specifically object files, would go > under 'temp_dir' unless you pass 'output_dir' to 'compile()' > * 'temp_dir' would really be the root of a temporary tree, > to avoid possible name collisions. Eg. if you compile > "src/foo/a.c" and "src/bar/a.c", you'd get "/src/foo/a.o" > and "/src/bar/a.o" > * in the distutils context (ie. the "build_ext" command), temp_dir > would be build/temp. -- ie. build_ext would do something like > self.compiler.temp_dir = self.build_temp > and that's the only use it would have for 'self.build_temp' > * the compiler classes would be responsible for making sure any > output directories (temp_dir or otherwise) exist before > writing to them > * the compiler classes are *not* responsible for cleaning up the > temp dir -- that way, we can reuse .o files across builds. > In the Distutils context, the user is responsible for cleaning > via the "clean" command > > Sound reasonable? Yes, this sounds great! Anxiously awaiting the next CVS update... From gward@python.net Tue May 23 03:14:37 2000 From: gward@python.net (Greg Ward) Date: Mon, 22 May 2000 22:14:37 -0400 Subject: [Distutils] the build_scripts patch In-Reply-To: ; from Bastian Kleineidam on Mon, May 22, 2000 at 01:31:05PM +0200 References: Message-ID: <20000522221437.A7359@beelzebub> On 22 May 2000, Bastian Kleineidam said: > - new command build_scripts: copy all scripts in build/scripts. If the > first line of a script begins with "#!" and ends with "python", > write the path to the current Python interpreter in this line. A *possible* variation on this: if the line starts wuth #! and *contains* "python", rewrite it. Not really necessary since command-line options to the Python interpreter are quite rare. I think your way will do just fine unless somebody howls. > - bug fixed in dist.py: import sysconfig for win32 platforms. Already fixed in CVS -- well, I'll probably ask you to "cvs up" and resubmit the patch, as I've been doing some heavy lifting in dist.py that will affect all of the commands (sigh). IOW, you get to deal with the conflict. ;-) > - new function Command.create_tree which calls util.create_tree. Fine. > - install_misc is now the base class for all install commands I'd like to know why this is necessary -- please explain your rationale. (I've only skimmed the patch, not read it closely.) > - install_data now creates leading directories of the files you supply > and copies the files in these directories. > So for example pixmaps/open.xpm gets installed in > /pixmaps/open.xpm and not in > /open.xpm > > I think the last point is a convenient way to install data in > different directories. Another way (like in automake) is to supply for > each set of filenames a different directory in which the files are > going to be installed, but I like my solution better. Good that you brought this up, because I think I like the Automake way better. Your installation directories shouldn't be constrained by your source directories, and it sounds like your scheme does that. Granted it's more convenient, and probably easier to implement, but I think I'd opt for more flexibility here. Other opinions? Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ Never put off till tomorrow what you can put off till the day after tomorrow. From gward@python.net Tue May 23 03:23:36 2000 From: gward@python.net (Greg Ward) Date: Mon, 22 May 2000 22:23:36 -0400 Subject: [Distutils] Supporting Borland's compiler In-Reply-To: <000101bfc435$367ce9d0$4e574dc0@cfdrc.com>; from Lyle Johnson on Mon, May 22, 2000 at 04:32:21PM -0500 References: <20000520084806.A322@beelzebub> <000101bfc435$367ce9d0$4e574dc0@cfdrc.com> Message-ID: <20000522222336.B7359@beelzebub> [me, proposing a new 'temp_dir' attribute for CCompiler and friends] > I think the right thing to do is add a 'temp_dir' attribute to > CCompiler. (I see no reason to allow overriding this in every method.) > Currently this would not gain much, just the ability to move a bit of > the MSVC-specific code out of build_ext.py (specifically, the stuff that > generates the /IMPLIB: option). But if it's necessary to support > Borland's compiler cleanly, I'm willing to do it. [...] [Lyle enthusiastically agrees] > Yes, this sounds great! Anxiously awaiting the next CVS update... OK, but it'll have to wait -- I'm currently in the throes of making config files a reality at last. Lots of upheaval involved, surprise surprise. Also, I started implementing my proposed 'temp_file' semantics only to discover a fly in the ointment. Now I can't even remember if it was just a harmless little housefly or a great bug-eyed blood-sucking poisonous monster. I'll get back to it when the config file stuff is done... in the meantime, keep on "cvs up"'ing ... Greg -- Greg Ward - "always the quiet one" gward@python.net http://starship.python.net/~gward/ MTV -- get off the air! -- Dead Kennedys From gward@python.net Tue May 23 03:46:51 2000 From: gward@python.net (Greg Ward) Date: Mon, 22 May 2000 22:46:51 -0400 Subject: [Distutils] CVS access In-Reply-To: <000201bfc406$bceab710$4e574dc0@cfdrc.com>; from Lyle Johnson on Mon, May 22, 2000 at 10:59:40AM -0500 References: <009901bfc405$936566c0$4500a8c0@thomasnb> <000201bfc406$bceab710$4e574dc0@cfdrc.com> Message-ID: <20000522224651.C7359@beelzebub> On 22 May 2000, Lyle Johnson said: > If your CVSROOT is > > :pserver:anonymous@cvs.python.sourceforge.net:/cvsroot/python > > you should be able to do a checkout of the distutils like so: > > cvs checkout distutils > > This worked for me... Yes, that is correct. See the Python CVS page at SourceForge for a slightly longer exposition: https://sourceforge.net/cvs/?group_id=5470 Note that the *project* is Python, and it has two *products*: Python and the Distutils. This makes it trivial for Guido to include the Distutils in Python releases as Lib/distutils, and makes it easy for me to release the Distutils as a separate package, which is essential for people not yet running Python 1.6. (If you're curious, it's done through a couple of judicious symlinks in the CVS tree: when you checkout distutils/distutils/*.py, you're really checking out python/dist/src/Lib/distutils/*.py, but CVS pays no attention to symlinks, so it all Just Works. Very nifty. The setup on SourceForge is exactly the way it was on cvs.python.org, except the direction of the symlinks has been reversed.) Also, anyone who has an existing Distutils (or Python) working tree probably wants to know about my "cvs_chroot" script, which walks a working tree and updates all the CVS/Root and CVS/Repository files to point to a new repository. Handy little tool, if I do say so myself. Get it from my Starship page: http://starship.python.net/~gward/python/ Thanks to Lyle Johnson and Skip Montanaro for testing/debugging! Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ "One world, one web, one program" --Microsoft "Eine volk, eine reich, eine führer" --Hitler From gward@python.net Tue May 23 05:09:59 2000 From: gward@python.net (Greg Ward) Date: Tue, 23 May 2000 00:09:59 -0400 Subject: [Distutils] Config files working (I hope) Message-ID: <20000523000959.A7632@beelzebub> Hi all -- I seem to have got the Distutils config file mechanism working. Please check out the latest code from the CVS archive (SourceForge!) and see how many bugs I left in. The basic idea is this: you can create 1 .. 3 config files, depending on your platform. On Unix: /lib/python1.x/site-packages/distutils/pydistutils.cfg [1] $HOME/.pydistutils.cfg setup.cfg [1] this is really just the directory of the distutils package -- so it could be the distutils development directory if you haven't installed the distutils, or it could be lib/python1.6/distutils -- you get the idea. I'm not entirely thrilled with putting a config file in the library directory, but I was even less thrilled with any of the alternatives. ;-( On Windows and Mac OS: /pydistutils.cfg setup.cfg Config files are read in the order listed above, ie. setup.cfg in the current directory takes precedence over ~/.pydistutils.cfg, which take precedence over the system pydistutils.cfg. Config files are in turn overridden by the command line. Syntax is as follows: [command] option=value ...as implemented by the standard ConfigParser module. Thus, [build] build_base=blib in setup.cfg is equivalent to python setup.py build --build-base=blib except, of course, that the config file is entirely passive: no commands are run based on what's found in the config file! Error-checking is done partly by the Distribution class and partly by the individual command classes. In particular, Distribution.get_command_obj() is responsible for ensuring that config files don't contain invalid options, ie. instance attributes not set in the command's 'initialize_options()' method. The command class itself is responsible for all other error-checking -- whether the content of an option is valid, whether certain options conflict, etc. This is the same mechanism as has worked for command-line options for ages now. There is a problem, though, which is that commands don't know *where* the options they are error-checking originate. The Distribution class keeps track of that information, in the 'command_options' dictionary, but it's currently not shared with the command classes. There are a couple of ways to do this, and I'm mulling the alternatives before diving in. Until that's fixed, you may get error messages that don't tell you if the offending option value was in a config file, on the command line, or what. Annoying but not fatal. Well, that's enough for tonight. Happy hacking! Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ The real Nazis run your schools / They're coaches, businessmen and cops -- Dead Kennedys From R.Liebscher@gmx.de Tue May 23 14:41:27 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Tue, 23 May 2000 15:41:27 +0200 Subject: [Distutils] bdist and --compiler Message-ID: <392A8A87.CCA7E76B@gmx.de> I'm currently working at the Cygwin-Compiler class on Win32, there I found a problem with "bdist". When I have build all extensions with my compiler class and then try to use "bdist", the msvc compiler class starts and fails (I don't have it on my machine.) I think there are two problems. First the system seems to check the filedates with the objectfile-extensions of the standard compiler ( msvc ".obj" , cygwin ".o" ). So it doesn't find my object files, and tries to recreate them, but uses a wrong compiler. I think it should be possible to configure the compiler also for "bdist". (If this is already possible? Please explain how.) Also I think "bdist" does a "build" if there aren't already the right files. In this case "bdist" should accept *all* parameters which "build" accepts. The second problem. Why "bdist" doesn't check only the source files against the finished extension modules? Currently it seems to check the source files against the compiled object files. Then there is something else concerning the compiler option. If the user uses help he get the information that he can use the compiler option, but how can he know which compilers(classes) are available. There should be a possibility to get a list. (In ccompiler.py we have such list, we only had print it.) kind regards Rene Liebscher From thomas.heller@ion-tof.com Tue May 23 15:14:18 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Tue, 23 May 2000 16:14:18 +0200 Subject: [Distutils] bdist and --compiler References: <392A8A87.CCA7E76B@gmx.de> Message-ID: <024b01bfc4c1$2f78a070$4500a8c0@thomasnb> > I'm currently working at the Cygwin-Compiler class on Win32, > there I found a problem with "bdist". > > When I have build all extensions with my compiler class and then > try to use "bdist", the msvc compiler class starts and > fails (I don't have it on my machine.) > > I think there are two problems. > > First the system seems to check the filedates > with the objectfile-extensions of the standard compiler > ( msvc ".obj" , cygwin ".o" ). So it doesn't find my > object files, and tries to recreate them, but uses a > wrong compiler. I think it should be > possible to configure the compiler also for "bdist". > (If this is already possible? Please explain how.) > Also I think "bdist" does a "build" if there aren't > already the right files. In this case "bdist" should > accept *all* parameters which "build" accepts. You could use: setup.py bdist build_ext --compiler Cygwin In this way you can use all the options build_ext accepts. You have to be carefull with the short options: setup.py bdist build_ext -f is NOT interpreted as build_ext --force but as bdist --format Thomas From thomas.heller@ion-tof.com Tue May 23 20:51:48 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Tue, 23 May 2000 21:51:48 +0200 Subject: [Distutils] bdist broken under Windows Message-ID: <035901bfc4f0$55188a50$4500a8c0@thomasnb> The bdist command in the CVS version is broken under windows. Two problems: 1. It seems the needed directories are not created: . . . self.bdist_dir = build\bdist.win32\dumb self.format = zip changing into 'build\bdist.win32\dumb' error: build\bdist.win32\dumb: No such file or directory 2. This error occurrs only after hacking around the second problem: change_root(), which is not implemented for nt. Having said this, I cannot really understand the purpose of change_root. Finally I tried distutils under Linux, and it seems that change_root converts relative into (nearly) absolute pathnames: usr/lib/python1.5/site-packages/distutils/... This MAY make sense under unix, where python is always(?) installed in the same path, but not under windows! Thomas Heller From thomas.heller@ion-tof.com Tue May 23 21:13:13 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Tue, 23 May 2000 22:13:13 +0200 Subject: [Distutils] Thinking about a Windows Installer References: <010901bfc01b$8fedf590$4500a8c0@thomasnb> <20000520104114.E318@beelzebub> Message-ID: <037501bfc4f3$53362e60$4500a8c0@thomasnb> From: "Greg Ward" To: Sent: Saturday, May 20, 2000 4:41 PM Subject: Re: [Distutils] Thinking about a Windows Installer > On 17 May 2000, Thomas Heller said: > > I'm currently thinking about a bdist_winexe command for distutils. > > (Is there a better name?) > > How about "bdist_wininst"? OK. > > > This command will create a single executable file similar to those > > created with Wise or Installshield installers (except that you don't > > need to have these _commercial_ programs installed). > > There is some sort of informal arrangement that lets Python developers > use Wise to create installers of free Python extensions for free. I > think the same arrangement lets Guido create Python installers for free. > So we probably shouldn't toss Wise out the window just because it's > commercial; it might be a good (and zero-cost, if not entirely free) > option for Python-on-Windows developers. OK, will submit an 'bdist_wise' sometime. Or maybe 'bdist_wisescript' because it will create an xxx.wse script, which has to be compiled with Wise32.exe. (See below for more about Wise). > > > This exe-File consists of a C-program embedding python, appended > > is a zip-compatible archive of the modules to distribute, the setup.py > > script, as well as an ini-file "setup.ini" or something like that which > > contains the distribution meta-data in a format easily readable by > > the C-program. > > Whether you want to embed Python really depends on your audience. Let's > face it, installing Python on Windows is not that hard. If a programmer > wants to use some collection of modules, it's not too bad to say, > "Download and install Python, then download and install the module > distribution". Painless * 2 is not too bad. Sure. But: Windows users are (normally) not used to the command line (neither will they read the README file :-). They are used to installer executables. > For end-user applications, though, embedding a Python interpreter (and > however much of the standard library as is needed) is probably the right > thing to do. I think it should be up to the module developer/packager > to decide he distributes a "Python-less" installer or a big fat one (or > both). I did not think about end-user applications here. Is distutils headed in this direction after all? > Now, if you *do* end up writing your own installer GUI (instead of using > Wise), how much of it can be written in Python rather than C? I assume > doing this would require the presence of the Win32 extensions, so > "painless * 2" might become "painless * 3". Hmmm... I'd be reluctant to > make someone install Python *and* the Win32 stuff just to run an > installer. > > This exe-File, when run, simply unpacks the archive into a temporary > > directory, displays a nice GUI, runs the setup.py script, and cleans > > up the temp-dir. > > I think the mode of operation should be as close to the other bdist > commands as possible: distribute a pseudo-installation tree and just > copy it in place. That is, the setup script shouldn't enter into it > here, *unless* you need it to extract package meta-data. (Unless that's > put into another file when you run "bdist_wininst".) I was more thinking about a zip-selfextractor, extracting the archive into the python installation directory automatically. The GUI is/will be not more than a dialog box displaying some meta-info (name, version,...) of the installed modules. The GUI is written in C. So it is not neccessary to embed python (Maybe for compiling pyc files?) More about Wise: Wise is a full fledged windows installer. These programs handle the following and more: - Check the access rights to install the program and its utilities - Let the user select an installation directory - Create shortcuts in the start menu so that the user can start the program easily - Care about incrementing the ref-count of shared files (usually dlls) - Create file associations for program specific data files - Install accessories needed for the program: database access, device drivers, system services - Create registry entries - Create some meta data for uninstallation and install an uninstaller - Care about replacing in-use files (common under windows) Nearly all of this is not needed for python modules and extensions, and if it is, IMO it should be handled by distutils. The price to pay for this flexibility is that the overhead of an empty wise script to the final installer program is about 130 kBytes (which may be MUCH for a collection of a handfull python modules), while a zip-selfextractor can be 20 - 30 kB. Thomas From calvin@cs.uni-sb.de Tue May 23 23:04:01 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Wed, 24 May 2000 00:04:01 +0200 (CEST) Subject: [Distutils] new build_scripts patch In-Reply-To: <20000522221437.A7359@beelzebub> Message-ID: This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. Send mail to mime@docserver.cac.washington.edu for more info. --1619418364-1236589548-959119441=:876 Content-Type: TEXT/PLAIN; charset=US-ASCII Ok, the patch is against latest CVS (sourceforge). >command-line options to the Python interpreter are quite rare. Now optionally ending command-line options are preserved in the scripts. >> - install_misc is now the base class for all install commands install_misc is now removed since install_scripts and install_data both changed. No need of a common base class any more >Good that you brought this up, because I think I like the Automake way >better. Your installation directories shouldn't be constrained by your Ok, implemented a bit of Automake: the data_files elements can be filename strings (these files are copied in install_data) and tuples with a directory to install to and a filename list. Example: data_files = ['info.txt', ('man/man1', ['bubble.1', 'bobble.1'])] ... installs /usr/share/info.txt /usr/share/man/man1/{bubble.1 bobble.1} Note: if you want to provide an absolute data path instead of man/man1, the --root install option will fail. Bastian --1619418364-1236589548-959119441=:876 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="scriptsdata.patch" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Content-Disposition: attachment; filename="scriptsdata.patch" ZGlmZiAtQnVyTiAtLW1pbmltYWwgLS1leGNsdWRlPSoucHljIGRpc3R1dGls cy5vcmlnL2Rpc3R1dGlscy9jbWQucHkgZGlzdHV0aWxzLnBhdGNoZWQvZGlz dHV0aWxzL2NtZC5weQ0KLS0tIGRpc3R1dGlscy5vcmlnL2Rpc3R1dGlscy9j bWQucHkJVHVlIE1heSAyMyAyMjoyODowOCAyMDAwDQorKysgZGlzdHV0aWxz LnBhdGNoZWQvZGlzdHV0aWxzL2NtZC5weQlUdWUgTWF5IDIzIDIzOjA3OjUw IDIwMDANCkBAIC0zNDMsMzMgKzM0Myw1IEBADQogDQogIyBjbGFzcyBDb21t YW5kDQogDQotDQotY2xhc3MgaW5zdGFsbF9taXNjIChDb21tYW5kKToNCi0g ICAgIiIiQ29tbW9uIGJhc2UgY2xhc3MgZm9yIGluc3RhbGxpbmcgc29tZSBm aWxlcyBpbiBhIHN1YmRpcmVjdG9yeS4NCi0gICAgQ3VycmVudGx5IHVzZWQg YnkgaW5zdGFsbF9kYXRhIGFuZCBpbnN0YWxsX3NjcmlwdHMuDQotICAgICIi Ig0KLSAgICANCi0gICAgdXNlcl9vcHRpb25zID0gWygnaW5zdGFsbC1kaXI9 JywgJ2QnLCAiZGlyZWN0b3J5IHRvIGluc3RhbGwgdGhlIGZpbGVzIHRvIild DQotDQotICAgIGRlZiBpbml0aWFsaXplX29wdGlvbnMgKHNlbGYpOg0KLSAg ICAgICAgc2VsZi5pbnN0YWxsX2RpciA9IE5vbmUNCi0gICAgICAgIHNlbGYu b3V0ZmlsZXMgPSBbXQ0KLQ0KLSAgICBkZWYgX2luc3RhbGxfZGlyX2Zyb20g KHNlbGYsIGRpcm5hbWUpOg0KLSAgICAgICAgc2VsZi5zZXRfdW5kZWZpbmVk X29wdGlvbnMoJ2luc3RhbGwnLCAoZGlybmFtZSwgJ2luc3RhbGxfZGlyJykp DQotDQotICAgIGRlZiBfY29weV9maWxlcyAoc2VsZiwgZmlsZWxpc3QpOg0K LSAgICAgICAgc2VsZi5vdXRmaWxlcyA9IFtdDQotICAgICAgICBpZiBub3Qg ZmlsZWxpc3Q6DQotICAgICAgICAgICAgcmV0dXJuDQotICAgICAgICBzZWxm Lm1rcGF0aChzZWxmLmluc3RhbGxfZGlyKQ0KLSAgICAgICAgZm9yIGYgaW4g ZmlsZWxpc3Q6DQotICAgICAgICAgICAgc2VsZi5jb3B5X2ZpbGUoZiwgc2Vs Zi5pbnN0YWxsX2RpcikNCi0gICAgICAgICAgICBzZWxmLm91dGZpbGVzLmFw cGVuZChvcy5wYXRoLmpvaW4oc2VsZi5pbnN0YWxsX2RpciwgZikpDQotDQot ICAgIGRlZiBnZXRfb3V0cHV0cyAoc2VsZik6DQotICAgICAgICByZXR1cm4g c2VsZi5vdXRmaWxlcw0KLQ0KLQ0KIGlmIF9fbmFtZV9fID09ICJfX21haW5f XyI6DQogICAgIHByaW50ICJvayINCmRpZmYgLUJ1ck4gLS1taW5pbWFsIC0t ZXhjbHVkZT0qLnB5YyBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFu ZC9fX2luaXRfXy5weSBkaXN0dXRpbHMucGF0Y2hlZC9kaXN0dXRpbHMvY29t bWFuZC9fX2luaXRfXy5weQ0KLS0tIGRpc3R1dGlscy5vcmlnL2Rpc3R1dGls cy9jb21tYW5kL19faW5pdF9fLnB5CVNhdCBNYXkgMTMgMDM6NDg6MTUgMjAw MA0KKysrIGRpc3R1dGlscy5wYXRjaGVkL2Rpc3R1dGlscy9jb21tYW5kL19f aW5pdF9fLnB5CVR1ZSBNYXkgMjMgMjI6MzY6NDYgMjAwMA0KQEAgLTksNiAr OSw3IEBADQogICAgICAgICAgICAnYnVpbGRfcHknLA0KICAgICAgICAgICAg J2J1aWxkX2V4dCcsDQogICAgICAgICAgICAnYnVpbGRfY2xpYicsDQorICAg ICAgICAgICAnYnVpbGRfc2NyaXB0cycsDQogICAgICAgICAgICAnaW5zdGFs bCcsDQogICAgICAgICAgICAnaW5zdGFsbF9saWInLA0KICAgICAgICAgICAg J2luc3RhbGxfc2NyaXB0cycsDQpkaWZmIC1CdXJOIC0tbWluaW1hbCAtLWV4 Y2x1ZGU9Ki5weWMgZGlzdHV0aWxzLm9yaWcvZGlzdHV0aWxzL2NvbW1hbmQv YnVpbGQucHkgZGlzdHV0aWxzLnBhdGNoZWQvZGlzdHV0aWxzL2NvbW1hbmQv YnVpbGQucHkNCi0tLSBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFu ZC9idWlsZC5weQlGcmkgTWF5IDEyIDAyOjMzOjE0IDIwMDANCisrKyBkaXN0 dXRpbHMucGF0Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9idWlsZC5weQlUdWUg TWF5IDIzIDIyOjUyOjUxIDIwMDANCkBAIC0yNCw2ICsyNCw4IEBADQogICAg ICAgICAoJ2J1aWxkLWxpYj0nLCBOb25lLA0KICAgICAgICAgICJidWlsZCBk aXJlY3RvcnkgZm9yIGFsbCBkaXN0cmlidXRpb24gKGRlZmF1bHRzIHRvIGVp dGhlciAiICsNCiAgICAgICAgICAiYnVpbGQtcHVyZWxpYiBvciBidWlsZC1w bGF0bGliIiksDQorICAgICAgICAoJ2J1aWxkLXNjcmlwdHM9JywgTm9uZSwN CisgICAgICAgICAiYnVpbGQgZGlyZWN0b3J5IGZvciBzY3JpcHRzIiksDQog ICAgICAgICAoJ2J1aWxkLXRlbXA9JywgJ3QnLA0KICAgICAgICAgICJ0ZW1w b3JhcnkgYnVpbGQgZGlyZWN0b3J5IiksDQogICAgICAgICAoJ2NvbXBpbGVy PScsICdjJywNCkBAIC00Miw2ICs0NCw3IEBADQogICAgICAgICBzZWxmLmJ1 aWxkX3BsYXRsaWIgPSBOb25lDQogICAgICAgICBzZWxmLmJ1aWxkX2xpYiA9 IE5vbmUNCiAgICAgICAgIHNlbGYuYnVpbGRfdGVtcCA9IE5vbmUNCisgICAg ICAgIHNlbGYuYnVpbGRfc2NyaXB0cyA9IE5vbmUNCiAgICAgICAgIHNlbGYu Y29tcGlsZXIgPSBOb25lDQogICAgICAgICBzZWxmLmRlYnVnID0gTm9uZQ0K ICAgICAgICAgc2VsZi5mb3JjZSA9IDANCkBAIC03Niw2ICs3OSw4IEBADQog ICAgICAgICBpZiBzZWxmLmJ1aWxkX3RlbXAgaXMgTm9uZToNCiAgICAgICAg ICAgICBzZWxmLmJ1aWxkX3RlbXAgPSBvcy5wYXRoLmpvaW4gKHNlbGYuYnVp bGRfYmFzZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICd0ZW1wLicgKyBzZWxmLnBsYXQpDQorICAgICAgICBpZiBz ZWxmLmJ1aWxkX3NjcmlwdHMgaXMgTm9uZToNCisgICAgICAgICAgICBzZWxm LmJ1aWxkX3NjcmlwdHMgPSBvcy5wYXRoLmpvaW4gKHNlbGYuYnVpbGRfYmFz ZSwgJ3NjcmlwdHMnKQ0KICAgICAjIGZpbmFsaXplX29wdGlvbnMgKCkNCiAN CiANCkBAIC05OSw1ICsxMDQsOCBAQA0KICAgICAgICAgIyBpbnRvIHRoZSBi dWlsZCB0cmVlDQogICAgICAgICBpZiBzZWxmLmRpc3RyaWJ1dGlvbi5oYXNf ZXh0X21vZHVsZXMoKToNCiAgICAgICAgICAgICBzZWxmLnJ1bl9wZWVyICgn YnVpbGRfZXh0JykNCisNCisgICAgICAgIGlmIHNlbGYuZGlzdHJpYnV0aW9u LnNjcmlwdHM6DQorICAgICAgICAgICAgc2VsZi5ydW5fcGVlciAoJ2J1aWxk X3NjcmlwdHMnKQ0KIA0KICMgZW5kIGNsYXNzIEJ1aWxkDQpkaWZmIC1CdXJO IC0tbWluaW1hbCAtLWV4Y2x1ZGU9Ki5weWMgZGlzdHV0aWxzLm9yaWcvZGlz dHV0aWxzL2NvbW1hbmQvYnVpbGRfc2NyaXB0cy5weSBkaXN0dXRpbHMucGF0 Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9idWlsZF9zY3JpcHRzLnB5DQotLS0g ZGlzdHV0aWxzLm9yaWcvZGlzdHV0aWxzL2NvbW1hbmQvYnVpbGRfc2NyaXB0 cy5weQlUaHUgSmFuICAxIDAxOjAwOjAwIDE5NzANCisrKyBkaXN0dXRpbHMu cGF0Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9idWlsZF9zY3JpcHRzLnB5CVR1 ZSBNYXkgMjMgMjM6NDI6MjEgMjAwMA0KQEAgLTAsMCArMSw3MSBAQA0KKyIi ImRpc3R1dGlscy5jb21tYW5kLmJ1aWxkX3NjcmlwdHMNCisNCitJbXBsZW1l bnRzIHRoZSBEaXN0dXRpbHMgJ2J1aWxkX3NjcmlwdHMnIGNvbW1hbmQuIiIi DQorDQorIyBjcmVhdGVkIDIwMDAvMDUvMjMsIEJhc3RpYW4gS2xlaW5laWRh bQ0KKw0KK19fcmV2aXNpb25fXyA9ICIkSWQkIg0KKw0KK2ltcG9ydCBzeXMs b3MscmUNCitmcm9tIGRpc3R1dGlscy5jb3JlIGltcG9ydCBDb21tYW5kDQor DQorIyBjaGVjayBpZiBQeXRob24gaXMgY2FsbGVkIG9uIHRoZSBmaXJzdCBs aW5lIHdpdGggdGhpcyBleHByZXNzaW9uDQorZmlyc3RfbGluZV9yZSA9IHJl LmNvbXBpbGUociJeIyEuK3B5dGhvbihccy1cdyspKiIpDQorDQorY2xhc3Mg YnVpbGRfc2NyaXB0cyAoQ29tbWFuZCk6DQorDQorICAgIGRlc2NyaXB0aW9u ID0gIlwiYnVpbGRcIiBzY3JpcHRzIg0KKw0KKyAgICB1c2VyX29wdGlvbnMg PSBbDQorICAgICAgICAoJ2J1aWxkLWRpcj0nLCAnZCcsICJkaXJlY3Rvcnkg dG8gXCJidWlsZFwiIChjb3B5KSB0byIpLA0KKyAgICAgICAgKCdmb3JjZScs ICdmJywgImZvcmNpYmx5IGJ1aWxkIGV2ZXJ5dGhpbmcgKGlnbm9yZSBmaWxl IHRpbWVzdGFtcHMiKSwNCisgICAgICAgIF0NCisNCisNCisgICAgZGVmIGlu aXRpYWxpemVfb3B0aW9ucyAoc2VsZik6DQorICAgICAgICBzZWxmLmJ1aWxk X2RpciA9IE5vbmUNCisgICAgICAgIHNlbGYuc2NyaXB0cyA9IE5vbmUNCisg ICAgICAgIHNlbGYuZm9yY2UgPSBOb25lDQorICAgICAgICBzZWxmLm91dGZp bGVzID0gTm9uZQ0KKw0KKyAgICBkZWYgZmluYWxpemVfb3B0aW9ucyAoc2Vs Zik6DQorICAgICAgICBzZWxmLnNldF91bmRlZmluZWRfb3B0aW9ucyAoJ2J1 aWxkJywNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAo J2J1aWxkX3NjcmlwdHMnLCAnYnVpbGRfZGlyJyksDQorICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgKCdmb3JjZScsICdmb3JjZScpKQ0K KyAgICAgICAgc2VsZi5zY3JpcHRzID0gc2VsZi5kaXN0cmlidXRpb24uc2Ny aXB0cw0KKw0KKw0KKyAgICBkZWYgcnVuIChzZWxmKToNCisgICAgICAgIGlm IG5vdCBzZWxmLnNjcmlwdHM6DQorICAgICAgICAgICAgcmV0dXJuDQorICAg ICAgICBzZWxmLl9jb3B5X2ZpbGVzKCkNCisgICAgICAgIHNlbGYuX2FkanVz dF9maWxlcygpDQorICAgICAgICANCisgICAgZGVmIF9jb3B5X2ZpbGVzKHNl bGYpOg0KKyAgICAgICAgIiIiQ29weSBhbGwgdGhlIHNjcmlwdHMgdG8gdGhl IGJ1aWxkIGRpciIiIg0KKyAgICAgICAgc2VsZi5vdXRmaWxlcyA9IFtdDQor ICAgICAgICBzZWxmLm1rcGF0aChzZWxmLmJ1aWxkX2RpcikNCisgICAgICAg IGZvciBmIGluIHNlbGYuc2NyaXB0czoNCisgICAgICAgICAgICBwcmludCBz ZWxmLmJ1aWxkX2Rpcg0KKyAgICAgICAgICAgIGlmIHNlbGYuY29weV9maWxl KGYsIHNlbGYuYnVpbGRfZGlyKToNCisgICAgICAgICAgICAgICAgc2VsZi5v dXRmaWxlcy5hcHBlbmQob3MucGF0aC5qb2luKHNlbGYuYnVpbGRfZGlyLCBm KSkNCisgICAgICAgICAgICANCisgICAgZGVmIF9hZGp1c3RfZmlsZXMoc2Vs Zik6DQorICAgICAgICAiIiJJZiB0aGUgZmlyc3QgbGluZSBiZWdpbnMgd2l0 aCAjISBhbmQgZW5kcyB3aXRoIHB5dGhvbg0KKwkgICByZXBsYWNlIGl0IHdp dGggdGhlIGN1cnJlbnQgcHl0aG9uIGludGVycHJldGVyIiIiDQorICAgICAg ICBmb3IgZiBpbiBzZWxmLm91dGZpbGVzOg0KKyAgICAgICAgICAgIGlmIG5v dCBzZWxmLmRyeV9ydW46DQorICAgICAgICAgICAgICAgIGRhdGEgPSBvcGVu KGYsICJyIikucmVhZGxpbmVzKCkNCisgICAgICAgICAgICAgICAgaWYgbm90 IGRhdGE6DQorICAgICAgICAgICAgICAgICAgICBzZWxmLndhcm4oIiVzIGlz IGFuIGVtcHR5IGZpbGUhIiAlIGYpDQorICAgICAgICAgICAgICAgICAgICBj b250aW51ZQ0KKyAgICAgICAgICAgICAgICBtbyA9IGZpcnN0X2xpbmVfcmUu bWF0Y2goZGF0YVswXSkNCisgICAgICAgICAgICAgICAgaWYgbW86DQorICAg ICAgICAgICAgICAgICAgICBzZWxmLmFubm91bmNlKCJBZGp1c3RpbmcgZmly c3QgbGluZSBvZiBmaWxlICVzIiAlIGYpDQorICAgICAgICAgICAgICAgICAg ICBkYXRhWzBdID0gIiMhIitzeXMuZXhlY3V0YWJsZQ0KKyAgICAgICAgICAg ICAgICAgICAgIyBhZGQgb3B0aW9uYWwgY29tbWFuZCBsaW5lIG9wdGlvbnMN CisgICAgICAgICAgICAgICAgICAgIGlmIG1vLmdyb3VwKDEpOg0KKyAgICAg ICAgICAgICAgICAgICAgICAgIGRhdGFbMF0gPSBkYXRhWzBdICsgbW8uZ3Jv dXAoMSkNCisgICAgICAgICAgICAgICAgICAgIGVsc2U6DQorICAgICAgICAg ICAgICAgICAgICAgICAgZGF0YVswXSA9IGRhdGFbMF0gKyAiXG4iDQorICAg ICAgICAgICAgICAgICAgICBvcGVuKGYsICJ3Iikud3JpdGVsaW5lcyhkYXRh KQ0KZGlmZiAtQnVyTiAtLW1pbmltYWwgLS1leGNsdWRlPSoucHljIGRpc3R1 dGlscy5vcmlnL2Rpc3R1dGlscy9jb21tYW5kL2luc3RhbGxfZGF0YS5weSBk aXN0dXRpbHMucGF0Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9pbnN0YWxsX2Rh dGEucHkNCi0tLSBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFuZC9p bnN0YWxsX2RhdGEucHkJU2F0IE1heSAxMyAwNTowOTo1MCAyMDAwDQorKysg ZGlzdHV0aWxzLnBhdGNoZWQvZGlzdHV0aWxzL2NvbW1hbmQvaW5zdGFsbF9k YXRhLnB5CVR1ZSBNYXkgMjMgMjM6MzE6MzYgMjAwMA0KQEAgLTcsMTcgKzcs NDAgQEANCiANCiBfX3JldmlzaW9uX18gPSAiJElkOiBpbnN0YWxsX2RhdGEu cHksdiAxLjUgMjAwMC8wNS8xMyAwMzowOTo1MCBncmVnIEV4cCAkIg0KIA0K LWZyb20gZGlzdHV0aWxzLmNtZCBpbXBvcnQgaW5zdGFsbF9taXNjDQoraW1w b3J0IG9zDQorZnJvbSB0eXBlcyBpbXBvcnQgU3RyaW5nVHlwZQ0KK2Zyb20g ZGlzdHV0aWxzLmNvcmUgaW1wb3J0IENvbW1hbmQNCiANCi1jbGFzcyBpbnN0 YWxsX2RhdGEgKGluc3RhbGxfbWlzYyk6DQorY2xhc3MgaW5zdGFsbF9kYXRh IChDb21tYW5kKToNCiANCiAgICAgZGVzY3JpcHRpb24gPSAiaW5zdGFsbCBk YXRhIGZpbGVzIg0KIA0KKyAgICB1c2VyX29wdGlvbnMgPSBbKCdpbnN0YWxs LWRpcj0nLCAnZCcsDQorICAgICAgICAgICAgICAgICAgICAgImRpcmVjdG9y eSB0byBpbnN0YWxsIHRoZSBmaWxlcyB0byIpXQ0KKw0KKyAgICBkZWYgaW5p dGlhbGl6ZV9vcHRpb25zIChzZWxmKToNCisgICAgICAgIHNlbGYuaW5zdGFs bF9kaXIgPSBOb25lDQorICAgICAgICBzZWxmLm91dGZpbGVzID0gTm9uZQ0K KyAgICAgICAgc2VsZi5kYXRhX2ZpbGVzID0gc2VsZi5kaXN0cmlidXRpb24u ZGF0YV9maWxlcw0KKw0KICAgICBkZWYgZmluYWxpemVfb3B0aW9ucyAoc2Vs Zik6DQotICAgICAgICBzZWxmLl9pbnN0YWxsX2Rpcl9mcm9tKCdpbnN0YWxs X2RhdGEnKQ0KKyAgICAgICAgc2VsZi5zZXRfdW5kZWZpbmVkX29wdGlvbnMo J2luc3RhbGwnLCAoJ2luc3RhbGxfZGF0YScsICdpbnN0YWxsX2RpcicpKQ0K IA0KICAgICBkZWYgcnVuIChzZWxmKToNCi0gICAgICAgIHNlbGYuX2NvcHlf ZmlsZXMoc2VsZi5kaXN0cmlidXRpb24uZGF0YV9maWxlcykNCisgICAgICAg IHNlbGYubWtwYXRoKHNlbGYuaW5zdGFsbF9kaXIpDQorICAgICAgICBmb3Ig ZiBpbiBzZWxmLmRhdGFfZmlsZXM6DQorICAgICAgICAgICAgaWYgdHlwZShm KSA9PSBTdHJpbmdUeXBlOg0KKyAgICAgICAgICAgICAgICAjIGl0cyBhIHNp bXBsZSBmaWxlLCBzbyBjb3B5IGl0DQorICAgICAgICAgICAgICAgIHNlbGYu Y29weV9maWxlKGYsIHNlbGYuaW5zdGFsbF9kaXIpDQorICAgICAgICAgICAg ZWxzZToNCisgICAgICAgICAgICAgICAgIyBpdHMgYSB0dXBsZSB3aXRoIHBh dGggdG8gaW5zdGFsbCB0byBhbmQgYSBsaXN0IG9mIGZpbGVzDQorICAgICAg ICAgICAgICAgIGRpciA9IG9zLnBhdGguam9pbihzZWxmLmluc3RhbGxfZGly LCBmWzBdKQ0KKyAgICAgICAgICAgICAgICBzZWxmLm1rcGF0aChkaXIpDQor ICAgICAgICAgICAgICAgIGZvciBkYXRhIGluIGZbMV06DQorICAgICAgICAg ICAgICAgICAgICBzZWxmLmNvcHlfZmlsZShkYXRhLCBkaXIpDQogDQogICAg IGRlZiBnZXRfaW5wdXRzIChzZWxmKToNCi0gICAgICAgIHJldHVybiBzZWxm LmRpc3RyaWJ1dGlvbi5kYXRhX2ZpbGVzIG9yIFtdDQorICAgICAgICByZXR1 cm4gc2VsZi5kYXRhX2ZpbGVzIG9yIFtdDQorDQorICAgIGRlZiBnZXRfb3V0 cHV0cyAoc2VsZik6DQorICAgICAgICByZXR1cm4gc2VsZi5vdXRmaWxlcw0K ZGlmZiAtQnVyTiAtLW1pbmltYWwgLS1leGNsdWRlPSoucHljIGRpc3R1dGls cy5vcmlnL2Rpc3R1dGlscy9jb21tYW5kL2luc3RhbGxfc2NyaXB0cy5weSBk aXN0dXRpbHMucGF0Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9pbnN0YWxsX3Nj cmlwdHMucHkNCi0tLSBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFu ZC9pbnN0YWxsX3NjcmlwdHMucHkJU2F0IE1heSAxMyAwNTowNzo1MyAyMDAw DQorKysgZGlzdHV0aWxzLnBhdGNoZWQvZGlzdHV0aWxzL2NvbW1hbmQvaW5z dGFsbF9zY3JpcHRzLnB5CVR1ZSBNYXkgMjMgMjM6MjU6MDIgMjAwMA0KQEAg LTgsMjMgKzgsMzkgQEANCiBfX3JldmlzaW9uX18gPSAiJElkOiBpbnN0YWxs X3NjcmlwdHMucHksdiAxLjQgMjAwMC8wNS8xMyAwMzowNzo1MyBncmVnIEV4 cCAkIg0KIA0KIGltcG9ydCBvcw0KLWZyb20gZGlzdHV0aWxzLmNtZCBpbXBv cnQgaW5zdGFsbF9taXNjDQorZnJvbSBkaXN0dXRpbHMuY29yZSBpbXBvcnQg Q29tbWFuZA0KIGZyb20gc3RhdCBpbXBvcnQgU1RfTU9ERQ0KIA0KLWNsYXNz IGluc3RhbGxfc2NyaXB0cyhpbnN0YWxsX21pc2MpOg0KK2NsYXNzIGluc3Rh bGxfc2NyaXB0cyhDb21tYW5kKToNCiANCiAgICAgZGVzY3JpcHRpb24gPSAi aW5zdGFsbCBzY3JpcHRzIg0KIA0KKyAgICB1c2VyX29wdGlvbnMgPSBbDQor ICAgICAgICAoJ2luc3RhbGwtZGlyPScsICdkJywgImRpcmVjdG9yeSB0byBp bnN0YWxsIHRvIiksDQorICAgICAgICAoJ2J1aWxkLWRpcj0nLCdiJywgImJ1 aWxkIGRpcmVjdG9yeSAod2hlcmUgdG8gaW5zdGFsbCBmcm9tKSIpLA0KKyAg ICAgICAgKCdza2lwLWJ1aWxkJywgTm9uZSwgInNraXAgdGhlIGJ1aWxkIHN0 ZXBzIiksDQorICAgIF0NCisNCisgICAgZGVmIGluaXRpYWxpemVfb3B0aW9u cyAoc2VsZik6DQorICAgICAgICBzZWxmLmluc3RhbGxfZGlyID0gTm9uZQ0K KyAgICAgICAgc2VsZi5idWlsZF9kaXIgPSBOb25lDQorICAgICAgICBzZWxm LnNraXBfYnVpbGQgPSBOb25lDQorDQogICAgIGRlZiBmaW5hbGl6ZV9vcHRp b25zIChzZWxmKToNCi0gICAgICAgIHNlbGYuX2luc3RhbGxfZGlyX2Zyb20o J2luc3RhbGxfc2NyaXB0cycpDQorICAgICAgICBzZWxmLnNldF91bmRlZmlu ZWRfb3B0aW9ucygnYnVpbGQnLCAoJ2J1aWxkX3NjcmlwdHMnLCAnYnVpbGRf ZGlyJykpDQorICAgICAgICBzZWxmLnNldF91bmRlZmluZWRfb3B0aW9ucyAo J2luc3RhbGwnLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICgnaW5zdGFsbF9zY3JpcHRzJywgJ2luc3RhbGxfZGlyJyksDQorICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCdza2lwX2J1aWxk JywgJ3NraXBfYnVpbGQnKSwNCisgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICkNCiANCiAgICAgZGVmIHJ1biAoc2VsZik6DQotICAgICAg ICBzZWxmLl9jb3B5X2ZpbGVzKHNlbGYuZGlzdHJpYnV0aW9uLnNjcmlwdHMp DQorICAgICAgICBpZiBub3Qgc2VsZi5za2lwX2J1aWxkOg0KKyAgICAgICAg ICAgIHNlbGYucnVuX3BlZXIoJ2J1aWxkX3NjcmlwdHMnKQ0KKyAgICAgICAg c2VsZi5vdXRmaWxlcyA9IHNlbGYuY29weV90cmVlIChzZWxmLmJ1aWxkX2Rp ciwgc2VsZi5pbnN0YWxsX2RpcikNCiAgICAgICAgIGlmIG9zLm5hbWUgPT0g J3Bvc2l4JzoNCiAgICAgICAgICAgICAjIFNldCB0aGUgZXhlY3V0YWJsZSBi aXRzIChvd25lciwgZ3JvdXAsIGFuZCB3b3JsZCkgb24NCiAgICAgICAgICAg ICAjIGFsbCB0aGUgc2NyaXB0cyB3ZSBqdXN0IGluc3RhbGxlZC4NCi0gICAg ICAgICAgICBmaWxlcyA9IHNlbGYuZ2V0X291dHB1dHMoKQ0KLSAgICAgICAg ICAgIGZvciBmaWxlIGluIGZpbGVzOg0KKyAgICAgICAgICAgIGZvciBmaWxl IGluIHNlbGYuZ2V0X291dHB1dHMoKToNCiAgICAgICAgICAgICAgICAgaWYg c2VsZi5kcnlfcnVuOg0KICAgICAgICAgICAgICAgICAgICAgc2VsZi5hbm5v dW5jZSgiY2hhbmdpbmcgbW9kZSBvZiAlcyIgJSBmaWxlKQ0KICAgICAgICAg ICAgICAgICBlbHNlOg0KQEAgLTM0LDUgKzUwLDggQEANCiANCiAgICAgZGVm IGdldF9pbnB1dHMgKHNlbGYpOg0KICAgICAgICAgcmV0dXJuIHNlbGYuZGlz dHJpYnV0aW9uLnNjcmlwdHMgb3IgW10NCisNCisgICAgZGVmIGdldF9vdXRw dXRzKHNlbGYpOg0KKyAgICAgICAgcmV0dXJuIHNlbGYub3V0ZmlsZXMgb3Ig W10NCiANCiAjIGNsYXNzIGluc3RhbGxfc2NyaXB0cw0K --1619418364-1236589548-959119441=:876-- From gward@python.net Wed May 24 03:54:52 2000 From: gward@python.net (Greg Ward) Date: Tue, 23 May 2000 22:54:52 -0400 Subject: [Distutils] bdist and --compiler In-Reply-To: <024b01bfc4c1$2f78a070$4500a8c0@thomasnb>; from Thomas Heller on Tue, May 23, 2000 at 04:14:18PM +0200 References: <392A8A87.CCA7E76B@gmx.de> <024b01bfc4c1$2f78a070$4500a8c0@thomasnb> Message-ID: <20000523225452.A506@beelzebub> On 23 May 2000, Thomas Heller said: > You could use: > setup.py bdist build_ext --compiler Cygwin Careful -- if you're using code earlier than last night, I think "build_ext" should come first. That particular bit of bogosity should be fixed with the config file changes, though. One more reason to be following the CVS tree. (Whaddya mean, time for a new release? ;-) > You have to be carefull with the short options: > setup.py bdist build_ext -f > is NOT interpreted as > build_ext --force > but as > bdist --format That's a feature. I think. ;-) Greg -- Greg Ward - "always the quiet one" gward@python.net http://starship.python.net/~gward/ Could I have a drug overdose? From gward@python.net Wed May 24 04:02:01 2000 From: gward@python.net (Greg Ward) Date: Tue, 23 May 2000 23:02:01 -0400 Subject: [Distutils] bdist and --compiler In-Reply-To: <392A8A87.CCA7E76B@gmx.de>; from Rene Liebscher on Tue, May 23, 2000 at 03:41:27PM +0200 References: <392A8A87.CCA7E76B@gmx.de> Message-ID: <20000523230201.B506@beelzebub> On 23 May 2000, Rene Liebscher said: > First the system seems to check the filedates > with the objectfile-extensions of the standard compiler > ( msvc ".obj" , cygwin ".o" ). So it doesn't find my > object files, and tries to recreate them, but uses a > wrong compiler. I think it should be > possible to configure the compiler also for "bdist". See Thomas' reply, and my reply to him, for one way of doing it. > (If this is already possible? Please explain how.) > Also I think "bdist" does a "build" if there aren't > already the right files. In this case "bdist" should > accept *all* parameters which "build" accepts. The trouble with that is that lots of commands run other commands. Currently there's very little formal notion of "sub-commands" -- if command X wants to replicate an option from command Y, it has to be done manually. This is deliberate design minimalism; the idea is to keep each command's scope under control. Of course, that leads to awkward command lines. Hence, config files. If you're running last night's code ("cvs update" -- it's your friend!), try this: create "/pydistutils.cfg" (on Windows and Mac OS -- it's different for Unix) and put the following in it [build_ext] compiler=cygwin and then you never have to worry about specifying the compiler again: it's a system default. Of course, be sure to read all the debugging output that is deliberately still in the code: I want everyone to share the pain! > The second problem. Why "bdist" doesn't check only the > source files against the finished extension modules? > Currently it seems to check the source files against > the compiled object files. Good point, I think. I'm trying *not* to emulate everything you'd do in a real Makefile, since Distutils != make. But this could be a useful addition, if I understand what you're saying -- I'll have to think about it. (Hint: working patches are an excellent way to prod me into thinking about something. They also clarify wonderfully what exactly you're talking about.) > Then there is something else concerning the compiler > option. > If the user uses help he get the information that he > can use the compiler option, but how can he know > which compilers(classes) are available. There should be > a possibility to get a list. (In ccompiler.py we have > such list, we only had print it.) That's definitely a good idea. Wasn't such a big deal in the "old days", when we only had UnixCCompiler and MSVCCompiler. Those days appear numbered, though... How does a "--help-compilers" global option sound? (Kind of on the same level as "--help-commands".) It's a bit klugey, but I can't think of a better option offhand. Greg -- Greg Ward - programmer-at-large gward@python.net http://starship.python.net/~gward/ Heisenberg may have slept here. From gward@python.net Wed May 24 04:05:19 2000 From: gward@python.net (Greg Ward) Date: Tue, 23 May 2000 23:05:19 -0400 Subject: [Distutils] new build_scripts patch In-Reply-To: ; from Bastian Kleineidam on Wed, May 24, 2000 at 12:04:01AM +0200 References: <20000522221437.A7359@beelzebub> Message-ID: <20000523230519.C506@beelzebub> On 24 May 2000, Bastian Kleineidam said: > >> - install_misc is now the base class for all install commands > install_misc is now removed since install_scripts and install_data both > changed. No need of a common base class any more Whoops, you may have gone too far! (Or maybe not: I haven't looked at the patch yet, this is just an off-the-cuff reply.) One more "simple" install command definitely needs to be added: "install_headers", which would put C header files into /python1.x/include/. This is essential for NumPy, PIL, CXX, and any other Python/C/C++ packages that are used by *other* extensions. I suspect "install_headers" would have a lot in common with "install_data". Can you resubmit your patch with install_misc intact, but loudly commented as "currently unused" so I don't forget about it? Thanks -- Greg -- Greg Ward - programmer-at-large gward@python.net http://starship.python.net/~gward/ God is omnipotent, omniscient, and omnibenevolent ---it says so right here on the label. From gward@python.net Wed May 24 04:10:50 2000 From: gward@python.net (Greg Ward) Date: Tue, 23 May 2000 23:10:50 -0400 Subject: [Distutils] bdist broken under Windows In-Reply-To: <035901bfc4f0$55188a50$4500a8c0@thomasnb>; from Thomas Heller on Tue, May 23, 2000 at 09:51:48PM +0200 References: <035901bfc4f0$55188a50$4500a8c0@thomasnb> Message-ID: <20000523231050.D506@beelzebub> On 23 May 2000, Thomas Heller said: > The bdist command in the CVS version is broken under windows. > > 1. It seems the needed directories are not created: Hmm, that shouldn't be too hard to fix... but I wonder why it's not happening? Arg... > 2. This error occurrs only after hacking around the second problem: > change_root(), which is not implemented for nt. > > Having said this, I cannot really understand the purpose of change_root. > > Finally I tried distutils under Linux, and it seems that > change_root converts relative into (nearly) absolute pathnames: > usr/lib/python1.5/site-packages/distutils/... > > This MAY make sense under unix, where python is always(?) installed > in the same path, but not under windows! Python is most certainly *not* always installed in the same place on Unix! The purpose of 'change_root()' is to change (eg.) "/usr/lib/python1.5/site-package/distutils" (where the "install" command would normally install the distutils on a Red Hat system) to "build/bdist.linux2-i586/dumb/usr/lib/python1.5/site-packages/distutils" (where it gets installed to create a "dumb" built distribution -- we cd to "build/bdist.linux2-i586/dumb" and then create a tarball or zip file which is meant to be unpacked from the root directory). Make sense? Hope so -- I'm zonked and have to hit the sack. Damn... another night of just dealing with email, no time to code... Greg -- Greg Ward - just another Python hacker gward@python.net http://starship.python.net/~gward/ No man is an island, but some of us are long peninsulas. From fdrake@acm.org Wed May 24 04:13:48 2000 From: fdrake@acm.org (Fred L. Drake) Date: Tue, 23 May 2000 20:13:48 -0700 (PDT) Subject: [Distutils] bdist and --compiler In-Reply-To: <20000523230201.B506@beelzebub> Message-ID: On Tue, 23 May 2000, Greg Ward wrote: > try this: create "/pydistutils.cfg" (on Windows and Mac OS -- > it's different for Unix) and put the following in it > > [build_ext] > compiler=cygwin As Python grows support for additional compilers, the Python installation should set this up with the proper compiler information. The admin can change the file after installation if necessary. -Fred -- Fred L. Drake, Jr. From andrew.macintyre@aba.gov.au Wed May 24 15:28:36 2000 From: andrew.macintyre@aba.gov.au (andrew.macintyre@aba.gov.au) Date: Wed, 24 May 2000 14:28:36 AES Subject: [Distutils] handling complex link/library specifications Message-ID: In the process of creating a Python module for a commercial package, I have built a Distutils package for it (using Distutils-0.8.2). Unfortunately, the commercial package I'm dealing with has a long list of libraries required to be linked, with several specified static and the rest dynamic. The recommended library spec (for Solaris, which is what I'm working with at the moment) looks something like this: -l ... -l -Bstatic -l... -l -Bdynamic -l...-l -R My setup.py (built from the distutils template) has all the libraries listed in a 'libraries' record against the module, and things appear to link OK as is though I'm still chasing down a couple of things which might turn out to be related to the static/dynamic stuff above. I tried looking in the documentation, but the bits that might answer my question haven't been written yet :-( What would be the recommended way to deal with this, if Distutils in its current form can handle this situation? (BTW http://www.python.org/sigs/distutils-sig/doc/dist/source-dist.html has an HTML problem, at least with IE 3.02) ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 From hgebel@inet.net Wed May 24 07:21:05 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Wed, 24 May 2000 02:21:05 -0400 Subject: [Distutils] handling complex link/library specifications In-Reply-To: ; from andrew.macintyre@aba.gov.au on Wed, May 24, 2000 at 02:28:36PM +0000 References: Message-ID: <20000524022105.E20880@inet.net> On Wed, May 24, 2000 at 02:28:36PM +0000, Andrew MacIntyre wrote: > Unfortunately, the commercial package I'm dealing with has a long list of > libraries required to be linked, with several specified static and the rest > dynamic. > > The recommended library spec (for Solaris, which is what I'm working with at > the moment) looks something like this: > > -l ... -l -Bstatic -l... -l -Bdynamic -l...-l > -R > > What would be the recommended way to deal with this, if Distutils in its > current form can handle this situation? The CVS version (I think you have to get it from SourceForge) should except the CFLAGS environment variable, I don't know if this will help you or not. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware From hgebel@inet.net Wed May 24 07:55:59 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Wed, 24 May 2000 02:55:59 -0400 Subject: [Distutils] handling complex link/library specifications In-Reply-To: <20000524022105.E20880@inet.net>; from hgebel@inet.net on Wed, May 24, 2000 at 02:21:05AM -0400 References: <20000524022105.E20880@inet.net> Message-ID: <20000524025559.F20880@inet.net> On Wed, May 24, 2000 at 02:21:05AM -0400, Harry Henry Gebel wrote: > The CVS version (I think you have to get it from SourceForge) should except That should have been accept, not except. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware From calvin@cs.uni-sb.de Wed May 24 09:49:12 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Wed, 24 May 2000 10:49:12 +0200 (CEST) Subject: [Distutils] another build_scripts patch In-Reply-To: <20000522221437.A7359@beelzebub> Message-ID: This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. Send mail to mime@docserver.cac.washington.edu for more info. --1619418364-364033880-959158152=:14230 Content-Type: TEXT/PLAIN; charset=US-ASCII Next try with the build_scripts patch. Again the changes: - build command additionally calls build_scripts - build_scripts builds your scripts in 'build/scripts' and adjusts the first line if it begins with "#!" and ends with "python", optionally ending with commandline options (like -O, -t ...). Adjusting means we write the current path to the Python interpreter in the first line. - install_misc class is commented out because its not needed any more - install_scripts copies the scripts to the install_scripts dir - install_data copies your data_files in install_data. You can supply individual directories for your data_files: data_files = ['doc/info.txt', # copy this file in install_scripts dir ('testdata', ['a.dat', 'b.dat']), # copy these files in # install_scripts/testdata ('/etc', ['packagerc']), # copy this in /etc. When --root is # given, copy this in rootdir/etc ] So you can use the --root option with absolute data paths. Bastian --1619418364-364033880-959158152=:14230 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="build_scripts.diff" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Content-Disposition: attachment; filename="build_scripts.diff" ZGlmZiAtQnVyTiAtLW1pbmltYWwgLS1leGNsdWRlPSoucHljIGRpc3R1dGls cy5vcmlnL2Rpc3R1dGlscy9jb21tYW5kL19faW5pdF9fLnB5IGRpc3R1dGls cy5wYXRjaGVkL2Rpc3R1dGlscy9jb21tYW5kL19faW5pdF9fLnB5DQotLS0g ZGlzdHV0aWxzLm9yaWcvZGlzdHV0aWxzL2NvbW1hbmQvX19pbml0X18ucHkJ U2F0IE1heSAxMyAwMzo0ODoxNSAyMDAwDQorKysgZGlzdHV0aWxzLnBhdGNo ZWQvZGlzdHV0aWxzL2NvbW1hbmQvX19pbml0X18ucHkJV2VkIE1heSAyNCAx MDoxMTo1NCAyMDAwDQpAQCAtOSw2ICs5LDcgQEANCiAgICAgICAgICAgICdi dWlsZF9weScsDQogICAgICAgICAgICAnYnVpbGRfZXh0JywNCiAgICAgICAg ICAgICdidWlsZF9jbGliJywNCisgICAgICAgICAgICdidWlsZF9zY3JpcHRz JywNCiAgICAgICAgICAgICdpbnN0YWxsJywNCiAgICAgICAgICAgICdpbnN0 YWxsX2xpYicsDQogICAgICAgICAgICAnaW5zdGFsbF9zY3JpcHRzJywNCmRp ZmYgLUJ1ck4gLS1taW5pbWFsIC0tZXhjbHVkZT0qLnB5YyBkaXN0dXRpbHMu b3JpZy9kaXN0dXRpbHMvY29tbWFuZC9idWlsZC5weSBkaXN0dXRpbHMucGF0 Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9idWlsZC5weQ0KLS0tIGRpc3R1dGls cy5vcmlnL2Rpc3R1dGlscy9jb21tYW5kL2J1aWxkLnB5CUZyaSBNYXkgMTIg MDI6MzM6MTQgMjAwMA0KKysrIGRpc3R1dGlscy5wYXRjaGVkL2Rpc3R1dGls cy9jb21tYW5kL2J1aWxkLnB5CVdlZCBNYXkgMjQgMTA6MTE6MDkgMjAwMA0K QEAgLTI0LDYgKzI0LDggQEANCiAgICAgICAgICgnYnVpbGQtbGliPScsIE5v bmUsDQogICAgICAgICAgImJ1aWxkIGRpcmVjdG9yeSBmb3IgYWxsIGRpc3Ry aWJ1dGlvbiAoZGVmYXVsdHMgdG8gZWl0aGVyICIgKw0KICAgICAgICAgICJi dWlsZC1wdXJlbGliIG9yIGJ1aWxkLXBsYXRsaWIiKSwNCisgICAgICAgICgn YnVpbGQtc2NyaXB0cz0nLCBOb25lLA0KKyAgICAgICAgICJidWlsZCBkaXJl Y3RvcnkgZm9yIHNjcmlwdHMiKSwNCiAgICAgICAgICgnYnVpbGQtdGVtcD0n LCAndCcsDQogICAgICAgICAgInRlbXBvcmFyeSBidWlsZCBkaXJlY3Rvcnki KSwNCiAgICAgICAgICgnY29tcGlsZXI9JywgJ2MnLA0KQEAgLTQyLDYgKzQ0 LDcgQEANCiAgICAgICAgIHNlbGYuYnVpbGRfcGxhdGxpYiA9IE5vbmUNCiAg ICAgICAgIHNlbGYuYnVpbGRfbGliID0gTm9uZQ0KICAgICAgICAgc2VsZi5i dWlsZF90ZW1wID0gTm9uZQ0KKyAgICAgICAgc2VsZi5idWlsZF9zY3JpcHRz ID0gTm9uZQ0KICAgICAgICAgc2VsZi5jb21waWxlciA9IE5vbmUNCiAgICAg ICAgIHNlbGYuZGVidWcgPSBOb25lDQogICAgICAgICBzZWxmLmZvcmNlID0g MA0KQEAgLTc2LDYgKzc5LDggQEANCiAgICAgICAgIGlmIHNlbGYuYnVpbGRf dGVtcCBpcyBOb25lOg0KICAgICAgICAgICAgIHNlbGYuYnVpbGRfdGVtcCA9 IG9zLnBhdGguam9pbiAoc2VsZi5idWlsZF9iYXNlLA0KICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RlbXAuJyArIHNl bGYucGxhdCkNCisgICAgICAgIGlmIHNlbGYuYnVpbGRfc2NyaXB0cyBpcyBO b25lOg0KKyAgICAgICAgICAgIHNlbGYuYnVpbGRfc2NyaXB0cyA9IG9zLnBh dGguam9pbiAoc2VsZi5idWlsZF9iYXNlLCAnc2NyaXB0cycpDQogICAgICMg ZmluYWxpemVfb3B0aW9ucyAoKQ0KIA0KIA0KQEAgLTk5LDUgKzEwNCw4IEBA DQogICAgICAgICAjIGludG8gdGhlIGJ1aWxkIHRyZWUNCiAgICAgICAgIGlm IHNlbGYuZGlzdHJpYnV0aW9uLmhhc19leHRfbW9kdWxlcygpOg0KICAgICAg ICAgICAgIHNlbGYucnVuX3BlZXIgKCdidWlsZF9leHQnKQ0KKw0KKyAgICAg ICAgaWYgc2VsZi5kaXN0cmlidXRpb24uc2NyaXB0czoNCisgICAgICAgICAg ICBzZWxmLnJ1bl9wZWVyICgnYnVpbGRfc2NyaXB0cycpDQogDQogIyBlbmQg Y2xhc3MgQnVpbGQNCmRpZmYgLUJ1ck4gLS1taW5pbWFsIC0tZXhjbHVkZT0q LnB5YyBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFuZC9idWlsZF9z Y3JpcHRzLnB5IGRpc3R1dGlscy5wYXRjaGVkL2Rpc3R1dGlscy9jb21tYW5k L2J1aWxkX3NjcmlwdHMucHkNCi0tLSBkaXN0dXRpbHMub3JpZy9kaXN0dXRp bHMvY29tbWFuZC9idWlsZF9zY3JpcHRzLnB5CVRodSBKYW4gIDEgMDE6MDA6 MDAgMTk3MA0KKysrIGRpc3R1dGlscy5wYXRjaGVkL2Rpc3R1dGlscy9jb21t YW5kL2J1aWxkX3NjcmlwdHMucHkJV2VkIE1heSAyNCAxMDoxMDowNiAyMDAw DQpAQCAtMCwwICsxLDcxIEBADQorIiIiZGlzdHV0aWxzLmNvbW1hbmQuYnVp bGRfc2NyaXB0cw0KKw0KK0ltcGxlbWVudHMgdGhlIERpc3R1dGlscyAnYnVp bGRfc2NyaXB0cycgY29tbWFuZC4iIiINCisNCisjIGNyZWF0ZWQgMjAwMC8w NS8yMywgQmFzdGlhbiBLbGVpbmVpZGFtDQorDQorX19yZXZpc2lvbl9fID0g IiRJZCQiDQorDQoraW1wb3J0IHN5cyxvcyxyZQ0KK2Zyb20gZGlzdHV0aWxz LmNvcmUgaW1wb3J0IENvbW1hbmQNCisNCisjIGNoZWNrIGlmIFB5dGhvbiBp cyBjYWxsZWQgb24gdGhlIGZpcnN0IGxpbmUgd2l0aCB0aGlzIGV4cHJlc3Np b24NCitmaXJzdF9saW5lX3JlID0gcmUuY29tcGlsZShyIl4jIS4rcHl0aG9u KFxzLVx3KykqIikNCisNCitjbGFzcyBidWlsZF9zY3JpcHRzIChDb21tYW5k KToNCisNCisgICAgZGVzY3JpcHRpb24gPSAiXCJidWlsZFwiIHNjcmlwdHMi DQorDQorICAgIHVzZXJfb3B0aW9ucyA9IFsNCisgICAgICAgICgnYnVpbGQt ZGlyPScsICdkJywgImRpcmVjdG9yeSB0byBcImJ1aWxkXCIgKGNvcHkpIHRv IiksDQorICAgICAgICAoJ2ZvcmNlJywgJ2YnLCAiZm9yY2libHkgYnVpbGQg ZXZlcnl0aGluZyAoaWdub3JlIGZpbGUgdGltZXN0YW1wcyIpLA0KKyAgICAg ICAgXQ0KKw0KKw0KKyAgICBkZWYgaW5pdGlhbGl6ZV9vcHRpb25zIChzZWxm KToNCisgICAgICAgIHNlbGYuYnVpbGRfZGlyID0gTm9uZQ0KKyAgICAgICAg c2VsZi5zY3JpcHRzID0gTm9uZQ0KKyAgICAgICAgc2VsZi5mb3JjZSA9IE5v bmUNCisgICAgICAgIHNlbGYub3V0ZmlsZXMgPSBOb25lDQorDQorICAgIGRl ZiBmaW5hbGl6ZV9vcHRpb25zIChzZWxmKToNCisgICAgICAgIHNlbGYuc2V0 X3VuZGVmaW5lZF9vcHRpb25zICgnYnVpbGQnLA0KKyAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICgnYnVpbGRfc2NyaXB0cycsICdidWls ZF9kaXInKSwNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAoJ2ZvcmNlJywgJ2ZvcmNlJykpDQorICAgICAgICBzZWxmLnNjcmlwdHMg PSBzZWxmLmRpc3RyaWJ1dGlvbi5zY3JpcHRzDQorDQorDQorICAgIGRlZiBy dW4gKHNlbGYpOg0KKyAgICAgICAgaWYgbm90IHNlbGYuc2NyaXB0czoNCisg ICAgICAgICAgICByZXR1cm4NCisgICAgICAgIHNlbGYuX2NvcHlfZmlsZXMo KQ0KKyAgICAgICAgc2VsZi5fYWRqdXN0X2ZpbGVzKCkNCisgICAgICAgIA0K KyAgICBkZWYgX2NvcHlfZmlsZXMoc2VsZik6DQorICAgICAgICAiIiJDb3B5 IGFsbCB0aGUgc2NyaXB0cyB0byB0aGUgYnVpbGQgZGlyIiIiDQorICAgICAg ICBzZWxmLm91dGZpbGVzID0gW10NCisgICAgICAgIHNlbGYubWtwYXRoKHNl bGYuYnVpbGRfZGlyKQ0KKyAgICAgICAgZm9yIGYgaW4gc2VsZi5zY3JpcHRz Og0KKyAgICAgICAgICAgIHByaW50IHNlbGYuYnVpbGRfZGlyDQorICAgICAg ICAgICAgaWYgc2VsZi5jb3B5X2ZpbGUoZiwgc2VsZi5idWlsZF9kaXIpOg0K KyAgICAgICAgICAgICAgICBzZWxmLm91dGZpbGVzLmFwcGVuZChvcy5wYXRo LmpvaW4oc2VsZi5idWlsZF9kaXIsIGYpKQ0KKyAgICAgICAgICAgIA0KKyAg ICBkZWYgX2FkanVzdF9maWxlcyhzZWxmKToNCisgICAgICAgICIiIklmIHRo ZSBmaXJzdCBsaW5lIGJlZ2lucyB3aXRoICMhIGFuZCBlbmRzIHdpdGggcHl0 aG9uDQorCSAgIHJlcGxhY2UgaXQgd2l0aCB0aGUgY3VycmVudCBweXRob24g aW50ZXJwcmV0ZXIiIiINCisgICAgICAgIGZvciBmIGluIHNlbGYub3V0Zmls ZXM6DQorICAgICAgICAgICAgaWYgbm90IHNlbGYuZHJ5X3J1bjoNCisgICAg ICAgICAgICAgICAgZGF0YSA9IG9wZW4oZiwgInIiKS5yZWFkbGluZXMoKQ0K KyAgICAgICAgICAgICAgICBpZiBub3QgZGF0YToNCisgICAgICAgICAgICAg ICAgICAgIHNlbGYud2FybigiJXMgaXMgYW4gZW1wdHkgZmlsZSEiICUgZikN CisgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlDQorICAgICAgICAgICAg ICAgIG1vID0gZmlyc3RfbGluZV9yZS5tYXRjaChkYXRhWzBdKQ0KKyAgICAg ICAgICAgICAgICBpZiBtbzoNCisgICAgICAgICAgICAgICAgICAgIHNlbGYu YW5ub3VuY2UoIkFkanVzdGluZyBmaXJzdCBsaW5lIG9mIGZpbGUgJXMiICUg ZikNCisgICAgICAgICAgICAgICAgICAgIGRhdGFbMF0gPSAiIyEiK3N5cy5l eGVjdXRhYmxlDQorICAgICAgICAgICAgICAgICAgICAjIGFkZCBvcHRpb25h bCBjb21tYW5kIGxpbmUgb3B0aW9ucw0KKyAgICAgICAgICAgICAgICAgICAg aWYgbW8uZ3JvdXAoMSk6DQorICAgICAgICAgICAgICAgICAgICAgICAgZGF0 YVswXSA9IGRhdGFbMF0gKyBtby5ncm91cCgxKQ0KKyAgICAgICAgICAgICAg ICAgICAgZWxzZToNCisgICAgICAgICAgICAgICAgICAgICAgICBkYXRhWzBd ID0gZGF0YVswXSArICJcbiINCisgICAgICAgICAgICAgICAgICAgIG9wZW4o ZiwgInciKS53cml0ZWxpbmVzKGRhdGEpDQpkaWZmIC1CdXJOIC0tbWluaW1h bCAtLWV4Y2x1ZGU9Ki5weWMgZGlzdHV0aWxzLm9yaWcvZGlzdHV0aWxzL2Nv bW1hbmQvaW5zdGFsbF9kYXRhLnB5IGRpc3R1dGlscy5wYXRjaGVkL2Rpc3R1 dGlscy9jb21tYW5kL2luc3RhbGxfZGF0YS5weQ0KLS0tIGRpc3R1dGlscy5v cmlnL2Rpc3R1dGlscy9jb21tYW5kL2luc3RhbGxfZGF0YS5weQlTYXQgTWF5 IDEzIDA1OjA5OjUwIDIwMDANCisrKyBkaXN0dXRpbHMucGF0Y2hlZC9kaXN0 dXRpbHMvY29tbWFuZC9pbnN0YWxsX2RhdGEucHkJV2VkIE1heSAyNCAxMDo0 MTo1MSAyMDAwDQpAQCAtNywxNyArNyw1MiBAQA0KIA0KIF9fcmV2aXNpb25f XyA9ICIkSWQ6IGluc3RhbGxfZGF0YS5weSx2IDEuNSAyMDAwLzA1LzEzIDAz OjA5OjUwIGdyZWcgRXhwICQiDQogDQotZnJvbSBkaXN0dXRpbHMuY21kIGlt cG9ydCBpbnN0YWxsX21pc2MNCitpbXBvcnQgb3MNCitmcm9tIHR5cGVzIGlt cG9ydCBTdHJpbmdUeXBlDQorZnJvbSBkaXN0dXRpbHMuY29yZSBpbXBvcnQg Q29tbWFuZA0KIA0KLWNsYXNzIGluc3RhbGxfZGF0YSAoaW5zdGFsbF9taXNj KToNCitjbGFzcyBpbnN0YWxsX2RhdGEgKENvbW1hbmQpOg0KIA0KICAgICBk ZXNjcmlwdGlvbiA9ICJpbnN0YWxsIGRhdGEgZmlsZXMiDQogDQorICAgIHVz ZXJfb3B0aW9ucyA9IFsNCisgICAgICAgICgnaW5zdGFsbC1kaXI9JywgJ2Qn LA0KKyAgICAgICAgICJkaXJlY3RvcnkgdG8gaW5zdGFsbCB0aGUgZmlsZXMg dG8iKSwNCisgICAgICAgICgncm9vdD0nLCBOb25lLA0KKyAgICAgICAgICJp bnN0YWxsIGV2ZXJ5dGhpbmcgcmVsYXRpdmUgdG8gdGhpcyBhbHRlcm5hdGUg cm9vdCBkaXJlY3RvcnkiKSwNCisgICAgICAgIF0NCisNCisgICAgZGVmIGlu aXRpYWxpemVfb3B0aW9ucyAoc2VsZik6DQorICAgICAgICBzZWxmLmluc3Rh bGxfZGlyID0gTm9uZQ0KKyAgICAgICAgc2VsZi5vdXRmaWxlcyA9IE5vbmUN CisgICAgICAgIHNlbGYucm9vdCA9IE5vbmUNCisgICAgICAgIHNlbGYuZGF0 YV9maWxlcyA9IHNlbGYuZGlzdHJpYnV0aW9uLmRhdGFfZmlsZXMNCisNCiAg ICAgZGVmIGZpbmFsaXplX29wdGlvbnMgKHNlbGYpOg0KLSAgICAgICAgc2Vs Zi5faW5zdGFsbF9kaXJfZnJvbSgnaW5zdGFsbF9kYXRhJykNCisgICAgICAg IHNlbGYuc2V0X3VuZGVmaW5lZF9vcHRpb25zKCdpbnN0YWxsJywNCisJICAg ICAgICAgICAgICAgICAgICAgICAgICAgKCdpbnN0YWxsX2RhdGEnLCAnaW5z dGFsbF9kaXInKSwNCisJCQkJICAgKCdyb290JywgJ3Jvb3QnKSwNCisJCQkJ ICApDQogDQogICAgIGRlZiBydW4gKHNlbGYpOg0KLSAgICAgICAgc2VsZi5f Y29weV9maWxlcyhzZWxmLmRpc3RyaWJ1dGlvbi5kYXRhX2ZpbGVzKQ0KKyAg ICAgICAgc2VsZi5ta3BhdGgoc2VsZi5pbnN0YWxsX2RpcikNCisgICAgICAg IGZvciBmIGluIHNlbGYuZGF0YV9maWxlczoNCisgICAgICAgICAgICBpZiB0 eXBlKGYpID09IFN0cmluZ1R5cGU6DQorICAgICAgICAgICAgICAgICMgaXRz IGEgc2ltcGxlIGZpbGUsIHNvIGNvcHkgaXQNCisgICAgICAgICAgICAgICAg c2VsZi5jb3B5X2ZpbGUoZiwgc2VsZi5pbnN0YWxsX2RpcikNCisgICAgICAg ICAgICBlbHNlOg0KKyAgICAgICAgICAgICAgICAjIGl0cyBhIHR1cGxlIHdp dGggcGF0aCB0byBpbnN0YWxsIHRvIGFuZCBhIGxpc3Qgb2YgZmlsZXMNCisg ICAgICAgICAgICAgICAgZGlyID0gZlswXQ0KKyAgICAgICAgICAgICAgICBp ZiBub3Qgb3MucGF0aC5pc2FicyhkaXIpOg0KKyAgICAgICAgICAgICAgICAg ICAgZGlyID0gb3MucGF0aC5qb2luKHNlbGYuaW5zdGFsbF9kaXIsIGRpcikN CisgICAgICAgICAgICAgICAgZWxpZiBzZWxmLnJvb3Q6DQorICAgICAgICAg ICAgICAgICAgICBkaXIgPSBvcy5wYXRoLmpvaW4oc2VsZi5yb290LCBkaXJb MTpdKQ0KKyAgICAgICAgICAgICAgICBzZWxmLm1rcGF0aChkaXIpDQorICAg ICAgICAgICAgICAgIGZvciBkYXRhIGluIGZbMV06DQorICAgICAgICAgICAg ICAgICAgICBzZWxmLmNvcHlfZmlsZShkYXRhLCBkaXIpDQogDQogICAgIGRl ZiBnZXRfaW5wdXRzIChzZWxmKToNCi0gICAgICAgIHJldHVybiBzZWxmLmRp c3RyaWJ1dGlvbi5kYXRhX2ZpbGVzIG9yIFtdDQorICAgICAgICByZXR1cm4g c2VsZi5kYXRhX2ZpbGVzIG9yIFtdDQorDQorICAgIGRlZiBnZXRfb3V0cHV0 cyAoc2VsZik6DQorICAgICAgICByZXR1cm4gc2VsZi5vdXRmaWxlcw0KZGlm ZiAtQnVyTiAtLW1pbmltYWwgLS1leGNsdWRlPSoucHljIGRpc3R1dGlscy5v cmlnL2Rpc3R1dGlscy9jb21tYW5kL2luc3RhbGxfc2NyaXB0cy5weSBkaXN0 dXRpbHMucGF0Y2hlZC9kaXN0dXRpbHMvY29tbWFuZC9pbnN0YWxsX3Njcmlw dHMucHkNCi0tLSBkaXN0dXRpbHMub3JpZy9kaXN0dXRpbHMvY29tbWFuZC9p bnN0YWxsX3NjcmlwdHMucHkJU2F0IE1heSAxMyAwNTowNzo1MyAyMDAwDQor KysgZGlzdHV0aWxzLnBhdGNoZWQvZGlzdHV0aWxzL2NvbW1hbmQvaW5zdGFs bF9zY3JpcHRzLnB5CVdlZCBNYXkgMjQgMTA6MTA6NDggMjAwMA0KQEAgLTgs MjMgKzgsMzkgQEANCiBfX3JldmlzaW9uX18gPSAiJElkOiBpbnN0YWxsX3Nj cmlwdHMucHksdiAxLjQgMjAwMC8wNS8xMyAwMzowNzo1MyBncmVnIEV4cCAk Ig0KIA0KIGltcG9ydCBvcw0KLWZyb20gZGlzdHV0aWxzLmNtZCBpbXBvcnQg aW5zdGFsbF9taXNjDQorZnJvbSBkaXN0dXRpbHMuY29yZSBpbXBvcnQgQ29t bWFuZA0KIGZyb20gc3RhdCBpbXBvcnQgU1RfTU9ERQ0KIA0KLWNsYXNzIGlu c3RhbGxfc2NyaXB0cyhpbnN0YWxsX21pc2MpOg0KK2NsYXNzIGluc3RhbGxf c2NyaXB0cyhDb21tYW5kKToNCiANCiAgICAgZGVzY3JpcHRpb24gPSAiaW5z dGFsbCBzY3JpcHRzIg0KIA0KKyAgICB1c2VyX29wdGlvbnMgPSBbDQorICAg ICAgICAoJ2luc3RhbGwtZGlyPScsICdkJywgImRpcmVjdG9yeSB0byBpbnN0 YWxsIHRvIiksDQorICAgICAgICAoJ2J1aWxkLWRpcj0nLCdiJywgImJ1aWxk IGRpcmVjdG9yeSAod2hlcmUgdG8gaW5zdGFsbCBmcm9tKSIpLA0KKyAgICAg ICAgKCdza2lwLWJ1aWxkJywgTm9uZSwgInNraXAgdGhlIGJ1aWxkIHN0ZXBz IiksDQorICAgIF0NCisNCisgICAgZGVmIGluaXRpYWxpemVfb3B0aW9ucyAo c2VsZik6DQorICAgICAgICBzZWxmLmluc3RhbGxfZGlyID0gTm9uZQ0KKyAg ICAgICAgc2VsZi5idWlsZF9kaXIgPSBOb25lDQorICAgICAgICBzZWxmLnNr aXBfYnVpbGQgPSBOb25lDQorDQogICAgIGRlZiBmaW5hbGl6ZV9vcHRpb25z IChzZWxmKToNCi0gICAgICAgIHNlbGYuX2luc3RhbGxfZGlyX2Zyb20oJ2lu c3RhbGxfc2NyaXB0cycpDQorICAgICAgICBzZWxmLnNldF91bmRlZmluZWRf b3B0aW9ucygnYnVpbGQnLCAoJ2J1aWxkX3NjcmlwdHMnLCAnYnVpbGRfZGly JykpDQorICAgICAgICBzZWxmLnNldF91bmRlZmluZWRfb3B0aW9ucyAoJ2lu c3RhbGwnLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICgnaW5zdGFsbF9zY3JpcHRzJywgJ2luc3RhbGxfZGlyJyksDQorICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCdza2lwX2J1aWxkJywg J3NraXBfYnVpbGQnKSwNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICkNCiANCiAgICAgZGVmIHJ1biAoc2VsZik6DQotICAgICAgICBz ZWxmLl9jb3B5X2ZpbGVzKHNlbGYuZGlzdHJpYnV0aW9uLnNjcmlwdHMpDQor ICAgICAgICBpZiBub3Qgc2VsZi5za2lwX2J1aWxkOg0KKyAgICAgICAgICAg IHNlbGYucnVuX3BlZXIoJ2J1aWxkX3NjcmlwdHMnKQ0KKyAgICAgICAgc2Vs Zi5vdXRmaWxlcyA9IHNlbGYuY29weV90cmVlIChzZWxmLmJ1aWxkX2Rpciwg c2VsZi5pbnN0YWxsX2RpcikNCiAgICAgICAgIGlmIG9zLm5hbWUgPT0gJ3Bv c2l4JzoNCiAgICAgICAgICAgICAjIFNldCB0aGUgZXhlY3V0YWJsZSBiaXRz IChvd25lciwgZ3JvdXAsIGFuZCB3b3JsZCkgb24NCiAgICAgICAgICAgICAj IGFsbCB0aGUgc2NyaXB0cyB3ZSBqdXN0IGluc3RhbGxlZC4NCi0gICAgICAg ICAgICBmaWxlcyA9IHNlbGYuZ2V0X291dHB1dHMoKQ0KLSAgICAgICAgICAg IGZvciBmaWxlIGluIGZpbGVzOg0KKyAgICAgICAgICAgIGZvciBmaWxlIGlu IHNlbGYuZ2V0X291dHB1dHMoKToNCiAgICAgICAgICAgICAgICAgaWYgc2Vs Zi5kcnlfcnVuOg0KICAgICAgICAgICAgICAgICAgICAgc2VsZi5hbm5vdW5j ZSgiY2hhbmdpbmcgbW9kZSBvZiAlcyIgJSBmaWxlKQ0KICAgICAgICAgICAg ICAgICBlbHNlOg0KQEAgLTM0LDUgKzUwLDggQEANCiANCiAgICAgZGVmIGdl dF9pbnB1dHMgKHNlbGYpOg0KICAgICAgICAgcmV0dXJuIHNlbGYuZGlzdHJp YnV0aW9uLnNjcmlwdHMgb3IgW10NCisNCisgICAgZGVmIGdldF9vdXRwdXRz KHNlbGYpOg0KKyAgICAgICAgcmV0dXJuIHNlbGYub3V0ZmlsZXMgb3IgW10N CiANCiAjIGNsYXNzIGluc3RhbGxfc2NyaXB0cw0K --1619418364-364033880-959158152=:14230-- From mwa@gate.net Wed May 24 16:30:02 2000 From: mwa@gate.net (Mark W. Alexander) Date: Wed, 24 May 2000 11:30:02 -0400 (EDT) Subject: [Distutils] Pondering multi-package packages Message-ID: I apologize of this is documented somewhere. If it is, I haven't found it. I've done lots of python modules, but not any packages, so if I'm just package ignorant feel free to slap me..... It all started in the early Zope days when I loaded Zope only to discover that all my scripts using Marc Lemburg's mxDateTime bombed because Zope's DateTime produced a namespace collision. The solution then was to move Zope, since I didn't 'need' it at the time. Now I do. So, I contacted Marc who, of course, knew about the collision and has already started looking at packaging all his stuff under an umbrella "mx" package. When I asked about Distutils, he hadn't really looked at it so I volunteered to see what it would take. Since Distutils includes a sample mxDateTime setup.py, it seemed fairly easy. I hacked it up to push it down a level (see attempt below). No problem except, of course, that it doesn't import because there's no mx.__init__.py. Ok, so I add an mx.__init__.py with __all__ defined and appropriate imports. Everything's happy and Distutils does fine. Now, I add in mx.TextTools and things get murkier. How does mx.__init__.py determine what __all__ should be and what to import? How do I tell Distutils about the other packages? I tried a single all-purpose Distutils setup.py that searches the mx package directory and adds in the sub-packages that it finds. So far so good. Now, what about=20 mx.__init__.py? Should it:=20 1) Search it's package directory at runtime to determine what __all__ should be and what subpackages to import? If it does that, then mx.__init__.py will exist in all possible mx packages. Distutils probably won't care and will happily copy the lastest __init__.py into place (since they "should" all be the same,=20 that's not a problem). BUT -- what if I make packages with --bdist-WHATEVER. Package manager WHATEVER is going to not be pleased with=20 multiple packages that all provide mx.__init__.py. Some type of package forcing is going to have to occur for all except the first subpackage=20 installed. - OR - 2) Be created dynamically at "install" time. The all-purpose setup.py can scan when Distutils runs and programatically create an __init__.py at installation time that meets the needs of the currently installed subpacakges. BUT -- that doesn't help when I used --bdist-WHATEVER again, because the resulting package is going to be installed on a system that probably does not have the same set of subpackages installed. I'll have to provide a postinstall script to WHATEVER to create __init__.py on the install host. Do-able, but now I'm manually tacking stuff on to the package that --bdist-WHATEVER=20 can't (unless I missed it) handle. And,=20 mx.__init__.py is not registered to the package somewhat defeating the purpose. It looks like --bdist-WHATEVER needs information about pre- and post-installation processing. This would have to be included in setup.py somewhere. But what should it be? Package managers (that support pre/post install) expect shell scripts. It would be really nice if --bdist took a python function and wrapped it for us in a shell wrapper, e.g. #!/bin/sh python -i < [repost as my original was misdirected - apologies to -admin. am] Thanks for your response. the -R option can certainly be handled that way, but the toggling of the static/dynamic library loading I don't think can be. Mind you, I'm no guru on the subject. ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 ---------- Original Text ---------- From: Harry Henry Gebel , on 24/05/00 16:35: On Wed, May 24, 2000 at 02:28:36PM +0000, Andrew MacIntyre wrote: > Unfortunately, the commercial package I'm dealing with has a long list of > libraries required to be linked, with several specified static and the rest > dynamic. > > The recommended library spec (for Solaris, which is what I'm working with at > the moment) looks something like this: > > -l ... -l -Bstatic -l... -l -Bdynamic -l...-l > -R > > What would be the recommended way to deal with this, if Distutils in its > current form can handle this situation? The CVS version (I think you have to get it from SourceForge) should except the CFLAGS environment variable, I don't know if this will help you or not. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware _______________________________________________ Distutils-SIG maillist - Distutils-SIG@python.org http://www.python.org/mailman/listinfo/distutils-sig From gward@python.net Thu May 25 00:20:47 2000 From: gward@python.net (Greg Ward) Date: Wed, 24 May 2000 19:20:47 -0400 Subject: [Distutils] Thinking about a Windows Installer In-Reply-To: <037501bfc4f3$53362e60$4500a8c0@thomasnb>; from Thomas Heller on Tue, May 23, 2000 at 10:13:13PM +0200 References: <010901bfc01b$8fedf590$4500a8c0@thomasnb> <20000520104114.E318@beelzebub> <037501bfc4f3$53362e60$4500a8c0@thomasnb> Message-ID: <20000524192047.A318@beelzebub> On 23 May 2000, Thomas Heller said: > OK, will submit an 'bdist_wise' sometime. Or maybe 'bdist_wisescript' > because it will create an xxx.wse script, which has to be compiled > with Wise32.exe. Great! A bit of calibration: "bdist_rpm" exists mainly to create the .spec file, but at the end of the job it runs "rpm -b..." for your convenience. It has --spec-only, --source-only, and --binary-only options for finer control. I think "bdist_wise" should do roughly the same: create the .wse file, and then (optionally, but by default) compile it with Wise32.exe. > > Whether you want to embed Python really depends on your audience. Let's > > face it, installing Python on Windows is not that hard. If a programmer > > wants to use some collection of modules, it's not too bad to say, > > "Download and install Python, then download and install the module > > distribution". Painless * 2 is not too bad. > > Sure. But: Windows users are (normally) not used to the command line > (neither will they read the README file :-). They are used to installer > executables. No no, I'm not arguing for a command-line installer. (Except for the hard-code Pythonistas who want to build everything from source, and think the current Distutils interface on Windows is just fine.) I'm arguing that Joe's Handy Python Modules should *just* include joes/module1.py, joes/module2.py, and related files -- ie. pretty much what goes into other Distutils-generated built distributions ("dumb" tarballs or zip files, or "smart" binary RPMs). The boundary between Joe's Handy Python Modules and Jim's Humongous Python-Based Application (which probably should include an embedded Python interpreter and library) is fuzzy -- I'm not sure where eg. NumPy falls. That should be the developer's decision to make. (Hmmm, now why did the name "Jim" come to mind when thinking of humongous Python-based applications...) > I did not think about end-user applications here. Is distutils headed in > this > direction after all? Well, yes, eventually. We have to keep it in mind. Support for "building" and installing scripts is already partly there. (When someone can download Zope and run "python setup.py install", and setup.py is a reasonably normal Distutils-style setup script, then I will hang up my keyboard and go home.) [I outline my vision] > I think the mode of operation should be as close to the other bdist > commands as possible: distribute a pseudo-installation tree and just > copy it in place. That is, the setup script shouldn't enter into it > here, *unless* you need it to extract package meta-data. (Unless that's > put into another file when you run "bdist_wininst".) [Thomas describes his] > I was more thinking about a zip-selfextractor, extracting the archive into > the python installation directory automatically. The GUI is/will be > not more than a dialog box displaying some meta-info (name, version,...) > of the installed modules. The GUI is written in C. > So it is not neccessary to embed python (Maybe for compiling pyc files?) We're not contradicting each other. By "mode of operation" I was more concerned with how "installers" or "built distributions" or whatever are created, and what's included in them, not how the user uses them. Of *course* on Windows it should be an executable -- that's the local convention. And if a self-extracting zip file is the best way to do it, then do it! A few questions/comments: * the default installation directory should obviously be where Python will find it: sys.prefix. So you'll either have to run "python -c 'import sys; print sys.prefix'" or get this information from the registry. I'm guessing the latter is preferable and doable -- as long as you can put arbitrary code into the self-extractor. * what if there are multiple Python installations -- are they sufficiently differentiated in the registry? Eg. I might have Python 1.5.2 and 1.6a2 installed, and I would have to choose which one to install to. What if it's a question of 1.6a1 vs 1.6a2 -- are Python's registry entries sufficently fine-grained to resolve this? * should we allow writing to a different directory than the default (sys.prefix)? (This would require writing a .pth file in sys.prefix.) Or is this getting too close to a "real" installer? * how would the actual installer be created? I'm hoping that the CCompiler abstraction would be good enough -- just create yourself a CCompiler (which could be a MSVCCompiler, BCCompiler, Mingw32CCompiler, ...) object, compile a few things, and link an executable. * interesting data point/existence proof: the Java installer- generator InstallAnywhere let me create an executable Windows installer *entirely* on my Solaris box -- I think it carries around a "stub" executable, and somehow generates the real executable by munging it with my Java code (and other stuff to install). Needless to say, this is *very* cool; it is also an incredibly fat, slow, and heavyweight product. If you can let me generate Windows installers under Solaris or Linux, I'll buy you *two* beers at the next Python conference. (I already owe you one.) ;-) > More about Wise: > Wise is a full fledged windows installer. These programs handle the > following > and more: > - Check the access rights to install the program and its utilities > - Let the user select an installation directory > - Create shortcuts in the start menu so that the user can start the program > easily > - Care about incrementing the ref-count of shared files (usually dlls) > - Create file associations for program specific data files > - Install accessories needed for the program: database access, device > drivers, system services > - Create registry entries > - Create some meta data for uninstallation and install an uninstaller > - Care about replacing in-use files (common under windows) > Nearly all of this is not needed for python modules and extensions, > and if it is, IMO it should be handled by distutils. Agreed, except for the somewhat mythical Jim's Humongous Python-Based Application -- there, all of these "real installer" problems are undoubtedly a concern. That's not a big concern for Distutils 1.0, though -- unless bdist_wise is really easy, I would focus on bdist_wininst, as it sounds like it would be a lot lighter weight, and not require any additional software other than Python/Distutils. Wow, this sounds *neat*! And I thought being able to build RPMs was cool (no offense, Harry...) Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ I wonder if I ought to tell them about my PREVIOUS LIFE as a COMPLETE STRANGER? From gward@python.net Thu May 25 03:17:51 2000 From: gward@python.net (Greg Ward) Date: Wed, 24 May 2000 22:17:51 -0400 Subject: [Distutils] another build_scripts patch In-Reply-To: ; from Bastian Kleineidam on Wed, May 24, 2000 at 10:49:12AM +0200 References: <20000522221437.A7359@beelzebub> Message-ID: <20000524221751.A612@beelzebub> On 24 May 2000, Bastian Kleineidam said: > Next try with the build_scripts patch. Again the changes: OK, I've checked it in. A few minor comments (I'm checking these changes in too, so howl if you don't like 'em and "cvs up" if you do.) > - install_misc class is commented out because its not needed any more You forgot to include this in the patch, but that's OK because that's not what I meant! I just wanted a comment next to "install_misc" to remind us that it's not (currently) used. I'll do it myself. > data_files = ['doc/info.txt', # copy this file in install_scripts dir > ('testdata', ['a.dat', 'b.dat']), # copy these files in > # install_scripts/testdata > ('/etc', ['packagerc']), # copy this in /etc. When --root is > # given, copy this in rootdir/etc > ] Perfect! (Assuming it works. ;-) > --- distutils.orig/distutils/command/__init__.py Sat May 13 03:48:15 2000 > +++ distutils.patched/distutils/command/__init__.py Wed May 24 10:11:54 2000 [...] > @@ -99,5 +104,8 @@ > # into the build tree > if self.distribution.has_ext_modules(): > self.run_peer ('build_ext') > + > + if self.distribution.scripts: > + self.run_peer ('build_scripts') This should use the 'has_scripts()' method of Distribution -- fixed. > +# check if Python is called on the first line with this expression > +first_line_re = re.compile(r"^#!.+python(\s-\w+)*") I think we can get away with a looser regex: I've changed this to r'^#!.*python(\s+.*)?'. Reasons: * I seem to recall having seen "#!python" notation somewhere -- it's a reasonable way to say, "Hey, ! Fix this up for me at install time!" * Why assume/impose a particular syntax on Python's command line? let's just preserve any old args on the #! line. > + def _copy_files(self): > + """Copy all the scripts to the build dir""" [...] > + def _adjust_files(self): > + """If the first line begins with #! and ends with python > + replace it with the current python interpreter""" [...] This strikes me as a rather wasteful implementation: in the worst case, we copy every file twice. I've merged them into the following method; it works for me, please look it over and try it out (from CVS -- a few other tweaks to build_scripts.py were needed to make this work): def copy_scripts (self): """Copy each script listed in 'self.scripts'; if it's marked as a Python script in the Unix way (first line matches 'first_line_re', ie. starts with "\#!" and contains "python"), then adjust the first line to refer to the current Python intepreter as we copy. """ outfiles = [] self.mkpath(self.build_dir) for script in self.scripts: adjust = 0 outfile = os.path.join(self.build_dir, script) if not self.force and not newer(script, outfile): self.announce("not copying %s (output up-to-date)" % script) continue # Always open the file, but ignore failures in dry-run mode -- # that way, we'll get accurate feedback if we can read the # script. try: f = open(script, "r") except IOError: if not self.dry_run: raise f = None else: first_line = f.readline() if not first_line: self.warn("%s is an empty file (skipping)" % script) continue match = first_line_re.match(first_line) if match: adjust = 1 post_interp = match.group(1) if adjust: self.announce("copying and adjusting %s -> %s" % (script, self.build_dir)) if not self.dry_run: outf = open(outfile, "w") outf.write("#!%s%s\n" % (os.path.normpath(sys.executable), post_interp)) outf.writelines(f.readlines()) outf.close() if f: f.close() else: f.close() self.copy_file(script, outfile) # copy_scripts () > --- distutils.orig/distutils/command/install_data.py Sat May 13 05:09:50 2000 > +++ distutils.patched/distutils/command/install_data.py Wed May 24 10:41:51 2000 [...] > def run (self): > - self._copy_files(self.distribution.data_files) > + self.mkpath(self.install_dir) > + for f in self.data_files: > + if type(f) == StringType: > + # its a simple file, so copy it > + self.copy_file(f, self.install_dir) > + else: > + # its a tuple with path to install to and a list of files > + dir = f[0] > + if not os.path.isabs(dir): > + dir = os.path.join(self.install_dir, dir) > + elif self.root: > + dir = os.path.join(self.root, dir[1:]) > + self.mkpath(dir) > + for data in f[1]: > + self.copy_file(data, dir) This looks unportable, in particular the 'dir[1:]' business. Should use the 'distutils.util.change_root()' function, which handles non-Unix platforms by blowing up with "I don't know how to do this!" error. (Which is really a function of me not having sat down and carefully thought through what it means to "change the root" of an MS-DOS filename: the presence of drive letters complicates matters.) Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ I'm a GENIUS! I want to dispute sentence structure with SUSAN SONTAG!! From gward@python.net Thu May 25 03:22:41 2000 From: gward@python.net (Greg Ward) Date: Wed, 24 May 2000 22:22:41 -0400 Subject: [Distutils] handling complex link/library specifications In-Reply-To: ; from Andrew MacIntyre on Wed, May 24, 2000 at 02:28:36PM +0000 References: Message-ID: <20000524222241.B612@beelzebub> On 24 May 2000, Andrew MacIntyre said: > The recommended library spec (for Solaris, which is what I'm working with at > the moment) looks something like this: > > -l ... -l -Bstatic -l... -l -Bdynamic -l...-l > -R Wow, same question twice in one day. Time to work on the docs again. You should be able to do this with an 'extra_link_args' entry in the "build info" dictionary that describes your extension. *rummage rummage rummage* Ahh, here's the example I sent to someone else not 'alf an 'our ago (I knew I should have cc'd the sig): ext_modules = [('_imaging', { 'sources': ['_imaging.c', 'decode.c', ... , 'path.c'] 'include_dirs': ['libImaging'], 'library_dirs': ['libImaging'], 'libraries': ['Imaging'], 'extra_link_args': ['-lX11', '-lXext', '-lXshm'], 'extra_compile_args': ['-Dfoo=bar', '-Ublah'] } )] 'extra_compile_args' is only in the current CVS code, but 'extra_link_args' has been around for a while. BTW, the requirement in the above example was to worm output from a configure script and from gtk-config into the compiler/linker commands. Obviously portability is thrown out the window, but in return you have a working setup script. > (BTW http://www.python.org/sigs/distutils-sig/doc/dist/source-dist.html has an > HTML problem, at least with IE 3.02) Hmm, based on my (indirect) experience with IE 3, I'd be more inclined to say *it's* the one with an HTML problem... *smirk* Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ I wonder if I ought to tell them about my PREVIOUS LIFE as a COMPLETE STRANGER? From gward@python.net Thu May 25 03:30:02 2000 From: gward@python.net (Greg Ward) Date: Wed, 24 May 2000 22:30:02 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: ; from Mark W. Alexander on Wed, May 24, 2000 at 11:30:02AM -0400 References: Message-ID: <20000524223002.C612@beelzebub> On 24 May 2000, Mark W. Alexander said: > I apologize of this is documented somewhere. If it > is, I haven't found it. I've done lots of python > modules, but not any packages, so if I'm just > package ignorant feel free to slap me..... It's not, and this problem is a fundamental design flaw in Python's packaging system. I have a few ideas on how we can live with it, and they generally involve "put nothing (important) in __init__.py". > Since Distutils includes a sample mxDateTime setup.py, > it seemed fairly easy. I hacked it up to push it down > a level (see attempt below). No problem except, of > course, that it doesn't import because there's no > mx.__init__.py. Ok, so I add an mx.__init__.py with > __all__ defined and appropriate imports. Everything's > happy and Distutils does fine. You may be labouring under the illusion that you have to define __all__. You don't. It's just there so that you can "from package import *", where * will presumably resolve to a list of modules. (It doesn't have to, though: __init__.py can define things on its own, which then become exported by the package.) The easiest solution is zero-byte __init__.py files. Then auto-generation is a snap, and there's no need to worry about mxDateTime clobbering the mx/__init__.py from mxTextTools (or vice-versa). It's nice to put a brief comment or docstring in __init__.py, though -- then, it would be up to the developer (Marc-Andre in this case) to make sure the mx/__init__.py included with all of his packages is the same (or at least that all are "content-free", i.e. only comments and docstrings). Dealing with conflicting mx/__init__.py's from multiple RPMs is another issue; I don't have a ready answer off the top o' my head. Hmmm. > It looks like --bdist-WHATEVER needs information about > pre- and post-installation processing. This would have > to be included in setup.py somewhere. Gee, I hope we can avoid it. But if we can't, I agree that such code should be provided as Python; it's up to the Distutils to cook up a way to run that code at installation-time. Yuck! Hairy, hairy, hairy... Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ Vote anarchist. From akuchlin@mems-exchange.org Thu May 25 03:34:43 2000 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Wed, 24 May 2000 22:34:43 -0400 (EDT) Subject: [Distutils] Pondering multi-package packages In-Reply-To: <20000524223002.C612@beelzebub> References: <20000524223002.C612@beelzebub> Message-ID: <14636.37187.914865.521848@newcnri.cnri.reston.va.us> Greg Ward writes: >The easiest solution is zero-byte __init__.py files. Then >auto-generation is a snap, and there's no need to worry about mxDateTime >clobbering the mx/__init__.py from mxTextTools (or vice-versa). Note that WinZip, which is commonly used, doesn't archive zero-length files under some circumstances; occasionally people run into this when they unzip a directory and can't import from the package. Hence the convention of just putting a comment in __init__.py, to avoid having a zero-length file. --amk From fdrake@acm.org Thu May 25 03:46:08 2000 From: fdrake@acm.org (Fred L. Drake) Date: Wed, 24 May 2000 19:46:08 -0700 (PDT) Subject: [Distutils] Pondering multi-package packages In-Reply-To: <14636.37187.914865.521848@newcnri.cnri.reston.va.us> Message-ID: On Wed, 24 May 2000, Andrew Kuchling wrote: > Note that WinZip, which is commonly used, doesn't archive zero-length > files under some circumstances; occasionally people run into this when > they unzip a directory and can't import from the package. Hence the > convention of just putting a comment in __init__.py, to avoid having a > zero-length file. Docstrings are also nice candidates, but I don't know if that's the right thing for the "mx" package. It's a little different from the simpler packages that were initialy envisioned. -Fred -- Fred L. Drake, Jr. From andrew.macintyre@aba.gov.au Thu May 25 15:07:14 2000 From: andrew.macintyre@aba.gov.au (andrew.macintyre@aba.gov.au) Date: Thu, 25 May 2000 14:07:14 AES Subject: [Distutils] handling complex link/library specifications Message-ID: 'extra_link_args' looks just what I'm after, especially for the "-R" option. Platform portability isn't important to me (yet!) with this particular project. The static/dynamic bits appear to have wrinkles at the compiler/linker level:- when used with "cc" as the linker it works, but it doesn't work with "ld" :-( At least things work without those toggles, albeit with administrative side-effects. There wouldn't be a convenient way to override the linker command ("ld -G" on Solaris, from the Python Makefile) would there? I have to say that Distutils, from my experience with it so far, has been easy to work with. Apart from my questions here, all my problems with this project have been with the commercial library I'm wrapping. Many thanks for the fine work! ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 ---------- Original Text ---------- From: Greg Ward , on 25/05/00 12:33: On 24 May 2000, Andrew MacIntyre said: > The recommended library spec (for Solaris, which is what I'm working with at > the moment) looks something like this: > > -l ... -l -Bstatic -l... -l -Bdynamic -l...-l > -R Wow, same question twice in one day. Time to work on the docs again. You should be able to do this with an 'extra_link_args' entry in the "build info" dictionary that describes your extension. *rummage rummage rummage* Ahh, here's the example I sent to someone else not 'alf an 'our ago (I knew I should have cc'd the sig): ext_modules = [('_imaging', { 'sources': ['_imaging.c', 'decode.c', ... , 'path.c'] 'include_dirs': ['libImaging'], 'library_dirs': ['libImaging'], 'libraries': ['Imaging'], 'extra_link_args': ['-lX11', '-lXext', '-lXshm'], 'extra_compile_args': ['-Dfoo=bar', '-Ublah'] } )] 'extra_compile_args' is only in the current CVS code, but 'extra_link_args' has been around for a while. BTW, the requirement in the above example was to worm output from a configure script and from gtk-config into the compiler/linker commands. Obviously portability is thrown out the window, but in return you have a working setup script. > (BTW http://www.python.org/sigs/distutils-sig/doc/dist/source-dist.html has an > HTML problem, at least with IE 3.02) Hmm, based on my (indirect) experience with IE 3, I'd be more inclined to say *it's* the one with an HTML problem... *smirk* Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ I wonder if I ought to tell them about my PREVIOUS LIFE as a COMPLETE STRANGER? _______________________________________________ Distutils-SIG maillist - Distutils-SIG@python.org http://www.python.org/mailman/listinfo/distutils-sig From andrew.macintyre@aba.gov.au Thu May 25 16:38:59 2000 From: andrew.macintyre@aba.gov.au (andrew.macintyre@aba.gov.au) Date: Thu, 25 May 2000 15:38:59 AES Subject: [Distutils] handling complex link/library specifications Message-ID: scratch the ... bit, I've found an incantation (library directory) that allows the 'extra_link_args' option to do all I need to do. Many thanks! ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 ---------- Original Text ---------- From: Andrew MacIntyre , on 25/05/00 14:08: 'extra_link_args' looks just what I'm after, especially for the "-R" option. Platform portability isn't important to me (yet!) with this particular project. The static/dynamic bits appear to have wrinkles at the compiler/linker level:- when used with "cc" as the linker it works, but it doesn't work with "ld" :-( At least things work without those toggles, albeit with administrative side-effects. There wouldn't be a convenient way to override the linker command ("ld -G" on Solaris, from the Python Makefile) would there? I have to say that Distutils, from my experience with it so far, has been easy to work with. Apart from my questions here, all my problems with this project have been with the commercial library I'm wrapping. Many thanks for the fine work! ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 ---------- Original Text ---------- From: Greg Ward , on 25/05/00 12:33: On 24 May 2000, Andrew MacIntyre said: > The recommended library spec (for Solaris, which is what I'm working with at > the moment) looks something like this: > > -l ... -l -Bstatic -l... -l -Bdynamic -l...-l > -R Wow, same question twice in one day. Time to work on the docs again. You should be able to do this with an 'extra_link_args' entry in the "build info" dictionary that describes your extension. *rummage rummage rummage* Ahh, here's the example I sent to someone else not 'alf an 'our ago (I knew I should have cc'd the sig): ext_modules = [('_imaging', { 'sources': ['_imaging.c', 'decode.c', ... , 'path.c'] 'include_dirs': ['libImaging'], 'library_dirs': ['libImaging'], 'libraries': ['Imaging'], 'extra_link_args': ['-lX11', '-lXext', '-lXshm'], 'extra_compile_args': ['-Dfoo=bar', '-Ublah'] } )] 'extra_compile_args' is only in the current CVS code, but 'extra_link_args' has been around for a while. BTW, the requirement in the above example was to worm output from a configure script and from gtk-config into the compiler/linker commands. Obviously portability is thrown out the window, but in return you have a working setup script. > (BTW http://www.python.org/sigs/distutils-sig/doc/dist/source-dist.html has an > HTML problem, at least with IE 3.02) Hmm, based on my (indirect) experience with IE 3, I'd be more inclined to say *it's* the one with an HTML problem... *smirk* Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ I wonder if I ought to tell them about my PREVIOUS LIFE as a COMPLETE STRANGER? _______________________________________________ Distutils-SIG maillist - Distutils-SIG@python.org http://www.python.org/mailman/listinfo/distutils-sig _______________________________________________ Distutils-SIG maillist - Distutils-SIG@python.org http://www.python.org/mailman/listinfo/distutils-sig From mal@lemburg.com Thu May 25 11:08:35 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Thu, 25 May 2000 12:08:35 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> Message-ID: <392CFBA3.E4B5131E@lemburg.com> Greg Ward wrote: > > On 24 May 2000, Mark W. Alexander said: > > I apologize of this is documented somewhere. If it > > is, I haven't found it. I've done lots of python > > modules, but not any packages, so if I'm just > > package ignorant feel free to slap me..... > > It's not, and this problem is a fundamental design flaw in Python's > packaging system. I have a few ideas on how we can live with it, and > they generally involve "put nothing (important) in __init__.py". > > > Since Distutils includes a sample mxDateTime setup.py, > > it seemed fairly easy. I hacked it up to push it down > > a level (see attempt below). No problem except, of > > course, that it doesn't import because there's no > > mx.__init__.py. Ok, so I add an mx.__init__.py with > > __all__ defined and appropriate imports. Everything's > > happy and Distutils does fine. > > You may be labouring under the illusion that you have to define __all__. > You don't. It's just there so that you can "from package import *", > where * will presumably resolve to a list of modules. (It doesn't have > to, though: __init__.py can define things on its own, which then become > exported by the package.) > > The easiest solution is zero-byte __init__.py files. Then > auto-generation is a snap, and there's no need to worry about mxDateTime > clobbering the mx/__init__.py from mxTextTools (or vice-versa). > > It's nice to put a brief comment or docstring in __init__.py, though -- > then, it would be up to the developer (Marc-Andre in this case) to make > sure the mx/__init__.py included with all of his packages is the same > (or at least that all are "content-free", i.e. only comments and > docstrings). > > Dealing with conflicting mx/__init__.py's from multiple RPMs is another > issue; I don't have a ready answer off the top o' my head. Hmmm. FYI, I'm going to package the mx stuff in 3-4 ZIP archives: 1. base (this one contains the __init__.py file and always has to be installed) 2. crypto (optional add-in with mx.Crypto) 3. mx-ug (subpackages only available to mx User Group members) 4. commercial (things like mx.ODBC and some other DB related subpackages) There will no longer be separate mxTools, mxTextTools, mxDateTime, etc. packages. > > It looks like --bdist-WHATEVER needs information about > > pre- and post-installation processing. This would have > > to be included in setup.py somewhere. > > Gee, I hope we can avoid it. But if we can't, I agree that such code > should be provided as Python; it's up to the Distutils to cook up a way > to run that code at installation-time. Yuck! Hairy, hairy, hairy... Umm, what's hairy about pre- and post-install code ? Pretty much all RPM-like archives provide this feature in some way or another. I'd suggest to have setup.py include a reference to two functions somewhere (probably in the setup constructor): one to run for pre-install and one for post-install. -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From hgebel@inet.net Thu May 25 13:35:00 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Thu, 25 May 2000 08:35:00 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392CFBA3.E4B5131E@lemburg.com>; from mal@lemburg.com on Thu, May 25, 2000 at 12:08:35PM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> Message-ID: <20000525083500.O29443@inet.net> On Thu, May 25, 2000 at 12:08:35PM +0200, M.-A. Lemburg wrote: > Umm, what's hairy about pre- and post-install code ? Pretty > much all RPM-like archives provide this feature in some way > or another. > > I'd suggest to have setup.py include a reference > to two functions somewhere (probably in the setup constructor): > one to run for pre-install and one for post-install. You can do this now by defining your own install command in setup, I am providing my own build command in PyNcurses to perform some pre-build actions. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware From mwa@gate.net Thu May 25 16:14:27 2000 From: mwa@gate.net (Mark W. Alexander) Date: Thu, 25 May 2000 11:14:27 -0400 (EDT) Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392CFBA3.E4B5131E@lemburg.com> Message-ID: On Thu, 25 May 2000, M.-A. Lemburg wrote: > > FYI, I'm going to package the mx stuff in 3-4 ZIP archives: > > 1. base (this one contains the __init__.py file and always > has to be installed) > 2. crypto (optional add-in with mx.Crypto) > 3. mx-ug (subpackages only available to mx User Group members) > 4. commercial (things like mx.ODBC and some other DB related > subpackages) > > There will no longer be separate mxTools, mxTextTools, > mxDateTime, etc. packages. I think that pretty much resolves the issue with mx.Stuff. It still remains a generic problem for other packages though. Do you have an ETA on your new packages? If not, shoot me an email and I'll be happy to do the setup.py scripts. > > > should be provided as Python; it's up to the Distutils to cook up a way > > to run that code at installation-time. Yuck! Hairy, hairy, hairy... > > Umm, what's hairy about pre- and post-install code ? Pretty > much all RPM-like archives provide this feature in some way > or another. > > I'd suggest to have setup.py include a reference > to two functions somewhere (probably in the setup constructor): > one to run for pre-install and one for post-install. I also think this is a definite long-term need. For "relocatable" python packages on some architectures (e.g. Solaris) it may be necessary to re-link at install time (ld -rpath) to avoid requiring the user to set LD_LIBRARY_PATH. (IANALG -- I Am Not A Linking Guru, but I've had problems when things libraries ar in different places on "install" machines than they are on "build" machines. That said, it's probably only an issue when you're stuck with bunches fo boxes with different file system setups where your forced to put things where you can find the room. That probably means me and some other guy whose still lost writing perl ;-) If no one else is interested, I'll do it when hell freezes^W^W I have time. mwa From mal@lemburg.com Thu May 25 16:10:26 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Thu, 25 May 2000 17:10:26 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> Message-ID: <392D4262.CF25D949@lemburg.com> Harry Henry Gebel wrote: > > On Thu, May 25, 2000 at 12:08:35PM +0200, M.-A. Lemburg wrote: > > Umm, what's hairy about pre- and post-install code ? Pretty > > much all RPM-like archives provide this feature in some way > > or another. > > > > I'd suggest to have setup.py include a reference > > to two functions somewhere (probably in the setup constructor): > > one to run for pre-install and one for post-install. > > You can do this now by defining your own install command in setup, I am > providing my own build command in PyNcurses to perform some pre-build actions. I'd rather like to see predefined hooks for this than having to define my own install command. BTW, how can I add some Q&A style setup dialog to build and install commands ? I will need this for mxODBC since there are plenty subpackages which can all be installed separately and each of them will need to know where to find the header files and libs to link against. mxDateTime has a different need, which I'm not really sure how to handle: it needs some sort of "try to compile this and return the exit code from the compiler" + "if this compiles, run the result and return the exit code" to be able to define symbols such as HAVE_TIMEGM (much like autoconf does on Unix). Is this possible with the current distutils ? And a final question: do I have to redistribute distutils together with the mx packages in order to make sure that the build and install process works ? What about 1.5.2 compatibility ? Thanks, -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From mal@lemburg.com Thu May 25 16:52:44 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Thu, 25 May 2000 17:52:44 +0200 Subject: [Distutils] Pondering multi-package packages References: Message-ID: <392D4C4C.1FB8E824@lemburg.com> "Mark W. Alexander" wrote: > > On Thu, 25 May 2000, M.-A. Lemburg wrote: > > > > FYI, I'm going to package the mx stuff in 3-4 ZIP archives: > > > > 1. base (this one contains the __init__.py file and always > > has to be installed) > > 2. crypto (optional add-in with mx.Crypto) > > 3. mx-ug (subpackages only available to mx User Group members) > > 4. commercial (things like mx.ODBC and some other DB related > > subpackages) > > > > There will no longer be separate mxTools, mxTextTools, > > mxDateTime, etc. packages. > > I think that pretty much resolves the issue with mx.Stuff. It > still remains a generic problem for other packages though. Do > you have an ETA on your new packages? If not, shoot me an > email and I'll be happy to do the setup.py scripts. This depends on whether I'll find time within the next month to get the docs right and setup the web site for the new tools. > > > should be provided as Python; it's up to the Distutils to cook up a way > > > to run that code at installation-time. Yuck! Hairy, hairy, hairy... > > > > Umm, what's hairy about pre- and post-install code ? Pretty > > much all RPM-like archives provide this feature in some way > > or another. > > > > I'd suggest to have setup.py include a reference > > to two functions somewhere (probably in the setup constructor): > > one to run for pre-install and one for post-install. > > I also think this is a definite long-term need. For "relocatable" > python packages on some architectures (e.g. Solaris) it may be > necessary to re-link at install time (ld -rpath) to avoid > requiring the user to set LD_LIBRARY_PATH. (IANALG -- I Am > Not A Linking Guru, but I've had problems when things libraries > ar in different places on "install" machines than they are on > "build" machines. Right, but there are other more serious needs as well, e.g. a package might want to prebuild some database or scan the system to figure out configuration information, initialize third party tools, register APIs, COM or CORBA objects, check package dependencies etc. (just look at what CPAN does when you let it do its thing in automatic mode). There are many possibilities which can't possibly all be covered by special install or build functions. -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From R.Liebscher@gmx.de Thu May 25 18:01:02 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Thu, 25 May 2000 19:01:02 +0200 Subject: [Distutils] bdist and --compiler References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> Message-ID: <392D5C4E.E4A180FD@gmx.de> This is a multi-part message in MIME format. --------------B6F1B09420B2FD52D6E9B154 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Greg Ward wrote: > > > The second problem. Why "bdist" doesn't check only the > > source files against the finished extension modules? > > Currently it seems to check the source files against > > the compiled object files. > > Good point, I think. I'm trying *not* to emulate everything you'd do in > a real Makefile, since Distutils != make. But this could be a useful > addition, if I understand what you're saying -- I'll have to think about > it. (Hint: working patches are an excellent way to prod me into > thinking about something. They also clarify wonderfully what exactly > you're talking about.) You have the following files: XXXX.c => XXXX.o => XXXX.pyd (on Windows) If you remove the object files or use a different compiler, which wants to see XXXX.obj instead XXXX.o (msvc <=> cygwin), it would try to rebuild all, even if the XXXX.pyd-file is up-to-date. I have the place in the build_ext.py file to change this, the patch is attached. I simple let check it before I start the compiler (which only can check XXXX.c<=>XXXX.o and XXXX.o<=>XXXX.pyd) > How does a "--help-compilers" global option sound? (Kind of on the same > level as "--help-commands".) It's a bit klugey, but I can't think of a > better option offhand. There are more options which could need such a list (bdist format), perhaps we should introduce something like --help-option XXXXX ( XXXXX = compiler,format,...) It could scan all commands for a option with this name and a more extensive description (string or Callable, which generates a string on the fly.) Kind regards Rene Liebscher --------------B6F1B09420B2FD52D6E9B154 Content-Type: text/plain; charset=us-ascii; name="build_ext.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="build_ext.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py distutils.patched/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Thu May 25 03:10:04 2000 +++ distutils.patched/distutils/command/build_ext.py Thu May 25 18:47:24 2000 @@ -12,7 +12,7 @@ from types import * from distutils.core import Command from distutils.errors import * - +from distutils.dep_util import newer_group # An extension name is just a dot-separated list of Python NAMEs (ie. # the same as a fully-qualified module name). @@ -285,7 +285,28 @@ "a list of source filenames") % extension_name sources = list (sources) - self.announce ("building '%s' extension" % extension_name) + fullname = self.get_ext_fullname (extension_name) + if self.inplace: + # ignore build-lib -- put the compiled extension into + # the source tree along with pure Python modules + + modpath = string.split (fullname, '.') + package = string.join (modpath[0:-1], '.') + base = modpath[-1] + + build_py = self.find_peer ('build_py') + package_dir = build_py.get_package_dir (package) + ext_filename = os.path.join (package_dir, + self.get_ext_filename(base)) + else: + ext_filename = os.path.join (self.build_lib, + self.get_ext_filename(fullname)) + + if not newer_group(sources,ext_filename,'newer'): + self.announce ("skipping '%s' extension (up-to-date)" % extension_name) + continue # 'for' loop over all extensions + else: + self.announce ("building '%s' extension" % extension_name) # First step: compile the source code to object files. This # drops the object files in the current directory, regardless @@ -356,23 +377,6 @@ extra_args.append ('/IMPLIB:' + implib_file) self.mkpath (os.path.dirname (implib_file)) # if MSVC - - fullname = self.get_ext_fullname (extension_name) - if self.inplace: - # ignore build-lib -- put the compiled extension into - # the source tree along with pure Python modules - - modpath = string.split (fullname, '.') - package = string.join (modpath[0:-1], '.') - base = modpath[-1] - - build_py = self.find_peer ('build_py') - package_dir = build_py.get_package_dir (package) - ext_filename = os.path.join (package_dir, - self.get_ext_filename(base)) - else: - ext_filename = os.path.join (self.build_lib, - self.get_ext_filename(fullname)) self.compiler.link_shared_object (objects, ext_filename, libraries=libraries, --------------B6F1B09420B2FD52D6E9B154-- From thomas.heller@ion-tof.com Thu May 25 20:41:29 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Thu, 25 May 2000 21:41:29 +0200 Subject: [Distutils] Thinking about a Windows Installer References: <010901bfc01b$8fedf590$4500a8c0@thomasnb> <20000520104114.E318@beelzebub> <037501bfc4f3$53362e60$4500a8c0@thomasnb> <20000524192047.A318@beelzebub> Message-ID: <032c01bfc681$38cb1f60$4500a8c0@thomasnb> From: "Greg Ward" > (When > someone can download Zope and run "python setup.py install", and > setup.py is a reasonably normal Distutils-style setup script, then I > will hang up my keyboard and go home.) Does not sound impossible, because: Zope is not more than some python-modules and some c-extensions. Well, python itself is also included (on Windows, have to check this on unix). Mark Hammonds win32all extensions are more of a challange (but that would not interest YOU very much, until they are ported to *nix ;-) > A few questions/comments: > > * the default installation directory should obviously be where > Python will find it: sys.prefix. So you'll either have to > run "python -c 'import sys; print sys.prefix'" or get this > information from the registry. I'm guessing the latter > is preferable and doable -- as long as you can put arbitrary code > into the self-extractor. I think it should use the python installation directory from the registry. How should the installer find python otherwise? > > * what if there are multiple Python installations -- are they > sufficiently differentiated in the registry? Eg. I might > have Python 1.5.2 and 1.6a2 installed, and I would have to > choose which one to install to. Would read the registry entries and ask the user which version to use. If this is possible at all: .pyc files or compiled c-extensions are specific to the python version (Not necessarily for pyc files, but see the current discussion on python-dev). Probably the default should be the python version used to build the installation. Question: The installer should probably compile the .py files to .pyc/.pyo? If this has to be done, we have no other choice than to embed (or call) python. > What if it's a question of > 1.6a1 vs 1.6a2 -- are Python's registry entries sufficently > fine-grained to resolve this? No. Registry entries are for 1.5 or 1.6. > > * should we allow writing to a different directory than the default > (sys.prefix)? (This would require writing a .pth file in > sys.prefix.) Or is this getting too close to a "real" installer? Not complicated. > > * how would the actual installer be created? I'm hoping that > the CCompiler abstraction would be good enough -- just create > yourself a CCompiler (which could be a MSVCCompiler, BCCompiler, > Mingw32CCompiler, ...) object, compile a few things, and > link an executable. build_wininst will NOT generate c-code needed to be compiled. > > * interesting data point/existence proof: the Java installer- > generator InstallAnywhere let me create an executable Windows > installer *entirely* on my Solaris box -- I think it carries > around a "stub" executable, and somehow generates the real > executable by munging it with my Java code (and other stuff > to install). Needless to say, this is *very* cool; it is also > an incredibly fat, slow, and heavyweight product. If you can > let me generate Windows installers under Solaris or Linux, > I'll buy you *two* beers at the next Python conference. (I > already owe you one.) ;-) Yes, I'm heading in this direction. build_wininst will certainly append metadata and files to be installed to a prebuilt stub program. Thomas From gward@python.net Thu May 25 23:33:54 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 18:33:54 -0400 Subject: [Distutils] Terminology question Message-ID: <20000525183354.A422@beelzebub> A question of terminology: frequently in the Distutils docs I need to refer to the package-that-is-not-a-package, ie. the "root" or "empty" package. I can't decide if I prefer "root package", "empty package" or what. ("Empty" just means the *name* is empty, so it's probably not a very good thing to say "empty package" -- but "package with no name" or "unnamed package" aren't much better.) Is there some accepted convention that I have missed? Here's the definition I've just written for the "Distribution Python Modules" manual: \item[root package] the ``package'' that modules not in a package live in. The vast majority of the standard library is in the root package, as are many small, standalone third-party modules that don't belong to a larger module collection. (The root package isn't really a package, since it doesn't have an \file{\_\_init\_\_.py} file. But we have to call it something.) Confusing enough? I thought so... Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ Beware of altruism. It is based on self-deception, the root of all evil. From guido@python.org Fri May 26 02:50:24 2000 From: guido@python.org (Guido van Rossum) Date: Thu, 25 May 2000 20:50:24 -0500 Subject: [Distutils] Re: [Python-Dev] Terminology question In-Reply-To: Your message of "Thu, 25 May 2000 18:33:54 -0400." <20000525183354.A422@beelzebub> References: <20000525183354.A422@beelzebub> Message-ID: <200005260150.UAA10169@cj20424-a.reston1.va.home.com> Greg, If you have to refer to it as a package (which I don't doubt), the correct name is definitely the "root package". A possible clarification of your glossary entry: \item[root package] the root of the hierarchy of packages. (This isn't really a package, since it doesn't have an \file{\_\_init\_\_.py} file. But we have to call it something.) The vast majority of the standard library is in the root package, as are many small, standalone third-party modules that don't belong to a larger module collection. --Guido van Rossum (home page: http://www.python.org/~guido/) From gward@python.net Fri May 26 02:22:05 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 21:22:05 -0400 Subject: [Distutils] Thinking about a Windows Installer In-Reply-To: <032c01bfc681$38cb1f60$4500a8c0@thomasnb>; from Thomas Heller on Thu, May 25, 2000 at 09:41:29PM +0200 References: <010901bfc01b$8fedf590$4500a8c0@thomasnb> <20000520104114.E318@beelzebub> <037501bfc4f3$53362e60$4500a8c0@thomasnb> <20000524192047.A318@beelzebub> <032c01bfc681$38cb1f60$4500a8c0@thomasnb> Message-ID: <20000525212205.A996@beelzebub> On 25 May 2000, Thomas Heller said: > Zope is not more than some python-modules and some c-extensions. > Well, python itself is also included (on Windows, have to check this > on unix). And the Linux kernel is some C files. ;-) (BTW, I believe Unix binary distributions include Python, but I've only built Zope from source.) > Mark Hammonds win32all extensions are more of a challange (but that > would not interest YOU very much, until they are ported to *nix ;-) Ahh, I hadn't thought about Mark's stuff. You're right, must be my Unix bias. > I think it should use the python installation directory > from the registry. How should the installer find python otherwise? Good point. My understanding is that we can assume "installation directory from the registry" == sys.prefix always. True? > Would read the registry entries and ask the user which version to use. > If this is possible at all: .pyc files or compiled c-extensions are > specific to the python version (Not necessarily for pyc files, but > see the current discussion on python-dev). Oohh, ick! That affects *all* built distributions -- RPMs, Debian packages, FreeBSD packages, dumb tarballs, executable installers, *everything*. I totally forgot about that. This means that we need to record the Python version (and/or the API version and marshall magic number) when we create the built distribution. Damn... wonder what the best way to do that is. I'm reluctant to jam one more piece of information into the filename: it's ugly, it's fragile, and it's may not be possible to retrieve when it's needed. I was just about to kill off the kludgey "package_data" file that Harry Gebel introduced to make bdist_rpm work... maybe something like that is needed after all, but to convey information from the packager's installation to the installer when running on the end-user's system. > Probably the default should be the python version used to > build the installation. Yes. > Question: The installer should probably compile the .py files to .pyc/.pyo? > If this has to be done, we have no other choice than to embed (or call) > python. The way things are going is this: * the bdist_* command runs the install command, "redirecting" the installation into an alternate location. (It does this by setting the 'root' option, eg. to "build/bdist.linux2-i586/rpm", or "build/bdist.nt/wininst".) * by default, install_lib (called by install) byte-compiles .py files. (Soon, it'll probably create both .pyc and .pyo.) Thus, .pyc (and maybe .pyo) files will be included in the built distribution for free. This makes the installer's job easier, less prone to mysterious errors, etc. etc. Apart from increasing the size of the installer by a factor of ~2-3, it's a win. I realize this is back-pedalling on a decision made many moons ago, the result of which is that byte-compilation -- when building from source! -- is done at install-time rather than build-time. I have been known to change my mind six times before breakfast, though, so this is not a huge departure for me. > build_wininst will NOT generate c-code needed to be compiled. [...] > Yes, I'm heading in this direction. > build_wininst will certainly append metadata and files to be installed > to a prebuilt stub program. I hate to sound like I want *everything*, but it might be nice to make compiling the installer an option. As long as the stub isn't too big (30-50k?), getting a workable stub is more important -- especially if it lets me generate Windows installers on my Linux box! Greg -- Greg Ward - just another Python hacker gward@python.net http://starship.python.net/~gward/ I appoint you ambassador to Fantasy Island!!! From gward@python.net Fri May 26 02:35:26 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 21:35:26 -0400 Subject: [Distutils] bdist and --compiler In-Reply-To: <392D5C4E.E4A180FD@gmx.de>; from Rene Liebscher on Thu, May 25, 2000 at 07:01:02PM +0200 References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> <392D5C4E.E4A180FD@gmx.de> Message-ID: <20000525213526.B996@beelzebub> On 25 May 2000, Rene Liebscher said: > You have the following files: > > XXXX.c => XXXX.o => XXXX.pyd > > (on Windows) > > If you remove the object files or use a different compiler, which wants > to see XXXX.obj instead XXXX.o (msvc <=> cygwin), it would try to > rebuild > all, even if the XXXX.pyd-file is up-to-date. Yup, good explanation. Now that you put it this way, this has bugged me in the past. The problem, of course, is that Distutils != make: we don't have a dependency graph, we're not doing topological sorts, etc. We just compare this timestamp to that timestamp. So we end up doing stupid stuff occasionally. > I have the place in the build_ext.py file to change this, the patch is > attached. I simple let check it before I start the compiler (which > only can check XXXX.c<=>XXXX.o and XXXX.o<=>XXXX.pyd) ...and this is a lovely hack: fixes the problem at hand without going overboard. Checked in -- thanks! > There are more options which could need such a list (bdist format), > perhaps we should introduce something like --help-option XXXXX > ( XXXXX = compiler,format,...) It could scan all commands for a option > with this name and a more extensive description (string or Callable, > which > generates a string on the fly.) Good point. This should be some sort of "extra interface" that certain commands will implement: they need to announce which of their options have a help option, what that help option should be called (default: "--help-" + option_name), and what the values are. If you want to give this a shot, go for it -- I'm kept busy enough just processing incoming patches and trying to write the docs! Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ A man wrapped up in himself makes a very small package. From gward@python.net Fri May 26 03:01:21 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 22:01:21 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392D4262.CF25D949@lemburg.com>; from M.-A. Lemburg on Thu, May 25, 2000 at 05:10:26PM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> Message-ID: <20000525220121.C996@beelzebub> [Marc-Andre wants pre- and post-install hooks] > I'd suggest to have setup.py include a reference > to two functions somewhere (probably in the setup constructor): > one to run for pre-install and one for post-install. [Harry Henry Gebel points out Distutils' extensibility mechanism] > You can do this now by defining your own install command in setup, I > am providing my own build command in PyNcurses to perform some > pre-build actions. [Marc-Andre thinks otherwise] > I'd rather like to see predefined hooks for this than > having to define my own install command. There are two meanings to "install", and I think each of you is talking about a different one. I believe MAL wants to supply pre-install and post-install hooks that would run when someone installs from (eg.) an RPM or executable installer -- ie. from a smart built distribution that has support for {pre,post}-install hooks. Harry was talking about overriding the Distutils "install" command, which is fine as long as people only build and install from source. They don't. If you define {pre,post}-install by defining your own "install" command, then they will run on the packager's system, might take effect in the packager's build/bdist./ directory, and might be propagated to the end-user's machine. But if you tweak the Windows registry, or add a user to /etc/passwd, or what-have-you, then it only affects the packager's machine. Not good. We need a way for module developers to supply a snippet (or a pile) of Python code that is carried along for the ride when a packager creates a smart built distribution (RPM, wininst, Wise, .deb, whatever) and executed when the installer installs from the smart built distribution. It's OK to write these hooks in Python, because of course there's a Python interpreter on the other end. It should be possibly to write completely portable hooks, but I imagine most such real-world hooks would look like this: if os.name == "posix": # poke around /lib, frob something in /etc, ... elif os.name == "nt": # twiddle the registry, check for some DLL, ... else: raise RuntimeError, \ "don't know how to install on platform '%s'" % os.name which in many cases is the Distutils approach to portability. Some of those if/elif/.../else constructs have grown "mac" branches, but not all yet. These install hooks should be run by the "install" command if this is a "real" installation, but not if it's a "fake" installation done on behalf of one of the "bdist" commands to a temp directory. Anyone got ideas for a good interface? Function, class, module, chunk of source code as text, or what? > BTW, how can I add some Q&A style setup dialog to build and > install commands ? > > I will need this for mxODBC since there are plenty subpackages > which can all be installed separately and each of them will > need to know where to find the header files and libs to link > against. Oops, this reminds me of the part of config files that I forgot to implement: custom configuration information for the current distribution. The idea is that users would edit setup.cfg to provide things like library search paths here. IMHO that's preferable to an interactive build process, but only slightly. > mxDateTime has a different need, which I'm not really sure > how to handle: it needs some sort of "try to compile this > and return the exit code from the compiler" + "if this > compiles, run the result and return the exit code" to be able > to define symbols such as HAVE_TIMEGM (much like autoconf > does on Unix). > > Is this possible with the current distutils ? No. I've been putting that off as long as possible, because I fear it's a huge job. It basically means rewriting Autoconf in Python. The good news is, no M4 or shell scripts; the bad news is, it has to be insanely portable. (The CCompiler framework should help enormously here, but even so...) > And a final question: do I have to redistribute distutils > together with the mx packages in order to make sure that > the build and install process works ? What about 1.5.2 > compatibility ? All versions of the Distutils will work with Python 1.5.2, at least until Python 1.5.2 is as dead as Python 1.4 is today. The basic idea is this: if someone wants to build from source, they either have to be running Python 1.6, or they have to download and install Distutils to their Python 1.5.2 installation. I will write up an exemplary blurb and put it in the "Distributing Python Modules" documentation -- most programmers seem to have a hard time expressing themselves clearly in README files, and this particular concept must be made loud and clear in every README for every Python module distribution. Incidentally, I have not had a single complaint of Python 1.5.1 incompatibility since March, when I released Distutils 0.1.4 and 0.1.5 expressly for Python 1.5.1 compatibility. I have not ported those changes forward to the current Distutils, have very little desire to do so, and have seen no reason to do so -- ie. no complaints from users. So does anyone care if I drop my goal of Python 1.5.1 compatibility? (Hey, there's always Distutils 0.1.5 for the Python 1.5.1 crowd...) Greg -- Greg Ward - programmer-at-large gward@python.net http://starship.python.net/~gward/ Hold the MAYO & pass the COSMIC AWARENESS ... From gward@python.net Fri May 26 03:03:16 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 22:03:16 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392CFBA3.E4B5131E@lemburg.com>; from M.-A. Lemburg on Thu, May 25, 2000 at 12:08:35PM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> Message-ID: <20000525220316.D996@beelzebub> On 25 May 2000, M.-A. Lemburg said: > FYI, I'm going to package the mx stuff in 3-4 ZIP archives: > > 1. base (this one contains the __init__.py file and always > has to be installed) > 2. crypto (optional add-in with mx.Crypto) > 3. mx-ug (subpackages only available to mx User Group members) > 4. commercial (things like mx.ODBC and some other DB related > subpackages) > > There will no longer be separate mxTools, mxTextTools, > mxDateTime, etc. packages. Do you mean "package" as in a directory with an __init__.py file, or as in something others download, build, and install? > Umm, what's hairy about pre- and post-install code ? Pretty > much all RPM-like archives provide this feature in some way > or another. See my previous post: it's not the code that's hairy, it's getting it from the developer to the installer correctly. Greg -- Greg Ward - "always the quiet one" gward@python.net http://starship.python.net/~gward/ I have a VISION! It's a RANCID double-FISHWICH on an ENRICHED BUN!! From gward@python.net Fri May 26 03:07:00 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 22:07:00 -0400 Subject: [Distutils] handling complex link/library specifications In-Reply-To: ; from Andrew MacIntyre on Thu, May 25, 2000 at 02:07:14PM +0000 References: Message-ID: <20000525220700.E996@beelzebub> On 25 May 2000, Andrew MacIntyre said: > > There wouldn't be a convenient way to override the linker command ("ld -G" on > Solaris, from the Python Makefile) would there? > I have taken to editing the Makefile installed by Python because of this problem. I also made a patch for the configure script that would fix this for Python 1.6 (use "$(CC) -g" on Solaris if cc=gcc); the only feedback I've had is "it can't make things *worse*". Hardly encouraging, that. But no, there's no way to override what's in Python's Makefile: Distutils takes it at face-value. This should probably be fixed, especially now that we have config files (hooray!). BTW, you mentioned in your followup that you figured out a workaround: care to share it with the rest of us? Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ Cheops' Law: Nothing *ever* gets built on schedule or within budget. From gward@python.net Fri May 26 03:10:38 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 22:10:38 -0400 Subject: [Distutils] Re: [Python-Dev] Terminology question In-Reply-To: <200005260150.UAA10169@cj20424-a.reston1.va.home.com>; from Guido van Rossum on Thu, May 25, 2000 at 08:50:24PM -0500 References: <20000525183354.A422@beelzebub> <200005260150.UAA10169@cj20424-a.reston1.va.home.com> Message-ID: <20000525221038.F996@beelzebub> On 25 May 2000, Guido van Rossum said: > A possible clarification of your glossary entry: > > \item[root package] the root of the hierarchy of packages. (This > isn't really a package, since it doesn't have an > \file{\_\_init\_\_.py} file. But we have to call it something.) The > vast majority of the standard library is in the root package, as are > many small, standalone third-party modules that don't belong to a > larger module collection. I like it. One more sentence and then I'll stop: Unlike regular packages, modules in the root package can be found in many directories: in fact, every directory listed in \code{sys.path} can contribute modules to the root package. (It's OK to refer to sys.path, since this is the manual for developers. The manual for installers is much harder...) Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ Just because you're paranoid doesn't mean they *aren't* out to get you. From andrew.macintyre@aba.gov.au Fri May 26 13:31:27 2000 From: andrew.macintyre@aba.gov.au (andrew.macintyre@aba.gov.au) Date: Fri, 26 May 2000 12:31:27 AES Subject: [Distutils] handling complex link/library specifications Message-ID: The reason that using "cc" worked and "ld" didn't was that the Sun compiler was silently using a different library directory (/opt/SUNWspro/SC4.2/lib) to what I thought was the correct library directory (/opt/SUNWspro/lib) for ld to use. The latter is just a set of symlinks to the former, but doesn't include links for the static libraries :-(. Once I fed the former to ld, the -B toggles had the desired result (all 4 of those libraries don't get installed on the target system, so static linking them removes a headache). I was then able to use 'extra_link_args' to handle those static libs and the -R option. ------------------------------------------------------------- Andrew MacIntyre \ andrew.macintyre@aba.gov.au Planning & Licensing Branch \ Tel: +61 2 6256 2812 Australian Broadcasting Authority \ Fax: +61 2 6253 3277 ---------- Original Text ---------- From: Greg Ward , on 26/05/00 12:17: On 25 May 2000, Andrew MacIntyre said: > > There wouldn't be a convenient way to override the linker command ("ld -G" on > Solaris, from the Python Makefile) would there? > I have taken to editing the Makefile installed by Python because of this problem. I also made a patch for the configure script that would fix this for Python 1.6 (use "$(CC) -g" on Solaris if cc=gcc); the only feedback I've had is "it can't make things *worse*". Hardly encouraging, that. But no, there's no way to override what's in Python's Makefile: Distutils takes it at face-value. This should probably be fixed, especially now that we have config files (hooray!). BTW, you mentioned in your followup that you figured out a workaround: care to share it with the rest of us? Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ Cheops' Law: Nothing *ever* gets built on schedule or within budget. _______________________________________________ Distutils-SIG maillist - Distutils-SIG@python.org http://www.python.org/mailman/listinfo/distutils-sig From gward@python.net Fri May 26 03:22:03 2000 From: gward@python.net (Greg Ward) Date: Thu, 25 May 2000 22:22:03 -0400 Subject: [Distutils] Where to install non-code files Message-ID: <20000525222203.A1114@beelzebub> Another one for the combined distutils/python-dev braintrust; apologies to those of you on both lists, but this is yet another distutils issue that treads on python-dev territory. The problem is this: some module distributions need to install files other than code (modules, extensions, and scripts). One example close to home is the Distutils; it has a "system config file" and will soon have a stub executable for creating Windows installers. On Windows and Mac OS, clearly these should go somewhere under sys.prefix: this is the directory for all things Python, including third-party module distributions. If Brian Hooper distributes a module "foo" that requires a data file containing character encoding data (yes, this is based on a true story), then the module belongs in (eg.) C:\Python and the data file in (?) C:\Python\Data. (Maybe C:\Python\Data\foo, but that's a minor wrinkle.) Any disagreement so far? Anyways, what's bugging me is where to put these files on Unix. /lib/python1.x is *almost* the home for all things Python, but not quite. (Let's ignore platform-specific files for now: they don't count as "miscellaneous data files", which is what I'm mainly concerned with.) Currently, misc. data files are put in /share, and the Distutil's config file is searched for in the directory of the distutils package -- ie. site-packages/distutils under 1.5.2 (or ~/lib/python/distutils if that's where you installed it, or ./distutils if you're running from the source directory, etc.). I'm not thrilled with either of these. My inclination is to nominate a directory under lib/python1.x for these sort of files: not sure if I want to call it "etc" or "share" or "data" or what, but it would be treading in Python-space. It would break the ability to have a standard library package called "etc" or "share" or "data" or whatever, but dammit it's convenient. Better ideas? Greg -- Greg Ward - "always the quiet one" gward@python.net http://starship.python.net/~gward/ I have many CHARTS and DIAGRAMS.. From mhammond@skippinet.com.au Fri May 26 03:35:47 2000 From: mhammond@skippinet.com.au (Mark Hammond) Date: Fri, 26 May 2000 12:35:47 +1000 Subject: [Distutils] RE: [Python-Dev] Where to install non-code files In-Reply-To: <20000525222203.A1114@beelzebub> Message-ID: > On Windows and Mac OS, clearly these should go somewhere under > sys.prefix: this is the directory for all things Python, including > third-party module distributions. If Brian Hooper distributes a module > "foo" that requires a data file containing character encoding data (yes, > this is based on a true story), then the module belongs in (eg.) > C:\Python and the data file in (?) C:\Python\Data. (Maybe > C:\Python\Data\foo, but that's a minor wrinkle.) > > Any disagreement so far? A little. I dont think we need a new dump for arbitary files that no one can associate with their application. Why not put the data with the code? It is quite trivial for a Python package or module to find its own location, and this way we are not dependent on anything. Why assume packages are installed _under_ Python? Why not just assume the package is _reachable_ by Python. Once our package/module is being executed by Python, we know exactly where we are. On my machine, there is no "data" equivilent; the closest would be "python-cvs\pcbuild\data", and that certainly doesnt make sense. Why can't I just place it where I put all my other Python extensions, ensure it is on the PythonPath, and have it "just work"? It sounds a little complicated - do we provide an API for this magic location, or does everybody cut-and-paste a reference implementation for locating it? Either way sounds pretty bad - the API shouldnt be distutils dependent (I may not have installed this package via distutils), and really Python itself shouldnt care about this... So all in all, I dont think it is a problem we need to push up to this level - let each package author do whatever makes sense, and point out how trivial it would be if you assumed code and data in the same place/tree. [If the data is considered read/write, then you need a better answer anyway, as you can't assume "c:\python\data" is writable (when actually running the code) anymore than "c:\python\my_package" is] Mark. From fdrake@acm.org Fri May 26 04:05:40 2000 From: fdrake@acm.org (Fred L. Drake) Date: Thu, 25 May 2000 20:05:40 -0700 (PDT) Subject: [Distutils] Terminology question In-Reply-To: <20000525183354.A422@beelzebub> Message-ID: On Thu, 25 May 2000, Greg Ward wrote: > A question of terminology: frequently in the Distutils docs I need to > refer to the package-that-is-not-a-package, ie. the "root" or "empty" > package. I can't decide if I prefer "root package", "empty package" or > what. ("Empty" just means the *name* is empty, so it's probably not a > very good thing to say "empty package" -- but "package with no name" or > "unnamed package" aren't much better.) Well, it's not a package -- it's similar to Java's unnamed package, but the idea that it's a package has never been advanced. Why not just call it the global module space (or namespace)? That's the only way I've heard it described, and it's more clear than "empty package" or "unnamed package". -Fred -- Fred L. Drake, Jr. From mal@lemburg.com Fri May 26 09:49:54 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 26 May 2000 10:49:54 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> <20000525220121.C996@beelzebub> Message-ID: <392E3AB2.D53CF1A0@lemburg.com> Greg Ward wrote: > > [Marc-Andre wants pre- and post-install hooks] > > I'd suggest to have setup.py include a reference > > to two functions somewhere (probably in the setup constructor): > > one to run for pre-install and one for post-install. > > [Harry Henry Gebel points out Distutils' extensibility mechanism] > > You can do this now by defining your own install command in setup, I > > am providing my own build command in PyNcurses to perform some > > pre-build actions. > > [Marc-Andre thinks otherwise] > > I'd rather like to see predefined hooks for this than > > having to define my own install command. > > There are two meanings to "install", and I think each of you is talking > about a different one. I believe MAL wants to supply pre-install and > post-install hooks that would run when someone installs from (eg.) an > RPM or executable installer -- ie. from a smart built distribution that > has support for {pre,post}-install hooks. Hmm, the pre/post-install hooks are definitely an install thing. We'd also need a pre-build, though, for the things I mentioned below, e.g. finding header files and libs, checking the compiler, etc. > Harry was talking about overriding the Distutils "install" command, > which is fine as long as people only build and install from source. > They don't. If you define {pre,post}-install by defining your own > "install" command, then they will run on the packager's system, might > take effect in the packager's build/bdist./ directory, and > might be propagated to the end-user's machine. But if you tweak the > Windows registry, or add a user to /etc/passwd, or what-have-you, then > it only affects the packager's machine. Not good. > > We need a way for module developers to supply a snippet (or a pile) of > Python code that is carried along for the ride when a packager creates a > smart built distribution (RPM, wininst, Wise, .deb, whatever) and > executed when the installer installs from the smart built distribution. > It's OK to write these hooks in Python, because of course there's a > Python interpreter on the other end. It should be possibly to write > completely portable hooks, but I imagine most such real-world hooks > would look like this: > > if os.name == "posix": > # poke around /lib, frob something in /etc, ... > elif os.name == "nt": > # twiddle the registry, check for some DLL, ... > else: > raise RuntimeError, \ > "don't know how to install on platform '%s'" % os.name > > which in many cases is the Distutils approach to portability. Some of > those if/elif/.../else constructs have grown "mac" branches, but not all > yet. > > These install hooks should be run by the "install" command if this is a > "real" installation, but not if it's a "fake" installation done on > behalf of one of the "bdist" commands to a temp directory. > > Anyone got ideas for a good interface? Function, class, module, chunk > of source code as text, or what? Why not add some keywords to the constructor ?! import mx.ODBC.Misc.DistSupport setup( preinstall = mx.ODBC.Misc.DistSupport.preinstall, postinstall = ...postinstall, prebuild = ...prebuild, postbuild = ...postbuild ) > > BTW, how can I add some Q&A style setup dialog to build and > > install commands ? > > > > I will need this for mxODBC since there are plenty subpackages > > which can all be installed separately and each of them will > > need to know where to find the header files and libs to link > > against. > > Oops, this reminds me of the part of config files that I forgot to > implement: custom configuration information for the current > distribution. The idea is that users would edit setup.cfg to provide > things like library search paths here. IMHO that's preferable to an > interactive build process, but only slightly. A config file is fine too, but given that someone may want to write an installer, I think we'd also need an API hook for this. > > mxDateTime has a different need, which I'm not really sure > > how to handle: it needs some sort of "try to compile this > > and return the exit code from the compiler" + "if this > > compiles, run the result and return the exit code" to be able > > to define symbols such as HAVE_TIMEGM (much like autoconf > > does on Unix). > > > > Is this possible with the current distutils ? > > No. I've been putting that off as long as possible, because I fear it's > a huge job. It basically means rewriting Autoconf in Python. The good > news is, no M4 or shell scripts; the bad news is, it has to be insanely > portable. (The CCompiler framework should help enormously here, but > even so...) Naa... no need to rewrite Autoconf in Python: the simple tests can easily be done using a few lines of Python provided that the compiler classes allow these trial-and-error approaches. > > And a final question: do I have to redistribute distutils > > together with the mx packages in order to make sure that > > the build and install process works ? What about 1.5.2 > > compatibility ? > > All versions of the Distutils will work with Python 1.5.2, at least > until Python 1.5.2 is as dead as Python 1.4 is today. The basic idea is > this: if someone wants to build from source, they either have to be > running Python 1.6, or they have to download and install Distutils to > their Python 1.5.2 installation. > > I will write up an exemplary blurb and put it in the "Distributing > Python Modules" documentation -- most programmers seem to have a hard > time expressing themselves clearly in README files, and this particular > concept must be made loud and clear in every README for every Python > module distribution. > > Incidentally, I have not had a single complaint of Python 1.5.1 > incompatibility since March, when I released Distutils 0.1.4 and 0.1.5 > expressly for Python 1.5.1 compatibility. I have not ported those > changes forward to the current Distutils, have very little desire to do > so, and have seen no reason to do so -- ie. no complaints from users. > So does anyone care if I drop my goal of Python 1.5.1 compatibility? > (Hey, there's always Distutils 0.1.5 for the Python 1.5.1 crowd...) 1.5.2 is fine with me. By the time I'll push out my new stuff, 1.6 will be out anyway... so 1.5.1 is not much of a problem anymore (I will keep the current Makefile.pre.in +Setup approach for a while too). -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From mal@lemburg.com Fri May 26 09:53:46 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 26 May 2000 10:53:46 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525220316.D996@beelzebub> Message-ID: <392E3B9A.96F11B1A@lemburg.com> Greg Ward wrote: > > On 25 May 2000, M.-A. Lemburg said: > > FYI, I'm going to package the mx stuff in 3-4 ZIP archives: > > > > 1. base (this one contains the __init__.py file and always > > has to be installed) > > 2. crypto (optional add-in with mx.Crypto) > > 3. mx-ug (subpackages only available to mx User Group members) > > 4. commercial (things like mx.ODBC and some other DB related > > subpackages) > > > > There will no longer be separate mxTools, mxTextTools, > > mxDateTime, etc. packages. > > Do you mean "package" as in a directory with an __init__.py file, or as > in something others download, build, and install? Well, e.g. mxDateTime was a package in the sense that you can unzip it directly in a directory on you PYTHONPATH. Only the "base" archive will have that property. The others are add-in archives which get unzipped on top of the "base" installation. Hmm, thinking of it: would distutils allow recursive builds/installs ? Or must I add logic to figure out which parts of the cake are available to build/install and then setup a single setup.py file ? -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From gmcm@hypernet.com Fri May 26 12:53:14 2000 From: gmcm@hypernet.com (Gordon McMillan) Date: Fri, 26 May 2000 07:53:14 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <20000525222203.A1114@beelzebub> Message-ID: <1252780469-123073242@hypernet.com> Greg Ward wrote: [installing data files] > On Windows and Mac OS, clearly these should go somewhere under > sys.prefix: this is the directory for all things Python, > including third-party module distributions. If Brian Hooper > distributes a module "foo" that requires a data file containing > character encoding data (yes, this is based on a true story), > then the module belongs in (eg.) C:\Python and the data file in > (?) C:\Python\Data. (Maybe C:\Python\Data\foo, but that's a > minor wrinkle.) > > Any disagreement so far? Yeah. I tend to install stuff outside the sys.prefix tree and then use .pth files. I realize I'm, um, unique in this regard but I lost everything in some upgrade gone bad. (When a Windows de- install goes wrong, your only option is to do some manual directory and registry pruning.) I often do much the same on my Linux box, but I don't worry about it as much - upgrading is not "click and pray" there. (Hmm, I guess it is if you use rpms.) So for Windows, I agree with Mark - put the data with the module. On a real OS, I guess I'd be inclined to put global data with the module, but user data in ~/.. > Greg Ward - "always the quiet one" - Gordon From guido@python.org Fri May 26 14:13:06 2000 From: guido@python.org (Guido van Rossum) Date: Fri, 26 May 2000 08:13:06 -0500 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: Your message of "Fri, 26 May 2000 07:53:14 -0400." <1252780469-123073242@hypernet.com> References: <1252780469-123073242@hypernet.com> Message-ID: <200005261313.IAA11285@cj20424-a.reston1.va.home.com> > So for Windows, I agree with Mark - put the data with the > module. On a real OS, I guess I'd be inclined to put global > data with the module, but user data in ~/.. Aha! Good distinction. Modifyable data needs to go in a per-user directory, even on Windows, outside the Python tree. But static data needs to go in the same directory as the module that uses it. (We use this in the standard test package, for example.) --Guido van Rossum (home page: http://www.python.org/~guido/) From thomas.heller@ion-tof.com Fri May 26 13:28:49 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Fri, 26 May 2000 14:28:49 +0200 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files References: <1252780469-123073242@hypernet.com> <200005261313.IAA11285@cj20424-a.reston1.va.home.com> Message-ID: <01ee01bfc70d$f1f17a20$4500a8c0@thomasnb> [Guido writes] > Modifyable data needs to go in a per-user directory, even on Windows, > outside the Python tree. > This seems to be the value of key "AppData" stored under in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Filders Right? Thomas From jlj@cfdrc.com Fri May 26 14:20:34 2000 From: jlj@cfdrc.com (Lyle Johnson) Date: Fri, 26 May 2000 08:20:34 -0500 Subject: [Distutils] Terminology question In-Reply-To: <20000525183354.A422@beelzebub> Message-ID: <003c01bfc715$2c8fde90$4e574dc0@cfdrc.com> How about "PWAN", the "package without a name"? ;) > -----Original Message----- > From: distutils-sig-admin@python.org > [mailto:distutils-sig-admin@python.org]On Behalf Of Greg Ward > Sent: Thursday, May 25, 2000 5:34 PM > To: distutils-sig@python.org; python-dev@python.org > Subject: [Distutils] Terminology question > > > A question of terminology: frequently in the Distutils docs I need to > refer to the package-that-is-not-a-package, ie. the "root" or "empty" > package. I can't decide if I prefer "root package", "empty package" or > what. ("Empty" just means the *name* is empty, so it's probably not a > very good thing to say "empty package" -- but "package with no name" or > "unnamed package" aren't much better.) > > Is there some accepted convention that I have missed? > > Here's the definition I've just written for the "Distribution Python > Modules" manual: > > \item[root package] the ``package'' that modules not in a package live > in. The vast majority of the standard library is in the root package, > as are many small, standalone third-party modules that don't belong to > a larger module collection. (The root package isn't really a package, > since it doesn't have an \file{\_\_init\_\_.py} file. But we have to > call it something.) > > Confusing enough? I thought so... > > Greg > -- > Greg Ward - Unix nerd gward@python.net > http://starship.python.net/~gward/ > Beware of altruism. It is based on self-deception, the root of all evil. > > _______________________________________________ > Distutils-SIG maillist - Distutils-SIG@python.org > http://www.python.org/mailman/listinfo/distutils-sig > From gward@mems-exchange.org Fri May 26 14:27:16 2000 From: gward@mems-exchange.org (Greg Ward) Date: Fri, 26 May 2000 09:27:16 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <1252780469-123073242@hypernet.com>; from gmcm@hypernet.com on Fri, May 26, 2000 at 07:53:14AM -0400 References: <20000525222203.A1114@beelzebub> <1252780469-123073242@hypernet.com> Message-ID: <20000526092716.B12100@mems-exchange.org> On 26 May 2000, Gordon McMillan said: > Yeah. I tend to install stuff outside the sys.prefix tree and then > use .pth files. I realize I'm, um, unique in this regard but I lost > everything in some upgrade gone bad. (When a Windows de- > install goes wrong, your only option is to do some manual > directory and registry pruning.) I think that's appropriate for Python "applications" -- in fact, now that Distutils can install scripts and miscellaneous data, about the only thing needed to properly support "applications" is an easy way for developers to say, "Please give me my own directory and create a .pth file". (Actually, the .pth file should only be one way to install an application: you might not want your app's Python library to muck up everybody else's Python path. An idea AMK and I cooked up yesterday would be an addition to the Distutils "build_scripts" command: along with frobbing the #! line to point to the right Python interpreter, add a second line: import sys ; sys.append(path-to-this-app's-python-lib) Or maybe "sys.insert(0, ...)". Anyways, that's neither here nor there. Except that applications that get their own directory should be free to put their (static) data files wherever they please, rather than having to put them in the app's Python library. I'm more concerned with the what the Distutils works best with now, though: module distributions. I think you guys have convinced me; static data should normally sit with the code. I think I'll make that the default (instead of prefix + "share"), but give developers a way to override it. So eg.: data_files = ["this.dat", "that.cfg"] will put the files in the same place as the code (which could be a bit tricky to figure out, what with the vagaries of package-ization and "extra" install dirs); data_files = [("share", ["this.dat"]), ("etc", ["that.cfg"])] would put the data file in (eg.) /usr/local/share and the config file in /usr/local/etc. This obviously makes the module writer's job harder: he has to grovel from sys.prefix looking for the files that he expects to have been installed with his modules. But if someone really wants to do this, they should be allowed to. Finally, you could also put absolute directories in 'data_files', although this would not be recommended. > (Hmm, I guess it is if you use rpms.) All the smart Unix installers (RPM, Debian, FreeBSD, ...?) I know of have some sort of dependency mechanism, which works to varying degrees of "work". I'm only familar with RPM, and my usual response to a dependency warning is "dammit, I know what I'm doing", and then I rerun "rpm --nodeps" to ignore the dependency checking. (This usually arises because I build my own Perl and Python, and don't use Red Hat's -- I just make /usr/bin/{perl,python} symlinks to /usr/local/bin, which RPM tends to whine about.) But it's nice to know that someone is watching. ;-) Greg -- Greg Ward - software developer gward@mems-exchange.org MEMS Exchange / CNRI voice: +1-703-262-5376 Reston, Virginia, USA fax: +1-703-262-5367 From gward@mems-exchange.org Fri May 26 14:30:29 2000 From: gward@mems-exchange.org (Greg Ward) Date: Fri, 26 May 2000 09:30:29 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <200005261313.IAA11285@cj20424-a.reston1.va.home.com>; from guido@python.org on Fri, May 26, 2000 at 08:13:06AM -0500 References: <1252780469-123073242@hypernet.com> <200005261313.IAA11285@cj20424-a.reston1.va.home.com> Message-ID: <20000526093028.C12100@mems-exchange.org> On 26 May 2000, Guido van Rossum said: > Modifyable data needs to go in a per-user directory, even on Windows, > outside the Python tree. > > But static data needs to go in the same directory as the module that > uses it. (We use this in the standard test package, for example.) What about the Distutils system config file (pydistutils.cfg)? This is something that should only be modified by the sysadmin, and sets the site-wide policy for building and installing Python modules. Does this belong in the code directory? (I hope so, because that's where it goes now...) (Under Unix, users can have a personal Distutils config file that overrides the system config (~/.pydistutils.cfg), and every module distribution can have a setup.cfg that overrides both of them. On Windows and Mac OS, there are only two config files: system and per-distribution.) Greg -- Greg Ward - software developer gward@mems-exchange.org MEMS Exchange / CNRI voice: +1-703-262-5376 Reston, Virginia, USA fax: +1-703-262-5367 From gward@mems-exchange.org Fri May 26 15:30:15 2000 From: gward@mems-exchange.org (Greg Ward) Date: Fri, 26 May 2000 10:30:15 -0400 Subject: [Distutils] py_compile and CR in source files Message-ID: <20000526103014.A18937@mems-exchange.org> Just made an unpleasant discovery: if a Python source file has CR-LF line-endings, you can import it just fine under Unix. But attempting to 'py_compile.compile()' it fails with a SyntaxError at the first line-ending. Arrghh! This means that Distutils will either have to check/convert line-endings at build-time (hey, finally, a good excuse for the "build_py" command), or implicitly compile modules by importing them (instead of using 'py_compile.compile()'). Perhaps I should "build" modules by line-at-a-time copying -- currently it copies them in 16k chunks, which would make it hard to fix line endings. Hmmm. Greg From skip@mojam.com (Skip Montanaro) Fri May 26 10:39:39 2000 From: skip@mojam.com (Skip Montanaro) (Skip Montanaro) Date: Fri, 26 May 2000 04:39:39 -0500 (CDT) Subject: [Distutils] Re: [Python-Dev] py_compile and CR in source files In-Reply-To: <20000526103014.A18937@mems-exchange.org> References: <20000526103014.A18937@mems-exchange.org> Message-ID: <14638.18011.331703.867404@beluga.mojam.com> Greg> Arrghh! This means that Distutils will either have to Greg> check/convert line-endings at build-time (hey, finally, a good Greg> excuse for the "build_py" command), or implicitly compile modules Greg> by importing them (instead of using 'py_compile.compile()'). I don't think you can safely compile modules by importing them. You have no idea what the side effects of the import might be. How about fixing py_compile.compile() instead? -- Skip Montanaro, skip@mojam.com, http://www.mojam.com/, http://www.musi-cal.com/ "We have become ... the stewards of life's continuity on earth. We did not ask for this role... We may not be suited to it, but here we are." - Stephen Jay Gould From gmcm@hypernet.com Fri May 26 15:56:27 2000 From: gmcm@hypernet.com (Gordon McMillan) Date: Fri, 26 May 2000 10:56:27 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <20000526092716.B12100@mems-exchange.org> References: <1252780469-123073242@hypernet.com>; from gmcm@hypernet.com on Fri, May 26, 2000 at 07:53:14AM -0400 Message-ID: <1252769476-123734481@hypernet.com> Greg Ward wrote: > On 26 May 2000, Gordon McMillan said: > > Yeah. I tend to install stuff outside the sys.prefix tree and > > then use .pth files. I realize I'm, um, unique in this regard > > but I lost everything in some upgrade gone bad. (When a Windows > > de- install goes wrong, your only option is to do some manual > > directory and registry pruning.) > > I think that's appropriate for Python "applications" -- in fact, > now that Distutils can install scripts and miscellaneous data, > about the only thing needed to properly support "applications" is > an easy way for developers to say, "Please give me my own > directory and create a .pth file". Hmm. I see an application as a module distribution that happens to have a script. (Or maybe I see a module distribution as a scriptless app ;-)). At any rate, I don't see the need to dignify /share and friends with an official position. > (Actually, the .pth file > should only be one way to install an application: you might not > want your app's Python library to muck up everybody else's Python > path. An idea AMK and I cooked up yesterday would be an addition > to the Distutils "build_scripts" command: along with frobbing the > #! line to point to the right Python interpreter, add a second > line: > import sys ; sys.append(path-to-this-app's-python-lib) > > Or maybe "sys.insert(0, ...)". $PYTHONSTARTUP ?? Never really had to deal with this. On my RH box, /usr/bin/python is my build. At a client site which had 1.4 installed, I built 1.5 into $HOME/bin with a hacked getpath.c. > I'm more concerned with the what the Distutils works best with > now, though: module distributions. I think you guys have > convinced me; static data should normally sit with the code. I > think I'll make that the default (instead of prefix + "share"), > but give developers a way to override it. So eg.: > > data_files = ["this.dat", "that.cfg"] > > will put the files in the same place as the code (which could be > a bit tricky to figure out, what with the vagaries of > package-ization and "extra" install dirs); That's an artifact of your code ;-). If you figured it out once, you stand at least a 50% chance of getting the same answer a second time <.5 wink>. - Gordon From gward@mems-exchange.org Fri May 26 16:06:09 2000 From: gward@mems-exchange.org (Greg Ward) Date: Fri, 26 May 2000 11:06:09 -0400 Subject: [Distutils] Re: [Python-Dev] py_compile and CR in source files In-Reply-To: <14638.18011.331703.867404@beluga.mojam.com>; from skip@mojam.com on Fri, May 26, 2000 at 04:39:39AM -0500 References: <20000526103014.A18937@mems-exchange.org> <14638.18011.331703.867404@beluga.mojam.com> Message-ID: <20000526110608.F9083@mems-exchange.org> On 26 May 2000, Skip Montanaro said: > I don't think you can safely compile modules by importing them. You have no > idea what the side effects of the import might be. Yeah, that's my concern. > How about fixing py_compile.compile() instead? Would be a good thing to do this for Python 1.6, but I can't go back and fix all the Python 1.5.2 installations out there. Does anyone know if any good reasons why 'import' and 'py_compile.compile()' are different? Or is it something easily fixable? Greg From akuchlin@mems-exchange.org Fri May 26 16:42:21 2000 From: akuchlin@mems-exchange.org (Andrew M. Kuchling) Date: Fri, 26 May 2000 11:42:21 -0400 (EDT) Subject: [Distutils] Installing config files Message-ID: <200005261542.LAA03170@amarok.cnri.reston.va.us> I'm working on packaging the remote microscope software using Distutils, because it'll make my life easier and be a good test case for installing an application. One issue that's just come up is configuration files and upgrading. If someone installed a previous version of the software, you don't want to just blow away their painstakingly customized configuration. Strawman proposal: do this the way RPM does it, marking configuration files as special and making a backup copy. You can list config filenames in the RPM spec file, and on installation the existing version of the file is copied to .rpmsave before the new version of the file is written. The distutils version of this would be: * Add another argument to setup(): config_files = ['spam.cfg', ...] * Add build_config and install_config commands. install_config checks before overwriting an existing config file, and renames the file by adding .backup (suggestions for the extension?). Because of its installation database, RPM can check if the file hasn't been modified from the originally installed version and doesn't bother backing it up if you haven't changed the file. That doesn't seem possible for Distutils, since there's no such database, so it'll just back up all the config files. What do you all think of the idea? -- A.M. Kuchling http://starship.python.net/crew/amk/ "Python? Oh, I've heard of that. I have a friend at the NSA who uses it." -- Overhead at a meeting, quoted in c.l.p on 3 Dec 1998 From gstein@lyra.org Fri May 26 17:18:14 2000 From: gstein@lyra.org (Greg Stein) Date: Fri, 26 May 2000 09:18:14 -0700 (PDT) Subject: [Distutils] Re: [Python-Dev] py_compile and CR in source files In-Reply-To: <20000526110608.F9083@mems-exchange.org> Message-ID: On Fri, 26 May 2000, Greg Ward wrote: > On 26 May 2000, Skip Montanaro said: > > I don't think you can safely compile modules by importing them. You have no > > idea what the side effects of the import might be. > > Yeah, that's my concern. I agree. You can't just import them. > > How about fixing py_compile.compile() instead? > > Would be a good thing to do this for Python 1.6, but I can't go back and > fix all the Python 1.5.2 installations out there. You and your 1.5 compatibility... :-) > Does anyone know if any good reasons why 'import' and > 'py_compile.compile()' are different? Or is it something easily > fixable? I seem to recall needing to put an extra carriage return on the file, but that the Python parser was fine with the different newline concepts. Guido explained the difference once to me, but I don't recall offhand -- I'd have to crawl back thru the email. Just yell over the cube at him to find out. *ponder* Well, assuming that it is NOT okay with \r\n in there, then read the whole blob in and use string.replace() on it. Cheers, -g -- Greg Stein, http://www.lyra.org/ From skip@mojam.com (Skip Montanaro) Fri May 26 17:30:08 2000 From: skip@mojam.com (Skip Montanaro) (Skip Montanaro) Date: Fri, 26 May 2000 11:30:08 -0500 (CDT) Subject: [Distutils] Re: [Python-Dev] py_compile and CR in source files In-Reply-To: References: <20000526110608.F9083@mems-exchange.org> Message-ID: <14638.42640.835838.859270@beluga.mojam.com> Greg> Well, assuming that it is NOT okay with \r\n in there, then read Greg> the whole blob in and use string.replace() on it. I thought of that too, but quickly dismissed it. You may have a CRLF pair embedded in a triple-quoted string. Those should be left untouched. -- Skip Montanaro, skip@mojam.com, http://www.mojam.com/, http://www.musi-cal.com/ "We have become ... the stewards of life's continuity on earth. We did not ask for this role... We may not be suited to it, but here we are." - Stephen Jay Gould From R.Liebscher@gmx.de Fri May 26 18:03:13 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Fri, 26 May 2000 19:03:13 +0200 Subject: [Distutils] bdist and --compiler References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> <392D5C4E.E4A180FD@gmx.de> <20000525213526.B996@beelzebub> Message-ID: <392EAE51.436E551C@gmx.de> Greg Ward wrote: > > On 25 May 2000, Rene Liebscher said: > > There are more options which could need such a list (bdist format), > > perhaps we should introduce something like --help-option XXXXX > > ( XXXXX = compiler,format,...) It could scan all commands for a option > > with this name and a more extensive description (string or Callable, > > which > > generates a string on the fly.) > > Good point. This should be some sort of "extra interface" that certain > commands will implement: they need to announce which of their options > have a help option, what that help option should be called (default: > "--help-" + option_name), and what the values are. If you want to give > this a shot, go for it -- I'm kept busy enough just processing incoming > patches and trying to write the docs! Perhaps, someone else has a better overview and wants to start it. At least it would be helpful to know all options which could need more documentation. So please, extend this list: * build_ext, compiler : list of available compilers (and their long names like 'Microsoft Visual C++ 5.X and higher' or so) * bdist, format : list + explanation (gztar : creates XXXX.tar.gz) Kind regards Rene Liebscher From fdrake@acm.org Fri May 26 18:18:00 2000 From: fdrake@acm.org (Fred L. Drake) Date: Fri, 26 May 2000 10:18:00 -0700 (PDT) Subject: [Distutils] Re: [Python-Dev] py_compile and CR in source files In-Reply-To: <14638.42640.835838.859270@beluga.mojam.com> Message-ID: On Fri, 26 May 2000, Skip Montanaro wrote: > I thought of that too, but quickly dismissed it. You may have a CRLF pair > embedded in a triple-quoted string. Those should be left untouched. No, it would be OK to do the replacement; source files are supposed to be treated as text, meaning that lineends should be represented as \n. We're not talking about changing the values of the strings, which will still be treated as \n and that's what will be incorporated in the value of the string. This has no impact on the explicit inclusion of \r or \r\n in strings. -Fred -- Fred L. Drake, Jr. From mwa@gate.net Fri May 26 19:02:25 2000 From: mwa@gate.net (Mark W. Alexander) Date: Fri, 26 May 2000 14:02:25 -0400 (EDT) Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392E3B9A.96F11B1A@lemburg.com> Message-ID: On Fri, 26 May 2000, M.-A. Lemburg wrote: > > Well, e.g. mxDateTime was a package in the sense that you can > unzip it directly in a directory on you PYTHONPATH. Only the > "base" archive will have that property. The others are > add-in archives which get unzipped on top of the "base" > installation. > > Hmm, thinking of it: would distutils allow recursive > builds/installs ? Or must I add logic to figure out > which parts of the cake are available to build/install and > then setup a single setup.py file ? It allows for nested packages, if that's what you mean. I didn't have much trouble backing a setup.py that did mxDateTime, mxTextTools, and mxTools. I don't see any problem with each having their own setup.py, IF you have (as you mentioned) a "core" package that provides the foundation for all the others. Earlier, someon else said: > > BTW, how can I add some Q&A style setup dialog to build and > > install commands ? This is another good question. The SysV 'pkgtool' utilities allow not only preinstall and postinstall, but preremove, postremove and request scripts. The request script is invoked before anything is done, and allows Q&A with the installer to support customized installation. Having to support multiple packages on multiple machines of multiple architectures, I'm a strong believer in the idea that the installer should have complete controll over package installation, IF they want it (appropriate defaults assumed). In order to provide that level of flexibility, the requirements for the bdist-* modules are pushed to the point of having to provide the maximum requirements of the most complex package manager supported. This is likely to get very ugly. Pardon me while I talk circles around myself...... I'm starting to go back to what someone (Henry?) said early in the bdist-rpm progress, provide the package specification file and let it go at that. Where possible, take it to the max like bdist-rpm is, but as a minimal bdist requirement the only function required (and possibly default?) could be that of --spec-only. I really like where distutils is headed (actually, where it's at is pretty darn good!), and I hate to see much effort go into the 20% of functions that hardly anyone would use. "Most" packages don't need any scripts. Those that have major scripting needs are probably best addressed by a packager who understands packaging fairly thoroughly. Getting a spec/prototype/pkginfo/psf file, can be tedious and is the one thing distutils can easily provide. The packager can plug scripts in as required. Mark Alexander mwa@gate.net From hgebel@inet.net Sat May 27 02:07:08 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Fri, 26 May 2000 21:07:08 -0400 Subject: [Distutils] Installing config files In-Reply-To: <200005261542.LAA03170@amarok.cnri.reston.va.us>; from akuchlin@mems-exchange.org on Fri, May 26, 2000 at 11:42:21AM -0400 References: <200005261542.LAA03170@amarok.cnri.reston.va.us> Message-ID: <20000526210708.C12144@inet.net> On Fri, May 26, 2000 at 11:42:21AM -0400, Andrew M. Kuchling wrote: > Because of its installation database, RPM can check if the file hasn't > been modified from the originally installed version and doesn't bother > backing it up if you haven't changed the file. That doesn't seem > possible for Distutils, since there's no such database, so it'll just > back up all the config files. Greg suggested to me the idea of storing meta-data as part of the installation process (for later use by an uninstall command), it seems to me that this could also be used for managing config files. Unfortunately I haven't got a chance to look into it yet, but I will Real Soon Now. -- Harry Henry Gebel, Senior Developer, Landon House SBS West Dover Hundred, Delaware PyNcurses ncurses binding for Python http://pyncurses.sourceforge.net From gward@python.net Sat May 27 02:42:34 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 21:42:34 -0400 Subject: [Distutils] New command: "install_headers" Message-ID: <20000526214234.A1181@beelzebub> Hi all -- just checked in a new command, "install_headers", for installing C/C++ headers. This makes the NumPy setup script a lot smaller, and should work similar wonders for CXX and any other module distribution that needs to install header files. (Commonly needed by extensions whose C code is used by other extensions.) On Unix, header files are installed to $prefix/include/python1.x/$distname> -- eg. for NumPy, $prefix/include/python1.x/Numerical. On Windows, they go in $prefix\Include\$distname, and on Mac OS to $prefix:Include:$distname. Please, give the latest CVS code a whirl -- I'd especially like to hear if anyone else has setup scripts that install header files, and find out if "install_headers" worked for you. Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ MTV -- get off the air! -- Dead Kennedys From gward@python.net Sat May 27 02:59:00 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 21:59:00 -0400 Subject: [Distutils] bdist and --compiler In-Reply-To: <392EAE51.436E551C@gmx.de>; from Rene Liebscher on Fri, May 26, 2000 at 07:03:13PM +0200 References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> <392D5C4E.E4A180FD@gmx.de> <20000525213526.B996@beelzebub> <392EAE51.436E551C@gmx.de> Message-ID: <20000526215900.A318@beelzebub> On 26 May 2000, Rene Liebscher said: > Perhaps, someone else has a better overview and wants to start it. > At least it would be helpful to know all options which could > need more documentation. > > So please, extend this list: > > * build_ext, compiler : list of available compilers > (and their long names like 'Microsoft Visual C++ 5.X and higher' or so) > > * bdist, format : list + explanation (gztar : creates XXXX.tar.gz) That's all I can think of right now. Here's a Stupid Unix Trick (TM) to get help for all Distutils commands: ./setup.py --help `./setup.py --help-commands | awk '/^ [a-z]/ {print $1}'` (err, assuming setup.py is executable and has a proper #! line). Scanning the output of this, I see: build, build_ext, build_clib --compiler sdist --formats bdist --formats written that way because the three commands with --compiler have the same list of compilers, but the two options with --format have different lists of formats. So yes, you got them all. But there could well be more in future, so I think it's worth adding a smidge of bureaucracy to grease the wheels here. Here's a strawman proposal for "custom help option" interface. The above five command classes (and any future commands with similar requirements) would define a class attribute 'help_options': class build (Command): # ... help_options = [('compiler', show_compilers, "list available compilers (for --compiler option)")] When 'parse_command_line()' (in Distribution) sees this list, it would mangle each entry as appropriate to feed into the FancyGetopt parser, so that the following would appear in the help for "build": [...] --compiler (-c) specify the compiler type --help-compiler list available compilers (for --compiler option) [...] When --help-compiler is seen on the command line, the function 'show_compilers()' would be called. (Presumably this would really be provided by the ccompiler module, since the same function would be needed in three commands.) This has to be a function object, not a method (or method name), since the command class hasn't been instantiated when we're just parsing the command line. Presence of any --help option should terminate processing -- see the code in 'parse_command_line()'. Rene, can you whip up a patch for this? Thanks! Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ I guess it was all a DREAM ... or an episode of HAWAII FIVE-O ... From gward@python.net Sat May 27 03:28:32 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 22:28:32 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392E3AB2.D53CF1A0@lemburg.com>; from M.-A. Lemburg on Fri, May 26, 2000 at 10:49:54AM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> <20000525220121.C996@beelzebub> <392E3AB2.D53CF1A0@lemburg.com> Message-ID: <20000526222832.B318@beelzebub> On 26 May 2000, M.-A. Lemburg said: > Hmm, the pre/post-install hooks are definitely an install thing. Again, there are two meanings to install: install from source and install from a built distribution. Hooks at install-from-source time should be doable with the Distutils' existing extension mechanism (if a bit cumbersome -- you have to know how to write a Distutils command class, which is a tad idiosyncratic). > We'd also need a pre-build, though, for the things I mentioned > below, e.g. finding header files and libs, checking the compiler, > etc. In principle, that should all be doable with the Distutils' existing facilities. I'd be willing to grease the wheels by adding a standard "prebuild" or "configure" command that runs before "build", but I'd leave it empty and open to subclassing -- there's just too many things that you might want to do there! So eg. you might do this in your setup script: class configure (Command): user_options = [('foo-inc', None, ("where to search for foo headers"), ('foo-lib', None, "where to search for foo library"), ] def initialize_options (self): self.foo_inc = None self.foo_lib = None def finalize_options (self): # if user doesn't define foo_inc and foo_lib, leave them # alone (we will search for foo.h and libfoo) pass def run (self): if self.foo_inc is None: for dir in (...): # list would vary by platform # try to compile "#include " with -Idir # break if success else: # die, couldn't find foo.h # similar loop, trying to link with -lfoo and -Ldir and then a little later: setup (..., cmdclass = {'configure': configure}, ..., ) Now, what the hell do we do with 'foo_inc' and 'foo_lib' -- as written, the 'configure' command finds the foo header and library paths, and then quits without doing anything with that information. If you happen to know the guts of the Distutils, you could be evil and sneaky and do something like this: build_ext_opts = self.distribution.get_option_dict('build_ext') include_dirs = build_ext_opts.get('include_dirs') if include_dirs is None: include_dirs = build_ext_opts['include_dirs'] = [] include_dirs.append(self.foo_inc) ...and then similar code to modify build_ext's 'library_dirs' option from 'self.foo_lib'. This is nasty, though. Come to think of it, it's not entirely reliable: if the "build_ext" command object has already been created by the time we run "configure", then it's too late to go frobbing the option dict owned by the Distribution object -- you'd want to frob the "build_ext" object directly. Well, it's a common idiom to *fetch* options from another command object. And, oh yeah, I decided many months ago to stick with this "pull" model -- if command X needs option Y from command Z, then it's X's responsibility to dig up a Z object and get attribute Y from it. Just search the code for 'find_peer' to see how often this happens. Eg. in bdist.py: build_base = self.find_peer('build').build_base to find the build base directory. But there's no way the general-purpose "build" command can know what's defined in your particular "configure" command -- so this is one place where we seem to need to support "pushing" options. The problem with pushing options from one command to another is that option initialization is *tricky*, because we need to be able to derive default values in an intelligent way. See build_ext.py for a rich, meaty, but comprehensible example; or install.py for an insanely complex example. I think the difficulty of pushing options boils down to the fact that 'finalize_options()' only expects to be called once, and most commands are written in such a way that they die horribly if it is called more than once. (I have accidentally ventured into option-pushing territory once or twice in the past, and quickly retreated, licking my wounds.) This is a design/implementation flaw that I have lived with up to now, but I might not be able to any longer. Now do you see why I have avoided a "configure" command? ;-) Other little things... > Why not add some keywords to the constructor ?! > > import mx.ODBC.Misc.DistSupport > setup( > preinstall = mx.ODBC.Misc.DistSupport.preinstall, > postinstall = ...postinstall, > prebuild = ...prebuild, > postbuild = ...postbuild > ) I realize that the OO write-your-own-class alternative is a little more clunky, but I don't think it's clunky enough to mandate a function-passing interface. Can you buy that? > Naa... no need to rewrite Autoconf in Python: the simple tests > can easily be done using a few lines of Python provided that > the compiler classes allow these trial-and-error approaches. You may be right, based on the above hypothetical configure command. Abstracting some of these common functions away shouldn't be too hard. Greg -- Greg Ward - geek-on-the-loose gward@python.net http://starship.python.net/~gward/ Hold the MAYO & pass the COSMIC AWARENESS ... From gward@python.net Sat May 27 03:40:24 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 22:40:24 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <1252769476-123734481@hypernet.com>; from Gordon McMillan on Fri, May 26, 2000 at 10:56:27AM -0400 References: <1252780469-123073242@hypernet.com>; <20000526092716.B12100@mems-exchange.org> <1252769476-123734481@hypernet.com> Message-ID: <20000526224024.C318@beelzebub> On 26 May 2000, Gordon McMillan said: > Hmm. I see an application as a module distribution that > happens to have a script. (Or maybe I see a module > distribution as a scriptless app ;-)). But end-users who just want to run a Python application see it as an application; the fact that it's (largely) written in Python and includes a Python library of its own is immaterial. However, all files from that application should most likely be installed in the same place -- /usr/local/myapp or "C:\Program Files\MyApp", pick your poison. And the module developer should have the option of just dumping his stuff in /usr/local/lib/python1.x/site-packages and /usr/local/bin, or C:\Python, or whatever is the locally appropriate place to dump Python modules. Currently, of course, that's the *only* option that the Distutils easily supports. (Although I suspect that with the current code, one could craft a setup.cfg that forces the "install" command to put files wherever you damn well please. That's icky, though -- it won't deal with setting the right sys.path for your application.) [me] > An idea AMK and I cooked up yesterday would be an addition > to the Distutils "build_scripts" command: along with frobbing the > #! line to point to the right Python interpreter, add a second > line: > import sys ; sys.append(path-to-this-app's-python-lib) > > Or maybe "sys.insert(0, ...)". Oops, meant "sys.path..." there of course. [Gordon] > $PYTHONSTARTUP ?? The idea is to set sys.path for *just this application* rather than for all Python code installed on the system. This is kind of important if you have an application that defines a module "DateTime" and another, independent module called "DateTime". /usr/local/myapp/lib/python should come first in sys.path when you run myapp, and it should never be seen when you run anything else. The possibilities are: * create shell script wrappers for every Python script: eg. script1 might be PYTHONPATH=/usr/local/myapp/lib/python \ exec /usr/local/bin/python1.6 /usr/local/myapp/_script1.py * adjust the scripts at build time so set the right sys.path Nasty as it is, I incline towards the latter: if nothing else, it's more portable! But this is all speculative. The immediate aim of the Distutils is *not* full-blown Python applications, but I am starting to see how we could support such applications. A little idle speculation never hurt anyone. > That's an artifact of your code ;-). If you figured it out once, > you stand at least a 50% chance of getting the same answer > a second time <.5 wink>. What!?! Are you accusing me of writing complex code? Well... ok... maybe a little bit... but only in install.py, really... the rest of it's quite straightforward! Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ I have many CHARTS and DIAGRAMS.. From gward@python.net Sat May 27 03:42:29 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 22:42:29 -0400 Subject: [Distutils] Installing config files In-Reply-To: <200005261542.LAA03170@amarok.cnri.reston.va.us>; from Andrew M. Kuchling on Fri, May 26, 2000 at 11:42:21AM -0400 References: <200005261542.LAA03170@amarok.cnri.reston.va.us> Message-ID: <20000526224229.D318@beelzebub> On 26 May 2000, Andrew M. Kuchling said: > The distutils version of this would be: > > * Add another argument to setup(): config_files = ['spam.cfg', ...] Yup. > * Add build_config and install_config commands. install_config > checks before overwriting an existing config file, and renames > the file by adding .backup (suggestions for the extension?). Shouldn't be necessary -- could just complicate "install_data" to deal with config files as a special case. BTW there is no "build_data" command, nor does there need to be. (I think... I hope!) Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ I'd like some JUNK FOOD ... and then I want to be ALONE -- From gward@python.net Sat May 27 03:45:24 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 22:45:24 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392E3B9A.96F11B1A@lemburg.com>; from M.-A. Lemburg on Fri, May 26, 2000 at 10:53:46AM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525220316.D996@beelzebub> <392E3B9A.96F11B1A@lemburg.com> Message-ID: <20000526224524.E318@beelzebub> On 26 May 2000, M.-A. Lemburg said: > Hmm, thinking of it: would distutils allow recursive > builds/installs ? Or must I add logic to figure out > which parts of the cake are available to build/install and > then setup a single setup.py file ? This is one of those things I've pondered about in the past. Haven't ever tried it though. At a minimum, there would have to be something in the setup script that says, "these directories are sub-distributions, please cd into them in turn and run the setup script there". Presumably it would run those setup scripts with the same arguments as the current script. All speculation, of course... Greg -- Greg Ward - maladjusted nerd gward@python.net http://starship.python.net/~gward/ I'm a lumberjack and I'm OK / I sleep all night and I work all day From gward@python.net Sat May 27 04:18:11 2000 From: gward@python.net (Greg Ward) Date: Fri, 26 May 2000 23:18:11 -0400 Subject: [Distutils] Current to-do list Message-ID: <20000526231811.A1433@beelzebub> I've started maintaining my Distutils to-do list again. In the absence of a proper bug database or issue tracker, this'll have to do. Please add any items I've missed; feel free to claim items for yourself if you can submit a patch. If you're already working on a patch, let me know so I can add you. If you see your name in a "delegated to" comment but you are unwilling/unable to do that task, let me know and I'll take you off. Here's the list... GENERAL ------- * I think fancy_getopt needs to get fancier to properly support the -I, -D, -l, -L, etc. options of "build_ext": need to be able to accumulate multiple options in a list, should be able to split a string on a given delimiter, probably want to specify if repetitions of the same option will accumulate or replace, etc. * do the above options even work at all? seem to recall hearing reports of dismal failure, but I never looked into it [knowing how FancyGetopt works, there's no way these options can work: damn] * think about how to support distribution-specific "configure" commands -- eg. how can they push option values (include/library directories, that sort of thing) onto the "build_ext" command? * should/can the 'finalize_options()' methods be made more robust, so you can sensibly call them multiple times? this might be all that's necessary to enable option-pushing... HELP ---- * interface for "help about some option" -- eg. --help-compiler to build_ext would list available compilers; --help-formats to "sdist" or "bdist" would list available distribution formats; ... [delegated to Rene Liebscher] DOCS ---- * write write write * standard blurb for README files BUILD/INSTALL ------------- EXTENSION BUILDING ------------------ * review and integrate cygwin patch from Rene Liebscher DISTRIBUTIONS ------------- * review/tweak bdist_rpm code from Harry Gebel (minor style issues, fix hardcoded directories) * figure out why bdist_rpm doesn't work with RPM 2.x, and make it work if possible EXTERNAL DEPENDENCIES --------------------- * ??? do we need to implement autoconf in Python (shudder) ??? * if not, how to handle the case of "if Tk present, build with it" in PIL, or "define HAVE_STRFTIME if we have strftime()" in mxDateTime"? -- Greg Ward - maladjusted computer geek gward@python.net http://starship.python.net/~gward/ "Passionate hatred can give meaning and purpose to an empty life." -- Eric Hoffer From fdrake@acm.org Sat May 27 05:50:05 2000 From: fdrake@acm.org (Fred L. Drake) Date: Fri, 26 May 2000 21:50:05 -0700 (PDT) Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: <20000526224024.C318@beelzebub> Message-ID: On Fri, 26 May 2000, Greg Ward wrote: > [Gordon] > > $PYTHONSTARTUP ?? > > The idea is to set sys.path for *just this application* rather than for > all Python code installed on the system. This is kind of important if It's useful to remember that $PYTHONSTARTUP only affects interactive interpreters, not scripts/applications. Using this for anything related to the installed base is pretty bogus. It would also be unreliable since users won't cooperate. ;) -Fred -- Fred L. Drake, Jr. From tim_one@email.msn.com Sat May 27 05:53:14 2000 From: tim_one@email.msn.com (Tim Peters) Date: Sat, 27 May 2000 00:53:14 -0400 Subject: [Distutils] RE: [Python-Dev] py_compile and CR in source files In-Reply-To: <14638.42640.835838.859270@beluga.mojam.com> Message-ID: <000001bfc797$781e3d20$cd2d153f@tim> [GregS] > Well, assuming that it is NOT okay with \r\n in there, then read > the whole blob in and use string.replace() on it. > [Skip Montanaro] > I thought of that too, but quickly dismissed it. You may have a CRLF pair > embedded in a triple-quoted string. Those should be left untouched. Why? When Python compiles a module "normally", line-ends get normalized, and the CRLF pairs on Windows vanish anyway. For example, here's cr.py: def f(): s = """a b c d """ for ch in s: print ord(ch), print f() import dis dis.dis(f) I'm running on Win98 as I type, and the source file has CRLF line ends. C:\Python16>python misc/cr.py 97 10 98 10 99 10 100 10 That line shows that only the LFs survived. The rest shows why: 0 SET_LINENO 1 3 SET_LINENO 2 6 LOAD_CONST 1 ('a\012b\012c\012d\012') 9 STORE_FAST 0 (s) etc That is, as far as the generated code is concerned, the CRs never existed. 60-years-of-computers-and-we-still-can't-agree-on-how-to-end-a-line-ly y'rs - tim From mal@lemburg.com Sat May 27 10:20:45 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Sat, 27 May 2000 11:20:45 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> <20000525220121.C996@beelzebub> <392E3AB2.D53CF1A0@lemburg.com> <20000526222832.B318@beelzebub> Message-ID: <392F936D.E2E3D42E@lemburg.com> Greg Ward wrote: > > On 26 May 2000, M.-A. Lemburg said: > > Hmm, the pre/post-install hooks are definitely an install thing. > > Again, there are two meanings to install: install from source and > install from a built distribution. Hooks at install-from-source time > should be doable with the Distutils' existing extension mechanism (if a > bit cumbersome -- you have to know how to write a Distutils command > class, which is a tad idiosyncratic). I was referring to installing a (pre)built binary -- just before copying the compiled files to their final install location and right after that step is done. "install-from-source" would execute these hooks too: right after having built the binaries. > > We'd also need a pre-build, though, for the things I mentioned > > below, e.g. finding header files and libs, checking the compiler, > > etc. > > In principle, that should all be doable with the Distutils' existing > facilities. I'd be willing to grease the wheels by adding a standard > "prebuild" or "configure" command that runs before "build", but I'd > leave it empty and open to subclassing -- there's just too many things > that you might want to do there! Ok... if you beat me to it, I'll do some subclassing then ;-) > So eg. you might do this in your setup script: > > class configure (Command): > user_options = [('foo-inc', None, > ("where to search for foo headers"), > ('foo-lib', None, > "where to search for foo library"), > ] > > def initialize_options (self): > self.foo_inc = None > self.foo_lib = None > > def finalize_options (self): > # if user doesn't define foo_inc and foo_lib, leave them > # alone (we will search for foo.h and libfoo) > pass > > def run (self): > if self.foo_inc is None: > for dir in (...): # list would vary by platform > # try to compile "#include " with -Idir > # break if success > else: > # die, couldn't find foo.h > > # similar loop, trying to link with -lfoo and -Ldir > > and then a little later: > setup (..., > cmdclass = {'configure': configure}, > ..., > ) Looks feasable :-) > Now, what the hell do we do with 'foo_inc' and 'foo_lib' -- as written, > the 'configure' command finds the foo header and library paths, and then > quits without doing anything with that information. > > If you happen to know the guts of the Distutils, you could be evil and > sneaky and do something like this: > > build_ext_opts = self.distribution.get_option_dict('build_ext') > include_dirs = build_ext_opts.get('include_dirs') > if include_dirs is None: > include_dirs = build_ext_opts['include_dirs'] = [] > include_dirs.append(self.foo_inc) > > ...and then similar code to modify build_ext's 'library_dirs' option > from 'self.foo_lib'. > > This is nasty, though. Come to think of it, it's not entirely reliable: > if the "build_ext" command object has already been created by the time > we run "configure", then it's too late to go frobbing the option dict > owned by the Distribution object -- you'd want to frob the "build_ext" > object directly. > > Well, it's a common idiom to *fetch* options from another command > object. And, oh yeah, I decided many months ago to stick with this > "pull" model -- if command X needs option Y from command Z, then it's > X's responsibility to dig up a Z object and get attribute Y from it. > Just search the code for 'find_peer' to see how often this happens. > Eg. in bdist.py: > build_base = self.find_peer('build').build_base > to find the build base directory. Wouldn't a method interface be more reliable and provide better means of extension using subclassing ? I usually wrap these attributes in .get_foobar(), .set_foobar() methods -- this also makes it clear which attributes are read-only, read-write or "better don't touch" :-) > But there's no way the general-purpose "build" command can know what's > defined in your particular "configure" command -- so this is one place > where we seem to need to support "pushing" options. The problem with > pushing options from one command to another is that option > initialization is *tricky*, because we need to be able to derive default > values in an intelligent way. See build_ext.py for a rich, meaty, but > comprehensible example; or install.py for an insanely complex example. > > I think the difficulty of pushing options boils down to the fact that > 'finalize_options()' only expects to be called once, and most commands > are written in such a way that they die horribly if it is called more > than once. (I have accidentally ventured into option-pushing territory > once or twice in the past, and quickly retreated, licking my wounds.) > This is a design/implementation flaw that I have lived with up to now, > but I might not be able to any longer. > > Now do you see why I have avoided a "configure" command? ;-) Ehm, yes... but I can't really follow here: ok, I don't know much about the internals of distutils, but wouldn't passing a (more-or-less) intelligent context object around solve the problem ? The context object would know which parts are readable, changeable or write-once, etc. (I've been doing this in an 55k LOC application server and it works great.) > Other little things... > > > Why not add some keywords to the constructor ?! > > > > import mx.ODBC.Misc.DistSupport > > setup( > > preinstall = mx.ODBC.Misc.DistSupport.preinstall, > > postinstall = ...postinstall, > > prebuild = ...prebuild, > > postbuild = ...postbuild > > ) > > I realize that the OO write-your-own-class alternative is a little more > clunky, but I don't think it's clunky enough to mandate a > function-passing interface. Can you buy that? Ok. > > Naa... no need to rewrite Autoconf in Python: the simple tests > > can easily be done using a few lines of Python provided that > > the compiler classes allow these trial-and-error approaches. > > You may be right, based on the above hypothetical configure command. > Abstracting some of these common functions away shouldn't be too hard. Basically, I need: rc = compile("""#include "foobar.h"\nmain(){}""", output="delete.me") if rc != 0: HAVE_FOOBAR_H = 0 else: HAVE_FOOBAR_H = 1 os.unlink("delete.me") and sometimes: rc = compile("""#include "foobar.h" main() { int x = frobnicate(); exit(x); }""", output="run-and-then-delete.me") if rc != 0: HAVE_FROBNICATE = 0 else: HAVE_FROBNICATE = 1 # Run and get rc = os.system("run-and-then-delete.me") FROBINATE_VALUE = rc os.unlink("run-and-then-delete.me") -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From mal@lemburg.com Sat May 27 10:30:54 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Sat, 27 May 2000 11:30:54 +0200 Subject: [Distutils] Pondering multi-package packages References: Message-ID: <392F95CE.742863D0@lemburg.com> "Mark W. Alexander" wrote: > > On Fri, 26 May 2000, M.-A. Lemburg wrote: > > > > Well, e.g. mxDateTime was a package in the sense that you can > > unzip it directly in a directory on you PYTHONPATH. Only the > > "base" archive will have that property. The others are > > add-in archives which get unzipped on top of the "base" > > installation. > > > > Hmm, thinking of it: would distutils allow recursive > > builds/installs ? Or must I add logic to figure out > > which parts of the cake are available to build/install and > > then setup a single setup.py file ? > > It allows for nested packages, if that's what you mean. I > didn't have much trouble backing a setup.py that did > mxDateTime, mxTextTools, and mxTools. I don't see any > problem with each having their own setup.py, IF you have > (as you mentioned) a "core" package that provides the > foundation for all the others. It would probably be wise to have one setup.py file per ZIP archive. The ZIP archives have predefined content and the setup.py files could have this information hard-coded somewhere. I would have to move away from my current installation logic though (simply unzipping and then compiling in place). With distutils help this shouldn't be much of a problem though (I hope ;-). -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From gward@python.net Sun May 28 20:25:34 2000 From: gward@python.net (Greg Ward) Date: Sun, 28 May 2000 15:25:34 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392F95CE.742863D0@lemburg.com>; from M.-A. Lemburg on Sat, May 27, 2000 at 11:30:54AM +0200 References: <392F95CE.742863D0@lemburg.com> Message-ID: <20000528152534.B698@beelzebub> On 27 May 2000, M.-A. Lemburg said: > It would probably be wise to have one setup.py file per ZIP > archive. The ZIP archives have predefined content and the setup.py > files could have this information hard-coded somewhere. Good point. Does this mean I don't have to worry about recursive setup scripts after all? ;-) > I would have to move away from my current installation logic > though (simply unzipping and then compiling in place). With > distutils help this shouldn't be much of a problem though > (I hope ;-). Yes, please do! The idea of having to unpack a distribution archive in a particular place has always deeply offended me; the fact that more than one Python module distributor thought this was a good idea is one of the things that motivated me to do the Distutils in the first place. IOW, forcing you to build in one place and install to another place is a feature. Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ Always look on the bright side of life. From gward@python.net Sun May 28 20:28:43 2000 From: gward@python.net (Greg Ward) Date: Sun, 28 May 2000 15:28:43 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files In-Reply-To: ; from Fred L. Drake on Fri, May 26, 2000 at 09:50:05PM -0700 References: <20000526224024.C318@beelzebub> Message-ID: <20000528152843.C698@beelzebub> On 26 May 2000, Fred L. Drake said: > It's useful to remember that $PYTHONSTARTUP only affects interactive > interpreters, not scripts/applications. Using this for anything related > to the installed base is pretty bogus. It would also be unreliable since > users won't cooperate. ;) Thanks for the reminder. The latter also applies to PYTHONPATH: if you expect an environment variable to be set, you had bloody well better supply a shell script that sets it appropriately. (And forget about portability to Mac OS or Windows -- or at least, forget about being used on Windows by anybody except Unix refugees.) I have yet to hear howls of my revulsion at my loopy idea of sticking this: import sys; sys.path.insert(0, application-python-path) into scripts that are installed as part of a "Python application" (ie. a module distribution whose main interface is a script or scripts, and that gets its own directory rather than dangling off Python's library directory). Could it be that people actually think this is a *good* idea? ;-) Greg -- Greg Ward - maladjusted nerd gward@python.net http://starship.python.net/~gward/ Hold the MAYO & pass the COSMIC AWARENESS ... From gward@python.net Sun May 28 20:23:17 2000 From: gward@python.net (Greg Ward) Date: Sun, 28 May 2000 15:23:17 -0400 Subject: [Distutils] Pondering multi-package packages In-Reply-To: <392F936D.E2E3D42E@lemburg.com>; from M.-A. Lemburg on Sat, May 27, 2000 at 11:20:45AM +0200 References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> <20000525220121.C996@beelzebub> <392E3AB2.D53CF1A0@lemburg.com> <20000526222832.B318@beelzebub> <392F936D.E2E3D42E@lemburg.com> Message-ID: <20000528152317.A698@beelzebub> On 27 May 2000, M.-A. Lemburg said: > I was referring to installing a (pre)built binary -- just before > copying the compiled files to their final install location and > right after that step is done. Yes: this is the one place where the Distutils' extension mechanism *won't* work, because the Distutils aren't present (or at least, not in control) when installing a pre-built binary. Here, some other mechanism will be needed: pass a function, or a module, or a chunk of code to be eval'd, or something. Still not sure what's best; we have to balance the needs of the developer writing the setup script with the facilities available at the time the hook is run, and how the hook will be run ("python hookscript.py"?). > "install-from-source" would execute these hooks too: right after > having built the binaries. Yes, *except* in the case where the installation is being done solely for the purpose of creating a built distribution. I'm pretty sure this can be handled by adding a "fake install" flag to the "install" command: if true, don't run the {pre,post}-install hooks. > Wouldn't a method interface be more reliable and provide > better means of extension using subclassing ? > > I usually wrap these attributes in .get_foobar(), .set_foobar() > methods -- this also makes it clear which attributes are > read-only, read-write or "better don't touch" :-) "Yes, but..." I have spent the weekend thinking hard about this problem, and I think I can explain the situation a little better now. Distutils commands are rather odd beasts, and the usual rules and conventions of OO programming don't work very well with them. Not only are they singletons (enforced by the Distribution method 'get_command_obj()'), but they have a prescribed life-cycle which is also enforced by the Distribution class. Until today, this life-cycle was strictly linear: non-existent ---> preinitialized ---> initialized ---> finalized ---> running ---> run "Preinitialized" and "initialized" are on the same line because, to outsiders, they are indistinguishable: the transition happens entirely inside the Command constructor. It works like this: * before we create any command objects, we find and parse all config files, and parse the command line; the results are stored in a dictionary 'command_options' belonging to the Distribution instance * somebody somewhere calls Distribution.get_command_obj("foo"), which notices that it hasn't yet instantiated the "foo" command (typically implemented by the class 'foo' in the module distutils.command.foo) * 'get_command_obj()' instantiates a 'foo' object; command classes do not define constructors, so we go straight into Command.__init__ * Command.__init__ calls self.initialize_options(), which must be provided by each individual command class * 'initialize_options()' is typically a series of self.this = None self.that = None assignments: ie. it "declares" the available "options" for this command. (The 'user_options' class attribute also "declares" the command's options. The two are redundant; every "foo-bar" option in 'user_options' must be matched by a "self.foo_bar = None" in 'initialize_options()', or it will all end in tears.) * some time later (usually immediately), the command's 'finalize_options()' method is called. The job of 'finalize_options()' is to make up the command's mind about everything that will happen when the command runs. Typical code in 'finalize_options()' is: if self.foo is None: self.foo = default value if self.bar is None: self.bar = f(self.foo) Thus, we respect the user's value for 'foo', and have a sensible default if the user didn't provide one. And we respect the user's value for 'bar', and have a sensible -- possibly complicated -- default to fallback on. The idea is to reduce the responsibilities of the 'run()' method, and to ensure that "full disclosure" about the command's intentions can be made before it is ever run. To play along with this complicated dance, Distutils command classes have to provide 1) the 'user_options' class attribute, 2) the 'initialize_options()' method, and 3) the 'finalize_options()' method. (They also have to provide a 'run()' method, of course, but that has nothing to do with setting/getting option values.) The payoff is that new command classes get all the Distutils user interface -- command-line parsing and config files, for now -- for free. The example "configure" command that I showed in a previous post, simply by virtue of having "foo-inc" and "foo-lib" in 'user_options' (and corresponding "self.xxx = None" statements in 'initialize_options()', will automatically use the Distutils' config file and command-line parsing mechanism to set values for those options. Only if the user doesn't supply the information do we have to poke around the target system to figure out where "foo" is installed. Anyways, the point of this long-winded discussion is this: certain attributes of command objects are public and fair game for anyone to set or modify. However, there are well-defined points in the object's life-cycle *before* which it is meaningless to *get* option values, and *after* which it is pointless to *set* option values. In particular, there's no point in getting an option value *before* finalization, because -- duh -- the options aren't finalized yet. More subtly, attempting to set some option *after* finalization time might have no effect at all (if eg. that option is only used to derive other options from, like the 'build_base' option in the "build" command); or it might have complicated, undesirable effects. I can see this happening in particular with the "install" command, which (necessarily) has a frighteningly complex finalization routine. If we go by the simple, linear state-transition diagram above, it turns out that setting option values for a particular command object is a dicey proposition: you simply don't know what state the command object is in, so you don't know what effect setting values on that command will have. If you try to force them to have the right effect, by calling 'finalize_options()', it won't work: the way that method is typically written ("if self.foo is None: self.foo = default value", for as many values of "foo" as are needed), calling it a second time just won't work. So today, I added a couple of new transitions to that state-transition diagram. Now, you can go from any state to the "initialized" state using the 'reinitialize_command()' method provided by Distribution. So it's now safe to do something like this, eg. in a "configure" command build = self.reinitialize_command("build") build.include_dirs.append(foo_inc) build.library_dirs.append(foo_lib) build.ensure_finalized() ...and you know that any user-specified options to the "build" command will be preserved, and that all dependent-but-unspecified options will be recomputed. (You don't need to call 'ensure_finalized()' here unless you will subsequently by getting some option values from the "build" object.) Thus, it should now be possible to write a "configure" command that respects the bureaucracy of the Distutils *and* forces the "build" command to do The Right Thing. This is a small change to the code, but a major change to the philosophy of option-passing in the Distutils, which until now was (theoretically) "pull only": it was not considered proper or safe to assign another command's option attributes; now it is, as long as you play by the above rules. Cool! BTW, I'm not opposed to the idea of 'get_foo()' and 'set_foo()' methods: they could add some value, but only if they are provided by the Command class, rather than each command having to implement a long list of near-identical accessor and modifier methods. Probably 'get_foo()' should die if the object hasn't been finalized, and 'set_foo()' should die if it has been finalized (or hasn't been initialized). Hope this makes some sense... Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ I haven't lost my mind; I know exactly where I left it. From mmuller@enduden.com Mon May 29 00:35:02 2000 From: mmuller@enduden.com (Michael Muller) Date: Sun, 28 May 2000 19:35:02 -0400 Subject: [Distutils] Re: [Python-Dev] Where to install non-code files Message-ID: <200005290000.UAA17073@bogus.com> Greg Ward wrote: [snip] > I have yet to hear howls of my revulsion at my loopy idea of sticking > this: > import sys; sys.path.insert(0, application-python-path) > > into scripts that are installed as part of a "Python application" (ie. > a module distribution whose main interface is a script or scripts, and > that gets its own directory rather than dangling off Python's library > directory). Could it be that people actually think this is a *good* > idea? ;-) [snip] Problem is, the alternatives are equally bad. Ok, playing Devil's advocate: one issue is that if the user (or sysadmin) chooses to move the application directory tree, everything will stop working. Since this also causes problems for uninstall (and probably many other things), the best solution for this problem is *don't do this*. One thing to consider is that the python interpreter automatically prepends the path of the script into sys.path. Therefore, if you install your scripts into the root of your application install directory, you don't need do do any path-mangling. ============================================================================= michaelMuller = mmuller@enduden.com | http://www.cloud9.net/~proteus ----------------------------------------------------------------------------- In this book it is spoken of the Sephiroth, and the Paths, of Spirits and Conjurations; of Gods, Spheres, Planes and many other things which may or may not exist. It is immaterial whether they exist or not. By doing certain things certain results follow. - Aleister Crowley ============================================================================= From R.Liebscher@gmx.de Mon May 29 10:56:35 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Mon, 29 May 2000 11:56:35 +0200 Subject: [Distutils] bdist and --compiler References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> <392D5C4E.E4A180FD@gmx.de> <20000525213526.B996@beelzebub> <392EAE51.436E551C@gmx.de> <20000526215900.A318@beelzebub> Message-ID: <39323ED3.74FEEFA1@gmx.de> Greg Ward wrote: > Scanning the output of this, I see: > > build, build_ext, build_clib --compiler > sdist --formats > bdist --formats > > written that way because the three commands with --compiler have the > same list of compilers, but the two options with --format have different > lists of formats. So yes, you got them all. If I try 'help' to sdist and bdist, I get 'formats' and 'format'. I think we should change this so both are called 'format'. > Rene, can you whip up a patch for this? Thanks! I will try to track down all your options processing and then send you a patch, but it will take a while. Kind regards Rene Liebscher From gward@python.net Tue May 30 02:33:17 2000 From: gward@python.net (Greg Ward) Date: Mon, 29 May 2000 21:33:17 -0400 Subject: [Distutils] bdist and --compiler In-Reply-To: <39323ED3.74FEEFA1@gmx.de>; from Rene Liebscher on Mon, May 29, 2000 at 11:56:35AM +0200 References: <392A8A87.CCA7E76B@gmx.de> <20000523230201.B506@beelzebub> <392D5C4E.E4A180FD@gmx.de> <20000525213526.B996@beelzebub> <392EAE51.436E551C@gmx.de> <20000526215900.A318@beelzebub> <39323ED3.74FEEFA1@gmx.de> Message-ID: <20000529213317.A6426@beelzebub> On 29 May 2000, Rene Liebscher said: > If I try 'help' to sdist and bdist, I get 'formats' and 'format'. I > think > we should change this so both are called 'format'. Not quite. First, we have to change it so both of them can take multiple formats. For obscure, annoying reasons (which I have since forgotten and which may have changed), "bdist" can only take one format -- ie. the syntax is inconsistent because the semantics are inconsistent. Fix the semantics, and we can fix the syntax. Oh, now I remember: because many formats map to the "bdist_dumb" command, and because the command life-cycle used to be strictly linear. That has been fixed, so it should be possible to run "bdist_dumb" multiple times with multiple formats. (The option is to complicate "bdist_dumb" so it can generate multiple formats in one go; I dislike this because it means duplicating the "multiple formats" logic in "bdist" and "bdist_dumb".) I've added this to my todo list -- have to think about the consequences a bit, but offhand it should work. Greg -- Greg Ward - Linux nerd gward@python.net http://starship.python.net/~gward/ Never try to outstubborn a cat. From thomas.heller@ion-tof.com Tue May 30 19:22:57 2000 From: thomas.heller@ion-tof.com (Thomas Heller) Date: Tue, 30 May 2000 20:22:57 +0200 Subject: Patch for util.py (was: Re: [Distutils] bdist broken under Windows) References: <035901bfc4f0$55188a50$4500a8c0@thomasnb> <20000523231050.D506@beelzebub> Message-ID: <027901bfca64$14af0ce0$4500a8c0@thomasnb> [I was wondering about the purpose of change_root(), and Greg wrote] > The purpose of 'change_root()' is to change (eg.) > "/usr/lib/python1.5/site-package/distutils" (where the "install" command > would normally install the distutils on a Red Hat system) to ^^^^^^^^ > "build/bdist.linux2-i586/dumb/usr/lib/python1.5/site-packages/distutils" > (where it gets installed to create a "dumb" built distribution -- we cd > to "build/bdist.linux2-i586/dumb" and then create a tarball or zip file > which is meant to be unpacked from the root directory). What would the user do with such an archive when his python-site-packages are to be installed into "/usr/local/lib/python1.5/site-packages" ? Converting this into the windows world: Normally python1.5 is installed into "C:\Program Files\Python". So the bdist-created archive would contain filenames like "C:\Program Files\Python\distutils\..." On a german windows installation Python would be installed (per default) in "C:\Programme\Python" On the other hand, users would have been able to nstall it into "D:\Work\Python\1.5" or whatever they like. So to me it seems like a bad idea to create archives containing pathnames relative to the root directory. Anyway, here is the relevant part of the implementation of change_root on windows: -------------------------------------- elif os.name == 'nt': (root_drive, root_path) = os.path.splitdrive (new_root) (drive, path) = os.path.splitdrive (pathname) if path[0] == '\\': path = path[1:] return os.path.join (new_root, path) -------------------------------------- With this fix I'm at least able to create bdist archives again (albeit unusable ones, see above). Another minor nit: distutils\archive_util.py, function make_zipfile: The (nested) function visit should normpath() the generated path names, otherwise the created zipfile contains pathnames like ".\distutils\archive_util.py" (Not nice at least). ------------------------------------------ def visit (z, dirname, names): for name in names: path = os.path.join (dirname, name) path = os.path.normpath (path) ^^^ added line if os.path.isfile (path): z.write (path, path) ------------------------------------------ Question: Zip-files created under windows contain backslashes as path-separators. Do we have to care about this? Thomas PS: As soon as the above problems have been cleared, I will prepare a first release of bdist_wininst.py as discussed before. From gward@python.net Wed May 31 01:42:56 2000 From: gward@python.net (Greg Ward) Date: Tue, 30 May 2000 20:42:56 -0400 Subject: [Distutils] Contemplating upheaval in CCompiler API Message-ID: <20000530204256.A456@beelzebub> Hi all (especially to the two [?] of you working on support for additional C/C++ compilers) -- I'm contemplating a major simplification in the CCompiler API that should make life easier for anyone writing or maintaining one of the CCompiler classes, but will raise a lot of dust for a few days. Specifically: currently, each of the compile/link/whatever methods takes a bunch of arguments that enhance instance attributes. For example, every CCompiler instance carries around attributes 'include_dirs', 'libraries', and 'library_dirs'; plus, the 'compile()' method takes an 'include_dirs' parameter, and the 'link_*()' methods all take 'libraries' and 'library_dirs' parameters. These are all combined by convenience functions provided by the CCompiler superclass, so the code overhead to supporting this rather complex interface isn't *too* great. However, I'm getting tired of the *conceptual* overhead: you're forever worrying about "instance attribute 'include_dirs' vs. method argument 'include_dirs'", and so forth. So I'd like to ditch all the extra method parameters and rely on instance attributes as much as possible. That moves CCompiler a little closer to representing a "compiler/linker session", which is meaningless in Unixworld but very much relevant in Macland. (Or so I gather from my spies in that strange and distant country. I'm not clear on the situation in Windowsia, given the constant turmoil in that troubled realm.) I think this is a good thing. The main drawback is that it would make the "build_ext" command a bit more complex. Currently, it sets the instance attributes for compilation properties that apply to all extensions, and passes method arguments for things that vary by extension. (Currently, only 'include_dirs' can do both.) It would have to take care of combining the "global" and "per-extension" properties when it starts to build each extension. This is not, IMHO, a big deal. If nothing else, it would make the signatures and docstrings for the common CCompiler methods a *lot* shorter. Opinions? Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ Screw up your courage! You've screwed up everything else. From gward@python.net Wed May 31 03:17:33 2000 From: gward@python.net (Greg Ward) Date: Tue, 30 May 2000 22:17:33 -0400 Subject: Patch for util.py (was: Re: [Distutils] bdist broken under Windows) In-Reply-To: <027901bfca64$14af0ce0$4500a8c0@thomasnb>; from Thomas Heller on Tue, May 30, 2000 at 08:22:57PM +0200 References: <035901bfc4f0$55188a50$4500a8c0@thomasnb> <20000523231050.D506@beelzebub> <027901bfca64$14af0ce0$4500a8c0@thomasnb> Message-ID: <20000530221733.A657@beelzebub> On 30 May 2000, Thomas Heller said: > What would the user do with such an archive when his python-site-packages > are to be installed into "/usr/local/lib/python1.5/site-packages" ? There's a reason these are called "dumb" built distributions. They're dumb! Stupid, moronic, clue-challenged -- call 'em what you will they're *dumb*. However, 'change_root()' is definitely needed to support "bdist_rpm", and may well be useful for other Unix build distributions. In Unix, /usr is always /usr, and /usr/local is always /usr/local -- and yes, Python is not necessarily installed in either one of them. However, prefix is not necessarily always exec-prefix, so if we want to put the whole dumb built distribution in one tarball, either we assume prefix == exec-prefix, or we start at the root. Neither one is good enough, which is why I don't expect dumb build distributions to catch on in a big way. > Converting this into the windows world: > > Normally python1.5 is installed into > "C:\Program Files\Python". > So the bdist-created archive would contain filenames like > "C:\Program Files\Python\distutils\..." > > On a german windows installation Python would be installed > (per default) in > "C:\Programme\Python" > On the other hand, users would have been able to nstall it into > "D:\Work\Python\1.5" or whatever they like. > > So to me it seems like a bad idea to create archives containing pathnames > relative to the root directory. Good point. Perhaps bdist_dumb should grow a *little* bit of intelligence, and allow the packager to specify if the archive should be relative to prefix or to the root. Yeah, I like that. Just added it to the to-do list. > Anyway, here is the relevant part of the implementation > of change_root on windows: > -------------------------------------- > elif os.name == 'nt': > (root_drive, root_path) = os.path.splitdrive (new_root) > (drive, path) = os.path.splitdrive (pathname) > if path[0] == '\\': > path = path[1:] > return os.path.join (new_root, path) Isn't splitdrive'ing new_root unnecessary here? (Oh wait, you just inherited that from my aborted attempt...) Apart from that, this looks right to me... but I just enumerated 20 distinct cases that 'change_root()' has to handle with MS-DOS pathnames, so you can be sure I'll be testing this one carefully. ;-) [...time passes...] OK, I went ahead and wrote the test script. Good thing too: I found a bug in the Unix case! Here's the output; first, the Unix cases: ok: change_root(baz, foo) == baz/foo ok: change_root(/baz, foo) == /baz/foo ok: change_root(baz, /foo) == baz/foo ok: change_root(/baz, /foo) == /baz/foo and now the DOS/Windows cases: ok: change_root(c:\baz, c:\foo) == c:\baz\foo ok: change_root(\baz, c:\foo) == \baz\foo ok: change_root(c:\baz, \foo) == c:\baz\foo ok: change_root(\baz, \foo) == \baz\foo not ok: change_root(c:\baz, c:foo) != c:\baz\foo (got c:\baz\c:foo) not ok: change_root(\baz, c:foo) != c:\baz\foo (got \baz\c:foo) ok: change_root(c:\baz, foo) == c:\baz\foo ok: change_root(\baz, foo) == \baz\foo ok: change_root(c:baz, c:\foo) == c:baz\foo ok: change_root(baz, c:\foo) == baz\foo ok: change_root(c:baz, \foo) == c:baz\foo ok: change_root(baz, \foo) == baz\foo not ok: change_root(c:baz, c:foo) != c:baz\foo (got c:baz\c:foo) not ok: change_root(baz, c:foo) != baz\foo (got baz\c:foo) ok: change_root(c:baz, foo) == c:baz\foo ok: change_root(baz, foo) == baz\foo ok: change_root(d:\baz, c:\foo) == d:\baz\foo not ok: change_root(d:\baz, c:foo) != d:\baz\foo (got d:\baz\c:foo) ok: change_root(d:baz, c:\foo) == d:baz\foo not ok: change_root(d:baz, c:foo) != d:baz\foo (got d:baz\c:foo) Hmmm, not quite there yet. [...more time passes...] OK, got it. Here's the revised 'change_root()'. Passes all those tests for both POSIX and DOS/Windows paths. Anyone care to contribute a Mac OS version (and tests!)? def change_root (new_root, pathname): """Return 'pathname' with 'new_root' prepended. If 'pathname' is relative, this is equivalent to "os.path.join(new_root,pathname)". Otherwise, it requires making 'pathname' relative and then joining the two, which is tricky on DOS/Windows and Mac OS. """ if os.name == 'posix': if not os.path.isabs (pathname): return os.path.join (new_root, pathname) else: return os.path.join (new_root, pathname[1:]) elif os.name == 'nt': (drive, path) = os.path.splitdrive (pathname) if path[0] == '\\': path = path[1:] return os.path.join (new_root, path) elif os.name == 'mac': raise RuntimeError, "no clue how to do this on Mac OS" else: raise DistutilsPlatformError, \ "nothing known about platform '%s'" % os.name There, I've checked it in. And the test script too! > Another minor nit: > distutils\archive_util.py, function make_zipfile: The (nested) function > visit > should normpath() the generated path names, otherwise the created zipfile > contains pathnames like ".\distutils\archive_util.py" (Not nice at least). OK, thanks -- I've checked in your fix. > Question: > Zip-files created under windows contain backslashes as path-separators. > Do we have to care about this? Shouldn't that be done magically by os.path.join()? > PS: As soon as the above problems have been cleared, I will prepare > a first release of bdist_wininst.py as discussed before. Hot dog! Greg -- Greg Ward - nerd gward@python.net http://starship.python.net/~gward/ I don't understand the HUMOUR of the THREE STOOGES!! From mal@lemburg.com Wed May 31 09:12:17 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Wed, 31 May 2000 10:12:17 +0200 Subject: [Distutils] Pondering multi-package packages References: <20000524223002.C612@beelzebub> <392CFBA3.E4B5131E@lemburg.com> <20000525083500.O29443@inet.net> <392D4262.CF25D949@lemburg.com> <20000525220121.C996@beelzebub> <392E3AB2.D53CF1A0@lemburg.com> <20000526222832.B318@beelzebub> <392F936D.E2E3D42E@lemburg.com> <20000528152317.A698@beelzebub> Message-ID: <3934C961.8DE617BE@lemburg.com> Greg Ward wrote: > > On 27 May 2000, M.-A. Lemburg said: > > I was referring to installing a (pre)built binary -- just before > > copying the compiled files to their final install location and > > right after that step is done. > > Yes: this is the one place where the Distutils' extension mechanism > *won't* work, because the Distutils aren't present (or at least, not in > control) when installing a pre-built binary. Why not ? The RPMs could use the existing Python installation which comes with a version of distutils (at least for 1.6) or use a copy which gets installed together with the package. The post-install script could then pass control to distutils and let it apply its magic. > Here, some other mechanism > will be needed: pass a function, or a module, or a chunk of code to be > eval'd, or something. Still not sure what's best; we have to balance > the needs of the developer writing the setup script with the facilities > available at the time the hook is run, and how the hook will be run > ("python hookscript.py"?). python .../distutils/setup.py --post-install ?! > > "install-from-source" would execute these hooks too: right after > > having built the binaries. > > Yes, *except* in the case where the installation is being done solely > for the purpose of creating a built distribution. I'm pretty sure this > can be handled by adding a "fake install" flag to the "install" command: > if true, don't run the {pre,post}-install hooks. Ok. > > Wouldn't a method interface be more reliable and provide > > better means of extension using subclassing ? > > > > I usually wrap these attributes in .get_foobar(), .set_foobar() > > methods -- this also makes it clear which attributes are > > read-only, read-write or "better don't touch" :-) > > "Yes, but..." > > I have spent the weekend thinking hard about this problem, and I think I > can explain the situation a little better now. Distutils commands are > rather odd beasts, and the usual rules and conventions of OO programming > don't work very well with them. Not only are they singletons (enforced > by the Distribution method 'get_command_obj()'), but they have a > prescribed life-cycle which is also enforced by the Distribution class. > Until today, this life-cycle was strictly linear: > > non-existent > ---> preinitialized ---> initialized > ---> finalized > ---> running > ---> run > > "Preinitialized" and "initialized" are on the same line because, to > outsiders, they are indistinguishable: the transition happens entirely > inside the Command constructor. It works like this: > > * before we create any command objects, we find and parse all config > files, and parse the command line; the results are stored in a > dictionary 'command_options' belonging to the Distribution instance > * somebody somewhere calls Distribution.get_command_obj("foo"), which > notices that it hasn't yet instantiated the "foo" command (typically > implemented by the class 'foo' in the module distutils.command.foo) > * 'get_command_obj()' instantiates a 'foo' object; command classes do > not define constructors, so we go straight into Command.__init__ > * Command.__init__ calls self.initialize_options(), which must > be provided by each individual command class > * 'initialize_options()' is typically a series of > self.this = None > self.that = None > assignments: ie. it "declares" the available "options" for this > command. (The 'user_options' class attribute also "declares" > the command's options. The two are redundant; every "foo-bar" > option in 'user_options' must be matched by a "self.foo_bar = None" > in 'initialize_options()', or it will all end in tears.) > * some time later (usually immediately), the command's > 'finalize_options()' method is called. The job of > 'finalize_options()' is to make up the command's mind about > everything that will happen when the command runs. Typical code > in 'finalize_options()' is: > if self.foo is None: > self.foo = default value > if self.bar is None: > self.bar = f(self.foo) > > Thus, we respect the user's value for 'foo', and have a sensible > default if the user didn't provide one. And we respect the user's > value for 'bar', and have a sensible -- possibly complicated -- > default to fallback on. > > The idea is to reduce the responsibilities of the 'run()' method, > and to ensure that "full disclosure" about the command's intentions > can be made before it is ever run. > > To play along with this complicated dance, Distutils command classes > have to provide 1) the 'user_options' class attribute, 2) the > 'initialize_options()' method, and 3) the 'finalize_options()' method. > (They also have to provide a 'run()' method, of course, but that has > nothing to do with setting/getting option values.) > > The payoff is that new command classes get all the Distutils user > interface -- command-line parsing and config files, for now -- for free. > The example "configure" command that I showed in a previous post, simply > by virtue of having "foo-inc" and "foo-lib" in 'user_options' (and > corresponding "self.xxx = None" statements in 'initialize_options()', > will automatically use the Distutils' config file and command-line > parsing mechanism to set values for those options. Only if the user > doesn't supply the information do we have to poke around the target > system to figure out where "foo" is installed. Nice :-) > Anyways, the point of this long-winded discussion is this: certain > attributes of command objects are public and fair game for anyone to set > or modify. However, there are well-defined points in the object's > life-cycle *before* which it is meaningless to *get* option values, and > *after* which it is pointless to *set* option values. In particular, > there's no point in getting an option value *before* finalization, > because -- duh -- the options aren't finalized yet. More subtly, > attempting to set some option *after* finalization time might have no > effect at all (if eg. that option is only used to derive other options > from, like the 'build_base' option in the "build" command); or it might > have complicated, undesirable effects. I can see this happening in > particular with the "install" command, which (necessarily) has a > frighteningly complex finalization routine. Hmm, I still don't see why you can't add attribute access methods which check and possibly control the forementioned problems. A few .set_this() and .get_that() methods would make the interface more transparent, add documentation (by virtue of __doc__ strings ;-) and could add check assertions. > If we go by the simple, linear state-transition diagram above, it turns > out that setting option values for a particular command object is a > dicey proposition: you simply don't know what state the command object > is in, so you don't know what effect setting values on that command will > have. If you try to force them to have the right effect, by calling > 'finalize_options()', it won't work: the way that method is typically > written ("if self.foo is None: self.foo = default value", for as many > values of "foo" as are needed), calling it a second time just won't > work. Why not let the .set_this() method take care of getting the state right ? (or raise an exception if that's impossible) > So today, I added a couple of new transitions to that state-transition > diagram. Now, you can go from any state to the "initialized" state > using the 'reinitialize_command()' method provided by Distribution. So > it's now safe to do something like this, eg. in a "configure" command > > build = self.reinitialize_command("build") > build.include_dirs.append(foo_inc) > build.library_dirs.append(foo_lib) > build.ensure_finalized() > > ...and you know that any user-specified options to the "build" command > will be preserved, and that all dependent-but-unspecified options will > be recomputed. (You don't need to call 'ensure_finalized()' here unless > you will subsequently by getting some option values from the "build" > object.) > > Thus, it should now be possible to write a "configure" command that > respects the bureaucracy of the Distutils *and* forces the "build" > command to do The Right Thing. This is a small change to the code, but > a major change to the philosophy of option-passing in the Distutils, > which until now was (theoretically) "pull only": it was not considered > proper or safe to assign another command's option attributes; now it is, > as long as you play by the above rules. Cool! Indeed :-) > BTW, I'm not opposed to the idea of 'get_foo()' and 'set_foo()' methods: > they could add some value, but only if they are provided by the Command > class, rather than each command having to implement a long list of > near-identical accessor and modifier methods. Probably 'get_foo()' > should die if the object hasn't been finalized, and 'set_foo()' should > die if it has been finalized (or hasn't been initialized). Right. I'd say: go for it ;-) In my experience, it's always better to define object access via methods rather than attributes. This is especially true when the projects evolves with time: you simply forget about the details, side-effects, assertions you made months ago (and possibly forgot to document) about the specific attributes. Performance is an argument here, but in the end you pay the few percent in performance gain with a much larger percentage in support costs... -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/ From mal@lemburg.com Wed May 31 09:14:33 2000 From: mal@lemburg.com (M.-A. Lemburg) Date: Wed, 31 May 2000 10:14:33 +0200 Subject: [Distutils] Pondering multi-package packages References: <392F95CE.742863D0@lemburg.com> <20000528152534.B698@beelzebub> Message-ID: <3934C9E9.76BD8D52@lemburg.com> Greg Ward wrote: > > On 27 May 2000, M.-A. Lemburg said: > > It would probably be wise to have one setup.py file per ZIP > > archive. The ZIP archives have predefined content and the setup.py > > files could have this information hard-coded somewhere. > > Good point. Does this mean I don't have to worry about recursive setup > scripts after all? ;-) Not for me anymore ;-) > > I would have to move away from my current installation logic > > though (simply unzipping and then compiling in place). With > > distutils help this shouldn't be much of a problem though > > (I hope ;-). > > Yes, please do! The idea of having to unpack a distribution archive in > a particular place has always deeply offended me; the fact that more > than one Python module distributor thought this was a good idea is one > of the things that motivated me to do the Distutils in the first place. > IOW, forcing you to build in one place and install to another place is a > feature. I've always found that kind of setup convenient (and I've only gotten about 2-3 complaints about this in all the years the mx stuff has been around). With distutils I can finally get those 3 guys happy too ;-) -- Marc-Andre Lemburg ______________________________________________________________________ Business: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/