1 """distutils.command.install 
   3 Implements the Distutils 'install' command.""" 
   5 from distutils 
import log
 
   7 # This module should be kept compatible with Python 1.5.2. 
  11 import sys
, os
, string
 
  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
.errors 
import DistutilsOptionError
 
  22 if sys
.version 
< "2.2": 
  26         'headers': '$base/Include/$dist_name', 
  27         'scripts': '$base/Scripts', 
  32         'purelib': '$base/Lib/site-packages', 
  33         'platlib': '$base/Lib/site-packages', 
  34         'headers': '$base/Include/$dist_name', 
  35         'scripts': '$base/Scripts', 
  41         'purelib': '$base/lib/python$py_version_short/site-packages', 
  42         'platlib': '$platbase/lib/python$py_version_short/site-packages', 
  43         'headers': '$base/include/python$py_version_short/$dist_name', 
  44         'scripts': '$base/bin', 
  48         'purelib': '$base/lib/python', 
  49         'platlib': '$base/lib/python', 
  50         'headers': '$base/include/python/$dist_name', 
  51         'scripts': '$base/bin', 
  56         'purelib': '$base/Lib/site-packages', 
  57         'platlib': '$base/Lib/site-packages', 
  58         'headers': '$base/Include/$dist_name', 
  59         'scripts': '$base/Scripts', 
  63         'purelib': '$base/Lib/site-packages', 
  64         'platlib': '$base/Lib/site-packages', 
  65         'headers': '$base/Include/$dist_name', 
  66         'scripts': '$base/Scripts', 
  71 # The keys to an installation scheme; if any new types of files are to be 
  72 # installed, be sure to add an entry to every installation scheme above, 
  73 # and to SCHEME_KEYS here. 
  74 SCHEME_KEYS 
= ('purelib', 'platlib', 'headers', 'scripts', 'data') 
  77 class install (Command
): 
  79     description 
= "install everything from build directory" 
  82         # Select installation scheme and set base director(y|ies) 
  84          "installation prefix"), 
  85         ('exec-prefix=', None, 
  86          "(Unix only) prefix for platform-specific files"), 
  88          "(Unix only) home directory to install under"), 
  90         # Or, just set the base director(y|ies) 
  91         ('install-base=', None, 
  92          "base installation directory (instead of --prefix or --home)"), 
  93         ('install-platbase=', None, 
  94          "base installation directory for platform-specific files " + 
  95          "(instead of --exec-prefix or --home)"), 
  97          "install everything relative to this alternate root directory"), 
  99         # Or, explicitly set the installation scheme 
 100         ('install-purelib=', None, 
 101          "installation directory for pure Python module distributions"), 
 102         ('install-platlib=', None, 
 103          "installation directory for non-pure module distributions"), 
 104         ('install-lib=', None, 
 105          "installation directory for all module distributions " + 
 106          "(overrides --install-purelib and --install-platlib)"), 
 108         ('install-headers=', None, 
 109          "installation directory for C/C++ headers"), 
 110         ('install-scripts=', None, 
 111          "installation directory for Python scripts"), 
 112         ('install-data=', None, 
 113          "installation directory for data files"), 
 115         # Byte-compilation options -- see install_lib.py for details, as 
 116         # these are duplicated from there (but only install_lib does 
 117         # anything with them). 
 118         ('compile', 'c', "compile .py to .pyc [default]"), 
 119         ('no-compile', None, "don't compile .py files"), 
 121          "also compile with optimization: -O1 for \"python -O\", " 
 122          "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), 
 124         # Miscellaneous control options 
 126          "force installation (overwrite any existing files)"), 
 128          "skip rebuilding everything (for testing/debugging)"), 
 130         # Where to install documentation (eventually!) 
 131         #('doc-format=', None, "format of documentation to generate"), 
 132         #('install-man=', None, "directory for Unix man pages"), 
 133         #('install-html=', None, "directory for HTML documentation"), 
 134         #('install-info=', None, "directory for GNU info files"), 
 137          "filename in which to record list of installed files"), 
 140     boolean_options 
= ['compile', 'force', 'skip-build'] 
 141     negative_opt 
= {'no-compile' : 'compile'}
 
 144     def initialize_options (self
): 
 146         # High-level options: these select both an installation base 
 149         self
.exec_prefix 
= None 
 152         # These select only the installation base; it's up to the user to 
 153         # specify the installation scheme (currently, that means supplying 
 154         # the --install-{platlib,purelib,scripts,data} options). 
 155         self
.install_base 
= None 
 156         self
.install_platbase 
= None 
 159         # These options are the actual installation directories; if not 
 160         # supplied by the user, they are filled in using the installation 
 161         # scheme implied by prefix/exec-prefix/home and the contents of 
 162         # that installation scheme. 
 163         self
.install_purelib 
= None     # for pure module distributions 
 164         self
.install_platlib 
= None     # non-pure (dists w/ extensions) 
 165         self
.install_headers 
= None     # for C/C++ headers 
 166         self
.install_lib 
= None         # set to either purelib or platlib 
 167         self
.install_scripts 
= None 
 168         self
.install_data 
= None 
 173         # These two are for putting non-packagized distributions into their 
 174         # own directory and creating a .pth file if it makes sense. 
 175         # 'extra_path' comes from the setup file; 'install_path_file' can 
 176         # be turned off if it makes no sense to install a .pth file.  (But 
 177         # better to install it uselessly than to guess wrong and not 
 178         # install it when it's necessary and would be used!)  Currently, 
 179         # 'install_path_file' is always true unless some outsider meddles 
 181         self
.extra_path 
= None 
 182         self
.install_path_file 
= 1 
 184         # 'force' forces installation, even if target files are not 
 185         # out-of-date.  'skip_build' skips running the "build" command, 
 186         # handy if you know it's not necessary.  'warn_dir' (which is *not* 
 187         # a user option, it's just there so the bdist_* commands can turn 
 188         # it off) determines whether we warn about installing to a 
 189         # directory not in sys.path. 
 194         # These are only here as a conduit from the 'build' command to the 
 195         # 'install_*' commands that do the real work.  ('build_base' isn't 
 196         # actually used anywhere, but it might be useful in future.)  They 
 197         # are not user options, because if the user told the install 
 198         # command where the build directory is, that wouldn't affect the 
 200         self
.build_base 
= None 
 201         self
.build_lib 
= None 
 203         # Not defined yet because we don't know anything about 
 205         #self.install_man = None 
 206         #self.install_html = None 
 207         #self.install_info = None 
 212     # -- Option finalizing methods ------------------------------------- 
 213     # (This is rather more involved than for most commands, 
 214     # because this is where the policy for installing third- 
 215     # party Python modules on various platforms given a wide 
 216     # array of user input is decided.  Yes, it's quite complex!) 
 218     def finalize_options (self
): 
 220         # This method (and its pliant slaves, like 'finalize_unix()', 
 221         # 'finalize_other()', and 'select_scheme()') is where the default 
 222         # installation directories for modules, extension modules, and 
 223         # anything else we care to install from a Python module 
 224         # distribution.  Thus, this code makes a pretty important policy 
 225         # statement about how third-party stuff is added to a Python 
 226         # installation!  Note that the actual work of installation is done 
 227         # by the relatively simple 'install_*' commands; they just take 
 228         # their orders from the installation directory options determined 
 231         # Check for errors/inconsistencies in the options; first, stuff 
 232         # that's wrong on any platform. 
 234         if ((self
.prefix 
or self
.exec_prefix 
or self
.home
) and 
 235             (self
.install_base 
or self
.install_platbase
)): 
 236             raise DistutilsOptionError
, \
 
 237                   ("must supply either prefix/exec-prefix/home or " + 
 238                    "install-base/install-platbase -- not both") 
 240         # Next, stuff that's wrong (or dubious) only on certain platforms. 
 241         if os
.name 
== 'posix': 
 242             if self
.home 
and (self
.prefix 
or self
.exec_prefix
): 
 243                 raise DistutilsOptionError
, \
 
 244                       ("must supply either home or prefix/exec-prefix -- " + 
 248                 self
.warn("exec-prefix option ignored on this platform") 
 249                 self
.exec_prefix 
= None 
 251                 self
.warn("home option ignored on this platform") 
 254         # Now the interesting logic -- so interesting that we farm it out 
 255         # to other methods.  The goal of these methods is to set the final 
 256         # values for the install_{lib,scripts,data,...}  options, using as 
 257         # input a heady brew of prefix, exec_prefix, home, install_base, 
 258         # install_platbase, user-supplied versions of 
 259         # install_{purelib,platlib,lib,scripts,data,...}, and the 
 260         # INSTALL_SCHEME dictionary above.  Phew! 
 262         self
.dump_dirs("pre-finalize_{unix,other}") 
 264         if os
.name 
== 'posix': 
 267             self
.finalize_other() 
 269         self
.dump_dirs("post-finalize_{unix,other}()") 
 271         # Expand configuration variables, tilde, etc. in self.install_base 
 272         # and self.install_platbase -- that way, we can use $base or 
 273         # $platbase in the other installation directories and not worry 
 274         # about needing recursive variable expansion (shudder). 
 276         py_version 
= (string
.split(sys
.version
))[0] 
 277         (prefix
, exec_prefix
) = get_config_vars('prefix', 'exec_prefix') 
 278         self
.config_vars 
= {'dist_name': self
.distribution
.get_name(), 
 279                             'dist_version': self
.distribution
.get_version(), 
 280                             'dist_fullname': self
.distribution
.get_fullname(), 
 281                             'py_version': py_version
, 
 282                             'py_version_short': py_version
[0:3], 
 283                             'sys_prefix': prefix
, 
 285                             'sys_exec_prefix': exec_prefix
, 
 286                             'exec_prefix': exec_prefix
, 
 288         self
.expand_basedirs() 
 290         self
.dump_dirs("post-expand_basedirs()") 
 292         # Now define config vars for the base directories so we can expand 
 294         self
.config_vars
['base'] = self
.install_base
 
 295         self
.config_vars
['platbase'] = self
.install_platbase
 
 298             from pprint 
import pprint
 
 300             pprint(self
.config_vars
) 
 302         # Expand "~" and configuration variables in the installation 
 306         self
.dump_dirs("post-expand_dirs()") 
 308         # Pick the actual directory to install all modules to: either 
 309         # install_purelib or install_platlib, depending on whether this 
 310         # module distribution is pure or not.  Of course, if the user 
 311         # already specified install_lib, use their selection. 
 312         if self
.install_lib 
is None: 
 313             if self
.distribution
.ext_modules
: # has extensions: non-pure 
 314                 self
.install_lib 
= self
.install_platlib
 
 316                 self
.install_lib 
= self
.install_purelib
 
 319         # Convert directories from Unix /-separated syntax to the local 
 321         self
.convert_paths('lib', 'purelib', 'platlib', 
 322                            'scripts', 'data', 'headers') 
 324         # Well, we're not actually fully completely finalized yet: we still 
 325         # have to deal with 'extra_path', which is the hack for allowing 
 326         # non-packagized module distributions (hello, Numerical Python!) to 
 327         # get their own directories. 
 328         self
.handle_extra_path() 
 329         self
.install_libbase 
= self
.install_lib 
# needed for .pth file 
 330         self
.install_lib 
= os
.path
.join(self
.install_lib
, self
.extra_dirs
) 
 332         # If a new root directory was supplied, make all the installation 
 333         # dirs relative to it. 
 334         if self
.root 
is not None: 
 335             self
.change_roots('libbase', 'lib', 'purelib', 'platlib', 
 336                               'scripts', 'data', 'headers') 
 338         self
.dump_dirs("after prepending root") 
 340         # Find out the build directories, ie. where to install from. 
 341         self
.set_undefined_options('build', 
 342                                    ('build_base', 'build_base'), 
 343                                    ('build_lib', 'build_lib')) 
 345         # Punt on doc directories for now -- after all, we're punting on 
 346         # documentation completely! 
 348     # finalize_options () 
 351     def dump_dirs (self
, msg
): 
 353             from distutils
.fancy_getopt 
import longopt_xlate
 
 355             for opt 
in self
.user_options
: 
 357                 if opt_name
[-1] == "=": 
 358                     opt_name 
= opt_name
[0:-1] 
 359                 opt_name 
= string
.translate(opt_name
, longopt_xlate
) 
 360                 val 
= getattr(self
, opt_name
) 
 361                 print "  %s: %s" % (opt_name
, val
) 
 364     def finalize_unix (self
): 
 366         if self
.install_base 
is not None or self
.install_platbase 
is not None: 
 367             if ((self
.install_lib 
is None and 
 368                  self
.install_purelib 
is None and 
 369                  self
.install_platlib 
is None) or 
 370                 self
.install_headers 
is None or 
 371                 self
.install_scripts 
is None or 
 372                 self
.install_data 
is None): 
 373                 raise DistutilsOptionError
, \
 
 374                       ("install-base or install-platbase supplied, but " 
 375                       "installation scheme is incomplete") 
 378         if self
.home 
is not None: 
 379             self
.install_base 
= self
.install_platbase 
= self
.home
 
 380             self
.select_scheme("unix_home") 
 382             if self
.prefix 
is None: 
 383                 if self
.exec_prefix 
is not None: 
 384                     raise DistutilsOptionError
, \
 
 385                           "must not supply exec-prefix without prefix" 
 387                 self
.prefix 
= os
.path
.normpath(sys
.prefix
) 
 388                 self
.exec_prefix 
= os
.path
.normpath(sys
.exec_prefix
) 
 391                 if self
.exec_prefix 
is None: 
 392                     self
.exec_prefix 
= self
.prefix
 
 394             self
.install_base 
= self
.prefix
 
 395             self
.install_platbase 
= self
.exec_prefix
 
 396             self
.select_scheme("unix_prefix") 
 401     def finalize_other (self
):          # Windows and Mac OS for now 
 403         if self
.prefix 
is None: 
 404             self
.prefix 
= os
.path
.normpath(sys
.prefix
) 
 406         self
.install_base 
= self
.install_platbase 
= self
.prefix
 
 408             self
.select_scheme(os
.name
) 
 410             raise DistutilsPlatformError
, \
 
 411                   "I don't know how to install stuff on '%s'" % os
.name
 
 416     def select_scheme (self
, name
): 
 417         # it's the caller's problem if they supply a bad name! 
 418         scheme 
= INSTALL_SCHEMES
[name
] 
 419         for key 
in SCHEME_KEYS
: 
 420             attrname 
= 'install_' + key
 
 421             if getattr(self
, attrname
) is None: 
 422                 setattr(self
, attrname
, scheme
[key
]) 
 425     def _expand_attrs (self
, attrs
): 
 427             val 
= getattr(self
, attr
) 
 429                 if os
.name 
== 'posix': 
 430                     val 
= os
.path
.expanduser(val
) 
 431                 val 
= subst_vars(val
, self
.config_vars
) 
 432                 setattr(self
, attr
, val
) 
 435     def expand_basedirs (self
): 
 436         self
._expand
_attrs
(['install_base', 
 440     def expand_dirs (self
): 
 441         self
._expand
_attrs
(['install_purelib', 
 449     def convert_paths (self
, *names
): 
 451             attr 
= "install_" + name
 
 452             setattr(self
, attr
, convert_path(getattr(self
, attr
))) 
 455     def handle_extra_path (self
): 
 457         if self
.extra_path 
is None: 
 458             self
.extra_path 
= self
.distribution
.extra_path
 
 460         if self
.extra_path 
is not None: 
 461             if type(self
.extra_path
) is StringType
: 
 462                 self
.extra_path 
= string
.split(self
.extra_path
, ',') 
 464             if len(self
.extra_path
) == 1: 
 465                 path_file 
= extra_dirs 
= self
.extra_path
[0] 
 466             elif len(self
.extra_path
) == 2: 
 467                 (path_file
, extra_dirs
) = self
.extra_path
 
 469                 raise DistutilsOptionError
, \
 
 470                       ("'extra_path' option must be a list, tuple, or " 
 471                       "comma-separated string with 1 or 2 elements") 
 473             # convert to local form in case Unix notation used (as it 
 474             # should be in setup scripts) 
 475             extra_dirs 
= convert_path(extra_dirs
) 
 481         # XXX should we warn if path_file and not extra_dirs? (in which 
 482         # case the path file would be harmless but pointless) 
 483         self
.path_file 
= path_file
 
 484         self
.extra_dirs 
= extra_dirs
 
 486     # handle_extra_path () 
 489     def change_roots (self
, *names
): 
 491             attr 
= "install_" + name
 
 492             setattr(self
, attr
, change_root(self
.root
, getattr(self
, attr
))) 
 495     # -- Command execution methods ------------------------------------- 
 499         # Obviously have to build before we can install 
 500         if not self
.skip_build
: 
 501             self
.run_command('build') 
 503         # Run all sub-commands (at least those that need to be run) 
 504         for cmd_name 
in self
.get_sub_commands(): 
 505             self
.run_command(cmd_name
) 
 508             self
.create_path_file() 
 510         # write list of installed files, if requested. 
 512             outputs 
= self
.get_outputs() 
 513             if self
.root
:               # strip any package prefix 
 514                 root_len 
= len(self
.root
) 
 515                 for counter 
in xrange(len(outputs
)): 
 516                     outputs
[counter
] = outputs
[counter
][root_len
:] 
 517             self
.execute(write_file
, 
 518                          (self
.record
, outputs
), 
 519                          "writing list of installed files to '%s'" % 
 522         sys_path 
= map(os
.path
.normpath
, sys
.path
) 
 523         sys_path 
= map(os
.path
.normcase
, sys_path
) 
 524         install_lib 
= os
.path
.normcase(os
.path
.normpath(self
.install_lib
)) 
 525         if (self
.warn_dir 
and 
 526             not (self
.path_file 
and self
.install_path_file
) and 
 527             install_lib 
not in sys_path
): 
 528             log
.debug(("modules installed to '%s', which is not in " 
 529                        "Python's module search path (sys.path) -- "  
 530                        "you'll have to change the search path yourself"), 
 535     def create_path_file (self
): 
 536         filename 
= os
.path
.join(self
.install_libbase
, 
 537                                 self
.path_file 
+ ".pth") 
 538         if self
.install_path_file
: 
 539             self
.execute(write_file
, 
 540                          (filename
, [self
.extra_dirs
]), 
 541                          "creating %s" % filename
) 
 543             self
.warn("path file '%s' not created" % filename
) 
 546     # -- Reporting methods --------------------------------------------- 
 548     def get_outputs (self
): 
 549         # Assemble the outputs of all the sub-commands. 
 551         for cmd_name 
in self
.get_sub_commands(): 
 552             cmd 
= self
.get_finalized_command(cmd_name
) 
 553             # Add the contents of cmd.get_outputs(), ensuring 
 554             # that outputs doesn't contain duplicate entries 
 555             for filename 
in cmd
.get_outputs(): 
 556                 if filename 
not in outputs
: 
 557                     outputs
.append(filename
) 
 559         if self
.path_file 
and self
.install_path_file
: 
 560             outputs
.append(os
.path
.join(self
.install_libbase
, 
 561                                         self
.path_file 
+ ".pth")) 
 565     def get_inputs (self
): 
 566         # XXX gee, this looks familiar ;-( 
 568         for cmd_name 
in self
.get_sub_commands(): 
 569             cmd 
= self
.get_finalized_command(cmd_name
) 
 570             inputs
.extend(cmd
.get_inputs()) 
 575     # -- Predicates for sub-command list ------------------------------- 
 578         """Return true if the current distribution has any Python 
 579         modules to install.""" 
 580         return (self
.distribution
.has_pure_modules() or 
 581                 self
.distribution
.has_ext_modules()) 
 583     def has_headers (self
): 
 584         return self
.distribution
.has_headers() 
 586     def has_scripts (self
): 
 587         return self
.distribution
.has_scripts() 
 590         return self
.distribution
.has_data_files() 
 593     # 'sub_commands': a list of commands this command might have to run to 
 594     # get its work done.  See cmd.py for more info. 
 595     sub_commands 
= [('install_lib',     has_lib
), 
 596                     ('install_headers', has_headers
), 
 597                     ('install_scripts', has_scripts
), 
 598                     ('install_data',    has_data
),