dist.py revision 282c7a0230b578147a89a18ec22410b830edddfe
1fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward"""distutils.dist
2fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
3fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg WardProvides the Distribution class, which represents the module distribution
4fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardbeing built/installed/distributed."""
5fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
6fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# created 2000/04/03, Greg Ward
7fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# (extricated from core.py; actually dates back to the beginning)
8fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
9fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward__revision__ = "$Id$"
10fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
111426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smithimport sys, os, string, re
12fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom types import *
13fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom copy import copy
14fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom distutils.errors import *
1536c36fec7cd7f056832c2043ec385f6e921c8c83Greg Wardfrom distutils import sysconfig
1682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardfrom distutils.fancy_getopt import FancyGetopt, longopt_xlate
171426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smithfrom distutils.util import check_environ
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:
28fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    """The core of the Distutils.  Most of the work hiding behind
29fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       'setup' is really done within a Distribution instance, which
30fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       farms the work out to the Distutils commands specified on the
31fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       command line.
32fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
33fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       Clients will almost never instantiate Distribution directly,
34fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       unless the 'setup' function is totally inadequate to their needs.
35fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       However, it is conceivable that a client might wish to subclass
36fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       Distribution for some specialized purpose, and then pass the
37fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       subclass to 'setup' as the 'distclass' keyword argument.  If so,
38fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       it is necessary to respect the expectations that 'setup' has of
39fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       Distribution: it must have a constructor and methods
40fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       'parse_command_line()' and 'run_commands()' with signatures like
41fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward       those described below."""
42fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
43fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
44fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # 'global_options' describes the command-line options that may be
4582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # supplied to the setup script prior to any actual commands.
4682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # these global options.  This list should be kept to a bare minimum,
48fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # since every global option is also valid as a command option -- and we
49fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # don't want to pollute the commands with too many options that they
50fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # have minimal control over.
51d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    global_options = [('verbose', 'v', "run verbosely (default)"),
52d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('quiet', 'q', "run quietly (turns verbosity off)"),
53d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('dry-run', 'n', "don't actually do anything"),
54d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('help', 'h', "show detailed help message"),
55fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                     ]
5682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
5782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # options that are not propagated to the commands
5882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_options = [
5982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('help-commands', None,
6082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "list all available commands"),
6182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('name', None,
6282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package name"),
6382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('version', 'V',
6482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package version"),
6582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('fullname', None,
6682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print <package name>-<version>"),
6782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author', None,
6882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's name"),
6982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author-email', None,
7082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's email address"),
7182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer', None,
7282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's name"),
7382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer-email', None,
7482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's email address"),
7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact', None,
76d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's name if known, else the author's"),
7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact-email', None,
78d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's email address if known, else the author's"),
7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('url', None,
8082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the URL for this package"),
8182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('licence', None,
8282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the licence of the package"),
8382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('license', None,
8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "alias for --licence"),
8582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('description', None,
8682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the package description"),
87e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        ('long-description', None,
88e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward         "print the long package description"),
8982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ]
9082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_option_names = map(lambda x: string.translate(x[0], longopt_xlate),
9182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                           display_options)
9282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
9382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # negative options are options that exclude other options
94fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    negative_opt = {'quiet': 'verbose'}
95fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
96fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
97fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Creation/initialization methods -------------------------------
98fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
99fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def __init__ (self, attrs=None):
100fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Construct a new Distribution instance: initialize all the
101fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           attributes of a Distribution, and then uses 'attrs' (a
102fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           dictionary mapping attribute names to values) to assign
103fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           some of those attributes their "real" values.  (Any attributes
104fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           not mentioned in 'attrs' will be assigned to some null
105fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           value: 0, None, an empty list or dictionary, etc.)  Most
106fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           importantly, initialize the 'command_obj' attribute
107fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           to the empty dictionary; this will be filled in with real
108fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward           command objects by 'parse_command_line()'."""
109fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
110fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Default values for our command-line options
111fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.verbose = 1
112fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.dry_run = 0
113fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.help = 0
11482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for attr in self.display_option_names:
11582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            setattr(self, attr, 0)
11682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
11782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # Store the distribution meta-data (name, version, author, and so
11882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # forth) in a separate object -- we're getting to have enough
11982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # information here (and enough command-line options) that it's
12082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
12182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # object in a sneaky and underhanded (but efficient!) way.
12282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.metadata = DistributionMetadata ()
1234982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward        method_basenames = dir(self.metadata) + \
1244982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward                           ['fullname', 'contact', 'contact_email']
1254982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward        for basename in method_basenames:
1264982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            method_name = "get_" + basename
1274982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            setattr(self, method_name, getattr(self.metadata, method_name))
128fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
129fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'cmdclass' maps command names to class objects, so we
130fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # can 1) quickly figure out which class to instantiate when
131fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # we need to create a new command object, and 2) have a way
13282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for the setup script to override command classes
133fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.cmdclass = {}
134fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
135d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 'command_options' is where we store command options between
136d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # parsing them (from config files, the command-line, etc.) and when
137d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # they are actually needed -- ie. when the command in question is
138d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
139d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        #   command_options = { command_name : { option : (source, value) } }
1401426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        self.command_options = {}
1411426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
142fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # These options are really the business of various commands, rather
143fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # than of the Distribution itself.  We provide aliases for them in
144fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Distribution as a convenience to the developer.
145fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.packages = None
146fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.package_dir = None
147fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.py_modules = None
148fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.libraries = None
14951def7d667a42eac177690e1fe00eab7f2102319Greg Ward        self.headers = None
150fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_modules = None
151fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_package = None
152fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.include_dirs = None
153fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.extra_path = None
154b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith        self.scripts = None
1556a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith        self.data_files = None
156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
157fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # And now initialize bookkeeping stuff that can't be supplied by
158fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the caller at all.  'command_obj' maps command names to
159fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Command instances -- that's how we enforce that every command
160fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # class is a singleton.
161fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.command_obj = {}
162fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
163fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'have_run' maps command names to boolean values; it keeps track
164fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # of whether we have actually run a particular command, to make it
165fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # cheap to "run" a command whenever we think we might need to -- if
166fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # it's already been done, no need for expensive filesystem
167fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # operations, we just check the 'have_run' dictionary and carry on.
168fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # It's only safe to query 'have_run' for a command class that has
169fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # been instantiated -- a false value will be inserted when the
170fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # command object is created, and replaced with a true value when
171fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the command is succesfully run.  Thus it's probably best to use
172fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # '.get()' rather than a straight lookup.
173fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run = {}
174fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
175fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Now we'll use the attrs dictionary (ultimately, keyword args from
17682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # the setup script) to possibly override any or all of these
17782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # distribution options.
17882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
179fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if attrs:
180fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
181fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Pull out the set of command options and work on them
182fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # specifically.  Note that this order guarantees that aliased
183fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # command options will override any supplied redundantly
184fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # through the general options dictionary.
185fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            options = attrs.get ('options')
186fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if options:
187fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                del attrs['options']
188fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                for (command, cmd_options) in options.items():
1890e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    opt_dict = self.get_option_dict(command)
1900e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    for (opt, val) in cmd_options.items():
1910e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = ("setup script", val)
192fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
193fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Now work on the rest of the attributes.  Any attribute that's
194fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # not already defined is invalid!
195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            for (key,val) in attrs.items():
19682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                if hasattr (self.metadata, key):
19782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                    setattr (self.metadata, key, val)
19882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                elif hasattr (self, key):
199fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                    setattr (self, key, val)
200fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                else:
20102a1a2b077e969e5fef8504cece5852bf641552dGreg Ward                    raise DistutilsSetupError, \
202fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                          "invalid distribution option '%s'" % key
203fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
204fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # __init__ ()
205fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
206fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
2070e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward    def get_option_dict (self, command):
2080e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """Get the option dictionary for a given command.  If that
2090e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        command's option dictionary hasn't been created yet, then create it
2100e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        and return the new dictionary; otherwise, return the existing
2110e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        option dictionary.
2120e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """
2130e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2140e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        dict = self.command_options.get(command)
2150e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        if dict is None:
2160e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            dict = self.command_options[command] = {}
2170e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        return dict
2180e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2190e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
220c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def dump_option_dicts (self, header=None, commands=None, indent=""):
221c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from pprint import pformat
222c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
223c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if commands is None:             # dump all command option dicts
224c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands = self.command_options.keys()
225c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands.sort()
226c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
227c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if header is not None:
228c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + header
229c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            indent = indent + "  "
230c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
231c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not commands:
232c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + "no commands known yet"
233c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            return
234c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
235c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for cmd_name in commands:
236c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            opt_dict = self.command_options.get(cmd_name)
237c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if opt_dict is None:
238c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "no option dict for '%s' command" % cmd_name
239c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            else:
240c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "option dict for '%s' command:" % cmd_name
241c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                out = pformat(opt_dict)
242c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                for line in string.split(out, "\n"):
243c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                    print indent + "  " + line
244c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
245c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    # dump_option_dicts ()
246c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
247c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
248c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
249d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Config file finding/parsing methods ---------------------------
250d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
2511426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def find_config_files (self):
2521426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        """Find as many configuration files as should be processed for this
2531426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        platform, and return a list of filenames in the order in which they
2541426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        should be parsed.  The filenames returned are guaranteed to exist
2551426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        (modulo nasty race conditions).
2561426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2571426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        On Unix, there are three possible config files: pydistutils.cfg in
2581426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        the Distutils installation directory (ie. where the top-level
2591426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Distutils __inst__.py file lives), .pydistutils.cfg in the user's
2601426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        home directory, and setup.cfg in the current directory.
2611426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2621426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        On Windows and Mac OS, there are two possible config files:
2631426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        pydistutils.cfg in the Python installation directory (sys.prefix)
264d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        and setup.cfg in the current directory.
265d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
2661426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        files = []
2671426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.name == "posix":
2681426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            check_environ()
2691426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2701426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
2711426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            sys_file = os.path.join(sys_dir, "pydistutils.cfg")
2721426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            if os.path.isfile(sys_file):
2731426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                files.append(sys_file)
2741426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2751426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            user_file = os.path.join(os.environ.get('HOME'),
2761426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                                     ".pydistutils.cfg")
2771426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            if os.path.isfile(user_file):
2781426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                files.append(user_file)
2791426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2801426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        else:
2811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            sys_file = os.path.join (sysconfig.PREFIX, "pydistutils.cfg")
2821426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            if os.path.isfile(sys_file):
2831426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                files.append(sys_file)
2841426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2851426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        # All platforms support local setup.cfg
2861426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        local_file = "setup.cfg"
2871426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.path.isfile(local_file):
2881426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            files.append(local_file)
2891426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2901426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        return files
2911426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2921426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    # find_config_files ()
2931426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2941426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2951426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def parse_config_files (self, filenames=None):
2961426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2971426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        from ConfigParser import ConfigParser
2981426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
2991426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if filenames is None:
3001426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            filenames = self.find_config_files()
3011426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
302474607777d10562679b1640d3831290b0c4284f7Greg Ward        print "Distribution.parse_config_files():"
303474607777d10562679b1640d3831290b0c4284f7Greg Ward
3041426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        parser = ConfigParser()
305d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for filename in filenames:
306474607777d10562679b1640d3831290b0c4284f7Greg Ward            print "  reading", filename
307d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.read(filename)
308d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            for section in parser.sections():
309d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                options = parser.options(section)
3100e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                opt_dict = self.get_option_dict(section)
311d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
312d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                for opt in options:
313d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    if opt != '__name__':
3140e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = (filename, parser.get(section,opt))
3151426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
316474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Make the ConfigParser forget everything (so we retain
317474607777d10562679b1640d3831290b0c4284f7Greg Ward            # the original filenames that options come from) -- gag,
318474607777d10562679b1640d3831290b0c4284f7Greg Ward            # retch, puke -- another good reason for a distutils-
319474607777d10562679b1640d3831290b0c4284f7Greg Ward            # specific config parser (sigh...)
320474607777d10562679b1640d3831290b0c4284f7Greg Ward            parser.__init__()
3211426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3221426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
323d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Command-line parsing methods ----------------------------------
324fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
325d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def parse_command_line (self, args):
326d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the setup script's command line.  'args' must be a list
327d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of command-line arguments, most likely 'sys.argv[1:]' (see the
328d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'setup()' function).  This list is first processed for "global
329d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        options" -- options that set attributes of the Distribution
330d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        instance.  Then, it is alternately scanned for Distutils
331d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        commands and options for that command.  Each new command
332d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        terminates the options for the previous command.  The allowed
333d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        options for a command are determined by the 'user_options'
334d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        attribute of the command class -- thus, we have to be able to
335d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        load command classes in order to parse the command line.  Any
336d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        error in that 'options' attribute raises DistutilsGetoptError;
337d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        any error on the command-line raises DistutilsArgError.  If no
338d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Distutils commands were found on the command line, raises
339d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        DistutilsArgError.  Return true if command-line were
340d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        successfully parsed and we should carry on with executing
341d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        commands; false if no errors but we shouldn't execute commands
342d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (currently, this only happens if user asks for help).
343d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
344fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # We have to parse the command line a bit at a time -- global
345fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # options, then the first command, then its options, and so on --
346fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # because each command will be handled by a different class, and
347d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # the options that are valid for a particular class aren't known
348d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we have loaded the command class, which doesn't happen
349d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we know what the command is.
350fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
351fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.commands = []
35282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        parser = FancyGetopt (self.global_options + self.display_options)
35382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        parser.set_negative_aliases (self.negative_opt)
35458ec6ede20d0b632f8325e1363aaa6e445ad61efGreg Ward        parser.set_aliases ({'license': 'licence'})
35582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        args = parser.getopt (object=self)
35682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        option_order = parser.get_option_order()
357fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
35882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for display options we return immediately
35982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.handle_display_options(option_order):
360fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
361fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
362fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        while args:
363d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            args = self._parse_command_opts(parser, args)
364d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if args is None:            # user asked for help (and got it)
365fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                return
366fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
367d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Handle the cases of --help as a "global" option, ie.
368d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # "setup.py --help" and "setup.py --help command ...".  For the
369d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # former, we show global options (--verbose, --dry-run, etc.)
370d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # and display-only options (--name, --version, etc.); for the
371d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # latter, we omit the display-only options and show help for
372d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # each command listed on the command line.
373d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if self.help:
374d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print "showing 'global' help; commands=", self.commands
375d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser,
376d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            display_options=len(self.commands) == 0,
377d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            commands=self.commands)
378fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
379fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
380fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Oops, no commands found -- an end-user error
381fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not self.commands:
382fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsArgError, "no commands supplied"
383fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
384fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # All is well: return true
385fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return 1
386fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
387fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # parse_command_line()
388fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
389d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _parse_command_opts (self, parser, args):
390d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
391d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the command-line options for a single command.
392d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'parser' must be a FancyGetopt instance; 'args' must be the list
393d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of arguments, starting with the current command (whose options
394d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        we are about to parse).  Returns a new version of 'args' with
395d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the next command at the front of the list; will be the empty
396d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        list if there are no more commands on the command line.  Returns
397d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        None if the user asked for help on this command.
398d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
399d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
400d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
401d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
402d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Pull the current command from the head of the command line
403d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command = args[0]
404d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if not command_re.match (command):
405d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise SystemExit, "invalid command name '%s'" % command
406d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        self.commands.append (command)
407d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
408d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Dig up the command class that implements this command, so we
409d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 1) know that it's a valid command, and 2) know which options
410d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # it takes.
411d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        try:
412d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            cmd_class = self.get_command_class (command)
413d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except DistutilsModuleError, msg:
414d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsArgError, msg
415d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
416d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Require that the command class be derived from Command -- want
417d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # to be sure that the basic "command" interface is implemented.
418d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if not issubclass (cmd_class, Command):
419d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
420d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  "command class %s must subclass Command" % cmd_class
421d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
422d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Also make sure that the command object provides a list of its
423d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # known options.
424d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if not (hasattr (cmd_class, 'user_options') and
425d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                type (cmd_class.user_options) is ListType):
426d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
427d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  ("command class %s must provide " +
428d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                   "'user_options' attribute (a list of tuples)") % \
429d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  cmd_class
430d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
431d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # If the command class has a list of negative alias options,
432d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # merge it in with the global negative aliases.
433d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        negative_opt = self.negative_opt
434d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if hasattr (cmd_class, 'negative_opt'):
435d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            negative_opt = copy (negative_opt)
436d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            negative_opt.update (cmd_class.negative_opt)
437d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
438d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # All commands support the global options too, just by adding
439d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # in 'global_options'.
440d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        parser.set_option_table (self.global_options +
441d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                                 cmd_class.user_options)
442d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        parser.set_negative_aliases (negative_opt)
443d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (args, opts) = parser.getopt (args[1:])
444474607777d10562679b1640d3831290b0c4284f7Greg Ward        if hasattr(opts, 'help') and opts.help:
445d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print "showing help for command", cmd_class
446d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser, display_options=0, commands=[cmd_class])
447d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return
448d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
449d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Put the options from the command-line into their official
450d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # holding pen, the 'command_options' dictionary.
4510e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        opt_dict = self.get_option_dict(command)
452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for (name, value) in vars(opts).items():
4530e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            opt_dict[name] = ("command line", value)
454d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
455d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return args
456d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
457d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _parse_command_opts ()
458d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
459d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
460d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _show_help (self,
461d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    parser,
462d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    global_options=1,
463d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    display_options=1,
464d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    commands=[]):
465d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Show help for the setup script command-line in the form of
466d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        several lists of command-line options.  'parser' should be a
467d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        FancyGetopt instance; do not expect it to be returned in the
468d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        same state, as its option table will be reset to make it
469d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        generate the correct help text.
470d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
471d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        If 'global_options' is true, lists the global options:
472d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        --verbose, --dry-run, etc.  If 'display_options' is true, lists
473d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the "display-only" options: --name, --version, etc.  Finally,
474d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        lists per-command help for every command name or command class
475d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        in 'commands'.
476d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
477d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.core import usage
479d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
480d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
481d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if global_options:
482d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.set_option_table (self.global_options)
483d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.print_help ("Global options:")
484d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
485d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
486d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if display_options:
487d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.set_option_table (self.display_options)
488d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.print_help (
489d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "Information display options (just display " +
490d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "information, ignore any commands)")
491d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
492d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
493d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for command in self.commands:
494d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if type(command) is ClassType and issubclass(klass, Command):
495d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = command
496d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            else:
497d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = self.get_command_class (command)
498d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.set_option_table (klass.user_options)
499d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.print_help ("Options for '%s' command:" % klass.__name__)
500d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
501d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
502d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        print usage
503d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return
504d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
505d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _show_help ()
506d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
507d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
50882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def handle_display_options (self, option_order):
50982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """If there were any non-global "display-only" options
510d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (--help-commands or the metadata display options) on the command
511d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        line, display the requested info and return true; else return
512d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        false.
513d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
51482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        from distutils.core import usage
51582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
51682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # User just wants a list of commands -- we'll print it out and stop
51782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # processing now (ie. if they ran "setup --help-commands foo bar",
51882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # we ignore "foo bar").
51982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.help_commands:
52082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            self.print_commands ()
52182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            print
52282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            print usage
52382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            return 1
52482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
52582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # If user supplied any of the "display metadata" options, then
52682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # display that metadata in the order in which the user supplied the
52782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # metadata options.
52882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        any_display_options = 0
52982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        is_display_option = {}
53082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for option in self.display_options:
53182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            is_display_option[option[0]] = 1
53282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
53382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for (opt, val) in option_order:
53482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            if val and is_display_option.get(opt):
53582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                opt = string.translate (opt, longopt_xlate)
53682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                print getattr(self.metadata, "get_"+opt)()
53782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                any_display_options = 1
53882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
53982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return any_display_options
54082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
54182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # handle_display_options()
542fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
543fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_command_list (self, commands, header, max_length):
544fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print a subset of the list of all commands -- used by
545d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'print_commands()'.
546d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
547fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
548fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        print header + ":"
549fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
550fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in commands:
551fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            klass = self.cmdclass.get (cmd)
552fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not klass:
553d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = self.get_command_class (cmd)
554fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            try:
555fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = klass.description
556fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            except AttributeError:
557fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = "(no description available)"
558fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
559fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print "  %-*s  %s" % (max_length, cmd, description)
560fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
561fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_command_list ()
562fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
563fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
564fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_commands (self):
565d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Print out a help message listing all available commands with a
566d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        description of each.  The list is divided into "standard commands"
567d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (listed in distutils.command.__all__) and "extra commands"
568d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (mentioned in self.cmdclass, but not a standard command).  The
569d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        descriptions come from the command class attribute
570d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'description'.
571d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
572fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
573fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        import distutils.command
574fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        std_commands = distutils.command.__all__
575fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        is_std = {}
576fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in std_commands:
577fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            is_std[cmd] = 1
578fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
579fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        extra_commands = []
580fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.cmdclass.keys():
581fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not is_std.get(cmd):
582fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                extra_commands.append (cmd)
583fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
584fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        max_length = 0
585fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in (std_commands + extra_commands):
586fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if len (cmd) > max_length:
587fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                max_length = len (cmd)
588fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
589fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.print_command_list (std_commands,
590fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                                 "Standard commands",
591fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                                 max_length)
592fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if extra_commands:
593fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print
594fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            self.print_command_list (extra_commands,
595fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                                     "Extra commands",
596fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                                     max_length)
597fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
598fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_commands ()
599fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
600fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
601fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Command class/object methods ----------------------------------
602fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
603d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_class (self, command):
604d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the class that implements the Distutils command named by
605d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'command'.  First we check the 'cmdclass' dictionary; if the
606d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command is mentioned there, we fetch the class object from the
607d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        dictionary and return it.  Otherwise we load the command module
608d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        ("distutils.command." + command) and fetch the command class from
609d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the module.  The loaded class is also stored in 'cmdclass'
610d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        to speed future calls to 'get_command_class()'.
6111426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
6121426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Raises DistutilsModuleError if the expected module could not be
613d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        found, or if that module does not define the expected class.
614d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
615d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        klass = self.cmdclass.get(command)
616d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if klass:
617d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return klass
618fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
619fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        module_name = 'distutils.command.' + command
620fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        klass_name = command
621fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
622fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
623fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            __import__ (module_name)
624fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            module = sys.modules[module_name]
625fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        except ImportError:
626fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
627fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no module named '%s')" % \
628fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  (command, module_name)
629fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
630fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
631d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = getattr(module, klass_name)
632d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except AttributeError:
633fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
634fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no class '%s' in module '%s')" \
635fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  % (command, klass_name, module_name)
636fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
637d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        self.cmdclass[command] = klass
638fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return klass
639fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
640d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # get_command_class ()
641fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
642d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_obj (self, command, create=1):
643d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the command object for 'command'.  Normally this object
644d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        is cached on a previous call to 'get_command_obj()'; if no comand
645d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        object for 'command' is in the cache, then we either create and
646d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return it (if 'create' is true) or return None.
647d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
648d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.command_obj.get(command)
649fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not cmd_obj and create:
650474607777d10562679b1640d3831290b0c4284f7Greg Ward            print "Distribution.get_command_obj(): " \
651474607777d10562679b1640d3831290b0c4284f7Greg Ward                  "creating '%s' command object" % command
652474607777d10562679b1640d3831290b0c4284f7Greg Ward
653d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = self.get_command_class(command)
654474607777d10562679b1640d3831290b0c4284f7Greg Ward            cmd_obj = self.command_obj[command] = klass(self)
655474607777d10562679b1640d3831290b0c4284f7Greg Ward            self.have_run[command] = 0
656474607777d10562679b1640d3831290b0c4284f7Greg Ward
657474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Set any options that were supplied in config files
658474607777d10562679b1640d3831290b0c4284f7Greg Ward            # or on the command line.  (NB. support for error
659474607777d10562679b1640d3831290b0c4284f7Greg Ward            # reporting is lame here: any errors aren't reported
660474607777d10562679b1640d3831290b0c4284f7Greg Ward            # until 'finalize_options()' is called, which means
661474607777d10562679b1640d3831290b0c4284f7Greg Ward            # we won't report the source of the error.)
662474607777d10562679b1640d3831290b0c4284f7Greg Ward            options = self.command_options.get(command)
663474607777d10562679b1640d3831290b0c4284f7Greg Ward            if options:
664c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                self._set_command_options(cmd_obj, options)
665fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
666fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return cmd_obj
667fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
668c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def _set_command_options (self, command_obj, option_dict=None):
669c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
670c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Set the options for 'command_obj' from 'option_dict'.  Basically
671c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        this means copying elements of a dictionary ('option_dict') to
672c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        attributes of an instance ('command').
673c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
674c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'command_obj' must be a Commnd instance.  If 'option_dict' is not
675c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        supplied, uses the standard option dictionary for this command
676c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        (from 'self.command_options').
677c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
678c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.core import DEBUG
679c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
680c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command_name = command_obj.get_command_name()
681c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if option_dict is None:
682c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            option_dict = self.get_option_dict(command_name)
683c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
684c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if DEBUG: print "  setting options for '%s' command:" % command_name
685c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for (option, (source, value)) in option_dict.items():
686c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if DEBUG: print "    %s = %s (from %s)" % (option, value, source)
687c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if not hasattr(command_obj, option):
688c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                raise DistutilsOptionError, \
689c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                      ("error in %s: command '%s' has no such option '%s'") % \
690c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                      (source, command_name, option)
691c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            setattr(command_obj, option, value)
692c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
693c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def reinitialize_command (self, command):
694c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Reinitializes a command to the state it was in when first
695c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        returned by 'get_command_obj()': ie., initialized but not yet
696c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        finalized.  This gives provides the opportunity to sneak option
697c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        values in programmatically, overriding or supplementing
698c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        user-supplied values from the config files and command line.
699c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        You'll have to re-finalize the command object (by calling
700c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'finalize_options()' or 'ensure_finalized()') before using it for
701c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        real.
702c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
703c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'command' should be a command name (string) or command object.
704c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        Returns the reinitialized command object.
705c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
706c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.cmd import Command
707c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not isinstance(command, Command):
708c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command
709c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command = self.get_command_obj(command_name)
710c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        else:
711c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command.get_command_name()
712c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
713c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not command.finalized:
714282c7a0230b578147a89a18ec22410b830edddfeGreg Ward            return command
715c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.initialize_options()
716c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.finalized = 0
717c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        self._set_command_options(command)
718c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        return command
719c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
720fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
721fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on the Distribution ----------------------
722fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
723fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def announce (self, msg, level=1):
724fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print 'msg' if 'level' is greater than or equal to the verbosity
725d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        level recorded in the 'verbose' attribute (which, currently, can be
726d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        only 0 or 1).
727d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
728fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if self.verbose >= level:
729fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print msg
730fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
731fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
732fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_commands (self):
73382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """Run each command that was seen on the setup script command line.
734d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Uses the list of commands found and cache of command objects
735d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        created by 'get_command_obj()'."""
736fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
737fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.commands:
738fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            self.run_command (cmd)
739fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
740fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
741fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on its Commands --------------------------
742fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
743fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_command (self, command):
744fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Do whatever it takes to run a command (including nothing at all,
745d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if the command has already been run).  Specifically: if we have
746d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        already created and run the command named by 'command', return
747d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        silently without doing anything.  If the command named by 'command'
748d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        doesn't even have a command object yet, create one.  Then invoke
749d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'run()' on that command object (or an existing one).
750d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
751fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
752fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Already been here, done that? then return silently.
753fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if self.have_run.get (command):
754fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
755fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
756fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.announce ("running " + command)
757d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.get_command_obj (command)
7584fb29e55f8f53e60b36eae3fbe56e9666aacc9c5Greg Ward        cmd_obj.ensure_finalized ()
759fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        cmd_obj.run ()
760fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run[command] = 1
761fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
762fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
763fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Distribution query methods ------------------------------------
764fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
765fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_pure_modules (self):
766fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return len (self.packages or self.py_modules or []) > 0
767fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
768fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_ext_modules (self):
769fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.ext_modules and len (self.ext_modules) > 0
770fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
771fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_c_libraries (self):
772fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.libraries and len (self.libraries) > 0
773fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
774fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_modules (self):
775fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.has_pure_modules() or self.has_ext_modules()
776fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
77751def7d667a42eac177690e1fe00eab7f2102319Greg Ward    def has_headers (self):
77851def7d667a42eac177690e1fe00eab7f2102319Greg Ward        return self.headers and len(self.headers) > 0
77951def7d667a42eac177690e1fe00eab7f2102319Greg Ward
78044a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_scripts (self):
78144a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.scripts and len(self.scripts) > 0
78244a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
78344a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_data_files (self):
78444a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.data_files and len(self.data_files) > 0
78544a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
786fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def is_pure (self):
787fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return (self.has_pure_modules() and
788fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_ext_modules() and
789fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_c_libraries())
790fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
79182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
79282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
79382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # If you're looking for 'get_name()', 'get_version()', and so forth,
79482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # they are defined in a sneaky way: the constructor binds self.get_XXX
79582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # to self.metadata.get_XXX.  The actual code is in the
79682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # DistributionMetadata class, below.
79782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
79882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class Distribution
79982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
80082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
80182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata:
80282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    """Dummy class to hold the distribution meta-data: name, version,
80382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    author, and so forth."""
80482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
80582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def __init__ (self):
80682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.name = None
80782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.version = None
80882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author = None
80982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author_email = None
81082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer = None
81182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer_email = None
81282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.url = None
81382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.licence = None
81482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.description = None
815e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        self.long_description = None
81682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
81782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
81882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
819fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def get_name (self):
820fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.name or "UNKNOWN"
821fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
82282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_version(self):
82382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.version or "???"
82482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
82582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_fullname (self):
82682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return "%s-%s" % (self.get_name(), self.get_version())
82782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
82882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author(self):
82982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author or "UNKNOWN"
830fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
83182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author_email(self):
83282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author_email or "UNKNOWN"
83382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
83482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer(self):
83582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer or "UNKNOWN"
83682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
83782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer_email(self):
83882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer_email or "UNKNOWN"
83982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
84082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact(self):
84182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer or
84282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author or
84382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
84482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
84582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact_email(self):
84682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer_email or
84782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author_email or
84882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
84982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
85082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_url(self):
85182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.url or "UNKNOWN"
85282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
85382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_licence(self):
85482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.licence or "UNKNOWN"
85582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
85682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_description(self):
85782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.description or "UNKNOWN"
858e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
859e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward    def get_long_description(self):
860e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        return self.long_description or "UNKNOWN"
861e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
86282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class DistributionMetadata
863fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
864fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardif __name__ == "__main__":
865fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    dist = Distribution ()
866fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    print "ok"
867