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
104b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadéfrom email import message_from_file
11ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
12ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchlingtry:
13ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    import warnings
14ccf4e421b829ce69eb62806fdd77eb71249713ddAndrew M. Kuchlingexcept ImportError:
15ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling    warnings = None
16ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling
172b66da7d15e47f9ca0d08d4f18fc63c3ee6a0d51Tarek Ziadéfrom distutils.errors import (DistutilsOptionError, DistutilsArgError,
182b66da7d15e47f9ca0d08d4f18fc63c3ee6a0d51Tarek Ziadé                              DistutilsModuleError, DistutilsClassError)
192f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Wardfrom distutils.fancy_getopt import FancyGetopt, translate_longopt
20a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchlingfrom distutils.util import check_environ, strtobool, rfc822_escape
21cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log
22fcd7353863c024bb87aabe7c4639ca8df692ac85Jeremy Hyltonfrom distutils.debug import DEBUG
23fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
24b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg# Encoding used for the PKG-INFO files
25b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André LemburgPKG_INFO_ENCODING = 'utf-8'
26b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg
27fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# Regex to define acceptable Distutils command names.  This is not *quite*
28fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# the same as a Python NAME -- I don't allow leading underscores.  The fact
29fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# that they're very similar is no coincidence; the default naming scheme is
30fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# to look for a Python module named after the command.
31fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardcommand_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
32fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
33fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
34fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardclass Distribution:
358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """The core of the Distutils.  Most of the work hiding behind 'setup'
368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    is really done within a Distribution instance, which farms the work out
378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to the Distutils commands specified on the command line.
388ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward
398ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Setup scripts will almost never instantiate Distribution directly,
408ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    unless the 'setup()' function is totally inadequate to their needs.
418ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    However, it is conceivable that a setup script might wish to subclass
428ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    Distribution for some specialized purpose, and then pass the subclass
438ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    to 'setup()' as the 'distclass' keyword argument.  If so, it is
448ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    necessary to respect the expectations that 'setup' has of Distribution.
458ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    See the code for 'setup()', in core.py, for details.
468ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward    """
47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
48fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
49fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # 'global_options' describes the command-line options that may be
5082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # supplied to the setup script prior to any actual commands.
5182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
52fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # these global options.  This list should be kept to a bare minimum,
53fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # since every global option is also valid as a command option -- and we
54fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # don't want to pollute the commands with too many options that they
55fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # have minimal control over.
56cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    # The fourth entry for verbose means that it can be repeated.
57cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    global_options = [('verbose', 'v', "run verbosely (default)", 1),
58d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('quiet', 'q', "run quietly (turns verbosity off)"),
59d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('dry-run', 'n', "don't actually do anything"),
60d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                      ('help', 'h', "show detailed help message"),
6140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                      ('no-user-cfg', None,
6240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                       'ignore pydistutils.cfg in your home directory'),
6340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé    ]
6482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
658ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    # 'common_usage' is a short (2-3 line) string describing the common
668ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    # usage of the setup script.
678ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis    common_usage = """\
688ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. LöwisCommon commands: (see '--help-commands' for more)
698ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis
708ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis  setup.py build      will build the package underneath 'build/'
718ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis  setup.py install    will install the package
728ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis"""
738ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis
7482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # options that are not propagated to the commands
7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    display_options = [
7682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('help-commands', None,
7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "list all available commands"),
7882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('name', None,
7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package name"),
8082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('version', 'V',
8182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print package version"),
8282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('fullname', None,
8382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print <package name>-<version>"),
8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author', None,
8582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's name"),
8682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('author-email', None,
8782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the author's email address"),
8882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer', None,
8982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's name"),
9082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('maintainer-email', None,
9182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the maintainer's email address"),
9282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact', None,
93d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's name if known, else the author's"),
9482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('contact-email', None,
95d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward         "print the maintainer's email address if known, else the author's"),
9682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('url', None,
9782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the URL for this package"),
9882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('license', None,
99fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "print the license of the package"),
100fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        ('licence', None,
101fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling         "alias for --license"),
10282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ('description', None,
10382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward         "print the package description"),
104e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward        ('long-description', None,
105e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward         "print the long package description"),
106a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('platforms', None,
107a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of platforms"),
108282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        ('classifiers', None,
109282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling         "print the list of classifiers"),
110a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        ('keywords', None,
111a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling         "print the list of keywords"),
112db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('provides', None,
113db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules provided"),
114db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('requires', None,
115db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules required"),
116db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        ('obsoletes', None,
117db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake         "print the list of packages/modules made obsolete")
11882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        ]
1192f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward    display_option_names = map(lambda x: translate_longopt(x[0]),
1202f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                               display_options)
12182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
12282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # negative options are options that exclude other options
123fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    negative_opt = {'quiet': 'verbose'}
124fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
125fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
126fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Creation/initialization methods -------------------------------
127b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
128fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    def __init__ (self, attrs=None):
129fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Construct a new Distribution instance: initialize all the
1308ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes of a Distribution, and then use 'attrs' (a dictionary
1318ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        mapping attribute names to values) to assign some of those
1328ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        attributes their "real" values.  (Any attributes not mentioned in
1338ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'attrs' will be assigned to some null value: 0, None, an empty list
1348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        or dictionary, etc.)  Most importantly, initialize the
1358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        'command_obj' attribute to the empty dictionary; this will be
1368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        filled in with real command objects by 'parse_command_line()'.
1378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward        """
138fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
139fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Default values for our command-line options
140fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.verbose = 1
141fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.dry_run = 0
142fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.help = 0
14382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for attr in self.display_option_names:
14482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            setattr(self, attr, 0)
14582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
14682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # Store the distribution meta-data (name, version, author, and so
14782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # forth) in a separate object -- we're getting to have enough
14882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # information here (and enough command-line options) that it's
14982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
15082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # object in a sneaky and underhanded (but efficient!) way.
151fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.metadata = DistributionMetadata()
152a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer        for basename in self.metadata._METHOD_BASENAMES:
1534982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            method_name = "get_" + basename
1544982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward            setattr(self, method_name, getattr(self.metadata, method_name))
155fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'cmdclass' maps command names to class objects, so we
157fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # can 1) quickly figure out which class to instantiate when
158fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # we need to create a new command object, and 2) have a way
15982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for the setup script to override command classes
160fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.cmdclass = {}
161fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
162d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # 'command_packages' is a list of packages in which commands
163d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # are searched for.  The factory for command 'foo' is expected
164d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # to be named 'foo' in the module 'foo' in one of the packages
165d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # named here.  This list is searched from the left; an error
166d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # is raised if no named package provides the command being
167d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        # searched for.  (Always access using get_command_packages().)
168d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        self.command_packages = None
169d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
1709821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # 'script_name' and 'script_args' are usually set to sys.argv[0]
1719821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # and sys.argv[1:], but they can be overridden when the caller is
1729821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        # not necessarily a setup script run from the command-line.
1739821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_name = None
1749821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        self.script_args = None
1759821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward
176d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 'command_options' is where we store command options between
177d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # parsing them (from config files, the command-line, etc.) and when
178d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # they are actually needed -- ie. when the command in question is
179d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
180d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        #   command_options = { command_name : { option : (source, value) } }
1811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        self.command_options = {}
1821426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
18398da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # 'dist_files' is the list of (command, pyversion, file) that
18498da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # have been created by any dist commands run so far. This is
18598da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # filled regardless of whether the run is dry or not. pyversion
18698da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # gives sysconfig.get_python_version() if the dist file is
18798da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # specific to a Python version, 'any' if it is good for all
18898da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # Python versions on the target platform, and '' for a source
18998da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # file. pyversion should not be used to specify minimum or
19098da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # maximum required Python versions; use the metainfo for that
19198da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis        # instead.
19255f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis        self.dist_files = []
19355f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis
194fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # These options are really the business of various commands, rather
195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # than of the Distribution itself.  We provide aliases for them in
196fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Distribution as a convenience to the developer.
197fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.packages = None
1980eb32a65b06613d25aeb18f0104554171bea4840Fred Drake        self.package_data = {}
199fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.package_dir = None
200fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.py_modules = None
201fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.libraries = None
20251def7d667a42eac177690e1fe00eab7f2102319Greg Ward        self.headers = None
203fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_modules = None
204fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.ext_package = None
205fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.include_dirs = None
206fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.extra_path = None
207b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith        self.scripts = None
2086a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith        self.data_files = None
2091a240fb9f038839f0e6f157ce4c7fcbcbf777ebcTarek Ziadé        self.password = ''
210fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
211fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # And now initialize bookkeeping stuff that can't be supplied by
212fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # the caller at all.  'command_obj' maps command names to
213fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Command instances -- that's how we enforce that every command
214fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # class is a singleton.
215fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.command_obj = {}
216fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
217fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # 'have_run' maps command names to boolean values; it keeps track
218fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # of whether we have actually run a particular command, to make it
219fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # cheap to "run" a command whenever we think we might need to -- if
220fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # it's already been done, no need for expensive filesystem
221fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # operations, we just check the 'have_run' dictionary and carry on.
222fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # It's only safe to query 'have_run' for a command class that has
223fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # been instantiated -- a false value will be inserted when the
224fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # command object is created, and replaced with a true value when
225612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        # the command is successfully run.  Thus it's probably best to use
226fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # '.get()' rather than a straight lookup.
227fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run = {}
228fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
229fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Now we'll use the attrs dictionary (ultimately, keyword args from
23082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # the setup script) to possibly override any or all of these
23182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # distribution options.
23282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
233fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if attrs:
234fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Pull out the set of command options and work on them
235fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # specifically.  Note that this order guarantees that aliased
236fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # command options will override any supplied redundantly
237fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # through the general options dictionary.
238fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            options = attrs.get('options')
239c13acb18bc2db9d8824ba94b86d8e4c8909d6b6cTarek Ziadé            if options is not None:
240fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                del attrs['options']
241fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                for (command, cmd_options) in options.items():
2420e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    opt_dict = self.get_option_dict(command)
2430e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                    for (opt, val) in cmd_options.items():
2440e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                        opt_dict[opt] = ("setup script", val)
245fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
2468bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum            if 'licence' in attrs:
247a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                attrs['license'] = attrs['licence']
248a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                del attrs['licence']
249a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                msg = "'licence' distribution option is deprecated; use 'license'"
250a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                if warnings is not None:
251a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    warnings.warn(msg)
252a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                else:
253a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                    sys.stderr.write(msg + "\n")
254a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling
255fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # Now work on the rest of the attributes.  Any attribute that's
256fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            # not already defined is invalid!
257c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            for (key, val) in attrs.items():
258db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                if hasattr(self.metadata, "set_" + key):
259db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                    getattr(self.metadata, "set_" + key)(val)
260db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                elif hasattr(self.metadata, key):
261fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self.metadata, key, val)
262fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                elif hasattr(self, key):
263fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                    setattr(self, key, val)
26473cc8479f000bbb84d0775aea55fb9de75ec110eAnthony Baxter                else:
265ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    msg = "Unknown distribution option: %s" % repr(key)
266ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    if warnings is not None:
267ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        warnings.warn(msg)
268ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                    else:
269ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling                        sys.stderr.write(msg + "\n")
270fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
27140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        # no-user-cfg is handled before other command line args
27240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        # because other args override the config files, and this
27340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        # one is needed before we can load the config files.
27440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        # If attrs['script_args'] wasn't passed, assume false.
27540b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        #
27640b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        # This also make sure we just look at the global options
27740b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        self.want_user_cfg = True
27840b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé
27940b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        if self.script_args is not None:
28040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé            for arg in self.script_args:
28140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                if not arg.startswith('-'):
28240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                    break
28340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                if arg == '--no-user-cfg':
28440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                    self.want_user_cfg = False
28540b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                    break
28640b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé
287a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        self.finalize_options()
288b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
289ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_option_dict(self, command):
2900e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """Get the option dictionary for a given command.  If that
2910e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        command's option dictionary hasn't been created yet, then create it
2920e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        and return the new dictionary; otherwise, return the existing
2930e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        option dictionary.
2940e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        """
2950e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        dict = self.command_options.get(command)
2960e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        if dict is None:
2970e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            dict = self.command_options[command] = {}
2980e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        return dict
2990e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward
300ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def dump_option_dicts(self, header=None, commands=None, indent=""):
301c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from pprint import pformat
302c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
303c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if commands is None:             # dump all command option dicts
304c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands = self.command_options.keys()
305c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            commands.sort()
306c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
307c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if header is not None:
308c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce(indent + header)
309c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            indent = indent + "  "
310c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
311c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not commands:
312c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce(indent + "no commands known yet")
313c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            return
314c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
315c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for cmd_name in commands:
316c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            opt_dict = self.command_options.get(cmd_name)
317c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            if opt_dict is None:
318c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce(indent +
319c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "no option dict for '%s' command" % cmd_name)
320c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            else:
321c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce(indent +
322c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "option dict for '%s' command:" % cmd_name)
323c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                out = pformat(opt_dict)
324c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                for line in out.split('\n'):
325c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                    self.announce(indent + "  " + line)
326c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
327d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Config file finding/parsing methods ---------------------------
328d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
329ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def find_config_files(self):
3301426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        """Find as many configuration files as should be processed for this
3311426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        platform, and return a list of filenames in the order in which they
3321426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        should be parsed.  The filenames returned are guaranteed to exist
3331426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        (modulo nasty race conditions).
3341426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
335d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        There are three possible config files: distutils.cfg in the
336d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils installation directory (ie. where the top-level
337d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        Distutils __inst__.py file lives), a file in the user's home
338d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling        directory named .pydistutils.cfg on Unix and pydistutils.cfg
33940b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        on Windows/Mac; and setup.cfg in the current directory.
34040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé
34140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        The file in the user's home directory can be disabled with the
34240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        --no-user-cfg option.
343d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
3441426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        files = []
345acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward        check_environ()
346acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward
3471169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Where to look for the system-wide Distutils config file
3481169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
3491169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
3501169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # Look for the system config file
3511169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        sys_file = os.path.join(sys_dir, "distutils.cfg")
3521169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.path.isfile(sys_file):
3531169687692e5e897033421fe6a73a3c32675a7d7Greg Ward            files.append(sys_file)
3541169687692e5e897033421fe6a73a3c32675a7d7Greg Ward
3551169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # What to call the per-user config file
3561169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        if os.name == 'posix':
35765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = ".pydistutils.cfg"
35865d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        else:
35965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            user_filename = "pydistutils.cfg"
360fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward
3611169687692e5e897033421fe6a73a3c32675a7d7Greg Ward        # And look for the user config file
36240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        if self.want_user_cfg:
36340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé            user_file = os.path.join(os.path.expanduser('~'), user_filename)
36440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé            if os.path.isfile(user_file):
36540b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé                files.append(user_file)
3661426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3671426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        # All platforms support local setup.cfg
3681426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        local_file = "setup.cfg"
3691426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if os.path.isfile(local_file):
3701426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            files.append(local_file)
3711426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
37240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé        if DEBUG:
37340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé            self.announce("using config files: %s" % ', '.join(files))
37440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé
3751426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        return files
3761426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
377ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def parse_config_files(self, filenames=None):
378392c6fc02d90f211dadc72448a07d9281260cb70Georg Brandl        from ConfigParser import ConfigParser
3791426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
3801426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        if filenames is None:
3811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith            filenames = self.find_config_files()
3821426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
383c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if DEBUG:
384c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce("Distribution.parse_config_files():")
385474607777d10562679b1640d3831290b0c4284f7Greg Ward
3861426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        parser = ConfigParser()
387d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for filename in filenames:
388c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if DEBUG:
38999773359843803c54574b6ee6fc1516e7fcde10fTarek Ziadé                self.announce("  reading %s" % filename)
390d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            parser.read(filename)
391d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            for section in parser.sections():
392d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                options = parser.options(section)
3930e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward                opt_dict = self.get_option_dict(section)
394d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
395d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                for opt in options:
396d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                    if opt != '__name__':
397ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        val = parser.get(section,opt)
398c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                        opt = opt.replace('-', '_')
399ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        opt_dict[opt] = (filename, val)
4001426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
401474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Make the ConfigParser forget everything (so we retain
402f06116dcab8f6066f78c522c056ffb9c2403706cFred Drake            # the original filenames that options come from)
403474607777d10562679b1640d3831290b0c4284f7Greg Ward            parser.__init__()
4041426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
405ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # If there was a "global" section in the config file, use it
406ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        # to set Distribution options.
407ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
4088bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum        if 'global' in self.command_options:
409ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            for (opt, (src, val)) in self.command_options['global'].items():
410ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                alias = self.negative_opt.get(opt)
411ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                try:
412ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    if alias:
413ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, alias, not strtobool(val))
414ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    elif opt in ('verbose', 'dry_run'): # ugh!
415ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                        setattr(self, opt, strtobool(val))
416d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                    else:
417d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                        setattr(self, opt, val)
418ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                except ValueError, msg:
419ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, msg
420ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
421d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward    # -- Command-line parsing methods ----------------------------------
422fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
423ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def parse_command_line(self):
4249821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        """Parse the setup script's command line, taken from the
4259821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
4269821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        -- see 'setup()' in core.py).  This list is first processed for
4279821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        "global options" -- options that set attributes of the Distribution
4289821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        instance.  Then, it is alternately scanned for Distutils commands
4299821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        and options for that command.  Each new command terminates the
4309821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        options for the previous command.  The allowed options for a
4319821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command are determined by the 'user_options' attribute of the
4329821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command class -- thus, we have to be able to load command classes
4339821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        in order to parse the command line.  Any error in that 'options'
4349821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        attribute raises DistutilsGetoptError; any error on the
4359821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        command-line raises DistutilsArgError.  If no Distutils commands
4369821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        were found on the command line, raises DistutilsArgError.  Return
437ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        true if command-line was successfully parsed and we should carry
4389821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        on with executing commands; false if no errors but we shouldn't
4399821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        execute commands (currently, this only happens if user asks for
4409821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        help).
441d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
4423f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
443981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # We now have enough information to show the Macintosh dialog
444981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake        # that allows the user to interactively specify the "command line".
4453f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling        #
446d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        toplevel_options = self._get_toplevel_options()
447b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
448fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # We have to parse the command line a bit at a time -- global
449fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # options, then the first command, then its options, and so on --
450fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # because each command will be handled by a different class, and
451d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # the options that are valid for a particular class aren't known
452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we have loaded the command class, which doesn't happen
453d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # until we know what the command is.
454fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
455fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.commands = []
456d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        parser = FancyGetopt(toplevel_options + self.display_options)
457fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(self.negative_opt)
458fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        parser.set_aliases({'licence': 'license'})
459fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        args = parser.getopt(args=self.script_args, object=self)
46082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        option_order = parser.get_option_order()
461cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.set_verbosity(self.verbose)
462fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
46382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # for display options we return immediately
46482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.handle_display_options(option_order):
465fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
466fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        while args:
467d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            args = self._parse_command_opts(parser, args)
468d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            if args is None:            # user asked for help (and got it)
469fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                return
470fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
471d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Handle the cases of --help as a "global" option, ie.
472d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # "setup.py --help" and "setup.py --help command ...".  For the
473d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # former, we show global options (--verbose, --dry-run, etc.)
474d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # and display-only options (--name, --version, etc.); for the
475d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # latter, we omit the display-only options and show help for
476d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # each command listed on the command line.
477d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if self.help:
478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser,
479d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            display_options=len(self.commands) == 0,
480d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                            commands=self.commands)
481fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
482fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
483fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Oops, no commands found -- an end-user error
484fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not self.commands:
485fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            raise DistutilsArgError, "no commands supplied"
486fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
487fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # All is well: return true
488fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return 1
489fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
490ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _get_toplevel_options(self):
491d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """Return the non-display options recognized at the top level.
492d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
493d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        This includes options that are recognized *only* at the top
494d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        level as well as options recognized for commands.
495d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """
496d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        return self.global_options + [
497d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            ("command-packages=", None,
498d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake             "list of packages that provide distutils commands"),
499d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            ]
500d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
501ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _parse_command_opts(self, parser, args):
502d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Parse the command-line options for a single command.
503d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'parser' must be a FancyGetopt instance; 'args' must be the list
504d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        of arguments, starting with the current command (whose options
505d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        we are about to parse).  Returns a new version of 'args' with
506d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the next command at the front of the list; will be the empty
507d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        list if there are no more commands on the command line.  Returns
508d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        None if the user asked for help on this command.
509d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
510d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
511d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
512d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
513d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Pull the current command from the head of the command line
514d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command = args[0]
515fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not command_re.match(command):
516d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise SystemExit, "invalid command name '%s'" % command
517fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.commands.append(command)
518d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
519d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Dig up the command class that implements this command, so we
520d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # 1) know that it's a valid command, and 2) know which options
521d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # it takes.
522d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        try:
523fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            cmd_class = self.get_command_class(command)
524d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        except DistutilsModuleError, msg:
525d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsArgError, msg
526d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
527d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Require that the command class be derived from Command -- want
528d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # to be sure that the basic "command" interface is implemented.
529fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not issubclass(cmd_class, Command):
530d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
531d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  "command class %s must subclass Command" % cmd_class
532d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
533d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Also make sure that the command object provides a list of its
534d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # known options.
535fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if not (hasattr(cmd_class, 'user_options') and
536c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                isinstance(cmd_class.user_options, list)):
537d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            raise DistutilsClassError, \
538d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  ("command class %s must provide " +
539d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                   "'user_options' attribute (a list of tuples)") % \
540d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                  cmd_class
541d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
542d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # If the command class has a list of negative alias options,
543d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # merge it in with the global negative aliases.
544d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        negative_opt = self.negative_opt
545fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if hasattr(cmd_class, 'negative_opt'):
546f541378d13e7750b67758b721e862fd3b27e9e6bAntoine Pitrou            negative_opt = negative_opt.copy()
547fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            negative_opt.update(cmd_class.negative_opt)
548d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
549fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # Check for help_options in command class.  They have a different
550fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward        # format (tuple of four) so we need to preprocess them here.
55165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
552c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            isinstance(cmd_class.help_options, list)):
5532ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward            help_options = fix_help_options(cmd_class.help_options)
5542ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        else:
55555fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward            help_options = []
5562ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward
5579d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
558d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # All commands support the global options too, just by adding
559d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # in 'global_options'.
560fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_option_table(self.global_options +
561fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                cmd_class.user_options +
562fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                help_options)
563fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        parser.set_negative_aliases(negative_opt)
564fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        (args, opts) = parser.getopt(args[1:])
565474607777d10562679b1640d3831290b0c4284f7Greg Ward        if hasattr(opts, 'help') and opts.help:
566d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            self._show_help(parser, display_options=0, commands=[cmd_class])
567d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return
568d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
56965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton        if (hasattr(cmd_class, 'help_options') and
570c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            isinstance(cmd_class.help_options, list)):
57165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            help_option_found=0
57265d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            for (help_option, short, desc, func) in cmd_class.help_options:
57365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                if hasattr(opts, parser.get_attr_name(help_option)):
57465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                    help_option_found=1
575de0559998fef231efc9ecbdef5b3a195d4eaa28dBenjamin Peterson                    if hasattr(func, '__call__'):
57665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                        func()
57755fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward                    else:
578981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                        raise DistutilsClassError(
57970a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            "invalid help function %r for help option '%s': "
580981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake                            "must be a callable object (function, etc.)"
58170a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                            % (func, help_option))
58255fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward
583b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake            if help_option_found:
58465d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton                return
5859d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward
586d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # Put the options from the command-line into their official
587d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # holding pen, the 'command_options' dictionary.
5880e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward        opt_dict = self.get_option_dict(command)
589d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for (name, value) in vars(opts).items():
5900e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward            opt_dict[name] = ("command line", value)
591d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
592d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return args
593d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
594ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def finalize_options(self):
595a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Set final values for all the options on the Distribution
596a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        instance, analogous to the .finalize_options() method of Command
597a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        objects.
598a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
599c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        for attr in ('keywords', 'platforms'):
600c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            value = getattr(self.metadata, attr)
601c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if value is None:
602c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                continue
603c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if isinstance(value, str):
604c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                value = [elm.strip() for elm in value.split(',')]
605c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                setattr(self.metadata, attr, value)
606a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
607ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _show_help(self, parser, global_options=1, display_options=1,
608ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé                   commands=[]):
609d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Show help for the setup script command-line in the form of
610d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        several lists of command-line options.  'parser' should be a
611d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        FancyGetopt instance; do not expect it to be returned in the
612d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        same state, as its option table will be reset to make it
613d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        generate the correct help text.
614d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
615d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        If 'global_options' is true, lists the global options:
616d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        --verbose, --dry-run, etc.  If 'display_options' is true, lists
617d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the "display-only" options: --name, --version, etc.  Finally,
618d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        lists per-command help for every command name or command class
619d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        in 'commands'.
620d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
621d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        # late import because of mutual dependence between these modules
6229821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
623d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        from distutils.cmd import Command
624d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
625d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if global_options:
626d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            if display_options:
627d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                options = self._get_toplevel_options()
628d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            else:
629d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                options = self.global_options
630d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            parser.set_option_table(options)
6318ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis            parser.print_help(self.common_usage + "\nGlobal options:")
632cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
633d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
634d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if display_options:
635fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.set_option_table(self.display_options)
636fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help(
637d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "Information display options (just display " +
638d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                "information, ignore any commands)")
639cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
640d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
641d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        for command in self.commands:
642c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if isinstance(command, type) and issubclass(command, Command):
643d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward                klass = command
644d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            else:
645fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(command)
64665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            if (hasattr(klass, 'help_options') and
647c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                isinstance(klass.help_options, list)):
648fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options +
649fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                        fix_help_options(klass.help_options))
65065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton            else:
651fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                parser.set_option_table(klass.user_options)
652fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            parser.print_help("Options for '%s' command:" % klass.__name__)
653cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
654d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
655cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé        print(gen_usage(self.script_name))
656d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward
657ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def handle_display_options(self, option_order):
65882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """If there were any non-global "display-only" options
659d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (--help-commands or the metadata display options) on the command
660d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        line, display the requested info and return true; else return
661d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        false.
662d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
6639821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward        from distutils.core import gen_usage
66482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
66582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # User just wants a list of commands -- we'll print it out and stop
66682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # processing now (ie. if they ran "setup --help-commands foo bar",
66782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # we ignore "foo bar").
66882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        if self.help_commands:
669fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_commands()
670cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print('')
671cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print(gen_usage(self.script_name))
67282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            return 1
67382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
67482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # If user supplied any of the "display metadata" options, then
67582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # display that metadata in the order in which the user supplied the
67682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        # metadata options.
67782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        any_display_options = 0
67882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        is_display_option = {}
67982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for option in self.display_options:
68082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            is_display_option[option[0]] = 1
68182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
68282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        for (opt, val) in option_order:
68382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward            if val and is_display_option.get(opt):
6842f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                opt = translate_longopt(opt)
685a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                value = getattr(self.metadata, "get_"+opt)()
686a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                if opt in ['keywords', 'platforms']:
687cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print(','.join(value))
688db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                elif opt in ('classifiers', 'provides', 'requires',
689db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                             'obsoletes'):
690cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print('\n'.join(value))
691a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling                else:
692cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé                    print(value)
69382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward                any_display_options = 1
69482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
69582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return any_display_options
69682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
697ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def print_command_list(self, commands, header, max_length):
698fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Print a subset of the list of all commands -- used by
699d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'print_commands()'.
700d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
701cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé        print(header + ":")
702fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
703fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in commands:
704fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            klass = self.cmdclass.get(cmd)
705fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not klass:
706fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                klass = self.get_command_class(cmd)
707fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            try:
708fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = klass.description
709fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            except AttributeError:
710fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                description = "(no description available)"
711fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
712cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé            print("  %-*s  %s" % (max_length, cmd, description))
713fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
714ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def print_commands(self):
715d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Print out a help message listing all available commands with a
716d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        description of each.  The list is divided into "standard commands"
717d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (listed in distutils.command.__all__) and "extra commands"
718d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        (mentioned in self.cmdclass, but not a standard command).  The
719d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        descriptions come from the command class attribute
720d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'description'.
721d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
722fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        import distutils.command
723fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        std_commands = distutils.command.__all__
724fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        is_std = {}
725fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in std_commands:
726fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            is_std[cmd] = 1
727fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
728fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        extra_commands = []
729fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.cmdclass.keys():
730fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            if not is_std.get(cmd):
731fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                extra_commands.append(cmd)
732fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
733fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        max_length = 0
734fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in (std_commands + extra_commands):
735fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            if len(cmd) > max_length:
736fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                max_length = len(cmd)
737fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
738fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        self.print_command_list(std_commands,
739fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                "Standard commands",
740fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                max_length)
741fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if extra_commands:
742fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            print
743fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.print_command_list(extra_commands,
744fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    "Extra commands",
745fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward                                    max_length)
746fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
747ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_list(self):
748f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """Get a list of (command, description) tuples.
749f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        The list is divided into "standard commands" (listed in
750f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        distutils.command.__all__) and "extra commands" (mentioned in
751f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        self.cmdclass, but not a standard command).  The descriptions come
752f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        from the command class attribute 'description'.
753f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        """
754f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Currently this is only used on Mac OS, for the Mac-only GUI
755f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        # Distutils interface (by Jack Jansen)
756f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
757f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        import distutils.command
758f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        std_commands = distutils.command.__all__
759f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        is_std = {}
760f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in std_commands:
761f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            is_std[cmd] = 1
762f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
763f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        extra_commands = []
764f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in self.cmdclass.keys():
765f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not is_std.get(cmd):
766f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                extra_commands.append(cmd)
767f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward
768f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        rv = []
769f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        for cmd in (std_commands + extra_commands):
770f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            klass = self.cmdclass.get(cmd)
771f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            if not klass:
772f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                klass = self.get_command_class(cmd)
773f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            try:
774f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = klass.description
775f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            except AttributeError:
776f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward                description = "(no description available)"
777f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward            rv.append((cmd, description))
778f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward        return rv
779fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
780fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Command class/object methods ----------------------------------
781fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
782ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_packages(self):
783d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        """Return a list of packages from which commands are loaded."""
784d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        pkgs = self.command_packages
785c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if not isinstance(pkgs, list):
786c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if pkgs is None:
787c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                pkgs = ''
788c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
789d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            if "distutils.command" not in pkgs:
790d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                pkgs.insert(0, "distutils.command")
791d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            self.command_packages = pkgs
792d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        return pkgs
793d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
794ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_class(self, command):
795d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the class that implements the Distutils command named by
796d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'command'.  First we check the 'cmdclass' dictionary; if the
797d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        command is mentioned there, we fetch the class object from the
798d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        dictionary and return it.  Otherwise we load the command module
799d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        ("distutils.command." + command) and fetch the command class from
800d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        the module.  The loaded class is also stored in 'cmdclass'
801d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        to speed future calls to 'get_command_class()'.
8021426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith
8031426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith        Raises DistutilsModuleError if the expected module could not be
804d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        found, or if that module does not define the expected class.
805d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
806d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        klass = self.cmdclass.get(command)
807d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if klass:
808d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            return klass
809fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
810d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        for pkgname in self.get_command_packages():
811d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            module_name = "%s.%s" % (pkgname, command)
812d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            klass_name = command
813fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
814d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            try:
815d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                __import__ (module_name)
816d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                module = sys.modules[module_name]
817d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            except ImportError:
818d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                continue
819d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
820d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            try:
821d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                klass = getattr(module, klass_name)
822d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            except AttributeError:
823d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                raise DistutilsModuleError, \
824d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                      "invalid command '%s' (no class '%s' in module '%s')" \
825d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake                      % (command, klass_name, module_name)
826d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
827d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            self.cmdclass[command] = klass
828d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake            return klass
829d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake
830d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake        raise DistutilsModuleError("invalid command '%s'" % command)
831fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
832fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
833ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_command_obj(self, command, create=1):
834d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """Return the command object for 'command'.  Normally this object
835612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward        is cached on a previous call to 'get_command_obj()'; if no command
836d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        object for 'command' is in the cache, then we either create and
837d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        return it (if 'create' is true) or return None.
838d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
839d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        cmd_obj = self.command_obj.get(command)
840fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        if not cmd_obj and create:
8412bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward            if DEBUG:
842c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce("Distribution.get_command_obj(): " \
843c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                              "creating '%s' command object" % command)
844474607777d10562679b1640d3831290b0c4284f7Greg Ward
845d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward            klass = self.get_command_class(command)
846474607777d10562679b1640d3831290b0c4284f7Greg Ward            cmd_obj = self.command_obj[command] = klass(self)
847474607777d10562679b1640d3831290b0c4284f7Greg Ward            self.have_run[command] = 0
848474607777d10562679b1640d3831290b0c4284f7Greg Ward
849474607777d10562679b1640d3831290b0c4284f7Greg Ward            # Set any options that were supplied in config files
850474607777d10562679b1640d3831290b0c4284f7Greg Ward            # or on the command line.  (NB. support for error
851474607777d10562679b1640d3831290b0c4284f7Greg Ward            # reporting is lame here: any errors aren't reported
852474607777d10562679b1640d3831290b0c4284f7Greg Ward            # until 'finalize_options()' is called, which means
853474607777d10562679b1640d3831290b0c4284f7Greg Ward            # we won't report the source of the error.)
854474607777d10562679b1640d3831290b0c4284f7Greg Ward            options = self.command_options.get(command)
855474607777d10562679b1640d3831290b0c4284f7Greg Ward            if options:
856c32d9a69527af6d2823650ea7674e207c975f090Greg Ward                self._set_command_options(cmd_obj, options)
857fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
858fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return cmd_obj
859fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
860ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def _set_command_options(self, command_obj, option_dict=None):
861c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Set the options for 'command_obj' from 'option_dict'.  Basically
862c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        this means copying elements of a dictionary ('option_dict') to
863c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        attributes of an instance ('command').
864c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
865ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward        'command_obj' must be a Command instance.  If 'option_dict' is not
866c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        supplied, uses the standard option dictionary for this command
867c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        (from 'self.command_options').
868c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
869c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command_name = command_obj.get_command_name()
870c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if option_dict is None:
871c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            option_dict = self.get_option_dict(command_name)
872c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
873c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        if DEBUG:
874c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            self.announce("  setting options for '%s' command:" % command_name)
875c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        for (option, (source, value)) in option_dict.items():
876c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé            if DEBUG:
877c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                self.announce("    %s = %s (from %s)" % (option, value,
878c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                                                         source))
879ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
8802f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward                bool_opts = map(translate_longopt, command_obj.boolean_options)
881ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
882ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                bool_opts = []
883ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
884ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = command_obj.negative_opt
885ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except AttributeError:
886ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                neg_opt = {}
887ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward
888ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            try:
889c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé                is_string = isinstance(value, str)
8908bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum                if option in neg_opt and is_string:
891ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, neg_opt[option], not strtobool(value))
8922c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward                elif option in bool_opts and is_string:
893ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, strtobool(value))
894ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                elif hasattr(command_obj, option):
895ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    setattr(command_obj, option, value)
896ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                else:
897ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                    raise DistutilsOptionError, \
898ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                          ("error in %s: command '%s' has no such option '%s'"
899ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                           % (source, command_name, option))
900ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward            except ValueError, msg:
901ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward                raise DistutilsOptionError, msg
902c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
903ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def reinitialize_command(self, command, reinit_subcommands=0):
904c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """Reinitializes a command to the state it was in when first
905c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        returned by 'get_command_obj()': ie., initialized but not yet
9067d9c705b234ad2ad013db1649e5fd2ffc2a59a75Greg Ward        finalized.  This provides the opportunity to sneak option
907c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        values in programmatically, overriding or supplementing
908c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        user-supplied values from the config files and command line.
909c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        You'll have to re-finalize the command object (by calling
910c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        'finalize_options()' or 'ensure_finalized()') before using it for
911b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake        real.
912c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
913f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'command' should be a command name (string) or command object.  If
914f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        'reinit_subcommands' is true, also reinitializes the command's
915f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        sub-commands, as declared by the 'sub_commands' class attribute (if
916f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        it has one).  See the "install" command for an example.  Only
917f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        reinitializes the sub-commands that actually matter, ie. those
918f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        whose test predicates return true.
919f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
920c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        Returns the reinitialized command object.
921c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        """
922c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        from distutils.cmd import Command
923c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not isinstance(command, Command):
924c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command
925c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command = self.get_command_obj(command_name)
926c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        else:
927c32d9a69527af6d2823650ea7674e207c975f090Greg Ward            command_name = command.get_command_name()
928c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
929c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        if not command.finalized:
930282c7a0230b578147a89a18ec22410b830edddfeGreg Ward            return command
931c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.initialize_options()
932c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        command.finalized = 0
93343955c9a023ea7b50b28052112dbdc914c090a27Greg Ward        self.have_run[command_name] = 0
934c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        self._set_command_options(command)
935f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
936f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward        if reinit_subcommands:
937f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward            for sub in command.get_sub_commands():
938b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake                self.reinitialize_command(sub, reinit_subcommands)
939f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward
940c32d9a69527af6d2823650ea7674e207c975f090Greg Ward        return command
941c32d9a69527af6d2823650ea7674e207c975f090Greg Ward
942fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on the Distribution ----------------------
943fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
94463f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé    def announce(self, msg, level=log.INFO):
94563f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé        log.log(level, msg)
946fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
947ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def run_commands(self):
94882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        """Run each command that was seen on the setup script command line.
949d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        Uses the list of commands found and cache of command objects
950fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        created by 'get_command_obj()'.
951fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        """
952fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        for cmd in self.commands:
953fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward            self.run_command(cmd)
954fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
955fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Methods that operate on its Commands --------------------------
956fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
957ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def run_command(self, command):
958fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        """Do whatever it takes to run a command (including nothing at all,
959d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        if the command has already been run).  Specifically: if we have
960d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        already created and run the command named by 'command', return
961d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        silently without doing anything.  If the command named by 'command'
962d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        doesn't even have a command object yet, create one.  Then invoke
963d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        'run()' on that command object (or an existing one).
964d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward        """
965fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        # Already been here, done that? then return silently.
966fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        if self.have_run.get(command):
967fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward            return
968fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
969cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.info("running %s", command)
970fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj = self.get_command_obj(command)
971fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.ensure_finalized()
972fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        cmd_obj.run()
973fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        self.have_run[command] = 1
974fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
975fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
976fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward    # -- Distribution query methods ------------------------------------
977fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
978ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_pure_modules(self):
979fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return len(self.packages or self.py_modules or []) > 0
980fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
981ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_ext_modules(self):
982fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.ext_modules and len(self.ext_modules) > 0
983fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
984ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_c_libraries(self):
985fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward        return self.libraries and len(self.libraries) > 0
986fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
987ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_modules(self):
988fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.has_pure_modules() or self.has_ext_modules()
989fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
990ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_headers(self):
99151def7d667a42eac177690e1fe00eab7f2102319Greg Ward        return self.headers and len(self.headers) > 0
99251def7d667a42eac177690e1fe00eab7f2102319Greg Ward
993ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_scripts(self):
99444a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.scripts and len(self.scripts) > 0
99544a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
996ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def has_data_files(self):
99744a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward        return self.data_files and len(self.data_files) > 0
99844a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward
999ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def is_pure(self):
1000fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return (self.has_pure_modules() and
1001fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_ext_modules() and
1002fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward                not self.has_c_libraries())
1003fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
100482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
100582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
100682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # If you're looking for 'get_name()', 'get_version()', and so forth,
100782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # they are defined in a sneaky way: the constructor binds self.get_XXX
100882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # to self.metadata.get_XXX.  The actual code is in the
100982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # DistributionMetadata class, below.
101082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
101182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata:
101282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    """Dummy class to hold the distribution meta-data: name, version,
1013fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    author, and so forth.
1014fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward    """
101582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1016a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer    _METHOD_BASENAMES = ("name", "version", "author", "author_email",
1017a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "maintainer", "maintainer_email", "url",
1018a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "license", "description", "long_description",
1019a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer                         "keywords", "platforms", "fullname", "contact",
1020a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling                         "contact_email", "license", "classifiers",
1021db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         "download_url",
1022db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         # PEP 314
1023db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         "provides", "requires", "obsoletes",
1024db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake                         )
1025a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer
1026a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé    def __init__(self, path=None):
1027a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        if path is not None:
1028a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.read_pkg_file(open(path))
1029a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        else:
1030a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.name = None
1031a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.version = None
1032a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.author = None
1033a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.author_email = None
1034a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.maintainer = None
1035a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.maintainer_email = None
1036a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.url = None
1037a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.license = None
1038a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.description = None
1039a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.long_description = None
1040a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.keywords = None
1041a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.platforms = None
1042a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.classifiers = None
1043a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.download_url = None
1044a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            # PEP 314
1045a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.provides = None
1046a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.requires = None
1047a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.obsoletes = None
1048a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
1049a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé    def read_pkg_file(self, file):
1050a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        """Reads the metadata values from a file object."""
10514b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        msg = message_from_file(file)
10524b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé
10534b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        def _read_field(name):
10544b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            value = msg[name]
10554b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            if value == 'UNKNOWN':
10564b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé                return None
10574b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            return value
10584b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé
10594b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        def _read_list(name):
10604b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            values = msg.get_all(name, None)
10614b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            if values == []:
10624b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé                return None
10634b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            return values
10644b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé
1065a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        metadata_version = msg['metadata-version']
10664b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.name = _read_field('name')
10674b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.version = _read_field('version')
10684b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.description = _read_field('summary')
1069a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        # we are filling author only.
10704b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.author = _read_field('author')
107182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer = None
10724b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.author_email = _read_field('author-email')
107382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        self.maintainer_email = None
10744b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.url = _read_field('home-page')
10754b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.license = _read_field('license')
1076a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
1077a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        if 'download-url' in msg:
10784b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            self.download_url = _read_field('download-url')
1079a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        else:
1080a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.download_url = None
1081a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
10824b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.long_description = _read_field('description')
10834b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.description = _read_field('summary')
1084a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
1085a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        if 'keywords' in msg:
10864b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            self.keywords = _read_field('keywords').split(',')
1087a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
10884b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.platforms = _read_list('platform')
10894b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé        self.classifiers = _read_list('classifier')
1090a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé
1091a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        # PEP 314 - these fields only exist in 1.1
1092a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        if metadata_version == '1.1':
10934b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            self.requires = _read_list('requires')
10944b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            self.provides = _read_list('provides')
10954b7f9439c0a61ce597675f27adca2465a9c1e76bTarek Ziadé            self.obsoletes = _read_list('obsoletes')
1096a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé        else:
1097a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.requires = None
1098a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.provides = None
1099a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé            self.obsoletes = None
1100b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1101ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def write_pkg_info(self, base_dir):
1102a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """Write the PKG-INFO file into the release tree.
1103a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        """
1104d1feff70a3c08f91066b99a74ee1ca8f65bdfec1Éric Araujo        pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w')
1105d1feff70a3c08f91066b99a74ee1ca8f65bdfec1Éric Araujo        try:
1106d1feff70a3c08f91066b99a74ee1ca8f65bdfec1Éric Araujo            self.write_pkg_file(pkg_info)
1107d1feff70a3c08f91066b99a74ee1ca8f65bdfec1Éric Araujo        finally:
1108d1feff70a3c08f91066b99a74ee1ca8f65bdfec1Éric Araujo            pkg_info.close()
1109db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1110ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def write_pkg_file(self, file):
1111db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        """Write the PKG-INFO format data to a file object.
1112db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        """
1113db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        version = '1.0'
1114a13cd39533038b1d841acac5a0f37e55b2fdff53Éric Araujo        if (self.provides or self.requires or self.obsoletes or
1115a13cd39533038b1d841acac5a0f37e55b2fdff53Éric Araujo            self.classifiers or self.download_url):
1116db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            version = '1.1'
1117db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1118b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Metadata-Version', version)
1119b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Name', self.get_name())
1120b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Version', self.get_version())
1121b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Summary', self.get_description())
1122b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Home-page', self.get_url())
1123b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Author', self.get_contact())
1124b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Author-email', self.get_contact_email())
1125b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'License', self.get_license())
1126188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        if self.download_url:
1127b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, 'Download-URL', self.download_url)
1128a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1129c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        long_desc = rfc822_escape(self.get_long_description())
1130b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg        self._write_field(file, 'Description', long_desc)
1131a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1132c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé        keywords = ','.join(self.get_keywords())
1133a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        if keywords:
1134b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, 'Keywords', keywords)
1135a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1136db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Platform', self.get_platforms())
1137db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Classifier', self.get_classifiers())
1138282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1139db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        # PEP 314
1140db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Requires', self.get_requires())
1141db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Provides', self.get_provides())
1142db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self._write_list(file, 'Obsoletes', self.get_obsoletes())
1143b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1144b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg    def _write_field(self, file, name, value):
1145f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        file.write('%s: %s\n' % (name, self._encode_field(value)))
1146b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg
1147db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def _write_list (self, file, name, values):
1148db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for value in values:
1149b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg            self._write_field(file, name, value)
1150b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
1151f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé    def _encode_field(self, value):
1152f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        if value is None:
1153f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé            return None
1154f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        if isinstance(value, unicode):
1155f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé            return value.encode(PKG_INFO_ENCODING)
1156f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return str(value)
1157f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé
115882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    # -- Metadata query methods ----------------------------------------
115982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1160ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_name(self):
1161fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward        return self.name or "UNKNOWN"
1162fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
116382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_version(self):
1164bcd8975740da47e7d1c8a5d2839ad4bf214fe34bThomas Heller        return self.version or "0.0.0"
116582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1166ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé    def get_fullname(self):
116782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return "%s-%s" % (self.get_name(), self.get_version())
116882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
116982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author(self):
1170f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return self._encode_field(self.author) or "UNKNOWN"
1171fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward
117282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_author_email(self):
117382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.author_email or "UNKNOWN"
117482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
117582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer(self):
1176f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return self._encode_field(self.maintainer) or "UNKNOWN"
117782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
117882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_maintainer_email(self):
117982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.maintainer_email or "UNKNOWN"
118082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
118182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact(self):
1182f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return (self._encode_field(self.maintainer) or
1183f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé                self._encode_field(self.author) or "UNKNOWN")
118482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
118582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_contact_email(self):
1186ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé        return self.maintainer_email or self.author_email or "UNKNOWN"
118782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
118882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_url(self):
118982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward        return self.url or "UNKNOWN"
119082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward
1191fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    def get_license(self):
1192fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling        return self.license or "UNKNOWN"
1193fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling    get_licence = get_license
1194b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
119582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward    def get_description(self):
1196f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return self._encode_field(self.description) or "UNKNOWN"
1197e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1198e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward    def get_long_description(self):
1199f14c7fc33da8ba3aa28bbb7b0305ea12ab30be09Tarek Ziadé        return self._encode_field(self.long_description) or "UNKNOWN"
1200e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward
1201a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_keywords(self):
1202a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.keywords or []
1203a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1204a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling    def get_platforms(self):
1205a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling        return self.platforms or ["UNKNOWN"]
1206a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling
1207282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling    def get_classifiers(self):
1208282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling        return self.classifiers or []
1209282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling
1210188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling    def get_download_url(self):
1211188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling        return self.download_url or "UNKNOWN"
1212188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling
1213db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    # PEP 314
1214db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_requires(self):
1215db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.requires or []
1216db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1217db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_requires(self, value):
1218db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        import distutils.versionpredicate
1219db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1220db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            distutils.versionpredicate.VersionPredicate(v)
1221db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.requires = value
1222db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1223db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_provides(self):
1224db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.provides or []
1225db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1226db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_provides(self, value):
1227db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        value = [v.strip() for v in value]
1228db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1229db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            import distutils.versionpredicate
1230227e8ffa20f7c2c3c1d1080da20c397bca51976dFred Drake            distutils.versionpredicate.split_provision(v)
1231db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.provides = value
1232db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1233db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def get_obsoletes(self):
1234db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        return self.obsoletes or []
1235db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1236db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake    def set_obsoletes(self, value):
1237db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        import distutils.versionpredicate
1238db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        for v in value:
1239db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake            distutils.versionpredicate.VersionPredicate(v)
1240db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake        self.obsoletes = value
1241db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake
1242ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadédef fix_help_options(options):
12432ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """Convert a 4-tuple 'help_options' list as found in various command
12442ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    classes to the 3-tuple form required by FancyGetopt.
12452ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    """
12462ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    new_options = []
12472ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    for help_tuple in options:
12482ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward        new_options.append(help_tuple[0:3])
12492ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward    return new_options
1250