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, <installation tool of choice>! 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!!