dist.py revision de0559998fef231efc9ecbdef5b3a195d4eaa28d
1fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward"""distutils.dist
2fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
3fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg WardProvides the Distribution class, which represents the module distribution
48ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Wardbeing built/installed/distributed.
58ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward"""
6fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
7fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward__revision__ = "$Id$"
8fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
9c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadéimport sys, os, re
10ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
11ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchlingtry:
12ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    import warnings
13ccf4e421b829ce69eb62806fdd77eb71249713ddAndrew M. Kuchlingexcept ImportError:
14ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    warnings = None
15ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
16fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom distutils.errors import *
172f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Wardfrom distutils.fancy_getopt import FancyGetopt, translate_longopt
18a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchlingfrom distutils.util import check_environ, strtobool, rfc822_escape
19cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log
20fcd7353863c024bb87aabe7c4639ca8df692ac85Jeremy Hyltonfrom distutils.debug import DEBUG
21fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
22b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg# Encoding used for the PKG-INFO files
23b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André LemburgPKG_INFO_ENCODING = 'utf-8'
24b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg
25fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# Regex to define acceptable Distutils command names.  This is not *quite*
26fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# the same as a Python NAME -- I don't allow leading underscores.  The fact
27fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# that they're very similar is no coincidence; the default naming scheme is
28fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# to look for a Python module named after the command.
29fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardcommand_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
30fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
31fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
32fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardclass Distribution:
338ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """The core of the Distutils.  Most of the work hiding behind 'setup'
348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    is really done within a Distribution instance, which farms the work out
358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to the Distutils commands specified on the command line.
368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward
378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Setup scripts will almost never instantiate Distribution directly,
388ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    unless the 'setup()' function is totally inadequate to their needs.
398ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    However, it is conceivable that a setup script might wish to subclass
408ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Distribution for some specialized purpose, and then pass the subclass
418ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to 'setup()' as the 'distclass' keyword argument.  If so, it is
428ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    necessary to respect the expectations that 'setup' has of Distribution.
438ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    See the code for 'setup()', in core.py, for details.
448ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """
45fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
46fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # 'global_options' describes the command-line options that may be
4882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # supplied to the setup script prior to any actual commands.
4982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
50fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # these global options.  This list should be kept to a bare minimum,
51fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # since every global option is also valid as a command option -- and we
52fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # don't want to pollute the commands with too many options that they
53fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # have minimal control over.
54cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    # The fourth entry for verbose means that it can be repeated.
55cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    global_options = [('verbose', 'v', "run verbosely (default)", 1),
56d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('quiet', 'q', "run quietly (turns verbosity off)"),
57d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('dry-run', 'n', "don't actually do anything"),
58d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('help', 'h', "show detailed help message"),
59fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                     ]
6082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
618ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    # 'common_usage' is a short (2-3 line) string describing the common
628ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    # usage of the setup script.
638ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    common_usage = """\
648ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. LöwisCommon commands: (see '--help-commands' for more)
658ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis
668ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis  setup.py build      will build the package underneath 'build/'
678ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis  setup.py install    will install the package
688ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis"""
698ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis
7082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # options that are not propagated to the commands
7182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_options = [
7282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('help-commands', None,
7382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "list all available commands"),
7482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('name', None,
7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package name"),
7682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('version', 'V',
7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package version"),
7882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('fullname', None,
7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print <package name>-<version>"),
8082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author', None,
8182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's name"),
8282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author-email', None,
8382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's email address"),
8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer', None,
8582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's name"),
8682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer-email', None,
8782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's email address"),
8882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact', None,
89d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's name if known, else the author's"),
9082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact-email', None,
91d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's email address if known, else the author's"),
9282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('url', None,
9382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the URL for this package"),
9482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('license', None,
95fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "print the license of the package"),
96fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        ('licence', None,
97fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "alias for --license"),
9882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('description', None,
9982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the package description"),
100e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        ('long-description', None,
101e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward         "print the long package description"),
102a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('platforms', None,
103a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of platforms"),
104282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        ('classifiers', None,
105282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling         "print the list of classifiers"),
106a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('keywords', None,
107a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of keywords"),
108db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('provides', None,
109db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules provided"),
110db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('requires', None,
111db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules required"),
112db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('obsoletes', None,
113db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules made obsolete")
11482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ]
1152f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward    display_option_names = map(lambda x: translate_longopt(x[0]),
1162f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                               display_options)
11782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
11882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # negative options are options that exclude other options
119fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    negative_opt = {'quiet': 'verbose'}
120fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
121fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
122fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Creation/initialization methods -------------------------------
123b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
124fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def __init__ (self, attrs=None):
125fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Construct a new Distribution instance: initialize all the
1268ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes of a Distribution, and then use 'attrs' (a dictionary
1278ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        mapping attribute names to values) to assign some of those
1288ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes their "real" values.  (Any attributes not mentioned in
1298ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'attrs' will be assigned to some null value: 0, None, an empty list
1308ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        or dictionary, etc.)  Most importantly, initialize the
1318ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'command_obj' attribute to the empty dictionary; this will be
1328ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        filled in with real command objects by 'parse_command_line()'.
1338ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        """
134fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
135fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Default values for our command-line options
136fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.verbose = 1
137fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.dry_run = 0
138fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.help = 0
13982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for attr in self.display_option_names:
14082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            setattr(self, attr, 0)
14182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
14282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # Store the distribution meta-data (name, version, author, and so
14382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # forth) in a separate object -- we're getting to have enough
14482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # information here (and enough command-line options) that it's
14582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
14682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # object in a sneaky and underhanded (but efficient!) way.
147fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.metadata = DistributionMetadata()
148a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer        for basename in self.metadata._METHOD_BASENAMES:
1494982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            method_name = "get_" + basename
1504982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            setattr(self, method_name, getattr(self.metadata, method_name))
151fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
152fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'cmdclass' maps command names to class objects, so we
153fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # can 1) quickly figure out which class to instantiate when
154fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # we need to create a new command object, and 2) have a way
15582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for the setup script to override command classes
156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.cmdclass = {}
157fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
158d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # 'command_packages' is a list of packages in which commands
159d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # are searched for.  The factory for command 'foo' is expected
160d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # to be named 'foo' in the module 'foo' in one of the packages
161d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # named here.  This list is searched from the left; an error
162d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # is raised if no named package provides the command being
163d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # searched for.  (Always access using get_command_packages().)
164d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        self.command_packages = None
165d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
1669821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # 'script_name' and 'script_args' are usually set to sys.argv[0]
1679821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # and sys.argv[1:], but they can be overridden when the caller is
1689821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # not necessarily a setup script run from the command-line.
1699821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_name = None
1709821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_args = None
1719821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward
172d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 'command_options' is where we store command options between
173d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # parsing them (from config files, the command-line, etc.) and when
174d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # they are actually needed -- ie. when the command in question is
175d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
176d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        #   command_options = { command_name : { option : (source, value) } }
1771426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        self.command_options = {}
1781426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
17998da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # 'dist_files' is the list of (command, pyversion, file) that
18098da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # have been created by any dist commands run so far. This is
18198da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # filled regardless of whether the run is dry or not. pyversion
18298da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # gives sysconfig.get_python_version() if the dist file is
18398da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # specific to a Python version, 'any' if it is good for all
18498da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # Python versions on the target platform, and '' for a source
18598da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # file. pyversion should not be used to specify minimum or
18698da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # maximum required Python versions; use the metainfo for that
18798da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # instead.
18855f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis        self.dist_files = []
18955f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis
190fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # These options are really the business of various commands, rather
191fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # than of the Distribution itself.  We provide aliases for them in
192fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Distribution as a convenience to the developer.
193fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.packages = None
1940eb32a65b06613d25aeb18f0104554171bea4840Fred Drake        self.package_data = {}
195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.package_dir = None
196fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.py_modules = None
197fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.libraries = None
19851def7d667a42eac177690e1fe00eab7f2102319Greg Ward        self.headers = None
199fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_modules = None
200fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_package = None
201fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.include_dirs = None
202fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.extra_path = None
203b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith        self.scripts = None
2046a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith        self.data_files = None
2051a240fb9f038839f0e6f157ce4c7fcbcbf777ebcTarek Ziadé        self.password = ''
206fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
207fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # And now initialize bookkeeping stuff that can't be supplied by
208fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the caller at all.  'command_obj' maps command names to
209fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Command instances -- that's how we enforce that every command
210fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # class is a singleton.
211fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.command_obj = {}
212fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
213fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'have_run' maps command names to boolean values; it keeps track
214fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # of whether we have actually run a particular command, to make it
215fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # cheap to "run" a command whenever we think we might need to -- if
216fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # it's already been done, no need for expensive filesystem
217fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # operations, we just check the 'have_run' dictionary and carry on.
218fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # It's only safe to query 'have_run' for a command class that has
219fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # been instantiated -- a false value will be inserted when the
220fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # command object is created, and replaced with a true value when
221612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        # the command is successfully run.  Thus it's probably best to use
222fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # '.get()' rather than a straight lookup.
223fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run = {}
224fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
225fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Now we'll use the attrs dictionary (ultimately, keyword args from
22682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # the setup script) to possibly override any or all of these
22782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # distribution options.
22882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
229fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if attrs:
230fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Pull out the set of command options and work on them
231fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # specifically.  Note that this order guarantees that aliased
232fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # command options will override any supplied redundantly
233fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # through the general options dictionary.
234fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            options = attrs.get('options')
235c13acb18bc2db9d8824ba94b86d8e4c8909d6b6cTarek Ziadé            if options is not None:
236fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                del attrs['options']
237fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                for (command, cmd_options) in options.items():
2380e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    opt_dict = self.get_option_dict(command)
2390e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    for (opt, val) in cmd_options.items():
2400e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = ("setup script", val)
241fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
2428bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum            if 'licence' in attrs:
243a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                attrs['license'] = attrs['licence']
244a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                del attrs['licence']
245a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                msg = "'licence' distribution option is deprecated; use 'license'"
246a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                if warnings is not None:
247a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    warnings.warn(msg)
248a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                else:
249a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    sys.stderr.write(msg + "\n")
250a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling
251fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Now work on the rest of the attributes.  Any attribute that's
252fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # not already defined is invalid!
253c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            for (key, val) in attrs.items():
254db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                if hasattr(self.metadata, "set_" + key):
255db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                    getattr(self.metadata, "set_" + key)(val)
256db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                elif hasattr(self.metadata, key):
257fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self.metadata, key, val)
258fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                elif hasattr(self, key):
259fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self, key, val)
26073cc8479f000bbb84d0775aea55fb9de75ec110eAnthony Baxter                else:
261ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    msg = "Unknown distribution option: %s" % repr(key)
262ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    if warnings is not None:
263ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        warnings.warn(msg)
264ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    else:
265ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        sys.stderr.write(msg + "\n")
266fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
267a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.finalize_options()
268b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
269ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_option_dict(self, command):
2700e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """Get the option dictionary for a given command.  If that
2710e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        command's option dictionary hasn't been created yet, then create it
2720e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        and return the new dictionary; otherwise, return the existing
2730e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        option dictionary.
2740e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """
2750e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        dict = self.command_options.get(command)
2760e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        if dict is None:
2770e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            dict = self.command_options[command] = {}
2780e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        return dict
2790e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
280ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def dump_option_dicts(self, header=None, commands=None, indent=""):
281c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from pprint import pformat
282c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
283c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if commands is None:             # dump all command option dicts
284c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands = self.command_options.keys()
285c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands.sort()
286c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
287c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if header is not None:
288c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce(indent + header)
289c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            indent = indent + "  "
290c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
291c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not commands:
292c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce(indent + "no commands known yet")
293c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            return
294c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
295c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for cmd_name in commands:
296c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            opt_dict = self.command_options.get(cmd_name)
297c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if opt_dict is None:
298c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce(indent +
299c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "no option dict for '%s' command" % cmd_name)
300c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            else:
301c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce(indent +
302c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "option dict for '%s' command:" % cmd_name)
303c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                out = pformat(opt_dict)
304c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                for line in out.split('\n'):
305c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                    self.announce(indent + "  " + line)
306c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
307d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Config file finding/parsing methods ---------------------------
308d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
309ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def find_config_files(self):
3101426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        """Find as many configuration files as should be processed for this
3111426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        platform, and return a list of filenames in the order in which they
3121426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        should be parsed.  The filenames returned are guaranteed to exist
3131426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        (modulo nasty race conditions).
3141426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
315d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        There are three possible config files: distutils.cfg in the
316d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils installation directory (ie. where the top-level
317d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils __inst__.py file lives), a file in the user's home
318d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        directory named .pydistutils.cfg on Unix and pydistutils.cfg
319d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        on Windows/Mac, and setup.cfg in the current directory.
320d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
3211426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        files = []
322acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward        check_environ()
323acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward
3241169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Where to look for the system-wide Distutils config file
3251169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
3261169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
3271169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Look for the system config file
3281169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_file = os.path.join(sys_dir, "distutils.cfg")
3291169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.path.isfile(sys_file):
3301169687692e5e897033421fe6a73a3c32675a7d7Greg Ward            files.append(sys_file)
3311169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
3321169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # What to call the per-user config file
3331169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.name == 'posix':
33465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = ".pydistutils.cfg"
33565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        else:
33665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = "pydistutils.cfg"
337fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
3381169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # And look for the user config file
339aac5c8669f34b285c9582dd7083d74dcca31dbaeAndrew M. Kuchling        user_file = os.path.join(os.path.expanduser('~'), user_filename)
340aac5c8669f34b285c9582dd7083d74dcca31dbaeAndrew M. Kuchling        if os.path.isfile(user_file):
341aac5c8669f34b285c9582dd7083d74dcca31dbaeAndrew M. Kuchling            files.append(user_file)
3421426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3431426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        # All platforms support local setup.cfg
3441426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        local_file = "setup.cfg"
3451426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.path.isfile(local_file):
3461426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            files.append(local_file)
3471426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3481426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        return files
3491426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
350ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def parse_config_files(self, filenames=None):
351392c6fc02d90f211dadc72448a07d9281260cb70Georg Brandl        from ConfigParser import ConfigParser
3521426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3531426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if filenames is None:
3541426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            filenames = self.find_config_files()
3551426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
356c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if DEBUG:
357c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce("Distribution.parse_config_files():")
358474607777d10562679b1640d3831290b0c4284f7Greg Ward
3591426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        parser = ConfigParser()
360d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for filename in filenames:
361c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if DEBUG:
36299773359843803c54574b6ee6fc1516e7fcde10fTarek Ziadé                self.announce("  reading %s" % filename)
363d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.read(filename)
364d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            for section in parser.sections():
365d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                options = parser.options(section)
3660e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                opt_dict = self.get_option_dict(section)
367d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
368d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                for opt in options:
369d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    if opt != '__name__':
370ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        val = parser.get(section,opt)
371c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                        opt = opt.replace('-', '_')
372ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt_dict[opt] = (filename, val)
3731426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
374474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Make the ConfigParser forget everything (so we retain
375f06116dcab8f6066f78c522c056ffb9c2403706cFred Drake            # the original filenames that options come from)
376474607777d10562679b1640d3831290b0c4284f7Greg Ward            parser.__init__()
3771426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
378ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # If there was a "global" section in the config file, use it
379ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # to set Distribution options.
380ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
3818bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum        if 'global' in self.command_options:
382ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            for (opt, (src, val)) in self.command_options['global'].items():
383ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                alias = self.negative_opt.get(opt)
384ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                try:
385ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    if alias:
386ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, alias, not strtobool(val))
387ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    elif opt in ('verbose', 'dry_run'): # ugh!
388ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, opt, strtobool(val))
389d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                    else:
390d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                        setattr(self, opt, val)
391ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                except ValueError, msg:
392ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, msg
393ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
394d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Command-line parsing methods ----------------------------------
395fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
396ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def parse_command_line(self):
3979821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        """Parse the setup script's command line, taken from the
3989821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
3999821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        -- see 'setup()' in core.py).  This list is first processed for
4009821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        "global options" -- options that set attributes of the Distribution
4019821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        instance.  Then, it is alternately scanned for Distutils commands
4029821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        and options for that command.  Each new command terminates the
4039821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        options for the previous command.  The allowed options for a
4049821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command are determined by the 'user_options' attribute of the
4059821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command class -- thus, we have to be able to load command classes
4069821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        in order to parse the command line.  Any error in that 'options'
4079821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        attribute raises DistutilsGetoptError; any error on the
4089821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command-line raises DistutilsArgError.  If no Distutils commands
4099821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        were found on the command line, raises DistutilsArgError.  Return
410ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        true if command-line was successfully parsed and we should carry
4119821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        on with executing commands; false if no errors but we shouldn't
4129821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        execute commands (currently, this only happens if user asks for
4139821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        help).
414d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
4153f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
416981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # We now have enough information to show the Macintosh dialog
417981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # that allows the user to interactively specify the "command line".
4183f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
419d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        toplevel_options = self._get_toplevel_options()
420b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
421fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # We have to parse the command line a bit at a time -- global
422fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # options, then the first command, then its options, and so on --
423fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # because each command will be handled by a different class, and
424d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # the options that are valid for a particular class aren't known
425d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we have loaded the command class, which doesn't happen
426d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we know what the command is.
427fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
428fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.commands = []
429d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        parser = FancyGetopt(toplevel_options + self.display_options)
430fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(self.negative_opt)
431fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        parser.set_aliases({'licence': 'license'})
432fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        args = parser.getopt(args=self.script_args, object=self)
43382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        option_order = parser.get_option_order()
434cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.set_verbosity(self.verbose)
435fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
43682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for display options we return immediately
43782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.handle_display_options(option_order):
438fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
439fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        while args:
440d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            args = self._parse_command_opts(parser, args)
441d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if args is None:            # user asked for help (and got it)
442fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                return
443fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
444d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Handle the cases of --help as a "global" option, ie.
445d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # "setup.py --help" and "setup.py --help command ...".  For the
446d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # former, we show global options (--verbose, --dry-run, etc.)
447d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # and display-only options (--name, --version, etc.); for the
448d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # latter, we omit the display-only options and show help for
449d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # each command listed on the command line.
450d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if self.help:
451d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser,
452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            display_options=len(self.commands) == 0,
453d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            commands=self.commands)
454fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
455fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
456fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Oops, no commands found -- an end-user error
457fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not self.commands:
458fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsArgError, "no commands supplied"
459fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
460fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # All is well: return true
461fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return 1
462fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
463ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _get_toplevel_options(self):
464d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """Return the non-display options recognized at the top level.
465d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
466d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        This includes options that are recognized *only* at the top
467d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        level as well as options recognized for commands.
468d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """
469d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        return self.global_options + [
470d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            ("command-packages=", None,
471d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake             "list of packages that provide distutils commands"),
472d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            ]
473d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
474ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _parse_command_opts(self, parser, args):
475d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the command-line options for a single command.
476d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'parser' must be a FancyGetopt instance; 'args' must be the list
477d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of arguments, starting with the current command (whose options
478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        we are about to parse).  Returns a new version of 'args' with
479d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the next command at the front of the list; will be the empty
480d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        list if there are no more commands on the command line.  Returns
481d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        None if the user asked for help on this command.
482d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
483d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
484d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
485d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
486d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Pull the current command from the head of the command line
487d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command = args[0]
488fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not command_re.match(command):
489d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise SystemExit, "invalid command name '%s'" % command
490fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.commands.append(command)
491d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
492d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Dig up the command class that implements this command, so we
493d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 1) know that it's a valid command, and 2) know which options
494d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # it takes.
495d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        try:
496fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            cmd_class = self.get_command_class(command)
497d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except DistutilsModuleError, msg:
498d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsArgError, msg
499d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
500d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Require that the command class be derived from Command -- want
501d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # to be sure that the basic "command" interface is implemented.
502fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not issubclass(cmd_class, Command):
503d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
504d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  "command class %s must subclass Command" % cmd_class
505d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
506d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Also make sure that the command object provides a list of its
507d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # known options.
508fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not (hasattr(cmd_class, 'user_options') and
509c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                isinstance(cmd_class.user_options, list)):
510d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
511d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  ("command class %s must provide " +
512d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                   "'user_options' attribute (a list of tuples)") % \
513d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  cmd_class
514d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
515d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # If the command class has a list of negative alias options,
516d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # merge it in with the global negative aliases.
517d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        negative_opt = self.negative_opt
518fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if hasattr(cmd_class, 'negative_opt'):
519f541378d13e7750b67758b721e862fd3b27e9e6bAntoine Pitrou            negative_opt = negative_opt.copy()
520fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt.update(cmd_class.negative_opt)
521d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
522fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # Check for help_options in command class.  They have a different
523fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # format (tuple of four) so we need to preprocess them here.
52465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
525c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            isinstance(cmd_class.help_options, list)):
5262ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward            help_options = fix_help_options(cmd_class.help_options)
5272ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        else:
52855fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward            help_options = []
5292ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
5309d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
531d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # All commands support the global options too, just by adding
532d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # in 'global_options'.
533fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_option_table(self.global_options +
534fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                cmd_class.user_options +
535fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                help_options)
536fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(negative_opt)
537fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        (args, opts) = parser.getopt(args[1:])
538474607777d10562679b1640d3831290b0c4284f7Greg Ward        if hasattr(opts, 'help') and opts.help:
539d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser, display_options=0, commands=[cmd_class])
540d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return
541d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
54265d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
543c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            isinstance(cmd_class.help_options, list)):
54465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            help_option_found=0
54565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            for (help_option, short, desc, func) in cmd_class.help_options:
54665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                if hasattr(opts, parser.get_attr_name(help_option)):
54765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                    help_option_found=1
548de0559998fef231efc9ecbdef5b3a195d4eaa28dBenjamin Peterson                    if hasattr(func, '__call__'):
54965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                        func()
55055fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    else:
551981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                        raise DistutilsClassError(
55270a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            "invalid help function %r for help option '%s': "
553981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                            "must be a callable object (function, etc.)"
55470a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            % (func, help_option))
55555fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
556b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake            if help_option_found:
55765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                return
5589d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
559d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Put the options from the command-line into their official
560d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # holding pen, the 'command_options' dictionary.
5610e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        opt_dict = self.get_option_dict(command)
562d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for (name, value) in vars(opts).items():
5630e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            opt_dict[name] = ("command line", value)
564d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
565d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return args
566d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
567ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def finalize_options(self):
568a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Set final values for all the options on the Distribution
569a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        instance, analogous to the .finalize_options() method of Command
570a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        objects.
571a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
572c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        for attr in ('keywords', 'platforms'):
573c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            value = getattr(self.metadata, attr)
574c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if value is None:
575c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                continue
576c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if isinstance(value, str):
577c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                value = [elm.strip() for elm in value.split(',')]
578c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                setattr(self.metadata, attr, value)
579a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
580ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _show_help(self, parser, global_options=1, display_options=1,
581ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé                   commands=[]):
582d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Show help for the setup script command-line in the form of
583d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        several lists of command-line options.  'parser' should be a
584d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        FancyGetopt instance; do not expect it to be returned in the
585d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        same state, as its option table will be reset to make it
586d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        generate the correct help text.
587d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
588d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        If 'global_options' is true, lists the global options:
589d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        --verbose, --dry-run, etc.  If 'display_options' is true, lists
590d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the "display-only" options: --name, --version, etc.  Finally,
591d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        lists per-command help for every command name or command class
592d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        in 'commands'.
593d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
594d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
5959821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
596d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
597d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
598d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if global_options:
599d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            if display_options:
600d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                options = self._get_toplevel_options()
601d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            else:
602d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                options = self.global_options
603d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            parser.set_option_table(options)
6048ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis            parser.print_help(self.common_usage + "\nGlobal options:")
605cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
606d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
607d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if display_options:
608fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.display_options)
609fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help(
610d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "Information display options (just display " +
611d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "information, ignore any commands)")
612cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
613d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
614d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for command in self.commands:
615c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if isinstance(command, type) and issubclass(command, Command):
616d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = command
617d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            else:
618fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(command)
61965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            if (hasattr(klass, 'help_options') and
620c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                isinstance(klass.help_options, list)):
621fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options +
622fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                        fix_help_options(klass.help_options))
62365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            else:
624fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options)
625fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Options for '%s' command:" % klass.__name__)
626cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
627d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
628cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé        print(gen_usage(self.script_name))
629d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
630ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def handle_display_options(self, option_order):
63182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """If there were any non-global "display-only" options
632d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (--help-commands or the metadata display options) on the command
633d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        line, display the requested info and return true; else return
634d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        false.
635d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
6369821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
63782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
63882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # User just wants a list of commands -- we'll print it out and stop
63982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # processing now (ie. if they ran "setup --help-commands foo bar",
64082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # we ignore "foo bar").
64182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.help_commands:
642fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_commands()
643cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
644cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print(gen_usage(self.script_name))
64582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            return 1
64682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
64782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # If user supplied any of the "display metadata" options, then
64882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # display that metadata in the order in which the user supplied the
64982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # metadata options.
65082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        any_display_options = 0
65182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        is_display_option = {}
65282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for option in self.display_options:
65382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            is_display_option[option[0]] = 1
65482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
65582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for (opt, val) in option_order:
65682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            if val and is_display_option.get(opt):
6572f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                opt = translate_longopt(opt)
658a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                value = getattr(self.metadata, "get_"+opt)()
659a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                if opt in ['keywords', 'platforms']:
660cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print(','.join(value))
661db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                elif opt in ('classifiers', 'provides', 'requires',
662db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                             'obsoletes'):
663cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print('\n'.join(value))
664a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                else:
665cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print(value)
66682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                any_display_options = 1
66782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
66882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return any_display_options
66982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
670ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def print_command_list(self, commands, header, max_length):
671fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print a subset of the list of all commands -- used by
672d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'print_commands()'.
673d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
674cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé        print(header + ":")
675fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
676fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in commands:
677fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            klass = self.cmdclass.get(cmd)
678fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not klass:
679fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(cmd)
680fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            try:
681fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = klass.description
682fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            except AttributeError:
683fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = "(no description available)"
684fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
685cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print("  %-*s  %s" % (max_length, cmd, description))
686fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
687ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def print_commands(self):
688d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Print out a help message listing all available commands with a
689d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        description of each.  The list is divided into "standard commands"
690d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (listed in distutils.command.__all__) and "extra commands"
691d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (mentioned in self.cmdclass, but not a standard command).  The
692d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        descriptions come from the command class attribute
693d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'description'.
694d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
695fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        import distutils.command
696fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        std_commands = distutils.command.__all__
697fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        is_std = {}
698fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in std_commands:
699fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            is_std[cmd] = 1
700fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
701fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        extra_commands = []
702fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.cmdclass.keys():
703fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not is_std.get(cmd):
704fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                extra_commands.append(cmd)
705fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
706fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        max_length = 0
707fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in (std_commands + extra_commands):
708fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            if len(cmd) > max_length:
709fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                max_length = len(cmd)
710fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
711fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.print_command_list(std_commands,
712fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                "Standard commands",
713fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                max_length)
714fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if extra_commands:
715fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print
716fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_command_list(extra_commands,
717fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    "Extra commands",
718fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    max_length)
719fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
720ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_list(self):
721f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """Get a list of (command, description) tuples.
722f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        The list is divided into "standard commands" (listed in
723f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        distutils.command.__all__) and "extra commands" (mentioned in
724f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        self.cmdclass, but not a standard command).  The descriptions come
725f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        from the command class attribute 'description'.
726f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """
727f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Currently this is only used on Mac OS, for the Mac-only GUI
728f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Distutils interface (by Jack Jansen)
729f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
730f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        import distutils.command
731f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        std_commands = distutils.command.__all__
732f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        is_std = {}
733f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in std_commands:
734f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            is_std[cmd] = 1
735f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
736f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        extra_commands = []
737f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in self.cmdclass.keys():
738f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not is_std.get(cmd):
739f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                extra_commands.append(cmd)
740f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
741f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        rv = []
742f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in (std_commands + extra_commands):
743f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            klass = self.cmdclass.get(cmd)
744f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not klass:
745f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                klass = self.get_command_class(cmd)
746f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            try:
747f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = klass.description
748f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            except AttributeError:
749f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = "(no description available)"
750f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            rv.append((cmd, description))
751f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        return rv
752fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
753fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Command class/object methods ----------------------------------
754fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
755ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_packages(self):
756d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """Return a list of packages from which commands are loaded."""
757d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        pkgs = self.command_packages
758c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if not isinstance(pkgs, list):
759c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if pkgs is None:
760c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                pkgs = ''
761c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
762d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            if "distutils.command" not in pkgs:
763d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                pkgs.insert(0, "distutils.command")
764d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            self.command_packages = pkgs
765d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        return pkgs
766d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
767ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_class(self, command):
768d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the class that implements the Distutils command named by
769d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'command'.  First we check the 'cmdclass' dictionary; if the
770d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command is mentioned there, we fetch the class object from the
771d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        dictionary and return it.  Otherwise we load the command module
772d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        ("distutils.command." + command) and fetch the command class from
773d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the module.  The loaded class is also stored in 'cmdclass'
774d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        to speed future calls to 'get_command_class()'.
7751426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
7761426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Raises DistutilsModuleError if the expected module could not be
777d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        found, or if that module does not define the expected class.
778d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
779d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        klass = self.cmdclass.get(command)
780d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if klass:
781d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return klass
782fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
783d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        for pkgname in self.get_command_packages():
784d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            module_name = "%s.%s" % (pkgname, command)
785d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            klass_name = command
786fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
787d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            try:
788d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                __import__ (module_name)
789d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                module = sys.modules[module_name]
790d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            except ImportError:
791d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                continue
792d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
793d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            try:
794d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                klass = getattr(module, klass_name)
795d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            except AttributeError:
796d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                raise DistutilsModuleError, \
797d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                      "invalid command '%s' (no class '%s' in module '%s')" \
798d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                      % (command, klass_name, module_name)
799d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
800d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            self.cmdclass[command] = klass
801d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            return klass
802d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
803d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        raise DistutilsModuleError("invalid command '%s'" % command)
804fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
805fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
806ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_obj(self, command, create=1):
807d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the command object for 'command'.  Normally this object
808612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        is cached on a previous call to 'get_command_obj()'; if no command
809d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        object for 'command' is in the cache, then we either create and
810d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return it (if 'create' is true) or return None.
811d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
812d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.command_obj.get(command)
813fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not cmd_obj and create:
8142bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG:
815c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce("Distribution.get_command_obj(): " \
816c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "creating '%s' command object" % command)
817474607777d10562679b1640d3831290b0c4284f7Greg Ward
818d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = self.get_command_class(command)
819474607777d10562679b1640d3831290b0c4284f7Greg Ward            cmd_obj = self.command_obj[command] = klass(self)
820474607777d10562679b1640d3831290b0c4284f7Greg Ward            self.have_run[command] = 0
821474607777d10562679b1640d3831290b0c4284f7Greg Ward
822474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Set any options that were supplied in config files
823474607777d10562679b1640d3831290b0c4284f7Greg Ward            # or on the command line.  (NB. support for error
824474607777d10562679b1640d3831290b0c4284f7Greg Ward            # reporting is lame here: any errors aren't reported
825474607777d10562679b1640d3831290b0c4284f7Greg Ward            # until 'finalize_options()' is called, which means
826474607777d10562679b1640d3831290b0c4284f7Greg Ward            # we won't report the source of the error.)
827474607777d10562679b1640d3831290b0c4284f7Greg Ward            options = self.command_options.get(command)
828474607777d10562679b1640d3831290b0c4284f7Greg Ward            if options:
829c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                self._set_command_options(cmd_obj, options)
830fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
831fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return cmd_obj
832fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
833ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _set_command_options(self, command_obj, option_dict=None):
834c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Set the options for 'command_obj' from 'option_dict'.  Basically
835c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        this means copying elements of a dictionary ('option_dict') to
836c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        attributes of an instance ('command').
837c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
838ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        'command_obj' must be a Command instance.  If 'option_dict' is not
839c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        supplied, uses the standard option dictionary for this command
840c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        (from 'self.command_options').
841c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
842c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command_name = command_obj.get_command_name()
843c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if option_dict is None:
844c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            option_dict = self.get_option_dict(command_name)
845c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
846c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if DEBUG:
847c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce("  setting options for '%s' command:" % command_name)
848c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for (option, (source, value)) in option_dict.items():
849c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if DEBUG:
850c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce("    %s = %s (from %s)" % (option, value,
851c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                                                         source))
852ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8532f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                bool_opts = map(translate_longopt, command_obj.boolean_options)
854ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
855ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                bool_opts = []
856ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
857ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = command_obj.negative_opt
858ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
859ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = {}
860ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
861ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
862c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                is_string = isinstance(value, str)
8638bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum                if option in neg_opt and is_string:
864ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, neg_opt[option], not strtobool(value))
8652c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                elif option in bool_opts and is_string:
866ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, strtobool(value))
867ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                elif hasattr(command_obj, option):
868ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, value)
869ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                else:
870ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, \
871ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                          ("error in %s: command '%s' has no such option '%s'"
872ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                           % (source, command_name, option))
873ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except ValueError, msg:
874ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                raise DistutilsOptionError, msg
875c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
876ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def reinitialize_command(self, command, reinit_subcommands=0):
877c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Reinitializes a command to the state it was in when first
878c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        returned by 'get_command_obj()': ie., initialized but not yet
8797d9c705b234ad2ad013db1649e5fd2ffc2a59a75Greg Ward        finalized.  This provides the opportunity to sneak option
880c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        values in programmatically, overriding or supplementing
881c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        user-supplied values from the config files and command line.
882c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        You'll have to re-finalize the command object (by calling
883c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'finalize_options()' or 'ensure_finalized()') before using it for
884b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake        real.
885c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
886f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'command' should be a command name (string) or command object.  If
887f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'reinit_subcommands' is true, also reinitializes the command's
888f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        sub-commands, as declared by the 'sub_commands' class attribute (if
889f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        it has one).  See the "install" command for an example.  Only
890f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        reinitializes the sub-commands that actually matter, ie. those
891f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        whose test predicates return true.
892f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
893c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        Returns the reinitialized command object.
894c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
895c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.cmd import Command
896c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not isinstance(command, Command):
897c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command
898c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command = self.get_command_obj(command_name)
899c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        else:
900c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command.get_command_name()
901c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
902c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not command.finalized:
903282c7a0230b578147a89a18ec22410b830edddfeGreg Ward            return command
904c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.initialize_options()
905c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.finalized = 0
90643955c9a023ea7b50b28052112dbdc914c090a27Greg Ward        self.have_run[command_name] = 0
907c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        self._set_command_options(command)
908f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
909f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        if reinit_subcommands:
910f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward            for sub in command.get_sub_commands():
911b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake                self.reinitialize_command(sub, reinit_subcommands)
912f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
913c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        return command
914c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
915fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on the Distribution ----------------------
916fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
91763f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé    def announce(self, msg, level=log.INFO):
91863f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé        log.log(level, msg)
919fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
920ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def run_commands(self):
92182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """Run each command that was seen on the setup script command line.
922d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Uses the list of commands found and cache of command objects
923fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        created by 'get_command_obj()'.
924fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        """
925fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.commands:
926fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.run_command(cmd)
927fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
928fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on its Commands --------------------------
929fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
930ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def run_command(self, command):
931fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Do whatever it takes to run a command (including nothing at all,
932d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if the command has already been run).  Specifically: if we have
933d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        already created and run the command named by 'command', return
934d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        silently without doing anything.  If the command named by 'command'
935d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        doesn't even have a command object yet, create one.  Then invoke
936d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'run()' on that command object (or an existing one).
937d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
938fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Already been here, done that? then return silently.
939fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if self.have_run.get(command):
940fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
941fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
942cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.info("running %s", command)
943fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj = self.get_command_obj(command)
944fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.ensure_finalized()
945fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.run()
946fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run[command] = 1
947fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
948fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
949fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Distribution query methods ------------------------------------
950fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
951ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_pure_modules(self):
952fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return len(self.packages or self.py_modules or []) > 0
953fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
954ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_ext_modules(self):
955fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.ext_modules and len(self.ext_modules) > 0
956fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
957ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_c_libraries(self):
958fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.libraries and len(self.libraries) > 0
959fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
960ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_modules(self):
961fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.has_pure_modules() or self.has_ext_modules()
962fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
963ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_headers(self):
96451def7d667a42eac177690e1fe00eab7f2102319Greg Ward        return self.headers and len(self.headers) > 0
96551def7d667a42eac177690e1fe00eab7f2102319Greg Ward
966ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_scripts(self):
96744a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.scripts and len(self.scripts) > 0
96844a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
969ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_data_files(self):
97044a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.data_files and len(self.data_files) > 0
97144a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
972ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def is_pure(self):
973fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return (self.has_pure_modules() and
974fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_ext_modules() and
975fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_c_libraries())
976fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
97782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
97882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
97982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # If you're looking for 'get_name()', 'get_version()', and so forth,
98082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # they are defined in a sneaky way: the constructor binds self.get_XXX
98182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # to self.metadata.get_XXX.  The actual code is in the
98282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # DistributionMetadata class, below.
98382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
98482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata:
98582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    """Dummy class to hold the distribution meta-data: name, version,
986fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    author, and so forth.
987fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    """
98882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
989a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer    _METHOD_BASENAMES = ("name", "version", "author", "author_email",
990a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "maintainer", "maintainer_email", "url",
991a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "license", "description", "long_description",
992a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "keywords", "platforms", "fullname", "contact",
993a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                         "contact_email", "license", "classifiers",
994db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         "download_url",
995db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         # PEP 314
996db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         "provides", "requires", "obsoletes",
997db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         )
998a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer
99982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def __init__ (self):
100082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.name = None
100182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.version = None
100282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author = None
100382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.author_email = None
100482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer = None
100582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer_email = None
100682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.url = None
1007fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        self.license = None
100882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.description = None
1009e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        self.long_description = None
1010a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.keywords = None
1011a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.platforms = None
1012282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        self.classifiers = None
1013188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        self.download_url = None
1014db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        # PEP 314
1015db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.provides = None
1016db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.requires = None
1017db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.obsoletes = None
1018b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1019ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def write_pkg_info(self, base_dir):
1020a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Write the PKG-INFO file into the release tree.
1021a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
1022a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
1023db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.write_pkg_file(pkg_info)
1024db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        pkg_info.close()
1025db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1026ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def write_pkg_file(self, file):
1027db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        """Write the PKG-INFO format data to a file object.
1028db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        """
1029db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        version = '1.0'
1030db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        if self.provides or self.requires or self.obsoletes:
1031db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            version = '1.1'
1032db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1033b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Metadata-Version', version)
1034b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Name', self.get_name())
1035b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Version', self.get_version())
1036b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Summary', self.get_description())
1037b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Home-page', self.get_url())
1038b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Author', self.get_contact())
1039b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Author-email', self.get_contact_email())
1040b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'License', self.get_license())
1041188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        if self.download_url:
1042b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, 'Download-URL', self.download_url)
1043a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1044c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        long_desc = rfc822_escape(self.get_long_description())
1045b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Description', long_desc)
1046a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1047c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        keywords = ','.join(self.get_keywords())
1048a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords:
1049b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, 'Keywords', keywords)
1050a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1051db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Platform', self.get_platforms())
1052db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Classifier', self.get_classifiers())
1053282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1054db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        # PEP 314
1055db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Requires', self.get_requires())
1056db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Provides', self.get_provides())
1057db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Obsoletes', self.get_obsoletes())
1058b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1059b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg    def _write_field(self, file, name, value):
1060b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        if isinstance(value, unicode):
1061b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            value = value.encode(PKG_INFO_ENCODING)
1062b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        else:
1063b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            value = str(value)
1064b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        file.write('%s: %s\n' % (name, value))
1065b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg
1066db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def _write_list (self, file, name, values):
1067db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for value in values:
1068b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, name, value)
1069b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
107082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
107182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1072ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_name(self):
1073fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.name or "UNKNOWN"
1074fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
107582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_version(self):
1076bcd8975740da47e7d1c8a5d2839ad4bf214fe34bThomas Heller        return self.version or "0.0.0"
107782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1078ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_fullname(self):
107982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return "%s-%s" % (self.get_name(), self.get_version())
108082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
108182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author(self):
108282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author or "UNKNOWN"
1083fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
108482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author_email(self):
108582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author_email or "UNKNOWN"
108682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
108782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer(self):
108882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer or "UNKNOWN"
108982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
109082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer_email(self):
109182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer_email or "UNKNOWN"
109282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
109382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact(self):
1094ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé        return self.maintainer or self.author or "UNKNOWN"
109582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
109682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact_email(self):
1097ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé        return self.maintainer_email or self.author_email or "UNKNOWN"
109882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
109982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_url(self):
110082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.url or "UNKNOWN"
110182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1102fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    def get_license(self):
1103fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        return self.license or "UNKNOWN"
1104fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    get_licence = get_license
1105b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
110682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_description(self):
110782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.description or "UNKNOWN"
1108e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1109e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward    def get_long_description(self):
1110e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        return self.long_description or "UNKNOWN"
1111e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1112a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_keywords(self):
1113a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.keywords or []
1114a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1115a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_platforms(self):
1116a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.platforms or ["UNKNOWN"]
1117a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1118282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling    def get_classifiers(self):
1119282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        return self.classifiers or []
1120282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1121188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling    def get_download_url(self):
1122188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        return self.download_url or "UNKNOWN"
1123188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling
1124db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    # PEP 314
1125db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_requires(self):
1126db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.requires or []
1127db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1128db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_requires(self, value):
1129db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        import distutils.versionpredicate
1130db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1131db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            distutils.versionpredicate.VersionPredicate(v)
1132db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.requires = value
1133db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1134db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_provides(self):
1135db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.provides or []
1136db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1137db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_provides(self, value):
1138db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        value = [v.strip() for v in value]
1139db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1140db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            import distutils.versionpredicate
1141227e8ffa20f7c2c3c1d1080da20c397bca51976dFred Drake            distutils.versionpredicate.split_provision(v)
1142db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.provides = value
1143db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1144db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_obsoletes(self):
1145db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.obsoletes or []
1146db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1147db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_obsoletes(self, value):
1148db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        import distutils.versionpredicate
1149db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1150db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            distutils.versionpredicate.VersionPredicate(v)
1151db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.obsoletes = value
1152db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1153ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadédef fix_help_options(options):
11542ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """Convert a 4-tuple 'help_options' list as found in various command
11552ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    classes to the 3-tuple form required by FancyGetopt.
11562ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """
11572ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    new_options = []
11582ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    for help_tuple in options:
11592ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        new_options.append(help_tuple[0:3])
11602ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    return new_options
1161