dist.py revision f06116dcab8f6066f78c522c056ffb9c2403706c
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
7d448f66317130555cfc157683c743b3d004374c4Andrew M. Kuchling# This module should be kept compatible with Python 1.5.2.
8d448f66317130555cfc157683c743b3d004374c4Andrew M. Kuchling
9fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward__revision__ = "$Id$"
10fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
111426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smithimport sys, os, string, re
12fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom types import *
13fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom copy import copy
14ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
15ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchlingtry:
16ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    import warnings
17ccf4e421b829ce69eb62806fdd77eb71249713ddAndrew M. Kuchlingexcept ImportError:
18ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    warnings = None
19ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
20fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom distutils.errors import *
212f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Wardfrom distutils.fancy_getopt import FancyGetopt, translate_longopt
22a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchlingfrom distutils.util import check_environ, strtobool, rfc822_escape
23cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log
24fcd7353863c024bb87aabe7c4639ca8df692ac85Jeremy Hyltonfrom distutils.debug import DEBUG
25fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
26fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# Regex to define acceptable Distutils command names.  This is not *quite*
27fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# the same as a Python NAME -- I don't allow leading underscores.  The fact
28fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# that they're very similar is no coincidence; the default naming scheme is
29fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# to look for a Python module named after the command.
30fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardcommand_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
31fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
32fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
33fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardclass Distribution:
348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """The core of the Distutils.  Most of the work hiding behind 'setup'
358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    is really done within a Distribution instance, which farms the work out
368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to the Distutils commands specified on the command line.
378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward
388ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Setup scripts will almost never instantiate Distribution directly,
398ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    unless the 'setup()' function is totally inadequate to their needs.
408ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    However, it is conceivable that a setup script might wish to subclass
418ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Distribution for some specialized purpose, and then pass the subclass
428ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to 'setup()' as the 'distclass' keyword argument.  If so, it is
438ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    necessary to respect the expectations that 'setup' has of Distribution.
448ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    See the code for 'setup()', in core.py, for details.
458ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """
46fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
48fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # 'global_options' describes the command-line options that may be
4982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # supplied to the setup script prior to any actual commands.
5082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
51fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # these global options.  This list should be kept to a bare minimum,
52fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # since every global option is also valid as a command option -- and we
53fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # don't want to pollute the commands with too many options that they
54fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # have minimal control over.
55cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    # The fourth entry for verbose means that it can be repeated.
56cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    global_options = [('verbose', 'v', "run verbosely (default)", 1),
57d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('quiet', 'q', "run quietly (turns verbosity off)"),
58d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('dry-run', 'n', "don't actually do anything"),
59d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('help', 'h', "show detailed help message"),
60fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                     ]
6182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
6282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # options that are not propagated to the commands
6382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_options = [
6482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('help-commands', None,
6582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "list all available commands"),
6682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('name', None,
6782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package name"),
6882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('version', 'V',
6982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package version"),
7082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('fullname', None,
7182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print <package name>-<version>"),
7282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author', None,
7382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's name"),
7482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author-email', None,
7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's email address"),
7682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer', None,
7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's name"),
7882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer-email', None,
7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's email address"),
8082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact', None,
81d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's name if known, else the author's"),
8282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact-email', None,
83d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's email address if known, else the author's"),
8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('url', None,
8582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the URL for this package"),
8682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('license', None,
87fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "print the license of the package"),
88fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        ('licence', None,
89fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "alias for --license"),
9082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('description', None,
9182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the package description"),
92e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        ('long-description', None,
93e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward         "print the long package description"),
94a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('platforms', None,
95a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of platforms"),
96282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        ('classifiers', None,
97282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling         "print the list of classifiers"),
98a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('keywords', None,
99a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of keywords"),
10082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ]
1012f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward    display_option_names = map(lambda x: translate_longopt(x[0]),
1022f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                               display_options)
10382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
10482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # negative options are options that exclude other options
105fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    negative_opt = {'quiet': 'verbose'}
106fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
107fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
108fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Creation/initialization methods -------------------------------
109b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
110fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def __init__ (self, attrs=None):
111fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Construct a new Distribution instance: initialize all the
1128ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes of a Distribution, and then use 'attrs' (a dictionary
1138ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        mapping attribute names to values) to assign some of those
1148ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes their "real" values.  (Any attributes not mentioned in
1158ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'attrs' will be assigned to some null value: 0, None, an empty list
1168ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        or dictionary, etc.)  Most importantly, initialize the
1178ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'command_obj' attribute to the empty dictionary; this will be
1188ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        filled in with real command objects by 'parse_command_line()'.
1198ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        """
120fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
121fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Default values for our command-line options
122fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.verbose = 1
123fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.dry_run = 0
124fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.help = 0
12582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for attr in self.display_option_names:
12682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            setattr(self, attr, 0)
12782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
12882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # Store the distribution meta-data (name, version, author, and so
12982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # forth) in a separate object -- we're getting to have enough
13082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # information here (and enough command-line options) that it's
13182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
13282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # object in a sneaky and underhanded (but efficient!) way.
133fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.metadata = DistributionMetadata()
134a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer        for basename in self.metadata._METHOD_BASENAMES:
1354982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            method_name = "get_" + basename
1364982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            setattr(self, method_name, getattr(self.metadata, method_name))
137fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
138fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'cmdclass' maps command names to class objects, so we
139fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # can 1) quickly figure out which class to instantiate when
140fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # we need to create a new command object, and 2) have a way
14182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for the setup script to override command classes
142fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.cmdclass = {}
143fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
1449821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # 'script_name' and 'script_args' are usually set to sys.argv[0]
1459821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # and sys.argv[1:], but they can be overridden when the caller is
1469821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # not necessarily a setup script run from the command-line.
1479821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_name = None
1489821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_args = None
1499821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward
150d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 'command_options' is where we store command options between
151d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # parsing them (from config files, the command-line, etc.) and when
152d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # they are actually needed -- ie. when the command in question is
153d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
154d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        #   command_options = { command_name : { option : (source, value) } }
1551426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        self.command_options = {}
1561426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
157fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # These options are really the business of various commands, rather
158fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # than of the Distribution itself.  We provide aliases for them in
159fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Distribution as a convenience to the developer.
160fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.packages = None
161fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.package_dir = None
162fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.py_modules = None
163fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.libraries = None
16451def7d667a42eac177690e1fe00eab7f2102319Greg Ward        self.headers = None
165fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_modules = None
166fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_package = None
167fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.include_dirs = None
168fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.extra_path = None
169b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith        self.scripts = None
1706a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith        self.data_files = None
171fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
172fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # And now initialize bookkeeping stuff that can't be supplied by
173fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the caller at all.  'command_obj' maps command names to
174fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Command instances -- that's how we enforce that every command
175fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # class is a singleton.
176fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.command_obj = {}
177fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
178fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'have_run' maps command names to boolean values; it keeps track
179fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # of whether we have actually run a particular command, to make it
180fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # cheap to "run" a command whenever we think we might need to -- if
181fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # it's already been done, no need for expensive filesystem
182fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # operations, we just check the 'have_run' dictionary and carry on.
183fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # It's only safe to query 'have_run' for a command class that has
184fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # been instantiated -- a false value will be inserted when the
185fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # command object is created, and replaced with a true value when
186612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        # the command is successfully run.  Thus it's probably best to use
187fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # '.get()' rather than a straight lookup.
188fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run = {}
189fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
190fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Now we'll use the attrs dictionary (ultimately, keyword args from
19182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # the setup script) to possibly override any or all of these
19282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # distribution options.
19382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
194fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if attrs:
195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
196fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Pull out the set of command options and work on them
197fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # specifically.  Note that this order guarantees that aliased
198fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # command options will override any supplied redundantly
199fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # through the general options dictionary.
200fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            options = attrs.get('options')
201fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if options:
202fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                del attrs['options']
203fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                for (command, cmd_options) in options.items():
2040e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    opt_dict = self.get_option_dict(command)
2050e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    for (opt, val) in cmd_options.items():
2060e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = ("setup script", val)
207fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
208a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling            if attrs.has_key('licence'):
209a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                attrs['license'] = attrs['licence']
210a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                del attrs['licence']
211a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                msg = "'licence' distribution option is deprecated; use 'license'"
212a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                if warnings is not None:
213a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    warnings.warn(msg)
214a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                else:
215a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    sys.stderr.write(msg + "\n")
216a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling
217fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Now work on the rest of the attributes.  Any attribute that's
218fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # not already defined is invalid!
219fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            for (key,val) in attrs.items():
220fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                if hasattr(self.metadata, key):
221fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self.metadata, key, val)
222fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                elif hasattr(self, key):
223fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self, key, val)
224fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                else:
225ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    msg = "Unknown distribution option: %s" % repr(key)
226ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    if warnings is not None:
227ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        warnings.warn(msg)
228ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    else:
229ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        sys.stderr.write(msg + "\n")
230fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
231a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.finalize_options()
232b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
233fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # __init__ ()
234fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
235fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
2360e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward    def get_option_dict (self, command):
2370e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """Get the option dictionary for a given command.  If that
2380e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        command's option dictionary hasn't been created yet, then create it
2390e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        and return the new dictionary; otherwise, return the existing
2400e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        option dictionary.
2410e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """
2420e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2430e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        dict = self.command_options.get(command)
2440e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        if dict is None:
2450e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            dict = self.command_options[command] = {}
2460e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        return dict
2470e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
2480e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
249c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def dump_option_dicts (self, header=None, commands=None, indent=""):
250c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from pprint import pformat
251c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
252c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if commands is None:             # dump all command option dicts
253c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands = self.command_options.keys()
254c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands.sort()
255c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
256c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if header is not None:
257c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + header
258c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            indent = indent + "  "
259c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
260c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not commands:
261c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            print indent + "no commands known yet"
262c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            return
263c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
264c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for cmd_name in commands:
265c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            opt_dict = self.command_options.get(cmd_name)
266c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if opt_dict is None:
267c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "no option dict for '%s' command" % cmd_name
268c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            else:
269c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                print indent + "option dict for '%s' command:" % cmd_name
270c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                out = pformat(opt_dict)
271c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                for line in string.split(out, "\n"):
272c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                    print indent + "  " + line
273c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
274c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    # dump_option_dicts ()
275b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
276c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
277c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
278d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Config file finding/parsing methods ---------------------------
279d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
2801426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def find_config_files (self):
2811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        """Find as many configuration files as should be processed for this
2821426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        platform, and return a list of filenames in the order in which they
2831426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        should be parsed.  The filenames returned are guaranteed to exist
2841426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        (modulo nasty race conditions).
2851426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
286d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        There are three possible config files: distutils.cfg in the
287d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils installation directory (ie. where the top-level
288d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils __inst__.py file lives), a file in the user's home
289d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        directory named .pydistutils.cfg on Unix and pydistutils.cfg
290d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        on Windows/Mac, and setup.cfg in the current directory.
291d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
2921426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        files = []
293acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward        check_environ()
294acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward
2951169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Where to look for the system-wide Distutils config file
2961169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
2971169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
2981169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Look for the system config file
2991169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_file = os.path.join(sys_dir, "distutils.cfg")
3001169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.path.isfile(sys_file):
3011169687692e5e897033421fe6a73a3c32675a7d7Greg Ward            files.append(sys_file)
3021169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
3031169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # What to call the per-user config file
3041169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.name == 'posix':
30565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = ".pydistutils.cfg"
30665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        else:
30765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = "pydistutils.cfg"
308fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
3091169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # And look for the user config file
31065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if os.environ.has_key('HOME'):
31165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_file = os.path.join(os.environ.get('HOME'), user_filename)
3121426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            if os.path.isfile(user_file):
3131426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith                files.append(user_file)
3141426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3151426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        # All platforms support local setup.cfg
3161426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        local_file = "setup.cfg"
3171426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.path.isfile(local_file):
3181426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            files.append(local_file)
3191426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3201426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        return files
3211426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3221426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    # find_config_files ()
3231426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3241426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3251426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith    def parse_config_files (self, filenames=None):
3261426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3271426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        from ConfigParser import ConfigParser
3281426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3291426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if filenames is None:
3301426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            filenames = self.find_config_files()
3311426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3322bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward        if DEBUG: print "Distribution.parse_config_files():"
333474607777d10562679b1640d3831290b0c4284f7Greg Ward
3341426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        parser = ConfigParser()
335d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for filename in filenames:
3362bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG: print "  reading", filename
337d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.read(filename)
338d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            for section in parser.sections():
339d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                options = parser.options(section)
3400e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                opt_dict = self.get_option_dict(section)
341d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
342d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                for opt in options:
343d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    if opt != '__name__':
344ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        val = parser.get(section,opt)
345ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt = string.replace(opt, '-', '_')
346ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt_dict[opt] = (filename, val)
3471426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
348474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Make the ConfigParser forget everything (so we retain
349f06116dcab8f6066f78c522c056ffb9c2403706cFred Drake            # the original filenames that options come from)
350474607777d10562679b1640d3831290b0c4284f7Greg Ward            parser.__init__()
3511426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
352ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # If there was a "global" section in the config file, use it
353ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # to set Distribution options.
354ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
355ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        if self.command_options.has_key('global'):
356ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            for (opt, (src, val)) in self.command_options['global'].items():
357ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                alias = self.negative_opt.get(opt)
358ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                try:
359ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    if alias:
360ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, alias, not strtobool(val))
361ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    elif opt in ('verbose', 'dry_run'): # ugh!
362ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, opt, strtobool(val))
363ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                except ValueError, msg:
364ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, msg
365ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
366ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward    # parse_config_files ()
367ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
3681426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
369d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Command-line parsing methods ----------------------------------
370fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
3719821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward    def parse_command_line (self):
3729821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        """Parse the setup script's command line, taken from the
3739821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
3749821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        -- see 'setup()' in core.py).  This list is first processed for
3759821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        "global options" -- options that set attributes of the Distribution
3769821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        instance.  Then, it is alternately scanned for Distutils commands
3779821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        and options for that command.  Each new command terminates the
3789821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        options for the previous command.  The allowed options for a
3799821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command are determined by the 'user_options' attribute of the
3809821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command class -- thus, we have to be able to load command classes
3819821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        in order to parse the command line.  Any error in that 'options'
3829821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        attribute raises DistutilsGetoptError; any error on the
3839821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command-line raises DistutilsArgError.  If no Distutils commands
3849821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        were found on the command line, raises DistutilsArgError.  Return
385ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        true if command-line was successfully parsed and we should carry
3869821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        on with executing commands; false if no errors but we shouldn't
3879821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        execute commands (currently, this only happens if user asks for
3889821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        help).
389d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
3903f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
391981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # We now have enough information to show the Macintosh dialog
392981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # that allows the user to interactively specify the "command line".
3933f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
3943f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        if sys.platform == 'mac':
3953f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            import EasyDialogs
3963f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            cmdlist = self.get_command_list()
3973f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling            self.script_args = EasyDialogs.GetArgv(
3983f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling                self.global_options + self.display_options, cmdlist)
399b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
400fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # We have to parse the command line a bit at a time -- global
401fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # options, then the first command, then its options, and so on --
402fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # because each command will be handled by a different class, and
403d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # the options that are valid for a particular class aren't known
404d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we have loaded the command class, which doesn't happen
405d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we know what the command is.
406fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
407fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.commands = []
408fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser = FancyGetopt(self.global_options + self.display_options)
409fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(self.negative_opt)
410fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        parser.set_aliases({'licence': 'license'})
411fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        args = parser.getopt(args=self.script_args, object=self)
41282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        option_order = parser.get_option_order()
413cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.set_verbosity(self.verbose)
414fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
41582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for display options we return immediately
41682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.handle_display_options(option_order):
417fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
418b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
419fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        while args:
420d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            args = self._parse_command_opts(parser, args)
421d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if args is None:            # user asked for help (and got it)
422fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                return
423fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
424d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Handle the cases of --help as a "global" option, ie.
425d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # "setup.py --help" and "setup.py --help command ...".  For the
426d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # former, we show global options (--verbose, --dry-run, etc.)
427d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # and display-only options (--name, --version, etc.); for the
428d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # latter, we omit the display-only options and show help for
429d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # each command listed on the command line.
430d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if self.help:
431d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser,
432d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            display_options=len(self.commands) == 0,
433d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            commands=self.commands)
434fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
435fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
436fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Oops, no commands found -- an end-user error
437fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not self.commands:
438fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsArgError, "no commands supplied"
439fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
440fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # All is well: return true
441fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return 1
442fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
443fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # parse_command_line()
444fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
445d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _parse_command_opts (self, parser, args):
446d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the command-line options for a single command.
447d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'parser' must be a FancyGetopt instance; 'args' must be the list
448d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of arguments, starting with the current command (whose options
449d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        we are about to parse).  Returns a new version of 'args' with
450d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the next command at the front of the list; will be the empty
451d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        list if there are no more commands on the command line.  Returns
452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        None if the user asked for help on this command.
453d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
454d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
455d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
456d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
457d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Pull the current command from the head of the command line
458d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command = args[0]
459fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not command_re.match(command):
460d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise SystemExit, "invalid command name '%s'" % command
461fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.commands.append(command)
462d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
463d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Dig up the command class that implements this command, so we
464d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 1) know that it's a valid command, and 2) know which options
465d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # it takes.
466d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        try:
467fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            cmd_class = self.get_command_class(command)
468d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except DistutilsModuleError, msg:
469d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsArgError, msg
470d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
471d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Require that the command class be derived from Command -- want
472d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # to be sure that the basic "command" interface is implemented.
473fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not issubclass(cmd_class, Command):
474d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
475d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  "command class %s must subclass Command" % cmd_class
476d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
477d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Also make sure that the command object provides a list of its
478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # known options.
479fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not (hasattr(cmd_class, 'user_options') and
480fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                type(cmd_class.user_options) is ListType):
481d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
482d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  ("command class %s must provide " +
483d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                   "'user_options' attribute (a list of tuples)") % \
484d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  cmd_class
485d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
486d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # If the command class has a list of negative alias options,
487d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # merge it in with the global negative aliases.
488d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        negative_opt = self.negative_opt
489fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if hasattr(cmd_class, 'negative_opt'):
490fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt = copy(negative_opt)
491fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt.update(cmd_class.negative_opt)
492d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
493fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # Check for help_options in command class.  They have a different
494fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # format (tuple of four) so we need to preprocess them here.
49565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
496fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            type(cmd_class.help_options) is ListType):
4972ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward            help_options = fix_help_options(cmd_class.help_options)
4982ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        else:
49955fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward            help_options = []
5002ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
5019d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
502d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # All commands support the global options too, just by adding
503d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # in 'global_options'.
504fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_option_table(self.global_options +
505fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                cmd_class.user_options +
506fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                help_options)
507fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(negative_opt)
508fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        (args, opts) = parser.getopt(args[1:])
509474607777d10562679b1640d3831290b0c4284f7Greg Ward        if hasattr(opts, 'help') and opts.help:
510d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser, display_options=0, commands=[cmd_class])
511d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return
512d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
51365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
514fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            type(cmd_class.help_options) is ListType):
51565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            help_option_found=0
51665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            for (help_option, short, desc, func) in cmd_class.help_options:
51765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                if hasattr(opts, parser.get_attr_name(help_option)):
51865d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                    help_option_found=1
519fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward                    #print "showing help for option %s of command %s" % \
5202ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward                    #      (help_option[0],cmd_class)
52155fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
52255fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    if callable(func):
52365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                        func()
52455fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    else:
525981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                        raise DistutilsClassError(
52670a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            "invalid help function %r for help option '%s': "
527981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                            "must be a callable object (function, etc.)"
52870a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            % (func, help_option))
52955fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
530b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake            if help_option_found:
53165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                return
5329d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
533d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Put the options from the command-line into their official
534d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # holding pen, the 'command_options' dictionary.
5350e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        opt_dict = self.get_option_dict(command)
536d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for (name, value) in vars(opts).items():
5370e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            opt_dict[name] = ("command line", value)
538d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
539d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return args
540d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
541d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _parse_command_opts ()
542d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
543d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
544a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def finalize_options (self):
545a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Set final values for all the options on the Distribution
546a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        instance, analogous to the .finalize_options() method of Command
547a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        objects.
548a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
549a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
550a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        keywords = self.metadata.keywords
551a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords is not None:
552a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            if type(keywords) is StringType:
553a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                keywordlist = string.split(keywords, ',')
554a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                self.metadata.keywords = map(string.strip, keywordlist)
555a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
556a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        platforms = self.metadata.platforms
557a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if platforms is not None:
558a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            if type(platforms) is StringType:
559a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                platformlist = string.split(platforms, ',')
560a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                self.metadata.platforms = map(string.strip, platformlist)
561a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
562d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def _show_help (self,
563d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    parser,
564d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    global_options=1,
565d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    display_options=1,
566d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    commands=[]):
567d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Show help for the setup script command-line in the form of
568d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        several lists of command-line options.  'parser' should be a
569d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        FancyGetopt instance; do not expect it to be returned in the
570d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        same state, as its option table will be reset to make it
571d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        generate the correct help text.
572d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
573d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        If 'global_options' is true, lists the global options:
574d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        --verbose, --dry-run, etc.  If 'display_options' is true, lists
575d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the "display-only" options: --name, --version, etc.  Finally,
576d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        lists per-command help for every command name or command class
577d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        in 'commands'.
578d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
579d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
5809821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
581d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
582d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
583d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if global_options:
584fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.global_options)
585fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Global options:")
586d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
587d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
588d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if display_options:
589fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.display_options)
590fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help(
591d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "Information display options (just display " +
592d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "information, ignore any commands)")
593d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
594d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
595d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for command in self.commands:
596fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling            if type(command) is ClassType and issubclass(command, Command):
597d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = command
598d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            else:
599fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(command)
60065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            if (hasattr(klass, 'help_options') and
601fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                type(klass.help_options) is ListType):
602fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options +
603fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                        fix_help_options(klass.help_options))
60465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            else:
605fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options)
606fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Options for '%s' command:" % klass.__name__)
607d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            print
608d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
6099821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        print gen_usage(self.script_name)
610d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return
611d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
612d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # _show_help ()
613fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
614d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
61582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def handle_display_options (self, option_order):
61682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """If there were any non-global "display-only" options
617d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (--help-commands or the metadata display options) on the command
618d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        line, display the requested info and return true; else return
619d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        false.
620d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
6219821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
62282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
62382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # User just wants a list of commands -- we'll print it out and stop
62482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # processing now (ie. if they ran "setup --help-commands foo bar",
62582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # we ignore "foo bar").
62682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.help_commands:
627fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_commands()
62882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            print
6299821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward            print gen_usage(self.script_name)
63082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            return 1
63182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
63282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # If user supplied any of the "display metadata" options, then
63382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # display that metadata in the order in which the user supplied the
63482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # metadata options.
63582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        any_display_options = 0
63682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        is_display_option = {}
63782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for option in self.display_options:
63882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            is_display_option[option[0]] = 1
63982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
64082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for (opt, val) in option_order:
64182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            if val and is_display_option.get(opt):
6422f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                opt = translate_longopt(opt)
643a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                value = getattr(self.metadata, "get_"+opt)()
644a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                if opt in ['keywords', 'platforms']:
645a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                    print string.join(value, ',')
646282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling                elif opt == 'classifiers':
647282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling                    print string.join(value, '\n')
648a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                else:
649a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                    print value
65082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                any_display_options = 1
65182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
65282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return any_display_options
65382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
65482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # handle_display_options()
655fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
656fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_command_list (self, commands, header, max_length):
657fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print a subset of the list of all commands -- used by
658d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'print_commands()'.
659d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
660fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
661fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        print header + ":"
662fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
663fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in commands:
664fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            klass = self.cmdclass.get(cmd)
665fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not klass:
666fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(cmd)
667fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            try:
668fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = klass.description
669fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            except AttributeError:
670fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = "(no description available)"
671fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
672fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print "  %-*s  %s" % (max_length, cmd, description)
673fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
674fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_command_list ()
675fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
676fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
677fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def print_commands (self):
678d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Print out a help message listing all available commands with a
679d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        description of each.  The list is divided into "standard commands"
680d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (listed in distutils.command.__all__) and "extra commands"
681d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (mentioned in self.cmdclass, but not a standard command).  The
682d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        descriptions come from the command class attribute
683d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'description'.
684d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
685fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
686fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        import distutils.command
687fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        std_commands = distutils.command.__all__
688fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        is_std = {}
689fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in std_commands:
690fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            is_std[cmd] = 1
691fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
692fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        extra_commands = []
693fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.cmdclass.keys():
694fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not is_std.get(cmd):
695fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                extra_commands.append(cmd)
696fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
697fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        max_length = 0
698fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in (std_commands + extra_commands):
699fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            if len(cmd) > max_length:
700fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                max_length = len(cmd)
701fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
702fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.print_command_list(std_commands,
703fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                "Standard commands",
704fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                max_length)
705fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if extra_commands:
706fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print
707fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_command_list(extra_commands,
708fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    "Extra commands",
709fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    max_length)
710fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
711fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # print_commands ()
712fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
713f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward    def get_command_list (self):
714f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """Get a list of (command, description) tuples.
715f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        The list is divided into "standard commands" (listed in
716f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        distutils.command.__all__) and "extra commands" (mentioned in
717f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        self.cmdclass, but not a standard command).  The descriptions come
718f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        from the command class attribute 'description'.
719f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """
720f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Currently this is only used on Mac OS, for the Mac-only GUI
721f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Distutils interface (by Jack Jansen)
722f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
723f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        import distutils.command
724f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        std_commands = distutils.command.__all__
725f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        is_std = {}
726f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in std_commands:
727f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            is_std[cmd] = 1
728f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
729f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        extra_commands = []
730f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in self.cmdclass.keys():
731f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not is_std.get(cmd):
732f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                extra_commands.append(cmd)
733f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
734f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        rv = []
735f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in (std_commands + extra_commands):
736f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            klass = self.cmdclass.get(cmd)
737f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not klass:
738f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                klass = self.get_command_class(cmd)
739f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            try:
740f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = klass.description
741f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            except AttributeError:
742f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = "(no description available)"
743f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            rv.append((cmd, description))
744f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        return rv
745fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
746fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Command class/object methods ----------------------------------
747fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
748d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_class (self, command):
749d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the class that implements the Distutils command named by
750d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'command'.  First we check the 'cmdclass' dictionary; if the
751d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command is mentioned there, we fetch the class object from the
752d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        dictionary and return it.  Otherwise we load the command module
753d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        ("distutils.command." + command) and fetch the command class from
754d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the module.  The loaded class is also stored in 'cmdclass'
755d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        to speed future calls to 'get_command_class()'.
7561426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
7571426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Raises DistutilsModuleError if the expected module could not be
758d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        found, or if that module does not define the expected class.
759d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
760d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        klass = self.cmdclass.get(command)
761d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if klass:
762d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return klass
763fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
764fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        module_name = 'distutils.command.' + command
765fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        klass_name = command
766fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
767fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
768fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            __import__ (module_name)
769fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            module = sys.modules[module_name]
770fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        except ImportError:
771fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
772fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no module named '%s')" % \
773fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  (command, module_name)
774fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
775fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        try:
776d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = getattr(module, klass_name)
777d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except AttributeError:
778fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsModuleError, \
779fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  "invalid command '%s' (no class '%s' in module '%s')" \
780fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                  % (command, klass_name, module_name)
781fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
782d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        self.cmdclass[command] = klass
783fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return klass
784fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
785d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # get_command_class ()
786fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
787d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    def get_command_obj (self, command, create=1):
788d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the command object for 'command'.  Normally this object
789612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        is cached on a previous call to 'get_command_obj()'; if no command
790d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        object for 'command' is in the cache, then we either create and
791d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return it (if 'create' is true) or return None.
792d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
793d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.command_obj.get(command)
794fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not cmd_obj and create:
7952bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG:
7962bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward                print "Distribution.get_command_obj(): " \
7972bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward                      "creating '%s' command object" % command
798474607777d10562679b1640d3831290b0c4284f7Greg Ward
799d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = self.get_command_class(command)
800474607777d10562679b1640d3831290b0c4284f7Greg Ward            cmd_obj = self.command_obj[command] = klass(self)
801474607777d10562679b1640d3831290b0c4284f7Greg Ward            self.have_run[command] = 0
802474607777d10562679b1640d3831290b0c4284f7Greg Ward
803474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Set any options that were supplied in config files
804474607777d10562679b1640d3831290b0c4284f7Greg Ward            # or on the command line.  (NB. support for error
805474607777d10562679b1640d3831290b0c4284f7Greg Ward            # reporting is lame here: any errors aren't reported
806474607777d10562679b1640d3831290b0c4284f7Greg Ward            # until 'finalize_options()' is called, which means
807474607777d10562679b1640d3831290b0c4284f7Greg Ward            # we won't report the source of the error.)
808474607777d10562679b1640d3831290b0c4284f7Greg Ward            options = self.command_options.get(command)
809474607777d10562679b1640d3831290b0c4284f7Greg Ward            if options:
810c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                self._set_command_options(cmd_obj, options)
811fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
812fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return cmd_obj
813fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
814c32d9a69527af6d2823650ea7674e207c975f090Greg Ward    def _set_command_options (self, command_obj, option_dict=None):
815c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Set the options for 'command_obj' from 'option_dict'.  Basically
816c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        this means copying elements of a dictionary ('option_dict') to
817c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        attributes of an instance ('command').
818c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
819ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        'command_obj' must be a Command instance.  If 'option_dict' is not
820c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        supplied, uses the standard option dictionary for this command
821c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        (from 'self.command_options').
822c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
823c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command_name = command_obj.get_command_name()
824c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if option_dict is None:
825c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            option_dict = self.get_option_dict(command_name)
826c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
827c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if DEBUG: print "  setting options for '%s' command:" % command_name
828c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for (option, (source, value)) in option_dict.items():
829c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if DEBUG: print "    %s = %s (from %s)" % (option, value, source)
830ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8312f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                bool_opts = map(translate_longopt, command_obj.boolean_options)
832ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
833ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                bool_opts = []
834ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
835ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = command_obj.negative_opt
836ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
837ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = {}
838ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
839ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8402c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                is_string = type(value) is StringType
8412c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                if neg_opt.has_key(option) and is_string:
842ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, neg_opt[option], not strtobool(value))
8432c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                elif option in bool_opts and is_string:
844ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, strtobool(value))
845ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                elif hasattr(command_obj, option):
846ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, value)
847ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                else:
848ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, \
849ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                          ("error in %s: command '%s' has no such option '%s'"
850ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                           % (source, command_name, option))
851ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except ValueError, msg:
852ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                raise DistutilsOptionError, msg
853c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
854f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward    def reinitialize_command (self, command, reinit_subcommands=0):
855c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Reinitializes a command to the state it was in when first
856c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        returned by 'get_command_obj()': ie., initialized but not yet
8577d9c705b234ad2ad013db1649e5fd2ffc2a59a75Greg Ward        finalized.  This provides the opportunity to sneak option
858c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        values in programmatically, overriding or supplementing
859c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        user-supplied values from the config files and command line.
860c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        You'll have to re-finalize the command object (by calling
861c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'finalize_options()' or 'ensure_finalized()') before using it for
862b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake        real.
863c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
864f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'command' should be a command name (string) or command object.  If
865f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'reinit_subcommands' is true, also reinitializes the command's
866f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        sub-commands, as declared by the 'sub_commands' class attribute (if
867f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        it has one).  See the "install" command for an example.  Only
868f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        reinitializes the sub-commands that actually matter, ie. those
869f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        whose test predicates return true.
870f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
871c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        Returns the reinitialized command object.
872c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
873c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.cmd import Command
874c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not isinstance(command, Command):
875c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command
876c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command = self.get_command_obj(command_name)
877c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        else:
878c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command.get_command_name()
879c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
880c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not command.finalized:
881282c7a0230b578147a89a18ec22410b830edddfeGreg Ward            return command
882c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.initialize_options()
883c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.finalized = 0
88443955c9a023ea7b50b28052112dbdc914c090a27Greg Ward        self.have_run[command_name] = 0
885c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        self._set_command_options(command)
886f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
887f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        if reinit_subcommands:
888f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward            for sub in command.get_sub_commands():
889b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake                self.reinitialize_command(sub, reinit_subcommands)
890f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
891c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        return command
892c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
893b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
894fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on the Distribution ----------------------
895fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
896fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def announce (self, msg, level=1):
897cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.debug(msg)
898fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
899fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_commands (self):
90082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """Run each command that was seen on the setup script command line.
901d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Uses the list of commands found and cache of command objects
902fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        created by 'get_command_obj()'.
903fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        """
904fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.commands:
905fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.run_command(cmd)
906fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
907fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
908fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on its Commands --------------------------
909fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
910fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def run_command (self, command):
911fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Do whatever it takes to run a command (including nothing at all,
912d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if the command has already been run).  Specifically: if we have
913d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        already created and run the command named by 'command', return
914d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        silently without doing anything.  If the command named by 'command'
915d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        doesn't even have a command object yet, create one.  Then invoke
916d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'run()' on that command object (or an existing one).
917d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
918fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Already been here, done that? then return silently.
919fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if self.have_run.get(command):
920fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
921fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
922cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.info("running %s", command)
923fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj = self.get_command_obj(command)
924fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.ensure_finalized()
925fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.run()
926fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run[command] = 1
927fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
928fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
929fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Distribution query methods ------------------------------------
930fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
931fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_pure_modules (self):
932fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return len(self.packages or self.py_modules or []) > 0
933fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
934fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_ext_modules (self):
935fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.ext_modules and len(self.ext_modules) > 0
936fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
937fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_c_libraries (self):
938fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.libraries and len(self.libraries) > 0
939fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
940fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def has_modules (self):
941fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.has_pure_modules() or self.has_ext_modules()
942fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
94351def7d667a42eac177690e1fe00eab7f2102319Greg Ward    def has_headers (self):
94451def7d667a42eac177690e1fe00eab7f2102319Greg Ward        return self.headers and len(self.headers) > 0
94551def7d667a42eac177690e1fe00eab7f2102319Greg Ward
94644a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_scripts (self):
94744a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.scripts and len(self.scripts) > 0
94844a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
94944a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward    def has_data_files (self):
95044a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.data_files and len(self.data_files) > 0
95144a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
952fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def is_pure (self):
953fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return (self.has_pure_modules() and
954fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_ext_modules() and
955fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_c_libraries())
956fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
95782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
95882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
95982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # If you're looking for 'get_name()', 'get_version()', and so forth,
96082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # they are defined in a sneaky way: the constructor binds self.get_XXX
96182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # to self.metadata.get_XXX.  The actual code is in the
96282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # DistributionMetadata class, below.
96382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
96482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class Distribution
96582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
96682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
96782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata:
96882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    """Dummy class to hold the distribution meta-data: name, version,
969fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    author, and so forth.
970fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    """
97182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
972a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer    _METHOD_BASENAMES = ("name", "version", "author", "author_email",
973a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "maintainer", "maintainer_email", "url",
974a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "license", "description", "long_description",
975a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "keywords", "platforms", "fullname", "contact",
976a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                         "contact_email", "license", "classifiers",
977188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling                         "download_url")
978a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer
97982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def __init__ (self):
98082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.name = None
98182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.version = None
98282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author = None
98382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author_email = None
98482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer = None
98582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer_email = None
98682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.url = None
987fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        self.license = None
98882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.description = None
989e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        self.long_description = None
990a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.keywords = None
991a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.platforms = None
992282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        self.classifiers = None
993188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        self.download_url = None
994b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
995a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def write_pkg_info (self, base_dir):
996a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Write the PKG-INFO file into the release tree.
997a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
998a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
999a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
1000a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1001a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Metadata-Version: 1.0\n')
1002a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Name: %s\n' % self.get_name() )
1003a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Version: %s\n' % self.get_version() )
1004a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Summary: %s\n' % self.get_description() )
1005a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Home-page: %s\n' % self.get_url() )
1006ffb963c7f699c9b6ab0debc1825a55ec8f98556fAndrew M. Kuchling        pkg_info.write('Author: %s\n' % self.get_contact() )
1007ffb963c7f699c9b6ab0debc1825a55ec8f98556fAndrew M. Kuchling        pkg_info.write('Author-email: %s\n' % self.get_contact_email() )
1008fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        pkg_info.write('License: %s\n' % self.get_license() )
1009188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        if self.download_url:
1010188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling            pkg_info.write('Download-URL: %s\n' % self.download_url)
1011a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1012a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        long_desc = rfc822_escape( self.get_long_description() )
1013a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.write('Description: %s\n' % long_desc)
1014a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1015a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        keywords = string.join( self.get_keywords(), ',')
1016a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords:
1017a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            pkg_info.write('Keywords: %s\n' % keywords )
1018a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1019a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        for platform in self.get_platforms():
1020a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling            pkg_info.write('Platform: %s\n' % platform )
1021a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1022282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        for classifier in self.get_classifiers():
1023282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling            pkg_info.write('Classifier: %s\n' % classifier )
1024282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1025a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info.close()
1026b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1027a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    # write_pkg_info ()
1028b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
102982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
103082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1031fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def get_name (self):
1032fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.name or "UNKNOWN"
1033fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
103482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_version(self):
1035bcd8975740da47e7d1c8a5d2839ad4bf214fe34bThomas Heller        return self.version or "0.0.0"
103682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
103782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_fullname (self):
103882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return "%s-%s" % (self.get_name(), self.get_version())
103982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
104082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author(self):
104182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author or "UNKNOWN"
1042fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
104382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author_email(self):
104482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author_email or "UNKNOWN"
104582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
104682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer(self):
104782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer or "UNKNOWN"
104882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
104982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer_email(self):
105082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer_email or "UNKNOWN"
105182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
105282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact(self):
105382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer or
105482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author or
105582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
105682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
105782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact_email(self):
105882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return (self.maintainer_email or
105982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                self.author_email or
106082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                "UNKNOWN")
106182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
106282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_url(self):
106382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.url or "UNKNOWN"
106482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1065fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    def get_license(self):
1066fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        return self.license or "UNKNOWN"
1067fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    get_licence = get_license
1068b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
106982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_description(self):
107082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.description or "UNKNOWN"
1071e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1072e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward    def get_long_description(self):
1073e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        return self.long_description or "UNKNOWN"
1074e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1075a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_keywords(self):
1076a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.keywords or []
1077a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1078a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_platforms(self):
1079a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.platforms or ["UNKNOWN"]
1080a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1081282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling    def get_classifiers(self):
1082282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        return self.classifiers or []
1083282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1084188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling    def get_download_url(self):
1085188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        return self.download_url or "UNKNOWN"
1086188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling
108782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward# class DistributionMetadata
1088fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
10892ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
10902ff7887270385bd6dddc2d5461486334b4fec8bcGreg Warddef fix_help_options (options):
10912ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """Convert a 4-tuple 'help_options' list as found in various command
10922ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    classes to the 3-tuple form required by FancyGetopt.
10932ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """
10942ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    new_options = []
10952ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    for help_tuple in options:
10962ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        new_options.append(help_tuple[0:3])
10972ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    return new_options
10982ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
10992ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
1100fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardif __name__ == "__main__":
1101fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    dist = Distribution()
1102fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    print "ok"
1103