From 13ae1c8ff81befcfd0b0ece98ef471cd504642d8 Mon Sep 17 00:00:00 2001 From: Greg Ward Date: Mon, 22 Mar 1999 14:55:25 +0000 Subject: First checkin of real Distutils command modules. --- Lib/distutils/command/__init__.py | 6 ++ Lib/distutils/command/build.py | 56 +++++++++++ Lib/distutils/command/build_py.py | 113 +++++++++++++++++++++ Lib/distutils/command/install.py | 189 +++++++++++++++++++++++++++++++++++ Lib/distutils/command/install_lib.py | 42 ++++++++ Lib/distutils/command/install_py.py | 42 ++++++++ 6 files changed, 448 insertions(+) create mode 100644 Lib/distutils/command/__init__.py create mode 100644 Lib/distutils/command/build.py create mode 100644 Lib/distutils/command/build_py.py create mode 100644 Lib/distutils/command/install.py create mode 100644 Lib/distutils/command/install_lib.py create mode 100644 Lib/distutils/command/install_py.py diff --git a/Lib/distutils/command/__init__.py b/Lib/distutils/command/__init__.py new file mode 100644 index 0000000..9567fd1 --- /dev/null +++ b/Lib/distutils/command/__init__.py @@ -0,0 +1,6 @@ +# this is solely for debugging convenience + +__all__ = ['build', + 'build_py', + 'make_blib', + ] diff --git a/Lib/distutils/command/build.py b/Lib/distutils/command/build.py new file mode 100644 index 0000000..7886092 --- /dev/null +++ b/Lib/distutils/command/build.py @@ -0,0 +1,56 @@ +"""distutils.command.build + +Implements the Distutils 'build' command.""" + +# created 1999/03/08, Greg Ward + +__rcsid__ = "$Id$" + +import os +from distutils.core import Command + + +class Build (Command): + + options = [('basedir=', 'b', "base directory for build library"), + ('libdir=', 'l', "directory for platform-shared files"), + ('platdir=', 'p', "directory for platform-specific files"), + + # Flags for 'build_py' + ('compile-py', None, "compile .py to .pyc"), + ('optimize-py', None, "compile .py to .pyo (optimized)"), + ] + + def set_default_options (self): + self.basedir = 'build' + # these are decided only after 'basedir' has its final value + # (unless overridden by the user or client) + self.libdir = None + self.platdir = None + + self.compile_py = 1 + self.optimize_py = 1 + + def set_final_options (self): + # 'libdir' and 'platdir' just default to 'lib' and 'plat' under + # the base build directory + if self.libdir is None: + self.libdir = os.path.join (self.basedir, 'lib') + if self.platdir is None: + self.platdir = os.path.join (self.basedir, 'plat') + + + def run (self): + + self.set_final_options () + + # For now, "build" means "build_py" then "build_ext". (Eventually + # it should also build documentation.) + + # Invoke the 'build_py' command + self.run_peer ('build_py') + + # And now 'build_ext' + #self.run_peer ('build_ext') + +# end class Build diff --git a/Lib/distutils/command/build_py.py b/Lib/distutils/command/build_py.py new file mode 100644 index 0000000..ae133f9 --- /dev/null +++ b/Lib/distutils/command/build_py.py @@ -0,0 +1,113 @@ +"""distutils.command.build_py + +Implements the Distutils 'build_py' command.""" + +# created 1999/03/08, Greg Ward + +__rcsid__ = "$Id$" + +import string, os +from distutils.core import Command +from distutils.errors import * +from distutils.util import mkpath, newer, make_file, copy_file + + +class BuildPy (Command): + + options = [('dir=', 'd', "directory for platform-shared files"), + ('compile', 'c', "compile .py to .pyc"), + ('optimize', 'o', "compile .py to .pyo (optimized)"), + ] + + + def set_default_options (self): + self.dir = None + self.compile = 1 + self.optimize = 1 + + def set_final_options (self): + self.set_undefined_options ('build', + ('libdir', 'dir'), + ('compile_py', 'compile'), + ('optimize_py', 'optimize')) + + + def run (self): + + # XXX copy_file by default preserves all stat info -- mode, atime, + # and mtime. IMHO this is the right thing to do, but perhaps it + # should be an option -- in particular, a site administrator might + # want installed files to reflect the time of installation rather + # than the last modification time before the installed release. + + # XXX copy_file does *not* preserve MacOS-specific file metadata. + # If this is a problem for building/installing Python modules, then + # we'll have to fix copy_file. (And what about installing scripts, + # when the time comes for that -- does MacOS use its special + # metadata to know that a file is meant to be interpreted by + # Python?) + + self.set_final_options () + + (modules, package) = \ + self.distribution.get_options ('py_modules', 'package') + package = package or '' + + infiles = [] + outfiles = [] + missing = [] + + # Loop over the list of "pure Python" modules, deriving + # input and output filenames and checking for missing + # input files. + + # XXX we should allow for wildcards, so eg. the Distutils setup.py + # file would just have to say + # py_modules = ['distutils.*', 'distutils.command.*'] + # without having to list each one explicitly. + for m in modules: + fn = apply (os.path.join, tuple (string.split (m, '.'))) + '.py' + if not os.path.exists (fn): + missing.append (fn) + else: + infiles.append (fn) + outfiles.append (os.path.join (self.dir, package, fn)) + + # Blow up if any input files were not found. + if missing: + raise DistutilsFileError, \ + "missing files: " + string.join (missing, ' ') + + # Loop over the list of input files, copying them to their + # temporary (build) destination. + created = {} + for i in range (len (infiles)): + outdir = os.path.split (outfiles[i])[0] + if not created.get(outdir): + mkpath (outdir, verbose=self.distribution.verbose) + created[outdir] = 1 + + copy_file (infiles[i], outfiles[i], + update=1, verbose=self.distribution.verbose) + + # (Optionally) compile .py to .pyc + # XXX hey! we can't control whether we optimize or not; that's up + # to the invocation of the current Python interpreter (at least + # according to the py_compile docs). That sucks. + + if self.compile: + from py_compile import compile + + for f in outfiles: + # XXX can't assume this filename mapping! + out_fn = string.replace (f, '.py', '.pyc') + + make_file (f, out_fn, compile, (f,), + verbose=self.distribution.verbose, + update_message="compiling %s" % f) + + # XXX ignore self.optimize for now, since we don't really know if + # we're compiling optimally or not, and couldn't pick what to do + # even if we did know. ;-( + +# end class BuildPy diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py new file mode 100644 index 0000000..1f45780 --- /dev/null +++ b/Lib/distutils/command/install.py @@ -0,0 +1,189 @@ +"""distutils.command.install + +Implements the Distutils 'install' command.""" + +# created 1999/03/13, Greg Ward + +__rcsid__ = "$Id$" + +import sys, os, string +from distutils import sysconfig +from distutils.core import Command + + +class Install (Command): + + options = [('prefix=', None, "installation prefix"), + ('execprefix=', None, + "prefix for platform-specific files"), + + # Build directories: where to install from + ('build-base=', None, + "base build directory"), + ('build-lib=', None, + "build directory for non-platform-specific library files"), + ('build-platlib=', None, + "build directory for platform-specific library files"), + + # Installation directories: where to put modules and packages + ('install-lib=', None, + "base Python library directory"), + ('install-platlib=', None, + "platform-specific Python library directory"), + ('install-site-lib=', None, + "directory for site-specific packages and modules"), + ('install-site-platlib=', None, + "platform-specific site directory"), + ('install-scheme=', None, + "install to 'system' or 'site' library directory?"), + + # Where to install documentation (eventually!) + ('doc-format=', None, "format of documentation to generate"), + ('install-man=', None, "directory for Unix man pages"), + ('install-html=', None, "directory for HTML documentation"), + ('install-info=', None, "directory for GNU info files"), + + ] + + def set_default_options (self): + + self.build_base = None + self.build_lib = None + self.build_platlib = None + + # Don't define 'prefix' or 'exec_prefix' so we can know when the + # command is run whether the user supplied values + self.prefix = None + self.exec_prefix = None + + # These two, we can supply real values for! (because they're + # not directories, and don't have a confusing multitude of + # possible derivations) + #self.install_scheme = 'site' + self.doc_format = None + + # The actual installation directories are determined only at + # run-time, so the user can supply just prefix (and exec_prefix?) + # as a base for everything else + self.install_lib = None + self.install_platlib = None + self.install_site_lib = None + self.install_site_platlib = None + + self.install_man = None + self.install_html = None + self.install_info = None + + + def set_final_options (self): + + # Figure out the build directories, ie. where to install from + self.set_peer_option ('build', 'basedir', self.build_base) + self.set_undefined_options ('build', + ('basedir', 'build_base'), + ('libdir', 'build_lib'), + ('platdir', 'build_platlib')) + + # Figure out actual installation directories; the basic principle + # is: if the user supplied nothing, then use the directories that + # Python was built and installed with (ie. the compiled-in prefix + # and exec_prefix, and the actual installation directories gleaned + # by sysconfig). If the user supplied a prefix (and possibly + # exec_prefix), then we generate our own installation directories, + # following any pattern gleaned from sysconfig's findings. If no + # such pattern can be gleaned, then we'll just make do and try to + # ape the behaviour of Python's configure script. + + if self.prefix is None: # user didn't override + self.prefix = sys.prefix + if self.exec_prefix is None: + self.exec_prefix = sys.exec_prefix + + if self.install_lib is None: + self.install_lib = \ + self.replace_sys_prefix ('LIBDEST', ('lib','python1.5')) + if self.install_platlib is None: + # XXX this should probably be DESTSHARED -- but why is there no + # equivalent to DESTSHARED for the "site-packages" dir"? + self.install_platlib = \ + self.replace_sys_prefix ('BINLIBDEST', ('lib','python1.5'), 1) + + if self.install_site_lib is None: + self.install_site_lib = \ + os.path.join (self.install_lib, 'site-packages') + if self.install_site_platlib is None: + # XXX ugh! this puts platform-specific files in with shared files, + # with no nice way to override it! (this might be a Python + # problem, though, not a Distutils problem...) + self.install_site_platlib = \ + os.path.join (self.install_lib, 'site-packages') + + #if self.install_scheme == 'site': + # install_lib = self.install_site_lib + # install_platlib = self.install_site_platlib + #elif self.install_scheme == 'system': + # install_lib = self.install_lib + # install_platlib = self.install_platlib + #else: + # # XXX new exception for this kind of misbehaviour? + # raise DistutilsArgError, \ + # "invalid install scheme '%s'" % self.install_scheme + + + # Punt on doc directories for now -- after all, we're punting on + # documentation completely! + + # set_final_options () + + + def replace_sys_prefix (self, config_attr, fallback_postfix, use_exec=0): + """Attempts to glean a simple pattern from an installation + directory available as a 'sysconfig' attribute: if the + directory name starts with the "system prefix" (the one + hard-coded in the Makefile and compiled into Python), + then replace it with the current installation prefix and + return the "relocated" installation directory.""" + + if use_exec: + sys_prefix = sys.exec_prefix + my_prefix = self.exec_prefix + else: + sys_prefix = sys.prefix + my_prefix = self.prefix + + val = getattr (sysconfig, config_attr) + if string.find (val, sys_prefix) == 0: + # If the sysconfig directory starts with the system prefix, + # then we can "relocate" it to the user-supplied prefix -- + # assuming, of course, it is different from the system prefix. + + if sys_prefix == my_prefix: + return val + else: + return my_prefix + val[len(sys_prefix):] + + else: + # Otherwise, just tack the "fallback postfix" onto the + # user-specified prefix. + + return apply (os.join, (my_prefix,) + fallback_postfix) + + # replace_sys_prefix () + + + def run (self): + + self.set_final_options () + + # Install modules in two steps: "platform-shared" files (ie. pure + # python modules) and platform-specific files (compiled C + # extensions). + + self.run_peer ('install_py') + + # don't have an 'install_ext' command just yet! + #self.run_peer ('install_ext')) + + # run () + +# class Install diff --git a/Lib/distutils/command/install_lib.py b/Lib/distutils/command/install_lib.py new file mode 100644 index 0000000..f2fa842 --- /dev/null +++ b/Lib/distutils/command/install_lib.py @@ -0,0 +1,42 @@ +# created 1999/03/13, Greg Ward + +__rcsid__ = "$Id$" + +import sys +from distutils.core import Command +from distutils.util import copy_tree + +class InstallPy (Command): + + options = [('dir=', 'd', "directory to install to"), + ('build-dir=' 'b', "build directory (where to install from)")] + + def set_default_options (self): + # let the 'install' command dictate our installation directory + self.dir = None + self.build_dir = None + + def set_final_options (self): + # If we don't have a 'dir' value, we'll have to ask the 'install' + # command for one. (This usually means the user ran 'install_py' + # directly, rather than going through 'install' -- so in reality, + # 'find_command_obj()' will create an 'install' command object, + # which we then query. + + self.set_undefined_options ('install', + ('build_lib', 'build_dir'), + ('install_site_lib', 'dir')) + + def run (self): + + self.set_final_options () + + # Dump entire contents of the build directory to the installation + # directory (that's the beauty of having a build directory!) + copy_tree (self.build_dir, self.dir, + verbose=self.distribution.verbose, + update=1) + + # run () + +# class InstallPy diff --git a/Lib/distutils/command/install_py.py b/Lib/distutils/command/install_py.py new file mode 100644 index 0000000..f2fa842 --- /dev/null +++ b/Lib/distutils/command/install_py.py @@ -0,0 +1,42 @@ +# created 1999/03/13, Greg Ward + +__rcsid__ = "$Id$" + +import sys +from distutils.core import Command +from distutils.util import copy_tree + +class InstallPy (Command): + + options = [('dir=', 'd', "directory to install to"), + ('build-dir=' 'b', "build directory (where to install from)")] + + def set_default_options (self): + # let the 'install' command dictate our installation directory + self.dir = None + self.build_dir = None + + def set_final_options (self): + # If we don't have a 'dir' value, we'll have to ask the 'install' + # command for one. (This usually means the user ran 'install_py' + # directly, rather than going through 'install' -- so in reality, + # 'find_command_obj()' will create an 'install' command object, + # which we then query. + + self.set_undefined_options ('install', + ('build_lib', 'build_dir'), + ('install_site_lib', 'dir')) + + def run (self): + + self.set_final_options () + + # Dump entire contents of the build directory to the installation + # directory (that's the beauty of having a build directory!) + copy_tree (self.build_dir, self.dir, + verbose=self.distribution.verbose, + update=1) + + # run () + +# class InstallPy -- cgit v0.12