install.py 22.7 KB
Newer Older
1 2 3 4
"""distutils.command.install

Implements the Distutils 'install' command."""

5 6
from distutils import log

7
# This module should be kept compatible with Python 2.1.
8

9
__revision__ = "$Id$"
10 11

import sys, os, string
12
from types import *
13 14
from distutils.core import Command
from distutils.debug import DEBUG
15
from distutils.sysconfig import get_config_vars
16
from distutils.errors import DistutilsPlatformError
17 18
from distutils.file_util import write_file
from distutils.util import convert_path, subst_vars, change_root
19
from distutils.errors import DistutilsOptionError
20
from glob import glob
21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
if sys.version < "2.2":
    WINDOWS_SCHEME = {
        'purelib': '$base',
        'platlib': '$base',
        'headers': '$base/Include/$dist_name',
        'scripts': '$base/Scripts',
        'data'   : '$base',
    }
else:
    WINDOWS_SCHEME = {
        'purelib': '$base/Lib/site-packages',
        'platlib': '$base/Lib/site-packages',
        'headers': '$base/Include/$dist_name',
        'scripts': '$base/Scripts',
        'data'   : '$base',
    }

39 40 41 42
INSTALL_SCHEMES = {
    'unix_prefix': {
        'purelib': '$base/lib/python$py_version_short/site-packages',
        'platlib': '$platbase/lib/python$py_version_short/site-packages',
43
        'headers': '$base/include/python$py_version_short/$dist_name',
44
        'scripts': '$base/bin',
45
        'data'   : '$base',
46 47 48 49
        },
    'unix_home': {
        'purelib': '$base/lib/python',
        'platlib': '$base/lib/python',
50
        'headers': '$base/include/python/$dist_name',
51
        'scripts': '$base/bin',
52
        'data'   : '$base',
53
        },
54
    'nt': WINDOWS_SCHEME,
55
    'mac': {
56 57 58 59 60 61 62
        'purelib': '$base/Lib/site-packages',
        'platlib': '$base/Lib/site-packages',
        'headers': '$base/Include/$dist_name',
        'scripts': '$base/Scripts',
        'data'   : '$base',
        },
    'os2': {
63 64 65 66
        'purelib': '$base/Lib/site-packages',
        'platlib': '$base/Lib/site-packages',
        'headers': '$base/Include/$dist_name',
        'scripts': '$base/Scripts',
67
        'data'   : '$base',
68 69 70
        }
    }

71 72 73 74 75
# The keys to an installation scheme; if any new types of files are to be
# installed, be sure to add an entry to every installation scheme above,
# and to SCHEME_KEYS here.
SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')

76

77
class install (Command):
78

79 80
    description = "install everything from build directory"

81
    user_options = [
82 83 84
        # Select installation scheme and set base director(y|ies)
        ('prefix=', None,
         "installation prefix"),
85
        ('exec-prefix=', None,
86 87 88 89 90 91 92 93 94 95
         "(Unix only) prefix for platform-specific files"),
        ('home=', None,
         "(Unix only) home directory to install under"),

        # Or, just set the base director(y|ies)
        ('install-base=', None,
         "base installation directory (instead of --prefix or --home)"),
        ('install-platbase=', None,
         "base installation directory for platform-specific files " +
         "(instead of --exec-prefix or --home)"),
96 97
        ('root=', None,
         "install everything relative to this alternate root directory"),
98 99 100 101

        # Or, explicitly set the installation scheme
        ('install-purelib=', None,
         "installation directory for pure Python module distributions"),
102
        ('install-platlib=', None,
103 104 105 106 107
         "installation directory for non-pure module distributions"),
        ('install-lib=', None,
         "installation directory for all module distributions " +
         "(overrides --install-purelib and --install-platlib)"),

108 109
        ('install-headers=', None,
         "installation directory for C/C++ headers"),
110 111 112 113
        ('install-scripts=', None,
         "installation directory for Python scripts"),
        ('install-data=', None,
         "installation directory for data files"),
114

115 116 117 118 119 120 121 122
        # Byte-compilation options -- see install_lib.py for details, as
        # these are duplicated from there (but only install_lib does
        # anything with them).
        ('compile', 'c', "compile .py to .pyc [default]"),
        ('no-compile', None, "don't compile .py files"),
        ('optimize=', 'O',
         "also compile with optimization: -O1 for \"python -O\", "
         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
Fred Drake's avatar
Fred Drake committed
123

124 125 126
        # Miscellaneous control options
        ('force', 'f',
         "force installation (overwrite any existing files)"),
127 128 129
        ('skip-build', None,
         "skip rebuilding everything (for testing/debugging)"),

130
        # Where to install documentation (eventually!)
131 132 133 134
        #('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"),
135

136 137
        ('record=', None,
         "filename in which to record list of installed files"),
138
        ]
139

140
    boolean_options = ['compile', 'force', 'skip-build']
141
    negative_opt = {'no-compile' : 'compile'}
142

143

144
    def initialize_options (self):
145

146 147
        # High-level options: these select both an installation base
        # and scheme.
148 149
        self.prefix = None
        self.exec_prefix = None
150 151
        self.home = None

152 153 154
        # These select only the installation base; it's up to the user to
        # specify the installation scheme (currently, that means supplying
        # the --install-{platlib,purelib,scripts,data} options).
155 156
        self.install_base = None
        self.install_platbase = None
157
        self.root = None
158

159 160 161 162 163 164
        # These options are the actual installation directories; if not
        # supplied by the user, they are filled in using the installation
        # scheme implied by prefix/exec-prefix/home and the contents of
        # that installation scheme.
        self.install_purelib = None     # for pure module distributions
        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 168
        self.install_scripts = None
        self.install_data = None
169

170
        self.compile = None
171 172
        self.optimize = None

173 174
        # These two are for putting non-packagized distributions into their
        # own directory and creating a .pth file if it makes sense.
175 176 177 178 179 180
        # 'extra_path' comes from the setup file; 'install_path_file' can
        # be turned off if it makes no sense to install a .pth file.  (But
        # better to install it uselessly than to guess wrong and not
        # install it when it's necessary and would be used!)  Currently,
        # 'install_path_file' is always true unless some outsider meddles
        # with it.
181
        self.extra_path = None
182 183 184 185
        self.install_path_file = 1

        # 'force' forces installation, even if target files are not
        # 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 188 189
        # a user option, it's just there so the bdist_* commands can turn
        # it off) determines whether we warn about installing to a
        # directory not in sys.path.
190
        self.force = 0
191
        self.skip_build = 0
192
        self.warn_dir = 1
193

194 195 196 197 198 199 200 201 202
        # These are only here as a conduit from the 'build' command to the
        # 'install_*' commands that do the real work.  ('build_base' isn't
        # actually used anywhere, but it might be useful in future.)  They
        # are not user options, because if the user told the install
        # command where the build directory is, that wouldn't affect the
        # build command.
        self.build_base = None
        self.build_lib = None

203 204
        # Not defined yet because we don't know anything about
        # documentation yet.
205 206 207
        #self.install_man = None
        #self.install_html = None
        #self.install_info = None
208

209
        self.record = None
210

211 212 213 214 215 216 217

    # -- Option finalizing methods -------------------------------------
    # (This is rather more involved than for most commands,
    # because this is where the policy for installing third-
    # party Python modules on various platforms given a wide
    # array of user input is decided.  Yes, it's quite complex!)

218
    def finalize_options (self):
219

220 221 222 223 224 225 226 227 228 229
        # This method (and its pliant slaves, like 'finalize_unix()',
        # 'finalize_other()', and 'select_scheme()') is where the default
        # installation directories for modules, extension modules, and
        # anything else we care to install from a Python module
        # distribution.  Thus, this code makes a pretty important policy
        # statement about how third-party stuff is added to a Python
        # installation!  Note that the actual work of installation is done
        # by the relatively simple 'install_*' commands; they just take
        # their orders from the installation directory options determined
        # here.
230

231 232
        # Check for errors/inconsistencies in the options; first, stuff
        # that's wrong on any platform.
233 234 235 236 237 238 239

        if ((self.prefix or self.exec_prefix or self.home) and
            (self.install_base or self.install_platbase)):
            raise DistutilsOptionError, \
                  ("must supply either prefix/exec-prefix/home or " +
                   "install-base/install-platbase -- not both")

240 241 242 243
        if self.home and (self.prefix or self.exec_prefix):
            raise DistutilsOptionError, \
                  "must supply either home or prefix/exec-prefix -- not both"

244
        # Next, stuff that's wrong (or dubious) only on certain platforms.
245
        if os.name != "posix":
246
            if self.exec_prefix:
247
                self.warn("exec-prefix option ignored on this platform")
248 249 250 251 252 253 254 255 256
                self.exec_prefix = None

        # Now the interesting logic -- so interesting that we farm it out
        # to other methods.  The goal of these methods is to set the final
        # values for the install_{lib,scripts,data,...}  options, using as
        # input a heady brew of prefix, exec_prefix, home, install_base,
        # install_platbase, user-supplied versions of
        # install_{purelib,platlib,lib,scripts,data,...}, and the
        # INSTALL_SCHEME dictionary above.  Phew!
257

258
        self.dump_dirs("pre-finalize_{unix,other}")
259

260
        if os.name == 'posix':
261
            self.finalize_unix()
262
        else:
263
            self.finalize_other()
264

265
        self.dump_dirs("post-finalize_{unix,other}()")
266 267 268 269 270 271

        # Expand configuration variables, tilde, etc. in self.install_base
        # and self.install_platbase -- that way, we can use $base or
        # $platbase in the other installation directories and not worry
        # about needing recursive variable expansion (shudder).

272
        py_version = (string.split(sys.version))[0]
Greg Ward's avatar
Greg Ward committed
273
        (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
274 275 276 277 278
        self.config_vars = {'dist_name': self.distribution.get_name(),
                            'dist_version': self.distribution.get_version(),
                            'dist_fullname': self.distribution.get_fullname(),
                            'py_version': py_version,
                            'py_version_short': py_version[0:3],
279 280 281 282
                            'sys_prefix': prefix,
                            'prefix': prefix,
                            'sys_exec_prefix': exec_prefix,
                            'exec_prefix': exec_prefix,
283
                           }
284
        self.expand_basedirs()
285

286
        self.dump_dirs("post-expand_basedirs()")
287 288 289 290 291 292

        # Now define config vars for the base directories so we can expand
        # everything else.
        self.config_vars['base'] = self.install_base
        self.config_vars['platbase'] = self.install_platbase

293 294 295
        if DEBUG:
            from pprint import pprint
            print "config vars:"
296
            pprint(self.config_vars)
297

298 299
        # Expand "~" and configuration variables in the installation
        # directories.
300
        self.expand_dirs()
301

302
        self.dump_dirs("post-expand_dirs()")
303

304 305 306 307 308 309 310 311 312
        # Pick the actual directory to install all modules to: either
        # install_purelib or install_platlib, depending on whether this
        # module distribution is pure or not.  Of course, if the user
        # already specified install_lib, use their selection.
        if self.install_lib is None:
            if self.distribution.ext_modules: # has extensions: non-pure
                self.install_lib = self.install_platlib
            else:
                self.install_lib = self.install_purelib
Fred Drake's avatar
Fred Drake committed
313

314 315 316 317 318 319

        # Convert directories from Unix /-separated syntax to the local
        # convention.
        self.convert_paths('lib', 'purelib', 'platlib',
                           'scripts', 'data', 'headers')

320 321 322 323
        # Well, we're not actually fully completely finalized yet: we still
        # have to deal with 'extra_path', which is the hack for allowing
        # non-packagized module distributions (hello, Numerical Python!) to
        # get their own directories.
324
        self.handle_extra_path()
325
        self.install_libbase = self.install_lib # needed for .pth file
326
        self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
327

328 329 330
        # If a new root directory was supplied, make all the installation
        # dirs relative to it.
        if self.root is not None:
331 332
            self.change_roots('libbase', 'lib', 'purelib', 'platlib',
                              'scripts', 'data', 'headers')
333

334
        self.dump_dirs("after prepending root")
335

336
        # Find out the build directories, ie. where to install from.
337 338 339
        self.set_undefined_options('build',
                                   ('build_base', 'build_base'),
                                   ('build_lib', 'build_lib'))
340 341 342

        # Punt on doc directories for now -- after all, we're punting on
        # documentation completely!
343

344 345 346
    # finalize_options ()


347
    def dump_dirs (self, msg):
348 349 350 351 352 353 354
        if DEBUG:
            from distutils.fancy_getopt import longopt_xlate
            print msg + ":"
            for opt in self.user_options:
                opt_name = opt[0]
                if opt_name[-1] == "=":
                    opt_name = opt_name[0:-1]
355 356 357 358 359 360 361
                if self.negative_opt.has_key(opt_name):
                    opt_name = string.translate(self.negative_opt[opt_name],
                                                longopt_xlate)
                    val = not getattr(self, opt_name)
                else:
                    opt_name = string.translate(opt_name, longopt_xlate)
                    val = getattr(self, opt_name)
362
                print "  %s: %s" % (opt_name, val)
363 364


365
    def finalize_unix (self):
Fred Drake's avatar
Fred Drake committed
366

367 368 369 370
        if self.install_base is not None or self.install_platbase is not None:
            if ((self.install_lib is None and
                 self.install_purelib is None and
                 self.install_platlib is None) or
371
                self.install_headers is None or
372 373 374
                self.install_scripts is None or
                self.install_data is None):
                raise DistutilsOptionError, \
375 376
                      ("install-base or install-platbase supplied, but "
                      "installation scheme is incomplete")
377 378 379 380
            return

        if self.home is not None:
            self.install_base = self.install_platbase = self.home
381
            self.select_scheme("unix_home")
382
        else:
383 384 385 386 387
            if self.prefix is None:
                if self.exec_prefix is not None:
                    raise DistutilsOptionError, \
                          "must not supply exec-prefix without prefix"

388 389
                self.prefix = os.path.normpath(sys.prefix)
                self.exec_prefix = os.path.normpath(sys.exec_prefix)
390 391 392 393 394 395 396

            else:
                if self.exec_prefix is None:
                    self.exec_prefix = self.prefix

            self.install_base = self.prefix
            self.install_platbase = self.exec_prefix
397
            self.select_scheme("unix_prefix")
398 399 400 401 402 403

    # finalize_unix ()


    def finalize_other (self):          # Windows and Mac OS for now

404 405 406 407 408 409
        if self.home is not None:
            self.install_base = self.install_platbase = self.home
            self.select_scheme("unix_home")
        else:
            if self.prefix is None:
                self.prefix = os.path.normpath(sys.prefix)
410

411 412 413 414 415 416
            self.install_base = self.install_platbase = self.prefix
            try:
                self.select_scheme(os.name)
            except KeyError:
                raise DistutilsPlatformError, \
                      "I don't know how to install stuff on '%s'" % os.name
417

418 419 420 421 422 423
    # finalize_other ()


    def select_scheme (self, name):
        # it's the caller's problem if they supply a bad name!
        scheme = INSTALL_SCHEMES[name]
424
        for key in SCHEME_KEYS:
425 426 427
            attrname = 'install_' + key
            if getattr(self, attrname) is None:
                setattr(self, attrname, scheme[key])
428 429


430 431
    def _expand_attrs (self, attrs):
        for attr in attrs:
432
            val = getattr(self, attr)
433 434
            if val is not None:
                if os.name == 'posix':
435 436 437
                    val = os.path.expanduser(val)
                val = subst_vars(val, self.config_vars)
                setattr(self, attr, val)
438 439


440
    def expand_basedirs (self):
441 442
        self._expand_attrs(['install_base',
                            'install_platbase',
Fred Drake's avatar
Fred Drake committed
443
                            'root'])
444 445

    def expand_dirs (self):
446 447 448 449 450 451
        self._expand_attrs(['install_purelib',
                            'install_platlib',
                            'install_lib',
                            'install_headers',
                            'install_scripts',
                            'install_data',])
452 453


454 455 456 457 458 459
    def convert_paths (self, *names):
        for name in names:
            attr = "install_" + name
            setattr(self, attr, convert_path(getattr(self, attr)))


460
    def handle_extra_path (self):
461

462 463 464 465
        if self.extra_path is None:
            self.extra_path = self.distribution.extra_path

        if self.extra_path is not None:
466 467
            if type(self.extra_path) is StringType:
                self.extra_path = string.split(self.extra_path, ',')
468

469
            if len(self.extra_path) == 1:
470
                path_file = extra_dirs = self.extra_path[0]
471
            elif len(self.extra_path) == 2:
472
                (path_file, extra_dirs) = self.extra_path
473
            else:
474
                raise DistutilsOptionError, \
475 476
                      ("'extra_path' option must be a list, tuple, or "
                      "comma-separated string with 1 or 2 elements")
477

478 479
            # convert to local form in case Unix notation used (as it
            # should be in setup scripts)
480
            extra_dirs = convert_path(extra_dirs)
481

482 483 484 485
        else:
            path_file = None
            extra_dirs = ''

486 487
        # XXX should we warn if path_file and not extra_dirs? (in which
        # case the path file would be harmless but pointless)
488 489 490
        self.path_file = path_file
        self.extra_dirs = extra_dirs

491
    # handle_extra_path ()
492 493


494 495 496 497 498 499
    def change_roots (self, *names):
        for name in names:
            attr = "install_" + name
            setattr(self, attr, change_root(self.root, getattr(self, attr)))


500 501
    # -- Command execution methods -------------------------------------

502 503
    def run (self):

504
        # Obviously have to build before we can install
505
        if not self.skip_build:
506
            self.run_command('build')
507

508 509
        # Run all sub-commands (at least those that need to be run)
        for cmd_name in self.get_sub_commands():
510
            self.run_command(cmd_name)
511 512

        if self.path_file:
513
            self.create_path_file()
514

515 516 517
        # write list of installed files, if requested.
        if self.record:
            outputs = self.get_outputs()
518
            if self.root:               # strip any package prefix
519
                root_len = len(self.root)
520
                for counter in xrange(len(outputs)):
521 522
                    outputs[counter] = outputs[counter][root_len:]
            self.execute(write_file,
523 524 525
                         (self.record, outputs),
                         "writing list of installed files to '%s'" %
                         self.record)
526

527
        sys_path = map(os.path.normpath, sys.path)
Greg Ward's avatar
Greg Ward committed
528
        sys_path = map(os.path.normcase, sys_path)
529
        install_lib = os.path.normcase(os.path.normpath(self.install_lib))
530 531
        if (self.warn_dir and
            not (self.path_file and self.install_path_file) and
532
            install_lib not in sys_path):
533
            log.debug(("modules installed to '%s', which is not in "
534
                       "Python's module search path (sys.path) -- "
535 536
                       "you'll have to change the search path yourself"),
                       self.install_lib)
537

538 539
    # run ()

540
    def create_path_file (self):
541 542
        filename = os.path.join(self.install_libbase,
                                self.path_file + ".pth")
543
        if self.install_path_file:
544 545 546
            self.execute(write_file,
                         (filename, [self.extra_dirs]),
                         "creating %s" % filename)
547 548
        else:
            self.warn("path file '%s' not created" % filename)
549

550

551
    # -- Reporting methods ---------------------------------------------
552

553
    def get_outputs (self):
554
        # Assemble the outputs of all the sub-commands.
555
        outputs = []
556
        for cmd_name in self.get_sub_commands():
557
            cmd = self.get_finalized_command(cmd_name)
558 559 560 561 562
            # Add the contents of cmd.get_outputs(), ensuring
            # that outputs doesn't contain duplicate entries
            for filename in cmd.get_outputs():
                if filename not in outputs:
                    outputs.append(filename)
563

564 565 566
        if self.path_file and self.install_path_file:
            outputs.append(os.path.join(self.install_libbase,
                                        self.path_file + ".pth"))
Fred Drake's avatar
Fred Drake committed
567

568 569
        return outputs

570 571 572
    def get_inputs (self):
        # XXX gee, this looks familiar ;-(
        inputs = []
573
        for cmd_name in self.get_sub_commands():
574 575
            cmd = self.get_finalized_command(cmd_name)
            inputs.extend(cmd.get_inputs())
576 577 578 579

        return inputs


580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
    # -- Predicates for sub-command list -------------------------------

    def has_lib (self):
        """Return true if the current distribution has any Python
        modules to install."""
        return (self.distribution.has_pure_modules() or
                self.distribution.has_ext_modules())

    def has_headers (self):
        return self.distribution.has_headers()

    def has_scripts (self):
        return self.distribution.has_scripts()

    def has_data (self):
        return self.distribution.has_data_files()

597

598 599 600 601 602 603
    # 'sub_commands': a list of commands this command might have to run to
    # get its work done.  See cmd.py for more info.
    sub_commands = [('install_lib',     has_lib),
                    ('install_headers', has_headers),
                    ('install_scripts', has_scripts),
                    ('install_data',    has_data),
604
                    ('install_egg_info', lambda self:True),
605 606
                   ]

607
# class install