dist.py revision fa7dc57d6c9023a5028aacb802438527ab2cface
1fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward"""distutils.dist
2fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
3fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg WardProvides the Distribution class, which represents the module distribution
48ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Wardbeing built/installed/distributed.
58ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward"""
6fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
7fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# created 2000/04/03, Greg Ward
8fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# (extricated from core.py; actually dates back to the beginning)
9fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
10fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward__revision__ = "$Id$"
11fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
121426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smithimport sys, os, string, re
13fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom types import *
14fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom copy import copy
15fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom distutils.errors import *
162f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Wardfrom distutils.fancy_getopt import FancyGetopt, translate_longopt
17a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchlingfrom distutils.util import check_environ, strtobool, rfc822_escape
18fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
19fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
20fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# Regex to define acceptable Distutils command names.  This is not *quite*
21fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# the same as a Python NAME -- I don't allow leading underscores.  The fact
22fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# that they're very similar is no coincidence; the default naming scheme is
23fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# to look for a Python module named after the command.
24fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardcommand_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
25fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
26fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
27fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardclass Distribution:
288ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """The core of the Distutils.  Most of the work hiding behind 'setup'
298ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    is really done within a Distribution instance, which farms the work out
308ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to the Distutils commands specified on the command line.
318ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward
328ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Setup scripts will almost never instantiate Distribution directly,
338ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    unless the 'setup()' function is totally inadequate to their needs.
348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    However, it is conceivable that a setup script might wish to subclass
358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Distribution for some specialized purpose, and then pass the subclass
368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to 'setup()' as the 'distclass' keyword argument.  If so, it is
378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    necessary to respect the expectations that 'setup' has of Distribution.
388ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    See the code for 'setup()', in core.py, for details.
398ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """
40fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
41fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
42fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # 'global_options' describes the command-line options that may be
4382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # supplied to the setup script prior to any actual commands.
4482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
45fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # these global options.  This list should be kept to a bare minimum,
46fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # since every global option is also valid as a command option -- and we
47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # don't want to pollute the commands with too many options that they
48fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # have minimal control over.
49d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    global_options = [('verbose', 'v', "run verbosely (default)"),
50d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('quiet', 'q', "run quietly (turns verbosity off)"),
51d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('dry-run', 'n', "don't actually do anything"),
52d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('help', 'h', "show detailed help message"),
53fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                     ]
5482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
5582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # options that are not propagated to the commands
5682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_options = [
5782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('help-commands', None,
5882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "list all available commands"),
5982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('name', None,
6082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package name"),
6182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('version', 'V',
6282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package version"),
6382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('fullname', None,
6482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print <package name>-<version>"),
6582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author', None,
6682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's name"),
6782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author-email', None,
6882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's email address"),
6982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer', None,
7082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's name"),
7182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer-email', None,
7282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's email address"),
7382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact', None,
74d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's name if known, else the author's"),
7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact-email', None,
76d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's email address if known, else the author's"),
7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('url', None,
7882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the URL for this package"),
7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('license', None,
80fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "print the license of the package"),
81fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        ('licence', None,
82fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "alias for --license"),
8382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('description', None,
8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the package description"),
85e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        ('long-description', None,
86e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward         "print the long package description"),
87a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('platforms', None,
88a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of platforms"),
89a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('keywords', None,
90a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of keywords"),
9182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ]
922f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward    display_option_names = map(lambda x: translate_longopt(x[0]),
932f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                               display_options)
9482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
9582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # negative options are options that exclude other options
96fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    negative_opt = {'quiet': 'verbose'}
97fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
98fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
99fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Creation/initialization methods -------------------------------
100fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
101fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def __init__ (self, attrs=None):
102fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Construct a new Distribution instance: initialize all the
1038ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes of a Distribution, and then use 'attrs' (a dictionary
1048ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        mapping attribute names to values) to assign some of those
1058ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes their "real" values.  (Any attributes not mentioned in
1068ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'attrs' will be assigned to some null value: 0, None, an empty list
1078ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        or dictionary, etc.)  Most importantly, initialize the
1088ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'command_obj' attribute to the empty dictionary; this will be
1098ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        filled in with real command objects by 'parse_command_line()'.
1108ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        """
111fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
112fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Default values for our command-line options
113fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.verbose = 1
114fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.dry_run = 0
115fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.help = 0
11682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for attr in self.display_option_names:
11782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            setattr(self, attr, 0)
11882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
11982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # Store the distribution meta-data (name, version, author, and so
12082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # forth) in a separate object -- we're getting to have enough
12182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # information here (and enough command-line options) that it's
12282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
12382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # object in a sneaky and underhanded (but efficient!) way.
124fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.metadata = DistributionMetadata()
1254982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward        method_basenames = dir(self.metadata) + \
1264982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward                           ['fullname', 'contact', 'contact_email']
1274982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward        for basename in method_basenames:
1284982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            method_name = "get_" + basename
1294982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            setattr(self, method_name, getattr(self.metadata, method_name))
130fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
131fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'cmdclass' maps command names to class objects, so we
132fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # can 1) quickly figure out which class to instantiate when
133fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # we need to create a new command object, and 2) have a way
13482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for the setup script to override command classes
135fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.cmdclass = {}
136fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
1379821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # 'script_name' and 'script_args' are usually set to sys.argv[0]
1389821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # and sys.argv[1:], but they can be overridden when the caller is
1399821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # not necessarily a setup script run from the command-line.
1409821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_name = None
1419821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_args = None
1429821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward
143d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 'command_options' is where we store command options between
144d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # parsing them (from config files, the command-line, etc.) and when
145d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # they are actually needed -- ie. when the command in question is
146d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
147d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        #   command_options = { command_name : { option : (source, value) } }
1481426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        self.command_options = {}
1491426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
150fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # These options are really the business of various commands, rather
151fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # than of the Distribution itself.  We provide aliases for them in
152fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Distribution as a convenience to the developer.
153fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.packages = None
154fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.package_dir = None
155fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.py_modules = None
156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.libraries = None
15751def7d667a42eac177690e1fe00eab7f2102319Greg Ward        self.headers = None
158fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_modules = None
159fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_package = None
160fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.include_dirs = None
161fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.extra_path = None
162b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith        self.scripts = None
1636a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith        self.data_files = None
164fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
165fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # And now initialize bookkeeping stuff that can't be supplied by
166fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the caller at all.  'command_obj' maps command names to
167fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Command instances -- that's how we enforce that every command
168fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # class is a singleton.
169fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.command_obj = {}
170fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
171fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'have_run' maps command names to boolean values; it keeps track
172fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # of whether we have actually run a particular command, to make it
173fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # cheap to "run" a command whenever we think we might need to -- if
174fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # it's already been done, no need for expensive filesystem
175fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # operations, we just check the 'have_run' dictionary and carry on.
176fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # It's only safe to query 'have_run' for a command class that has
177fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # been instantiated -- a false value will be inserted when the
178fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # command object is created, and replaced with a true value when
179612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        # the command is successfully run.  Thus it's probably best to use
180fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # '.get()' rather than a straight lookup.
181fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run = {}
182fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
183fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Now we'll use the attrs dictionary (ultimately, keyword args from
18482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # the setup script) to possibly override any or all of these
18582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # distribution options.
18682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
187fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if attrs:
188fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
189fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Pull out the set of command options and work on them
190fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # specifically.  Note that this order guarantees that aliased
191fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # command options will override any supplied redundantly
192fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # through the general options dictionary.
193fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            options = attrs.get('options')
194fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if options:
195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                del attrs['options']
196fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                for (command, cmd_options) in options.items():
1970e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    opt_dict = self.get_option_dict(command)
1980e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    for (opt, val) in cmd_options.items():
1990e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = ("setup script", val)
200fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
201fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Now work on the rest of the attributes.  Any attribute that's
202fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # not already defined is invalid!
203fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            for (key,val) in attrs.items():
204fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                if hasattr(self.metadata, key):
205fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self.metadata, key, val)
206fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                elif hasattr(self, key):
207fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self, key, val)
208fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                else:
20902a1a2b077e969e5fef8504cece5852bf641552dGreg Ward                    raise DistutilsSetupError, \
210fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                          "invalid distribution option '%s'" % key
211fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
212a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.finalize_options()
213898f099dc61c3efbaa28cc727f5dbfd773d38444Andrew M. Kuchling
214fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # __init__ ()
215fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
216fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
2170e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward    def get_option_dict (self, command):
2180e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """Get the option dictionary for a given command.  If that
2190e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        command's option dictionary hasn't been created yet, then create it
2200e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        and return the new dictionary; otherwise, return the existing
2210e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        option dictionary.
2220e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """
2230e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2240e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        dict = self.command_options.get(command)
2250e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        if dict is None:
2260e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            dict = self.command_options[command] = {}
2270e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        return dict
2280e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2290e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
230c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def dump_option_dicts (self, header=None, commands=None, indent=""):
231c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from pprint import pformat
232c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
233c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if commands is None:             # dump all command option dicts
234c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands = self.command_options.keys()
235c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands.sort()
236c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
237c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if header is not None:
238c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + header
239c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            indent = indent + "  "
240c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
241c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not commands:
242c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + "no commands known yet"
243c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            return
244c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
245c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for cmd_name in commands:
246c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            opt_dict = self.command_options.get(cmd_name)
247c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if opt_dict is None:
248c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "no option dict for '%s' command" % cmd_name
249c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            else:
250c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "option dict for '%s' command:" % cmd_name
251c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                out = pformat(opt_dict)
252c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                for line in string.split(out, "\n"):
253c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                    print indent + "  " + line
254c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
255c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    # dump_option_dicts ()
256c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
257c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
258c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
259d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Config file finding/parsing methods ---------------------------
260d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
2611426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def find_config_files (self):
2621426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        """Find as many configuration files as should be processed for this
2631426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        platform, and return a list of filenames in the order in which they
2641426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        should be parsed.  The filenames returned are guaranteed to exist
2651426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        (modulo nasty race conditions).
2661426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2671426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        On Unix, there are three possible config files: pydistutils.cfg in
2681426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        the Distutils installation directory (ie. where the top-level
2691426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Distutils __inst__.py file lives), .pydistutils.cfg in the user's
2701426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        home directory, and setup.cfg in the current directory.
2711426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2721426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        On Windows and Mac OS, there are two possible config files:
2731426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        pydistutils.cfg in the Python installation directory (sys.prefix)
274d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        and setup.cfg in the current directory.
275d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
2761426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        files = []
277acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward        check_environ()
278acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward
2791169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Where to look for the system-wide Distutils config file
2801169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
2811169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
2821169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Look for the system config file
2831169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_file = os.path.join(sys_dir, "distutils.cfg")
2841169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.path.isfile(sys_file):
2851169687692e5e897033421fe6a73a3c32675a7d7Greg Ward            files.append(sys_file)
2861169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
2871169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # What to call the per-user config file
2881169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.name == 'posix':
28965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = ".pydistutils.cfg"
29065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        else:
29165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = "pydistutils.cfg"
292fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
2931169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # And look for the user config file
29465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if os.environ.has_key('HOME'):
29565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_file = os.path.join(os.environ.get('HOME'), user_filename)
2961426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            if os.path.isfile(user_file):
2971426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                files.append(user_file)
2981426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2991426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        # All platforms support local setup.cfg
3001426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        local_file = "setup.cfg"
3011426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.path.isfile(local_file):
3021426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            files.append(local_file)
3031426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3041426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        return files
3051426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3061426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    # find_config_files ()
3071426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3081426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3091426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def parse_config_files (self, filenames=None):
3101426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3111426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        from ConfigParser import ConfigParser
3122bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward        from distutils.core import DEBUG
3131426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3141426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if filenames is None:
3151426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            filenames = self.find_config_files()
3161426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3172bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward        if DEBUG: print "Distribution.parse_config_files():"
318474607777d10562679b1640d3831290b0c4284f7Greg Ward
3191426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        parser = ConfigParser()
320d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for filename in filenames:
3212bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG: print "  reading", filename
322d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.read(filename)
323d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            for section in parser.sections():
324d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                options = parser.options(section)
3250e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                opt_dict = self.get_option_dict(section)
326d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
327d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                for opt in options:
328d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    if opt != '__name__':
329ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        val = parser.get(section,opt)
330ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt = string.replace(opt, '-', '_')
331ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt_dict[opt] = (filename, val)
3321426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
333474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Make the ConfigParser forget everything (so we retain
334474607777d10562679b1640d3831290b0c4284f7Greg Ward            # the original filenames that options come from) -- gag,
335474607777d10562679b1640d3831290b0c4284f7Greg Ward            # retch, puke -- another good reason for a distutils-
336474607777d10562679b1640d3831290b0c4284f7Greg Ward            # specific config parser (sigh...)
337474607777d10562679b1640d3831290b0c4284f7Greg Ward            parser.__init__()
3381426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
339ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # If there was a "global" section in the config file, use it
340ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # to set Distribution options.
341ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
342ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        if self.command_options.has_key('global'):
343ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            for (opt, (src, val)) in self.command_options['global'].items():
344ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                alias = self.negative_opt.get(opt)
345ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                try:
346ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    if alias:
347ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, alias, not strtobool(val))
348ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    elif opt in ('verbose', 'dry_run'): # ugh!
349ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, opt, strtobool(val))
350ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                except ValueError, msg:
351ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, msg
352ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
353ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward    # parse_config_files ()
354ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
3551426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
356d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Command-line parsing methods ----------------------------------
357fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
3589821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward    def parse_command_line (self):
3599821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        """Parse the setup script's command line, taken from the
3609821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
3619821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        -- see 'setup()' in core.py).  This list is first processed for
3629821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        "global options" -- options that set attributes of the Distribution
3639821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        instance.  Then, it is alternately scanned for Distutils commands
3649821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        and options for that command.  Each new command terminates the
3659821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        options for the previous command.  The allowed options for a
3669821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command are determined by the 'user_options' attribute of the
3679821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command class -- thus, we have to be able to load command classes
3689821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        in order to parse the command line.  Any error in that 'options'
3699821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        attribute raises DistutilsGetoptError; any error on the
3709821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command-line raises DistutilsArgError.  If no Distutils commands
3719821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        were found on the command line, raises DistutilsArgError.  Return
372ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        true if command-line was successfully parsed and we should carry
3739821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        on with executing commands; false if no errors but we shouldn't
3749821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        execute commands (currently, this only happens if user asks for
3759821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        help).
376d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
3773f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
3783f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        # We now have enough information to show the Macintosh dialog that allows
3793f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        # the user to interactively specify the "command line".
3803f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
3813f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        if sys.platform == 'mac':
3823f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            import EasyDialogs
3833f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            cmdlist = self.get_command_list()
3843f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            self.script_args = EasyDialogs.GetArgv(
3853f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling                self.global_options + self.display_options, cmdlist)
3863f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling
387fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # We have to parse the command line a bit at a time -- global
388fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # options, then the first command, then its options, and so on --
389fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # because each command will be handled by a different class, and
390d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # the options that are valid for a particular class aren't known
391d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we have loaded the command class, which doesn't happen
392d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we know what the command is.
393fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
394fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.commands = []
395fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser = FancyGetopt(self.global_options + self.display_options)
396fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(self.negative_opt)
397fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        parser.set_aliases({'licence': 'license'})
398fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        args = parser.getopt(args=self.script_args, object=self)
39982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        option_order = parser.get_option_order()
400fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
40182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for display options we return immediately
40282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.handle_display_options(option_order):
403fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
404fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
405fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        while args:
406d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            args = self._parse_command_opts(parser, args)
407d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if args is None:            # user asked for help (and got it)
408fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                return
409fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
410d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Handle the cases of --help as a "global" option, ie.
411d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # "setup.py --help" and "setup.py --help command ...".  For the
412d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # former, we show global options (--verbose, --dry-run, etc.)
413d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # and display-only options (--name, --version, etc.); for the
414d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # latter, we omit the display-only options and show help for
415d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # each command listed on the command line.
416d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if self.help:
417d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser,
418d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            display_options=len(self.commands) == 0,
419d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            commands=self.commands)
420fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
421fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
422fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Oops, no commands found -- an end-user error
423fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not self.commands:
424fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsArgError, "no commands supplied"
425fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
426fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # All is well: return true
427fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return 1
428fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
429fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # parse_command_line()
430fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
431d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _parse_command_opts (self, parser, args):
432d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the command-line options for a single command.
433d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'parser' must be a FancyGetopt instance; 'args' must be the list
434d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of arguments, starting with the current command (whose options
435d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        we are about to parse).  Returns a new version of 'args' with
436d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the next command at the front of the list; will be the empty
437d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        list if there are no more commands on the command line.  Returns
438d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        None if the user asked for help on this command.
439d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
440d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
441d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
442d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
443d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Pull the current command from the head of the command line
444d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command = args[0]
445fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not command_re.match(command):
446d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise SystemExit, "invalid command name '%s'" % command
447fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.commands.append(command)
448d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
449d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Dig up the command class that implements this command, so we
450d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 1) know that it's a valid command, and 2) know which options
451d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # it takes.
452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        try:
453fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            cmd_class = self.get_command_class(command)
454d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except DistutilsModuleError, msg:
455d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsArgError, msg
456d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
457d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Require that the command class be derived from Command -- want
458d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # to be sure that the basic "command" interface is implemented.
459fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not issubclass(cmd_class, Command):
460d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
461d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  "command class %s must subclass Command" % cmd_class
462d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
463d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Also make sure that the command object provides a list of its
464d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # known options.
465fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not (hasattr(cmd_class, 'user_options') and
466fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                type(cmd_class.user_options) is ListType):
467d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
468d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  ("command class %s must provide " +
469d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                   "'user_options' attribute (a list of tuples)") % \
470d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  cmd_class
471d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
472d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # If the command class has a list of negative alias options,
473d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # merge it in with the global negative aliases.
474d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        negative_opt = self.negative_opt
475fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if hasattr(cmd_class, 'negative_opt'):
476fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt = copy(negative_opt)
477fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt.update(cmd_class.negative_opt)
478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
479fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # Check for help_options in command class.  They have a different
480fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # format (tuple of four) so we need to preprocess them here.
48165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
482fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            type(cmd_class.help_options) is ListType):
4832ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward            help_options = fix_help_options(cmd_class.help_options)
4842ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        else:
48555fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward            help_options = []
4862ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
4879d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
488d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # All commands support the global options too, just by adding
489d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # in 'global_options'.
490fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_option_table(self.global_options +
491fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                cmd_class.user_options +
492fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                help_options)
493fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(negative_opt)
494fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        (args, opts) = parser.getopt(args[1:])
495474607777d10562679b1640d3831290b0c4284f7Greg Ward        if hasattr(opts, 'help') and opts.help:
496d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser, display_options=0, commands=[cmd_class])
497d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return
498d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
49965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
500fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            type(cmd_class.help_options) is ListType):
50165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            help_option_found=0
50265d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            for (help_option, short, desc, func) in cmd_class.help_options:
50365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                if hasattr(opts, parser.get_attr_name(help_option)):
50465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                    help_option_found=1
505fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward                    #print "showing help for option %s of command %s" % \
5062ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward                    #      (help_option[0],cmd_class)
50755fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
50855fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    if callable(func):
50965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                        func()
51055fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    else:
51155fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                        raise DistutilsClassError, \
51255fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                            ("invalid help function %s for help option '%s': "
51355fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                             "must be a callable object (function, etc.)") % \
51455fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                            (`func`, help_option)
51555fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
51655fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward            if help_option_found:
51765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                return
5189d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
519d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Put the options from the command-line into their official
520d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # holding pen, the 'command_options' dictionary.
5210e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        opt_dict = self.get_option_dict(command)
522d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for (name, value) in vars(opts).items():
5230e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            opt_dict[name] = ("command line", value)
524d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
525d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return args
526d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
527d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _parse_command_opts ()
528d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
529d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
530a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def finalize_options (self):
531a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Set final values for all the options on the Distribution
532a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        instance, analogous to the .finalize_options() method of Command
533a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        objects.
534a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
535a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
536a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        keywords = self.metadata.keywords
537a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords is not None:
538a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            if type(keywords) is StringType:
539a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                keywordlist = string.split(keywords, ',')
540a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                self.metadata.keywords = map(string.strip, keywordlist)
541a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
542a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        platforms = self.metadata.platforms
543a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if platforms is not None:
544a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            if type(platforms) is StringType:
545a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                platformlist = string.split(platforms, ',')
546a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                self.metadata.platforms = map(string.strip, platformlist)
547a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
548d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _show_help (self,
549d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    parser,
550d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    global_options=1,
551d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    display_options=1,
552d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    commands=[]):
553d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Show help for the setup script command-line in the form of
554d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        several lists of command-line options.  'parser' should be a
555d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        FancyGetopt instance; do not expect it to be returned in the
556d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        same state, as its option table will be reset to make it
557d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        generate the correct help text.
558d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
559d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        If 'global_options' is true, lists the global options:
560d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        --verbose, --dry-run, etc.  If 'display_options' is true, lists
561d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the "display-only" options: --name, --version, etc.  Finally,
562d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        lists per-command help for every command name or command class
563d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        in 'commands'.
564d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
565d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
5669821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
567d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
568d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
569d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if global_options:
570fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.global_options)
571fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Global options:")
572d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
573d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
574d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if display_options:
575fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.display_options)
576fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help(
577d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "Information display options (just display " +
578d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "information, ignore any commands)")
579d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
580d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
581d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for command in self.commands:
582fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling            if type(command) is ClassType and issubclass(command, Command):
583d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = command
584d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            else:
585fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(command)
58665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            if (hasattr(klass, 'help_options') and
587fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                type(klass.help_options) is ListType):
588fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options +
589fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                        fix_help_options(klass.help_options))
59065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            else:
591fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options)
592fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Options for '%s' command:" % klass.__name__)
593d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
594d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
5959821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        print gen_usage(self.script_name)
596d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return
597d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
598d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _show_help ()
599fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
600d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
60182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def handle_display_options (self, option_order):
60282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """If there were any non-global "display-only" options
603d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (--help-commands or the metadata display options) on the command
604d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        line, display the requested info and return true; else return
605d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        false.
606d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
6079821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
60882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
60982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # User just wants a list of commands -- we'll print it out and stop
61082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # processing now (ie. if they ran "setup --help-commands foo bar",
61182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # we ignore "foo bar").
61282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.help_commands:
613fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_commands()
61482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            print
6159821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward            print gen_usage(self.script_name)
61682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            return 1
61782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
61882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # If user supplied any of the "display metadata" options, then
61982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # display that metadata in the order in which the user supplied the
62082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # metadata options.
62182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        any_display_options = 0
62282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        is_display_option = {}
62382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for option in self.display_options:
62482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            is_display_option[option[0]] = 1
62582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
62682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for (opt, val) in option_order:
62782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            if val and is_display_option.get(opt):
6282f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                opt = translate_longopt(opt)
629a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                value = getattr(self.metadata, "get_"+opt)()
630a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                if opt in ['keywords', 'platforms']:
631a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                    print string.join(value, ',')
632a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                else:
633a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                    print value
63482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                any_display_options = 1
63582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
63682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return any_display_options
63782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
63882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # handle_display_options()
639fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
640fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_command_list (self, commands, header, max_length):
641fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print a subset of the list of all commands -- used by
642d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'print_commands()'.
643d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
644fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
645fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        print header + ":"
646fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
647fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in commands:
648fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            klass = self.cmdclass.get(cmd)
649fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not klass:
650fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(cmd)
651fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            try:
652fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = klass.description
653fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            except AttributeError:
654fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = "(no description available)"
655fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
656fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print "  %-*s  %s" % (max_length, cmd, description)
657fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
658fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_command_list ()
659fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
660fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
661fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_commands (self):
662d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Print out a help message listing all available commands with a
663d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        description of each.  The list is divided into "standard commands"
664d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (listed in distutils.command.__all__) and "extra commands"
665d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (mentioned in self.cmdclass, but not a standard command).  The
666d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        descriptions come from the command class attribute
667d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'description'.
668d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
669fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
670fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        import distutils.command
671fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        std_commands = distutils.command.__all__
672fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        is_std = {}
673fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in std_commands:
674fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            is_std[cmd] = 1
675fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
676fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        extra_commands = []
677fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.cmdclass.keys():
678fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not is_std.get(cmd):
679fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                extra_commands.append(cmd)
680fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
681fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        max_length = 0
682fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in (std_commands + extra_commands):
683fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            if len(cmd) > max_length:
684fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                max_length = len(cmd)
685fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
686fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.print_command_list(std_commands,
687fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                "Standard commands",
688fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                max_length)
689fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if extra_commands:
690fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print
691fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_command_list(extra_commands,
692fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    "Extra commands",
693fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    max_length)
694fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
695fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_commands ()
696fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
697f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward    def get_command_list (self):
698f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """Get a list of (command, description) tuples.
699f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        The list is divided into "standard commands" (listed in
700f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        distutils.command.__all__) and "extra commands" (mentioned in
701f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        self.cmdclass, but not a standard command).  The descriptions come
702f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        from the command class attribute 'description'.
703f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """
704f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Currently this is only used on Mac OS, for the Mac-only GUI
705f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Distutils interface (by Jack Jansen)
706f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
707f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        import distutils.command
708f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        std_commands = distutils.command.__all__
709f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        is_std = {}
710f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in std_commands:
711f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            is_std[cmd] = 1
712f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
713f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        extra_commands = []
714f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in self.cmdclass.keys():
715f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not is_std.get(cmd):
716f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                extra_commands.append(cmd)
717f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
718f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        rv = []
719f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in (std_commands + extra_commands):
720f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            klass = self.cmdclass.get(cmd)
721f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not klass:
722f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                klass = self.get_command_class(cmd)
723f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            try:
724f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = klass.description
725f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            except AttributeError:
726f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = "(no description available)"
727f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            rv.append((cmd, description))
728f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        return rv
729fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
730fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Command class/object methods ----------------------------------
731fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
732d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_class (self, command):
733d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the class that implements the Distutils command named by
734d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'command'.  First we check the 'cmdclass' dictionary; if the
735d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command is mentioned there, we fetch the class object from the
736d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        dictionary and return it.  Otherwise we load the command module
737d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        ("distutils.command." + command) and fetch the command class from
738d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the module.  The loaded class is also stored in 'cmdclass'
739d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        to speed future calls to 'get_command_class()'.
7401426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
7411426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Raises DistutilsModuleError if the expected module could not be
742d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        found, or if that module does not define the expected class.
743d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
744d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        klass = self.cmdclass.get(command)
745d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if klass:
746d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return klass
747fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
748fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        module_name = 'distutils.command.' + command
749fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        klass_name = command
750fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
751fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
752fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            __import__ (module_name)
753fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            module = sys.modules[module_name]
754fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        except ImportError:
755fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
756fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no module named '%s')" % \
757fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  (command, module_name)
758fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
759fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
760d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = getattr(module, klass_name)
761d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except AttributeError:
762fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
763fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no class '%s' in module '%s')" \
764fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  % (command, klass_name, module_name)
765fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
766d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        self.cmdclass[command] = klass
767fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return klass
768fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
769d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # get_command_class ()
770fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
771d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_obj (self, command, create=1):
772d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the command object for 'command'.  Normally this object
773612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        is cached on a previous call to 'get_command_obj()'; if no command
774d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        object for 'command' is in the cache, then we either create and
775d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return it (if 'create' is true) or return None.
776d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
7772bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward        from distutils.core import DEBUG
778d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.command_obj.get(command)
779fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not cmd_obj and create:
7802bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG:
7812bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward                print "Distribution.get_command_obj(): " \
7822bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward                      "creating '%s' command object" % command
783474607777d10562679b1640d3831290b0c4284f7Greg Ward
784d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = self.get_command_class(command)
785474607777d10562679b1640d3831290b0c4284f7Greg Ward            cmd_obj = self.command_obj[command] = klass(self)
786474607777d10562679b1640d3831290b0c4284f7Greg Ward            self.have_run[command] = 0
787474607777d10562679b1640d3831290b0c4284f7Greg Ward
788474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Set any options that were supplied in config files
789474607777d10562679b1640d3831290b0c4284f7Greg Ward            # or on the command line.  (NB. support for error
790474607777d10562679b1640d3831290b0c4284f7Greg Ward            # reporting is lame here: any errors aren't reported
791474607777d10562679b1640d3831290b0c4284f7Greg Ward            # until 'finalize_options()' is called, which means
792474607777d10562679b1640d3831290b0c4284f7Greg Ward            # we won't report the source of the error.)
793474607777d10562679b1640d3831290b0c4284f7Greg Ward            options = self.command_options.get(command)
794474607777d10562679b1640d3831290b0c4284f7Greg Ward            if options:
795c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                self._set_command_options(cmd_obj, options)
796fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
797fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return cmd_obj
798fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
799c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def _set_command_options (self, command_obj, option_dict=None):
800c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Set the options for 'command_obj' from 'option_dict'.  Basically
801c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        this means copying elements of a dictionary ('option_dict') to
802c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        attributes of an instance ('command').
803c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
804ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        'command_obj' must be a Command instance.  If 'option_dict' is not
805c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        supplied, uses the standard option dictionary for this command
806c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        (from 'self.command_options').
807c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
808c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.core import DEBUG
809c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
810c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command_name = command_obj.get_command_name()
811c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if option_dict is None:
812c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            option_dict = self.get_option_dict(command_name)
813c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
814c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if DEBUG: print "  setting options for '%s' command:" % command_name
815c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for (option, (source, value)) in option_dict.items():
816c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if DEBUG: print "    %s = %s (from %s)" % (option, value, source)
817ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8182f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                bool_opts = map(translate_longopt, command_obj.boolean_options)
819ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
820ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                bool_opts = []
821ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
822ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = command_obj.negative_opt
823ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
824ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = {}
825ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
826ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8272c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                is_string = type(value) is StringType
8282c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                if neg_opt.has_key(option) and is_string:
829ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, neg_opt[option], not strtobool(value))
8302c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                elif option in bool_opts and is_string:
831ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, strtobool(value))
832ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                elif hasattr(command_obj, option):
833ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, value)
834ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                else:
835ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, \
836ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                          ("error in %s: command '%s' has no such option '%s'"
837ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                           % (source, command_name, option))
838ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except ValueError, msg:
839ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                raise DistutilsOptionError, msg
840c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
841f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward    def reinitialize_command (self, command, reinit_subcommands=0):
842c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Reinitializes a command to the state it was in when first
843c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        returned by 'get_command_obj()': ie., initialized but not yet
8447d9c705b234ad2ad013db1649e5fd2ffc2a59a75Greg Ward        finalized.  This provides the opportunity to sneak option
845c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        values in programmatically, overriding or supplementing
846c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        user-supplied values from the config files and command line.
847c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        You'll have to re-finalize the command object (by calling
848c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'finalize_options()' or 'ensure_finalized()') before using it for
849c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        real.
850c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
851f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'command' should be a command name (string) or command object.  If
852f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'reinit_subcommands' is true, also reinitializes the command's
853f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        sub-commands, as declared by the 'sub_commands' class attribute (if
854f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        it has one).  See the "install" command for an example.  Only
855f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        reinitializes the sub-commands that actually matter, ie. those
856f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        whose test predicates return true.
857f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
858c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        Returns the reinitialized command object.
859c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
860c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.cmd import Command
861c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not isinstance(command, Command):
862c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command
863c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command = self.get_command_obj(command_name)
864c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        else:
865c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command.get_command_name()
866c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
867c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not command.finalized:
868282c7a0230b578147a89a18ec22410b830edddfeGreg Ward            return command
869c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.initialize_options()
870c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.finalized = 0
87143955c9a023ea7b50b28052112dbdc914c090a27Greg Ward        self.have_run[command_name] = 0
872c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        self._set_command_options(command)
873f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
874f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        if reinit_subcommands:
875f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward            for sub in command.get_sub_commands():
876f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward                self.reinitialize_command(sub, reinit_subcommands)
877f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
878c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        return command
879c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
880fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
881fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on the Distribution ----------------------
882fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
883fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def announce (self, msg, level=1):
884fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print 'msg' if 'level' is greater than or equal to the verbosity
885d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        level recorded in the 'verbose' attribute (which, currently, can be
886d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        only 0 or 1).
887d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
888fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if self.verbose >= level:
889fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print msg
890fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
891fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
892fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_commands (self):
89382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """Run each command that was seen on the setup script command line.
894d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Uses the list of commands found and cache of command objects
895fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        created by 'get_command_obj()'.
896fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        """
897fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.commands:
898fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.run_command(cmd)
899fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
900fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
901fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on its Commands --------------------------
902fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
903fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_command (self, command):
904fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Do whatever it takes to run a command (including nothing at all,
905d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if the command has already been run).  Specifically: if we have
906d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        already created and run the command named by 'command', return
907d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        silently without doing anything.  If the command named by 'command'
908d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        doesn't even have a command object yet, create one.  Then invoke
909d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'run()' on that command object (or an existing one).
910d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
911fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Already been here, done that? then return silently.
912fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if self.have_run.get(command):
913fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
914fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
915fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.announce("running " + command)
916fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj = self.get_command_obj(command)
917fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.ensure_finalized()
918fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.run()
919fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run[command] = 1
920fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
921fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
922fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Distribution query methods ------------------------------------
923fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
924fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_pure_modules (self):
925fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return len(self.packages or self.py_modules or []) > 0
926fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
927fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_ext_modules (self):
928fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.ext_modules and len(self.ext_modules) > 0
929fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
930fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_c_libraries (self):
931fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.libraries and len(self.libraries) > 0
932fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
933fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_modules (self):
934fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.has_pure_modules() or self.has_ext_modules()
935fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
93651def7d667a42eac177690e1fe00eab7f2102319Greg Ward    def has_headers (self):
93751def7d667a42eac177690e1fe00eab7f2102319Greg Ward        return self.headers and len(self.headers) > 0
93851def7d667a42eac177690e1fe00eab7f2102319Greg Ward
93944a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_scripts (self):
94044a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.scripts and len(self.scripts) > 0
94144a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
94244a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_data_files (self):
94344a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.data_files and len(self.data_files) > 0
94444a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
945fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def is_pure (self):
946fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return (self.has_pure_modules() and
947fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_ext_modules() and
948fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_c_libraries())
949fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
95082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
95182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
95282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # If you're looking for 'get_name()', 'get_version()', and so forth,
95382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # they are defined in a sneaky way: the constructor binds self.get_XXX
95482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # to self.metadata.get_XXX.  The actual code is in the
95582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # DistributionMetadata class, below.
95682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
95782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class Distribution
95882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
95982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
96082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata:
96182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    """Dummy class to hold the distribution meta-data: name, version,
962fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    author, and so forth.
963fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    """
96482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
96582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def __init__ (self):
96682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.name = None
96782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.version = None
96882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author = None
96982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author_email = None
97082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer = None
97182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer_email = None
97282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.url = None
973fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        self.license = None
97482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.description = None
975e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        self.long_description = None
976a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.keywords = None
977a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.platforms = None
97882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
979a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def write_pkg_info (self, base_dir):
980a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Write the PKG-INFO file into the release tree.
981a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
982a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
983a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
984a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
985a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Metadata-Version: 1.0\n')
986a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Name: %s\n' % self.get_name() )
987a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Version: %s\n' % self.get_version() )
988a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Summary: %s\n' % self.get_description() )
989a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Home-page: %s\n' % self.get_url() )
990ffb963c7f699c9b6ab0debc1825a55ec8f98556fAndrew M. Kuchling        pkg_info.write('Author: %s\n' % self.get_contact() )
991ffb963c7f699c9b6ab0debc1825a55ec8f98556fAndrew M. Kuchling        pkg_info.write('Author-email: %s\n' % self.get_contact_email() )
992fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        pkg_info.write('License: %s\n' % self.get_license() )
993a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
994a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        long_desc = rfc822_escape( self.get_long_description() )
995a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Description: %s\n' % long_desc)
996a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
997a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        keywords = string.join( self.get_keywords(), ',')
998a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords:
999a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            pkg_info.write('Keywords: %s\n' % keywords )
1000a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1001a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        for platform in self.get_platforms():
1002a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            pkg_info.write('Platform: %s\n' % platform )
1003a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1004a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.close()
1005a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1006a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    # write_pkg_info ()
1007a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
100882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
100982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1010fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def get_name (self):
1011fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.name or "UNKNOWN"
1012fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
101382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_version(self):
101482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.version or "???"
101582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
101682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_fullname (self):
101782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return "%s-%s" % (self.get_name(), self.get_version())
101882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
101982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author(self):
102082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author or "UNKNOWN"
1021fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
102282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author_email(self):
102382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author_email or "UNKNOWN"
102482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
102582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer(self):
102682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer or "UNKNOWN"
102782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
102882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer_email(self):
102982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer_email or "UNKNOWN"
103082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
103182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact(self):
103282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer or
103382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author or
103482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
103582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
103682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact_email(self):
103782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer_email or
103882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author_email or
103982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
104082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
104182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_url(self):
104282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.url or "UNKNOWN"
104382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1044fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    def get_license(self):
1045fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        return self.license or "UNKNOWN"
1046fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    get_licence = get_license
1047fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling
104882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_description(self):
104982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.description or "UNKNOWN"
1050e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1051e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward    def get_long_description(self):
1052e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        return self.long_description or "UNKNOWN"
1053e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1054a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_keywords(self):
1055a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.keywords or []
1056a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1057a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_platforms(self):
1058a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.platforms or ["UNKNOWN"]
1059a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
106082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class DistributionMetadata
1061fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
10622ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
10632ff7887270385bd6dddc2d5461486334b4fec8bcGreg Warddef fix_help_options (options):
10642ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """Convert a 4-tuple 'help_options' list as found in various command
10652ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    classes to the 3-tuple form required by FancyGetopt.
10662ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """
10672ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    new_options = []
10682ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    for help_tuple in options:
10692ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        new_options.append(help_tuple[0:3])
10702ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    return new_options
10712ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
10722ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
1073fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardif __name__ == "__main__":
1074fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    dist = Distribution()
1075fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    print "ok"
1076