Home | History | Annotate | Download | only in command
      1 """distutils.command.install
      2 
      3 Implements the Distutils 'install' command."""
      4 
      5 from distutils import log
      6 
      7 # This module should be kept compatible with Python 2.1.
      8 
      9 __revision__ = "$Id$"
     10 
     11 import sys, os, string, re
     12 from types import *
     13 from distutils.core import Command
     14 from distutils.debug import DEBUG
     15 from distutils.sysconfig import get_config_vars
     16 from distutils.errors import DistutilsPlatformError
     17 from distutils.file_util import write_file
     18 from distutils.util import convert_path, subst_vars, change_root
     19 from distutils.util import get_platform
     20 from distutils.errors import DistutilsOptionError
     21 from site import USER_BASE
     22 from site import USER_SITE
     23 from string import maketrans
     24 
     25 def is_msys_mingw():
     26     if sys.platform == "win32" and "MSYSTEM" in os.environ and sys.version.find("GCC") >= 0:
     27         if os.environ["MSYSTEM"] == "MINGW32":
     28             return 1
     29     return 0
     30 
     31 def has_msys():
     32     _msysdll = "msys-1.0.dll"
     33     for _path in os.environ["PATH"].split(os.pathsep):
     34         currpath = os.path.join(_path, _msysdll)
     35         if os.path.isfile(currpath) and os.access(currpath, os.F_OK):
     36             return _path
     37     return None
     38 
     39 def msys_root():
     40     if is_msys_mingw() and has_msys() is not None:
     41         arg = has_msys()
     42         arg = arg.rstrip("\\")
     43         if arg.endswith("\\bin"):
     44             # drop the \\bin
     45             arg = arg[:-4]
     46         table = maketrans('\\', '/')
     47         arg = arg.translate(table)
     48         if arg.endswith("/"):
     49             arg = arg[:-1]
     50         return arg
     51     else:
     52         return None
     53 
     54 if sys.version < "2.2":
     55     WINDOWS_SCHEME = {
     56         'purelib': '$base',
     57         'platlib': '$base',
     58         'headers': '$base/Include/$dist_name',
     59         'scripts': '$base/Scripts',
     60         'data'   : '$base',
     61     }
     62 else:
     63     WINDOWS_SCHEME = {
     64         'purelib': '$base/Lib/site-packages',
     65         'platlib': '$base/Lib/site-packages',
     66         'headers': '$base/Include/$dist_name',
     67         'scripts': '$base/Scripts',
     68         'data'   : '$base',
     69     }
     70 
     71 INSTALL_SCHEMES = {
     72     'unix_prefix': {
     73         'purelib': '$base/lib/python$py_version_short/site-packages',
     74         'platlib': '$platbase/lib/python$py_version_short/site-packages',
     75         'headers': '$base/include/python$py_version_short/$dist_name',
     76         'scripts': '$base/bin',
     77         'data'   : '$base',
     78         },
     79     'unix_home': {
     80         'purelib': '$base/lib/python',
     81         'platlib': '$base/lib/python',
     82         'headers': '$base/include/python/$dist_name',
     83         'scripts': '$base/bin',
     84         'data'   : '$base',
     85         },
     86     'unix_user': {
     87         'purelib': '$usersite',
     88         'platlib': '$usersite',
     89         'headers': '$userbase/include/python$py_version_short/$dist_name',
     90         'scripts': '$userbase/bin',
     91         'data'   : '$userbase',
     92         },
     93     'nt': WINDOWS_SCHEME,
     94     'nt_user': {
     95         'purelib': '$usersite',
     96         'platlib': '$usersite',
     97         'headers': '$userbase/Python$py_version_nodot/Include/$dist_name',
     98         'scripts': '$userbase/Scripts',
     99         'data'   : '$userbase',
    100         },
    101     'os2': {
    102         'purelib': '$base/Lib/site-packages',
    103         'platlib': '$base/Lib/site-packages',
    104         'headers': '$base/Include/$dist_name',
    105         'scripts': '$base/Scripts',
    106         'data'   : '$base',
    107         },
    108     'os2_home': {
    109         'purelib': '$usersite',
    110         'platlib': '$usersite',
    111         'headers': '$userbase/include/python$py_version_short/$dist_name',
    112         'scripts': '$userbase/bin',
    113         'data'   : '$userbase',
    114         },
    115     }
    116 
    117 # The keys to an installation scheme; if any new types of files are to be
    118 # installed, be sure to add an entry to every installation scheme above,
    119 # and to SCHEME_KEYS here.
    120 SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
    121 
    122 
    123 class install (Command):
    124 
    125     description = "install everything from build directory"
    126 
    127     user_options = [
    128         # Select installation scheme and set base director(y|ies)
    129         ('prefix=', None,
    130          "installation prefix"),
    131         ('exec-prefix=', None,
    132          "(Unix only) prefix for platform-specific files"),
    133         ('home=', None,
    134          "(Unix only) home directory to install under"),
    135         ('user', None,
    136          "install in user site-package '%s'" % USER_SITE),
    137 
    138         # Or, just set the base director(y|ies)
    139         ('install-base=', None,
    140          "base installation directory (instead of --prefix or --home)"),
    141         ('install-platbase=', None,
    142          "base installation directory for platform-specific files " +
    143          "(instead of --exec-prefix or --home)"),
    144         ('root=', None,
    145          "install everything relative to this alternate root directory"),
    146 
    147         # Or, explicitly set the installation scheme
    148         ('install-purelib=', None,
    149          "installation directory for pure Python module distributions"),
    150         ('install-platlib=', None,
    151          "installation directory for non-pure module distributions"),
    152         ('install-lib=', None,
    153          "installation directory for all module distributions " +
    154          "(overrides --install-purelib and --install-platlib)"),
    155 
    156         ('install-headers=', None,
    157          "installation directory for C/C++ headers"),
    158         ('install-scripts=', None,
    159          "installation directory for Python scripts"),
    160         ('install-data=', None,
    161          "installation directory for data files"),
    162 
    163         # Byte-compilation options -- see install_lib.py for details, as
    164         # these are duplicated from there (but only install_lib does
    165         # anything with them).
    166         ('compile', 'c', "compile .py to .pyc [default]"),
    167         ('no-compile', None, "don't compile .py files"),
    168         ('optimize=', 'O',
    169          "also compile with optimization: -O1 for \"python -O\", "
    170          "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
    171 
    172         # Miscellaneous control options
    173         ('force', 'f',
    174          "force installation (overwrite any existing files)"),
    175         ('skip-build', None,
    176          "skip rebuilding everything (for testing/debugging)"),
    177 
    178         # Where to install documentation (eventually!)
    179         #('doc-format=', None, "format of documentation to generate"),
    180         #('install-man=', None, "directory for Unix man pages"),
    181         #('install-html=', None, "directory for HTML documentation"),
    182         #('install-info=', None, "directory for GNU info files"),
    183 
    184         ('record=', None,
    185          "filename in which to record list of installed files"),
    186         ]
    187 
    188     boolean_options = ['compile', 'force', 'skip-build', 'user']
    189     negative_opt = {'no-compile' : 'compile'}
    190 
    191 
    192     def initialize_options (self):
    193 
    194         # High-level options: these select both an installation base
    195         # and scheme.
    196         self.prefix = None
    197         self.exec_prefix = None
    198         self.home = None
    199         self.user = 0
    200 
    201         # These select only the installation base; it's up to the user to
    202         # specify the installation scheme (currently, that means supplying
    203         # the --install-{platlib,purelib,scripts,data} options).
    204         self.install_base = None
    205         self.install_platbase = None
    206         self.root = None
    207 
    208         # These options are the actual installation directories; if not
    209         # supplied by the user, they are filled in using the installation
    210         # scheme implied by prefix/exec-prefix/home and the contents of
    211         # that installation scheme.
    212         self.install_purelib = None     # for pure module distributions
    213         self.install_platlib = None     # non-pure (dists w/ extensions)
    214         self.install_headers = None     # for C/C++ headers
    215         self.install_lib = None         # set to either purelib or platlib
    216         self.install_scripts = None
    217         self.install_data = None
    218         self.install_userbase = USER_BASE
    219         self.install_usersite = USER_SITE
    220 
    221         self.compile = None
    222         self.optimize = None
    223 
    224         # These two are for putting non-packagized distributions into their
    225         # own directory and creating a .pth file if it makes sense.
    226         # 'extra_path' comes from the setup file; 'install_path_file' can
    227         # be turned off if it makes no sense to install a .pth file.  (But
    228         # better to install it uselessly than to guess wrong and not
    229         # install it when it's necessary and would be used!)  Currently,
    230         # 'install_path_file' is always true unless some outsider meddles
    231         # with it.
    232         self.extra_path = None
    233         self.install_path_file = 1
    234 
    235         # 'force' forces installation, even if target files are not
    236         # out-of-date.  'skip_build' skips running the "build" command,
    237         # handy if you know it's not necessary.  'warn_dir' (which is *not*
    238         # a user option, it's just there so the bdist_* commands can turn
    239         # it off) determines whether we warn about installing to a
    240         # directory not in sys.path.
    241         self.force = 0
    242         self.skip_build = 0
    243         self.warn_dir = 1
    244 
    245         # These are only here as a conduit from the 'build' command to the
    246         # 'install_*' commands that do the real work.  ('build_base' isn't
    247         # actually used anywhere, but it might be useful in future.)  They
    248         # are not user options, because if the user told the install
    249         # command where the build directory is, that wouldn't affect the
    250         # build command.
    251         self.build_base = None
    252         self.build_lib = None
    253 
    254         # Not defined yet because we don't know anything about
    255         # documentation yet.
    256         #self.install_man = None
    257         #self.install_html = None
    258         #self.install_info = None
    259 
    260         self.record = None
    261 
    262 
    263     # -- Option finalizing methods -------------------------------------
    264     # (This is rather more involved than for most commands,
    265     # because this is where the policy for installing third-
    266     # party Python modules on various platforms given a wide
    267     # array of user input is decided.  Yes, it's quite complex!)
    268 
    269     def finalize_options (self):
    270 
    271         # This method (and its pliant slaves, like 'finalize_unix()',
    272         # 'finalize_other()', and 'select_scheme()') is where the default
    273         # installation directories for modules, extension modules, and
    274         # anything else we care to install from a Python module
    275         # distribution.  Thus, this code makes a pretty important policy
    276         # statement about how third-party stuff is added to a Python
    277         # installation!  Note that the actual work of installation is done
    278         # by the relatively simple 'install_*' commands; they just take
    279         # their orders from the installation directory options determined
    280         # here.
    281 
    282         # Check for errors/inconsistencies in the options; first, stuff
    283         # that's wrong on any platform.
    284 
    285         if ((self.prefix or self.exec_prefix or self.home) and
    286             (self.install_base or self.install_platbase)):
    287             raise DistutilsOptionError, \
    288                   ("must supply either prefix/exec-prefix/home or " +
    289                    "install-base/install-platbase -- not both")
    290 
    291         if self.home and (self.prefix or self.exec_prefix):
    292             raise DistutilsOptionError, \
    293                   "must supply either home or prefix/exec-prefix -- not both"
    294 
    295         if self.user and (self.prefix or self.exec_prefix or self.home or
    296                 self.install_base or self.install_platbase):
    297             raise DistutilsOptionError("can't combine user with prefix, "
    298                                        "exec_prefix/home, or install_(plat)base")
    299 
    300         # Next, stuff that's wrong (or dubious) only on certain platforms.
    301         if os.name != "posix":
    302             if self.exec_prefix:
    303                 self.warn("exec-prefix option ignored on this platform")
    304                 self.exec_prefix = None
    305 
    306         # Now the interesting logic -- so interesting that we farm it out
    307         # to other methods.  The goal of these methods is to set the final
    308         # values for the install_{lib,scripts,data,...}  options, using as
    309         # input a heady brew of prefix, exec_prefix, home, install_base,
    310         # install_platbase, user-supplied versions of
    311         # install_{purelib,platlib,lib,scripts,data,...}, and the
    312         # INSTALL_SCHEME dictionary above.  Phew!
    313 
    314         self.dump_dirs("pre-finalize_{unix,other}")
    315 
    316         if os.name == 'posix':
    317             self.finalize_unix()
    318         else:
    319             self.finalize_other()
    320 
    321         self.dump_dirs("post-finalize_{unix,other}()")
    322 
    323         # Expand configuration variables, tilde, etc. in self.install_base
    324         # and self.install_platbase -- that way, we can use $base or
    325         # $platbase in the other installation directories and not worry
    326         # about needing recursive variable expansion (shudder).
    327 
    328         py_version = (string.split(sys.version))[0]
    329         (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
    330         self.config_vars = {'dist_name': self.distribution.get_name(),
    331                             'dist_version': self.distribution.get_version(),
    332                             'dist_fullname': self.distribution.get_fullname(),
    333                             'py_version': py_version,
    334                             'py_version_short': py_version[0:3],
    335                             'py_version_nodot': py_version[0] + py_version[2],
    336                             'sys_prefix': prefix,
    337                             'prefix': prefix,
    338                             'sys_exec_prefix': exec_prefix,
    339                             'exec_prefix': exec_prefix,
    340                             'userbase': self.install_userbase,
    341                             'usersite': self.install_usersite,
    342                            }
    343         self.expand_basedirs()
    344 
    345         self.dump_dirs("post-expand_basedirs()")
    346 
    347         # MSYS (probably) will have transformed --root=/ to the
    348         # windows path where the msys is installed, so we check if root begins
    349         # with msysroot and if it does then remove this part.
    350         if self.root is not None and is_msys_mingw():
    351             msysroot = msys_root()
    352             if msysroot != None and self.root.find(msysroot)==0:
    353                 self.root = self.root.replace(msysroot, "/")
    354 
    355         # Now define config vars for the base directories so we can expand
    356         # everything else.
    357         self.config_vars['base'] = self.install_base
    358         self.config_vars['platbase'] = self.install_platbase
    359 
    360         if DEBUG:
    361             from pprint import pprint
    362             print "config vars:"
    363             pprint(self.config_vars)
    364 
    365         # Expand "~" and configuration variables in the installation
    366         # directories.
    367         self.expand_dirs()
    368 
    369         self.dump_dirs("post-expand_dirs()")
    370 
    371         # Create directories in the home dir:
    372         if self.user:
    373             self.create_home_path()
    374 
    375         # Pick the actual directory to install all modules to: either
    376         # install_purelib or install_platlib, depending on whether this
    377         # module distribution is pure or not.  Of course, if the user
    378         # already specified install_lib, use their selection.
    379         if self.install_lib is None:
    380             if self.distribution.ext_modules: # has extensions: non-pure
    381                 self.install_lib = self.install_platlib
    382             else:
    383                 self.install_lib = self.install_purelib
    384 
    385 
    386         # Convert directories from Unix /-separated syntax to the local
    387         # convention.
    388         self.convert_paths('lib', 'purelib', 'platlib',
    389                            'scripts', 'data', 'headers',
    390                            'userbase', 'usersite')
    391 
    392         # Well, we're not actually fully completely finalized yet: we still
    393         # have to deal with 'extra_path', which is the hack for allowing
    394         # non-packagized module distributions (hello, Numerical Python!) to
    395         # get their own directories.
    396         self.handle_extra_path()
    397         self.install_libbase = self.install_lib # needed for .pth file
    398         self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
    399 
    400         # If a new root directory was supplied, make all the installation
    401         # dirs relative to it.
    402         if self.root is not None:
    403             self.change_roots('libbase', 'lib', 'purelib', 'platlib',
    404                               'scripts', 'data', 'headers')
    405 
    406         self.dump_dirs("after prepending root")
    407 
    408         # Find out the build directories, ie. where to install from.
    409         self.set_undefined_options('build',
    410                                    ('build_base', 'build_base'),
    411                                    ('build_lib', 'build_lib'))
    412 
    413         # Punt on doc directories for now -- after all, we're punting on
    414         # documentation completely!
    415 
    416     # finalize_options ()
    417 
    418 
    419     def dump_dirs (self, msg):
    420         if DEBUG:
    421             from distutils.fancy_getopt import longopt_xlate
    422             print msg + ":"
    423             for opt in self.user_options:
    424                 opt_name = opt[0]
    425                 if opt_name[-1] == "=":
    426                     opt_name = opt_name[0:-1]
    427                 if opt_name in self.negative_opt:
    428                     opt_name = string.translate(self.negative_opt[opt_name],
    429                                                 longopt_xlate)
    430                     val = not getattr(self, opt_name)
    431                 else:
    432                     opt_name = string.translate(opt_name, longopt_xlate)
    433                     val = getattr(self, opt_name)
    434                 print "  %s: %s" % (opt_name, val)
    435 
    436 
    437     def finalize_unix (self):
    438 
    439         if self.install_base is not None or self.install_platbase is not None:
    440             if ((self.install_lib is None and
    441                  self.install_purelib is None and
    442                  self.install_platlib is None) or
    443                 self.install_headers is None or
    444                 self.install_scripts is None or
    445                 self.install_data is None):
    446                 raise DistutilsOptionError, \
    447                       ("install-base or install-platbase supplied, but "
    448                       "installation scheme is incomplete")
    449             return
    450 
    451         if self.user:
    452             if self.install_userbase is None:
    453                 raise DistutilsPlatformError(
    454                     "User base directory is not specified")
    455             self.install_base = self.install_platbase = self.install_userbase
    456             self.select_scheme("unix_user")
    457         elif self.home is not None:
    458             self.install_base = self.install_platbase = self.home
    459             self.select_scheme("unix_home")
    460         else:
    461             if self.prefix is None:
    462                 if self.exec_prefix is not None:
    463                     raise DistutilsOptionError, \
    464                           "must not supply exec-prefix without prefix"
    465 
    466                 self.prefix = os.path.normpath(sys.prefix)
    467                 self.exec_prefix = os.path.normpath(sys.exec_prefix)
    468 
    469             else:
    470                 if self.exec_prefix is None:
    471                     self.exec_prefix = self.prefix
    472 
    473             self.install_base = self.prefix
    474             self.install_platbase = self.exec_prefix
    475             self.select_scheme("unix_prefix")
    476 
    477     # finalize_unix ()
    478 
    479 
    480     def finalize_other (self):          # Windows and Mac OS for now
    481 
    482         if self.user:
    483             if self.install_userbase is None:
    484                 raise DistutilsPlatformError(
    485                     "User base directory is not specified")
    486             self.install_base = self.install_platbase = self.install_userbase
    487             self.select_scheme(os.name + "_user")
    488         elif self.home is not None:
    489             self.install_base = self.install_platbase = self.home
    490             self.select_scheme("unix_home")
    491         else:
    492             if self.prefix is None:
    493                 self.prefix = os.path.normpath(sys.prefix)
    494 
    495             self.install_base = self.install_platbase = self.prefix
    496             try:
    497                 self.select_scheme(os.name)
    498             except KeyError:
    499                 raise DistutilsPlatformError, \
    500                       "I don't know how to install stuff on '%s'" % os.name
    501 
    502     # finalize_other ()
    503 
    504 
    505     def select_scheme (self, name):
    506         # it's the caller's problem if they supply a bad name!
    507         scheme = INSTALL_SCHEMES[name]
    508         for key in SCHEME_KEYS:
    509             attrname = 'install_' + key
    510             if getattr(self, attrname) is None:
    511                 setattr(self, attrname, scheme[key])
    512 
    513 
    514     def _expand_attrs (self, attrs):
    515         for attr in attrs:
    516             val = getattr(self, attr)
    517             if val is not None:
    518                 if os.name == 'posix' or os.name == 'nt':
    519                     val = os.path.expanduser(val)
    520                 val = subst_vars(val, self.config_vars)
    521                 setattr(self, attr, val)
    522 
    523 
    524     def expand_basedirs (self):
    525         self._expand_attrs(['install_base',
    526                             'install_platbase',
    527                             'root'])
    528 
    529     def expand_dirs (self):
    530         self._expand_attrs(['install_purelib',
    531                             'install_platlib',
    532                             'install_lib',
    533                             'install_headers',
    534                             'install_scripts',
    535                             'install_data',])
    536 
    537 
    538     def convert_paths (self, *names):
    539         for name in names:
    540             attr = "install_" + name
    541             setattr(self, attr, convert_path(getattr(self, attr)))
    542 
    543 
    544     def handle_extra_path (self):
    545 
    546         if self.extra_path is None:
    547             self.extra_path = self.distribution.extra_path
    548 
    549         if self.extra_path is not None:
    550             if type(self.extra_path) is StringType:
    551                 self.extra_path = string.split(self.extra_path, ',')
    552 
    553             if len(self.extra_path) == 1:
    554                 path_file = extra_dirs = self.extra_path[0]
    555             elif len(self.extra_path) == 2:
    556                 (path_file, extra_dirs) = self.extra_path
    557             else:
    558                 raise DistutilsOptionError, \
    559                       ("'extra_path' option must be a list, tuple, or "
    560                       "comma-separated string with 1 or 2 elements")
    561 
    562             # convert to local form in case Unix notation used (as it
    563             # should be in setup scripts)
    564             extra_dirs = convert_path(extra_dirs)
    565 
    566         else:
    567             path_file = None
    568             extra_dirs = ''
    569 
    570         # XXX should we warn if path_file and not extra_dirs? (in which
    571         # case the path file would be harmless but pointless)
    572         self.path_file = path_file
    573         self.extra_dirs = extra_dirs
    574 
    575     # handle_extra_path ()
    576 
    577 
    578     def change_roots (self, *names):
    579         for name in names:
    580             attr = "install_" + name
    581             setattr(self, attr, change_root(self.root, getattr(self, attr)))
    582 
    583     def create_home_path(self):
    584         """Create directories under ~
    585         """
    586         if not self.user:
    587             return
    588         home = convert_path(os.path.expanduser("~"))
    589         for name, path in self.config_vars.iteritems():
    590             if path.startswith(home) and not os.path.isdir(path):
    591                 self.debug_print("os.makedirs('%s', 0700)" % path)
    592                 os.makedirs(path, 0700)
    593 
    594     # -- Command execution methods -------------------------------------
    595 
    596     def run (self):
    597 
    598         # Obviously have to build before we can install
    599         if not self.skip_build:
    600             self.run_command('build')
    601             # If we built for any other platform, we can't install.
    602             build_plat = self.distribution.get_command_obj('build').plat_name
    603             # check warn_dir - it is a clue that the 'install' is happening
    604             # internally, and not to sys.path, so we don't check the platform
    605             # matches what we are running.
    606             if self.warn_dir and build_plat != get_platform():
    607                 raise DistutilsPlatformError("Can't install when "
    608                                              "cross-compiling")
    609 
    610         # Run all sub-commands (at least those that need to be run)
    611         for cmd_name in self.get_sub_commands():
    612             self.run_command(cmd_name)
    613 
    614         if self.path_file:
    615             self.create_path_file()
    616 
    617         # write list of installed files, if requested.
    618         if self.record:
    619             outputs = self.get_outputs()
    620             if self.root:               # strip any package prefix
    621                 root_len = len(self.root)
    622                 for counter in xrange(len(outputs)):
    623                     outputs[counter] = outputs[counter][root_len:]
    624             self.execute(write_file,
    625                          (self.record, outputs),
    626                          "writing list of installed files to '%s'" %
    627                          self.record)
    628 
    629         sys_path = map(os.path.normpath, sys.path)
    630         sys_path = map(os.path.normcase, sys_path)
    631         install_lib = os.path.normcase(os.path.normpath(self.install_lib))
    632         if (self.warn_dir and
    633             not (self.path_file and self.install_path_file) and
    634             install_lib not in sys_path):
    635             log.debug(("modules installed to '%s', which is not in "
    636                        "Python's module search path (sys.path) -- "
    637                        "you'll have to change the search path yourself"),
    638                        self.install_lib)
    639 
    640     # run ()
    641 
    642     def create_path_file (self):
    643         filename = os.path.join(self.install_libbase,
    644                                 self.path_file + ".pth")
    645         if self.install_path_file:
    646             self.execute(write_file,
    647                          (filename, [self.extra_dirs]),
    648                          "creating %s" % filename)
    649         else:
    650             self.warn("path file '%s' not created" % filename)
    651 
    652 
    653     # -- Reporting methods ---------------------------------------------
    654 
    655     def get_outputs (self):
    656         # Assemble the outputs of all the sub-commands.
    657         outputs = []
    658         for cmd_name in self.get_sub_commands():
    659             cmd = self.get_finalized_command(cmd_name)
    660             # Add the contents of cmd.get_outputs(), ensuring
    661             # that outputs doesn't contain duplicate entries
    662             for filename in cmd.get_outputs():
    663                 if filename not in outputs:
    664                     outputs.append(filename)
    665 
    666         if self.path_file and self.install_path_file:
    667             outputs.append(os.path.join(self.install_libbase,
    668                                         self.path_file + ".pth"))
    669 
    670         return outputs
    671 
    672     def get_inputs (self):
    673         # XXX gee, this looks familiar ;-(
    674         inputs = []
    675         for cmd_name in self.get_sub_commands():
    676             cmd = self.get_finalized_command(cmd_name)
    677             inputs.extend(cmd.get_inputs())
    678 
    679         return inputs
    680 
    681 
    682     # -- Predicates for sub-command list -------------------------------
    683 
    684     def has_lib (self):
    685         """Return true if the current distribution has any Python
    686         modules to install."""
    687         return (self.distribution.has_pure_modules() or
    688                 self.distribution.has_ext_modules())
    689 
    690     def has_headers (self):
    691         return self.distribution.has_headers()
    692 
    693     def has_scripts (self):
    694         return self.distribution.has_scripts()
    695 
    696     def has_data (self):
    697         return self.distribution.has_data_files()
    698 
    699 
    700     # 'sub_commands': a list of commands this command might have to run to
    701     # get its work done.  See cmd.py for more info.
    702     sub_commands = [('install_lib',     has_lib),
    703                     ('install_headers', has_headers),
    704                     ('install_scripts', has_scripts),
    705                     ('install_data',    has_data),
    706                     ('install_egg_info', lambda self:True),
    707                    ]
    708 
    709 # class install
    710