dist.py revision a939ecd95bada6552e86ac57c08b757efb01ab40
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 10a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadéimport rfc822 11ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling 12ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchlingtry: 13ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling import warnings 14ccf4e421b829ce69eb62806fdd77eb71249713ddAndrew M. Kuchlingexcept ImportError: 15ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling warnings = None 16ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling 17fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardfrom distutils.errors import * 182f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Wardfrom distutils.fancy_getopt import FancyGetopt, translate_longopt 19a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchlingfrom distutils.util import check_environ, strtobool, rfc822_escape 20cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log 21fcd7353863c024bb87aabe7c4639ca8df692ac85Jeremy Hyltonfrom distutils.debug import DEBUG 22fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 23b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg# Encoding used for the PKG-INFO files 24b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André LemburgPKG_INFO_ENCODING = 'utf-8' 25b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg 26fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# Regex to define acceptable Distutils command names. This is not *quite* 27fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# the same as a Python NAME -- I don't allow leading underscores. The fact 28fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# that they're very similar is no coincidence; the default naming scheme is 29fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward# to look for a Python module named after the command. 30fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardcommand_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$') 31fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 32fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 33fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Wardclass Distribution: 348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward """The core of the Distutils. Most of the work hiding behind 'setup' 358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward is really done within a Distribution instance, which farms the work out 368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward to the Distutils commands specified on the command line. 378ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward 388ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward Setup scripts will almost never instantiate Distribution directly, 398ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward unless the 'setup()' function is totally inadequate to their needs. 408ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward However, it is conceivable that a setup script might wish to subclass 418ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward Distribution for some specialized purpose, and then pass the subclass 428ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward to 'setup()' as the 'distclass' keyword argument. If so, it is 438ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward necessary to respect the expectations that 'setup' has of Distribution. 448ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward See the code for 'setup()', in core.py, for details. 458ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward """ 46fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 47fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 48fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # 'global_options' describes the command-line options that may be 4982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # supplied to the setup script prior to any actual commands. 5082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of 51fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # these global options. This list should be kept to a bare minimum, 52fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # since every global option is also valid as a command option -- and we 53fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # don't want to pollute the commands with too many options that they 54fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # have minimal control over. 55cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton # The fourth entry for verbose means that it can be repeated. 56cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton global_options = [('verbose', 'v', "run verbosely (default)", 1), 57d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward ('quiet', 'q', "run quietly (turns verbosity off)"), 58d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward ('dry-run', 'n', "don't actually do anything"), 59d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward ('help', 'h', "show detailed help message"), 6040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé ('no-user-cfg', None, 6140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé 'ignore pydistutils.cfg in your home directory'), 6240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé ] 6382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 648ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis # 'common_usage' is a short (2-3 line) string describing the common 658ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis # usage of the setup script. 668ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis common_usage = """\ 678ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. LöwisCommon commands: (see '--help-commands' for more) 688ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis 698ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis setup.py build will build the package underneath 'build/' 708ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis setup.py install will install the package 718ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis""" 728ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis 7382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # options that are not propagated to the commands 7482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward display_options = [ 7582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('help-commands', None, 7682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "list all available commands"), 7782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('name', None, 7882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print package name"), 7982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('version', 'V', 8082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print package version"), 8182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('fullname', None, 8282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print <package name>-<version>"), 8382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('author', None, 8482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the author's name"), 8582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('author-email', None, 8682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the author's email address"), 8782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('maintainer', None, 8882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the maintainer's name"), 8982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('maintainer-email', None, 9082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the maintainer's email address"), 9182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('contact', None, 92d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "print the maintainer's name if known, else the author's"), 9382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('contact-email', None, 94d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "print the maintainer's email address if known, else the author's"), 9582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('url', None, 9682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the URL for this package"), 9782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('license', None, 98fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling "print the license of the package"), 99fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling ('licence', None, 100fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling "alias for --license"), 10182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ('description', None, 10282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward "print the package description"), 103e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward ('long-description', None, 104e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward "print the long package description"), 105a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling ('platforms', None, 106a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling "print the list of platforms"), 107282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling ('classifiers', None, 108282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling "print the list of classifiers"), 109a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling ('keywords', None, 110a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling "print the list of keywords"), 111db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake ('provides', None, 112db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake "print the list of packages/modules provided"), 113db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake ('requires', None, 114db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake "print the list of packages/modules required"), 115db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake ('obsoletes', None, 116db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake "print the list of packages/modules made obsolete") 11782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward ] 1182f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward display_option_names = map(lambda x: translate_longopt(x[0]), 1192f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward display_options) 12082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 12182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # negative options are options that exclude other options 122fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward negative_opt = {'quiet': 'verbose'} 123fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 124fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 125fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # -- Creation/initialization methods ------------------------------- 126b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 127fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward def __init__ (self, attrs=None): 128fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward """Construct a new Distribution instance: initialize all the 1298ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward attributes of a Distribution, and then use 'attrs' (a dictionary 1308ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward mapping attribute names to values) to assign some of those 1318ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward attributes their "real" values. (Any attributes not mentioned in 1328ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward 'attrs' will be assigned to some null value: 0, None, an empty list 1338ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward or dictionary, etc.) Most importantly, initialize the 1348ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward 'command_obj' attribute to the empty dictionary; this will be 1358ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward filled in with real command objects by 'parse_command_line()'. 1368ff5a3fd926cd42ed8f4ceaf5300d64bbe43d152Greg Ward """ 137fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 138fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Default values for our command-line options 139fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.verbose = 1 140fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.dry_run = 0 141fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.help = 0 14282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward for attr in self.display_option_names: 14382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward setattr(self, attr, 0) 14482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 14582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # Store the distribution meta-data (name, version, author, and so 14682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # forth) in a separate object -- we're getting to have enough 14782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # information here (and enough command-line options) that it's 14882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # worth it. Also delegate 'get_XXX()' methods to the 'metadata' 14982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # object in a sneaky and underhanded (but efficient!) way. 150fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.metadata = DistributionMetadata() 151a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer for basename in self.metadata._METHOD_BASENAMES: 1524982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward method_name = "get_" + basename 1534982f98bc919d2a6377e3e0e82c186bc5b1d70ffGreg Ward setattr(self, method_name, getattr(self.metadata, method_name)) 154fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 155fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # 'cmdclass' maps command names to class objects, so we 156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # can 1) quickly figure out which class to instantiate when 157fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # we need to create a new command object, and 2) have a way 15882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # for the setup script to override command classes 159fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.cmdclass = {} 160fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 161d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # 'command_packages' is a list of packages in which commands 162d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # are searched for. The factory for command 'foo' is expected 163d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # to be named 'foo' in the module 'foo' in one of the packages 164d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # named here. This list is searched from the left; an error 165d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # is raised if no named package provides the command being 166d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake # searched for. (Always access using get_command_packages().) 167d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake self.command_packages = None 168d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 1699821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward # 'script_name' and 'script_args' are usually set to sys.argv[0] 1709821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward # and sys.argv[1:], but they can be overridden when the caller is 1719821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward # not necessarily a setup script run from the command-line. 1729821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward self.script_name = None 1739821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward self.script_args = None 1749821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward 175d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # 'command_options' is where we store command options between 176d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # parsing them (from config files, the command-line, etc.) and when 177d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # they are actually needed -- ie. when the command in question is 178d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # instantiated. It is a dictionary of dictionaries of 2-tuples: 179d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # command_options = { command_name : { option : (source, value) } } 1801426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith self.command_options = {} 1811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 18298da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # 'dist_files' is the list of (command, pyversion, file) that 18398da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # have been created by any dist commands run so far. This is 18498da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # filled regardless of whether the run is dry or not. pyversion 18598da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # gives sysconfig.get_python_version() if the dist file is 18698da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # specific to a Python version, 'any' if it is good for all 18798da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # Python versions on the target platform, and '' for a source 18898da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # file. pyversion should not be used to specify minimum or 18998da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # maximum required Python versions; use the metainfo for that 19098da562600def4f3e2054ec52acff32f397aa096Martin v. Löwis # instead. 19155f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis self.dist_files = [] 19255f1bb8bfa362569b6698a91a1cf421bdfcd13d7Martin v. Löwis 193fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # These options are really the business of various commands, rather 194fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # than of the Distribution itself. We provide aliases for them in 195fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Distribution as a convenience to the developer. 196fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.packages = None 1970eb32a65b06613d25aeb18f0104554171bea4840Fred Drake self.package_data = {} 198fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.package_dir = None 199fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.py_modules = None 200fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.libraries = None 20151def7d667a42eac177690e1fe00eab7f2102319Greg Ward self.headers = None 202fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.ext_modules = None 203fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.ext_package = None 204fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.include_dirs = None 205fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.extra_path = None 206b2e3bb3d6aaf4ef04211b932c64ef9cd5adc56bbGregory P. Smith self.scripts = None 2076a901dd1bd1d2cfdd744bf7524ccb9b890b28d06Gregory P. Smith self.data_files = None 2081a240fb9f038839f0e6f157ce4c7fcbcbf777ebcTarek Ziadé self.password = '' 209fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 210fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # And now initialize bookkeeping stuff that can't be supplied by 211fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # the caller at all. 'command_obj' maps command names to 212fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Command instances -- that's how we enforce that every command 213fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # class is a singleton. 214fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.command_obj = {} 215fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 216fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # 'have_run' maps command names to boolean values; it keeps track 217fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # of whether we have actually run a particular command, to make it 218fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # cheap to "run" a command whenever we think we might need to -- if 219fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # it's already been done, no need for expensive filesystem 220fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # operations, we just check the 'have_run' dictionary and carry on. 221fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # It's only safe to query 'have_run' for a command class that has 222fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # been instantiated -- a false value will be inserted when the 223fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # command object is created, and replaced with a true value when 224612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward # the command is successfully run. Thus it's probably best to use 225fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # '.get()' rather than a straight lookup. 226fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.have_run = {} 227fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 228fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Now we'll use the attrs dictionary (ultimately, keyword args from 22982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # the setup script) to possibly override any or all of these 23082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # distribution options. 23182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 232fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if attrs: 233fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Pull out the set of command options and work on them 234fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # specifically. Note that this order guarantees that aliased 235fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # command options will override any supplied redundantly 236fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # through the general options dictionary. 237fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward options = attrs.get('options') 238c13acb18bc2db9d8824ba94b86d8e4c8909d6b6cTarek Ziadé if options is not None: 239fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward del attrs['options'] 240fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for (command, cmd_options) in options.items(): 2410e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward opt_dict = self.get_option_dict(command) 2420e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward for (opt, val) in cmd_options.items(): 2430e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward opt_dict[opt] = ("setup script", val) 244fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 2458bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum if 'licence' in attrs: 246a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling attrs['license'] = attrs['licence'] 247a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling del attrs['licence'] 248a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling msg = "'licence' distribution option is deprecated; use 'license'" 249a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling if warnings is not None: 250a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling warnings.warn(msg) 251a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling else: 252a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling sys.stderr.write(msg + "\n") 253a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling 254fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Now work on the rest of the attributes. Any attribute that's 255fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # not already defined is invalid! 256c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé for (key, val) in attrs.items(): 257db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake if hasattr(self.metadata, "set_" + key): 258db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake getattr(self.metadata, "set_" + key)(val) 259db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake elif hasattr(self.metadata, key): 260fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward setattr(self.metadata, key, val) 261fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward elif hasattr(self, key): 262fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward setattr(self, key, val) 26373cc8479f000bbb84d0775aea55fb9de75ec110eAnthony Baxter else: 264ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling msg = "Unknown distribution option: %s" % repr(key) 265ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling if warnings is not None: 266ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling warnings.warn(msg) 267ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling else: 268ff4ad9a1cec90b66b65cb5f1b647e41742d7aab1Andrew M. Kuchling sys.stderr.write(msg + "\n") 269fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 27040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # no-user-cfg is handled before other command line args 27140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # because other args override the config files, and this 27240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # one is needed before we can load the config files. 27340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # If attrs['script_args'] wasn't passed, assume false. 27440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # 27540b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé # This also make sure we just look at the global options 27640b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé self.want_user_cfg = True 27740b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé 27840b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if self.script_args is not None: 27940b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé for arg in self.script_args: 28040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if not arg.startswith('-'): 28140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé break 28240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if arg == '--no-user-cfg': 28340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé self.want_user_cfg = False 28440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé break 28540b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé 286a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling self.finalize_options() 287b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 288ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_option_dict(self, command): 2890e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward """Get the option dictionary for a given command. If that 2900e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward command's option dictionary hasn't been created yet, then create it 2910e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward and return the new dictionary; otherwise, return the existing 2920e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward option dictionary. 2930e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward """ 2940e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward dict = self.command_options.get(command) 2950e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward if dict is None: 2960e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward dict = self.command_options[command] = {} 2970e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward return dict 2980e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward 299ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def dump_option_dicts(self, header=None, commands=None, indent=""): 300c32d9a69527af6d2823650ea7674e207c975f090Greg Ward from pprint import pformat 301c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 302c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if commands is None: # dump all command option dicts 303c32d9a69527af6d2823650ea7674e207c975f090Greg Ward commands = self.command_options.keys() 304c32d9a69527af6d2823650ea7674e207c975f090Greg Ward commands.sort() 305c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 306c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if header is not None: 307c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(indent + header) 308c32d9a69527af6d2823650ea7674e207c975f090Greg Ward indent = indent + " " 309c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 310c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if not commands: 311c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(indent + "no commands known yet") 312c32d9a69527af6d2823650ea7674e207c975f090Greg Ward return 313c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 314c32d9a69527af6d2823650ea7674e207c975f090Greg Ward for cmd_name in commands: 315c32d9a69527af6d2823650ea7674e207c975f090Greg Ward opt_dict = self.command_options.get(cmd_name) 316c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if opt_dict is None: 317c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(indent + 318c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé "no option dict for '%s' command" % cmd_name) 319c32d9a69527af6d2823650ea7674e207c975f090Greg Ward else: 320c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(indent + 321c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé "option dict for '%s' command:" % cmd_name) 322c32d9a69527af6d2823650ea7674e207c975f090Greg Ward out = pformat(opt_dict) 323c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé for line in out.split('\n'): 324c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(indent + " " + line) 325c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 326d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # -- Config file finding/parsing methods --------------------------- 327d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 328ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def find_config_files(self): 3291426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith """Find as many configuration files as should be processed for this 3301426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith platform, and return a list of filenames in the order in which they 3311426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith should be parsed. The filenames returned are guaranteed to exist 3321426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith (modulo nasty race conditions). 3331426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 334d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling There are three possible config files: distutils.cfg in the 335d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling Distutils installation directory (ie. where the top-level 336d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling Distutils __inst__.py file lives), a file in the user's home 337d303b61eb4f8e893ea558bd3b829561ffc28514eAndrew M. Kuchling directory named .pydistutils.cfg on Unix and pydistutils.cfg 33840b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé on Windows/Mac; and setup.cfg in the current directory. 33940b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé 34040b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé The file in the user's home directory can be disabled with the 34140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé --no-user-cfg option. 342d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 3431426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith files = [] 344acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward check_environ() 345acf3f6a7000eaed43f8c4e5df249967b06dfc474Greg Ward 3461169687692e5e897033421fe6a73a3c32675a7d7Greg Ward # Where to look for the system-wide Distutils config file 3471169687692e5e897033421fe6a73a3c32675a7d7Greg Ward sys_dir = os.path.dirname(sys.modules['distutils'].__file__) 3481169687692e5e897033421fe6a73a3c32675a7d7Greg Ward 3491169687692e5e897033421fe6a73a3c32675a7d7Greg Ward # Look for the system config file 3501169687692e5e897033421fe6a73a3c32675a7d7Greg Ward sys_file = os.path.join(sys_dir, "distutils.cfg") 3511169687692e5e897033421fe6a73a3c32675a7d7Greg Ward if os.path.isfile(sys_file): 3521169687692e5e897033421fe6a73a3c32675a7d7Greg Ward files.append(sys_file) 3531169687692e5e897033421fe6a73a3c32675a7d7Greg Ward 3541169687692e5e897033421fe6a73a3c32675a7d7Greg Ward # What to call the per-user config file 3551169687692e5e897033421fe6a73a3c32675a7d7Greg Ward if os.name == 'posix': 35665d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton user_filename = ".pydistutils.cfg" 35765d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton else: 35865d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton user_filename = "pydistutils.cfg" 359fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward 3601169687692e5e897033421fe6a73a3c32675a7d7Greg Ward # And look for the user config file 36140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if self.want_user_cfg: 36240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé user_file = os.path.join(os.path.expanduser('~'), user_filename) 36340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if os.path.isfile(user_file): 36440b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé files.append(user_file) 3651426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 3661426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith # All platforms support local setup.cfg 3671426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith local_file = "setup.cfg" 3681426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith if os.path.isfile(local_file): 3691426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith files.append(local_file) 3701426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 37140b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé if DEBUG: 37240b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé self.announce("using config files: %s" % ', '.join(files)) 37340b998b05dc2fe6cfd96793793f9087eb075d475Tarek Ziadé 3741426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith return files 3751426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 376ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def parse_config_files(self, filenames=None): 377392c6fc02d90f211dadc72448a07d9281260cb70Georg Brandl from ConfigParser import ConfigParser 3781426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 3791426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith if filenames is None: 3801426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith filenames = self.find_config_files() 3811426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 382c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if DEBUG: 383c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce("Distribution.parse_config_files():") 384474607777d10562679b1640d3831290b0c4284f7Greg Ward 3851426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith parser = ConfigParser() 386d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward for filename in filenames: 387c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if DEBUG: 38899773359843803c54574b6ee6fc1516e7fcde10fTarek Ziadé self.announce(" reading %s" % filename) 389d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward parser.read(filename) 390d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward for section in parser.sections(): 391d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward options = parser.options(section) 3920e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward opt_dict = self.get_option_dict(section) 393d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 394d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward for opt in options: 395d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if opt != '__name__': 396ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward val = parser.get(section,opt) 397c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé opt = opt.replace('-', '_') 398ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward opt_dict[opt] = (filename, val) 3991426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 400474607777d10562679b1640d3831290b0c4284f7Greg Ward # Make the ConfigParser forget everything (so we retain 401f06116dcab8f6066f78c522c056ffb9c2403706cFred Drake # the original filenames that options come from) 402474607777d10562679b1640d3831290b0c4284f7Greg Ward parser.__init__() 4031426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 404ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward # If there was a "global" section in the config file, use it 405ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward # to set Distribution options. 406ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward 4078bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum if 'global' in self.command_options: 408ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward for (opt, (src, val)) in self.command_options['global'].items(): 409ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward alias = self.negative_opt.get(opt) 410ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward try: 411ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward if alias: 412ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward setattr(self, alias, not strtobool(val)) 413ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward elif opt in ('verbose', 'dry_run'): # ugh! 414ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward setattr(self, opt, strtobool(val)) 415d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake else: 416d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake setattr(self, opt, val) 417ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward except ValueError, msg: 418ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward raise DistutilsOptionError, msg 419ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward 420d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # -- Command-line parsing methods ---------------------------------- 421fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 422ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def parse_command_line(self): 4239821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward """Parse the setup script's command line, taken from the 4249821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward 'script_args' instance attribute (which defaults to 'sys.argv[1:]' 4259821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward -- see 'setup()' in core.py). This list is first processed for 4269821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward "global options" -- options that set attributes of the Distribution 4279821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward instance. Then, it is alternately scanned for Distutils commands 4289821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward and options for that command. Each new command terminates the 4299821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward options for the previous command. The allowed options for a 4309821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward command are determined by the 'user_options' attribute of the 4319821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward command class -- thus, we have to be able to load command classes 4329821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward in order to parse the command line. Any error in that 'options' 4339821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward attribute raises DistutilsGetoptError; any error on the 4349821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward command-line raises DistutilsArgError. If no Distutils commands 4359821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward were found on the command line, raises DistutilsArgError. Return 436ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward true if command-line was successfully parsed and we should carry 4379821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward on with executing commands; false if no errors but we shouldn't 4389821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward execute commands (currently, this only happens if user asks for 4399821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward help). 440d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 4413f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling # 442981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake # We now have enough information to show the Macintosh dialog 443981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake # that allows the user to interactively specify the "command line". 4443f819ec2edc54c8ccf0e6edb836a908ff6e31904Andrew M. Kuchling # 445d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake toplevel_options = self._get_toplevel_options() 446b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 447fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # We have to parse the command line a bit at a time -- global 448fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # options, then the first command, then its options, and so on -- 449fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # because each command will be handled by a different class, and 450d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # the options that are valid for a particular class aren't known 451d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # until we have loaded the command class, which doesn't happen 452d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # until we know what the command is. 453fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 454fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.commands = [] 455d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake parser = FancyGetopt(toplevel_options + self.display_options) 456fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_negative_aliases(self.negative_opt) 457fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling parser.set_aliases({'licence': 'license'}) 458fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward args = parser.getopt(args=self.script_args, object=self) 45982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward option_order = parser.get_option_order() 460cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton log.set_verbosity(self.verbose) 461fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 46282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # for display options we return immediately 46382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward if self.handle_display_options(option_order): 464fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return 465fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward while args: 466d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward args = self._parse_command_opts(parser, args) 467d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if args is None: # user asked for help (and got it) 468fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return 469fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 470d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Handle the cases of --help as a "global" option, ie. 471d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # "setup.py --help" and "setup.py --help command ...". For the 472d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # former, we show global options (--verbose, --dry-run, etc.) 473d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # and display-only options (--name, --version, etc.); for the 474d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # latter, we omit the display-only options and show help for 475d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # each command listed on the command line. 476d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if self.help: 477d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward self._show_help(parser, 478d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward display_options=len(self.commands) == 0, 479d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward commands=self.commands) 480fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return 481fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 482fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Oops, no commands found -- an end-user error 483fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if not self.commands: 484fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward raise DistutilsArgError, "no commands supplied" 485fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 486fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # All is well: return true 487fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return 1 488fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 489ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def _get_toplevel_options(self): 490d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake """Return the non-display options recognized at the top level. 491d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 492d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake This includes options that are recognized *only* at the top 493d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake level as well as options recognized for commands. 494d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake """ 495d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake return self.global_options + [ 496d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake ("command-packages=", None, 497d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake "list of packages that provide distutils commands"), 498d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake ] 499d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 500ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def _parse_command_opts(self, parser, args): 501d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """Parse the command-line options for a single command. 502d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 'parser' must be a FancyGetopt instance; 'args' must be the list 503d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward of arguments, starting with the current command (whose options 504d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward we are about to parse). Returns a new version of 'args' with 505d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward the next command at the front of the list; will be the empty 506d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward list if there are no more commands on the command line. Returns 507d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward None if the user asked for help on this command. 508d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 509d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # late import because of mutual dependence between these modules 510d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward from distutils.cmd import Command 511d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 512d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Pull the current command from the head of the command line 513d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward command = args[0] 514fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if not command_re.match(command): 515d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward raise SystemExit, "invalid command name '%s'" % command 516fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.commands.append(command) 517d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 518d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Dig up the command class that implements this command, so we 519d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # 1) know that it's a valid command, and 2) know which options 520d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # it takes. 521d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward try: 522fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward cmd_class = self.get_command_class(command) 523d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward except DistutilsModuleError, msg: 524d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward raise DistutilsArgError, msg 525d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 526d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Require that the command class be derived from Command -- want 527d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # to be sure that the basic "command" interface is implemented. 528fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if not issubclass(cmd_class, Command): 529d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward raise DistutilsClassError, \ 530d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "command class %s must subclass Command" % cmd_class 531d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 532d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Also make sure that the command object provides a list of its 533d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # known options. 534fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if not (hasattr(cmd_class, 'user_options') and 535c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé isinstance(cmd_class.user_options, list)): 536d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward raise DistutilsClassError, \ 537d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward ("command class %s must provide " + 538d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "'user_options' attribute (a list of tuples)") % \ 539d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward cmd_class 540d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 541d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # If the command class has a list of negative alias options, 542d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # merge it in with the global negative aliases. 543d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward negative_opt = self.negative_opt 544fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if hasattr(cmd_class, 'negative_opt'): 545f541378d13e7750b67758b721e862fd3b27e9e6bAntoine Pitrou negative_opt = negative_opt.copy() 546fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward negative_opt.update(cmd_class.negative_opt) 547d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 548fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward # Check for help_options in command class. They have a different 549fa9ff76aae32ecaae6b5409a410c10ff12116732Greg Ward # format (tuple of four) so we need to preprocess them here. 55065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton if (hasattr(cmd_class, 'help_options') and 551c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé isinstance(cmd_class.help_options, list)): 5522ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward help_options = fix_help_options(cmd_class.help_options) 5532ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward else: 55455fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward help_options = [] 5552ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward 5569d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward 557d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # All commands support the global options too, just by adding 558d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # in 'global_options'. 559fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_option_table(self.global_options + 560fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward cmd_class.user_options + 561fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward help_options) 562fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_negative_aliases(negative_opt) 563fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward (args, opts) = parser.getopt(args[1:]) 564474607777d10562679b1640d3831290b0c4284f7Greg Ward if hasattr(opts, 'help') and opts.help: 565d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward self._show_help(parser, display_options=0, commands=[cmd_class]) 566d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward return 567d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 56865d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton if (hasattr(cmd_class, 'help_options') and 569c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé isinstance(cmd_class.help_options, list)): 57065d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton help_option_found=0 57165d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton for (help_option, short, desc, func) in cmd_class.help_options: 57265d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton if hasattr(opts, parser.get_attr_name(help_option)): 57365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton help_option_found=1 574de0559998fef231efc9ecbdef5b3a195d4eaa28dBenjamin Peterson if hasattr(func, '__call__'): 57565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton func() 57655fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward else: 577981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake raise DistutilsClassError( 57870a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald "invalid help function %r for help option '%s': " 579981a1787b7de07033dff56bc8bf8af631a3b181dFred Drake "must be a callable object (function, etc.)" 58070a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald % (func, help_option)) 58155fced3df9efac28e4ead6e3115a4e8658e28bf5Greg Ward 582b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake if help_option_found: 58365d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton return 5849d17a7ad6df0a940f8f10cf7a113aaffc4222309Greg Ward 585d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # Put the options from the command-line into their official 586d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # holding pen, the 'command_options' dictionary. 5870e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward opt_dict = self.get_option_dict(command) 588d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward for (name, value) in vars(opts).items(): 5890e48cfd2c5735a500d638aed929c3207173a4f9eGreg Ward opt_dict[name] = ("command line", value) 590d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 591d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward return args 592d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 593ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def finalize_options(self): 594a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling """Set final values for all the options on the Distribution 595a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling instance, analogous to the .finalize_options() method of Command 596a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling objects. 597a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling """ 598c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé for attr in ('keywords', 'platforms'): 599c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé value = getattr(self.metadata, attr) 600c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if value is None: 601c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé continue 602c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if isinstance(value, str): 603c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé value = [elm.strip() for elm in value.split(',')] 604c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé setattr(self.metadata, attr, value) 605a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 606ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def _show_help(self, parser, global_options=1, display_options=1, 607ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé commands=[]): 608d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """Show help for the setup script command-line in the form of 609d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward several lists of command-line options. 'parser' should be a 610d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward FancyGetopt instance; do not expect it to be returned in the 611d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward same state, as its option table will be reset to make it 612d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward generate the correct help text. 613d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 614d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward If 'global_options' is true, lists the global options: 615d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward --verbose, --dry-run, etc. If 'display_options' is true, lists 616d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward the "display-only" options: --name, --version, etc. Finally, 617d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward lists per-command help for every command name or command class 618d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward in 'commands'. 619d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 620d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward # late import because of mutual dependence between these modules 6219821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward from distutils.core import gen_usage 622d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward from distutils.cmd import Command 623d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 624d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if global_options: 625d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake if display_options: 626d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake options = self._get_toplevel_options() 627d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake else: 628d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake options = self.global_options 629d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake parser.set_option_table(options) 6308ed338ab44daf3cd681d73156fd1d9b6bed53795Martin v. Löwis parser.print_help(self.common_usage + "\nGlobal options:") 631cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print('') 632d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 633d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if display_options: 634fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_option_table(self.display_options) 635fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.print_help( 636d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "Information display options (just display " + 637d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward "information, ignore any commands)") 638cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print('') 639d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 640d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward for command in self.commands: 641c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if isinstance(command, type) and issubclass(command, Command): 642d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward klass = command 643d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward else: 644fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward klass = self.get_command_class(command) 64565d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton if (hasattr(klass, 'help_options') and 646c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé isinstance(klass.help_options, list)): 647fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_option_table(klass.user_options + 648fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward fix_help_options(klass.help_options)) 64965d6edb478d8c649766c59c5ae186bf0d1e812e6Jeremy Hylton else: 650fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.set_option_table(klass.user_options) 651fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward parser.print_help("Options for '%s' command:" % klass.__name__) 652cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print('') 653d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 654cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(gen_usage(self.script_name)) 655d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 656ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def handle_display_options(self, option_order): 65782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward """If there were any non-global "display-only" options 658d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward (--help-commands or the metadata display options) on the command 659d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward line, display the requested info and return true; else return 660d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward false. 661d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 6629821bf4e62bcb7d503aed782a8f6398e5de720afGreg Ward from distutils.core import gen_usage 66382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 66482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # User just wants a list of commands -- we'll print it out and stop 66582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # processing now (ie. if they ran "setup --help-commands foo bar", 66682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # we ignore "foo bar"). 66782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward if self.help_commands: 668fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.print_commands() 669cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print('') 670cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(gen_usage(self.script_name)) 67182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return 1 67282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 67382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # If user supplied any of the "display metadata" options, then 67482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # display that metadata in the order in which the user supplied the 67582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # metadata options. 67682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward any_display_options = 0 67782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward is_display_option = {} 67882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward for option in self.display_options: 67982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward is_display_option[option[0]] = 1 68082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 68182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward for (opt, val) in option_order: 68282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward if val and is_display_option.get(opt): 6832f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward opt = translate_longopt(opt) 684a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling value = getattr(self.metadata, "get_"+opt)() 685a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling if opt in ['keywords', 'platforms']: 686cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(','.join(value)) 687db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake elif opt in ('classifiers', 'provides', 'requires', 688db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 'obsoletes'): 689cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print('\n'.join(value)) 690a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling else: 691cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(value) 69282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward any_display_options = 1 69382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 69482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return any_display_options 69582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 696ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def print_command_list(self, commands, header, max_length): 697fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward """Print a subset of the list of all commands -- used by 698d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 'print_commands()'. 699d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 700cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(header + ":") 701fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 702fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for cmd in commands: 703fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward klass = self.cmdclass.get(cmd) 704fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if not klass: 705fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward klass = self.get_command_class(cmd) 706fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward try: 707fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward description = klass.description 708fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward except AttributeError: 709fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward description = "(no description available)" 710fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 711cd947e0c6af9b81d5069cb57080f1d0eedec7bfdTarek Ziadé print(" %-*s %s" % (max_length, cmd, description)) 712fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 713ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def print_commands(self): 714d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """Print out a help message listing all available commands with a 715d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward description of each. The list is divided into "standard commands" 716d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward (listed in distutils.command.__all__) and "extra commands" 717d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward (mentioned in self.cmdclass, but not a standard command). The 718d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward descriptions come from the command class attribute 719d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 'description'. 720d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 721fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward import distutils.command 722fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward std_commands = distutils.command.__all__ 723fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward is_std = {} 724fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for cmd in std_commands: 725fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward is_std[cmd] = 1 726fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 727fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward extra_commands = [] 728fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for cmd in self.cmdclass.keys(): 729fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if not is_std.get(cmd): 730fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward extra_commands.append(cmd) 731fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 732fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward max_length = 0 733fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for cmd in (std_commands + extra_commands): 734fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if len(cmd) > max_length: 735fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward max_length = len(cmd) 736fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 737fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.print_command_list(std_commands, 738fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward "Standard commands", 739fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward max_length) 740fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if extra_commands: 741fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward print 742fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.print_command_list(extra_commands, 743fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward "Extra commands", 744fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward max_length) 745fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 746ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_command_list(self): 747f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward """Get a list of (command, description) tuples. 748f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward The list is divided into "standard commands" (listed in 749f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward distutils.command.__all__) and "extra commands" (mentioned in 750f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward self.cmdclass, but not a standard command). The descriptions come 751f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward from the command class attribute 'description'. 752f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward """ 753f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward # Currently this is only used on Mac OS, for the Mac-only GUI 754f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward # Distutils interface (by Jack Jansen) 755f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward 756f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward import distutils.command 757f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward std_commands = distutils.command.__all__ 758f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward is_std = {} 759f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward for cmd in std_commands: 760f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward is_std[cmd] = 1 761f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward 762f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward extra_commands = [] 763f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward for cmd in self.cmdclass.keys(): 764f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward if not is_std.get(cmd): 765f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward extra_commands.append(cmd) 766f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward 767f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward rv = [] 768f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward for cmd in (std_commands + extra_commands): 769f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward klass = self.cmdclass.get(cmd) 770f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward if not klass: 771f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward klass = self.get_command_class(cmd) 772f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward try: 773f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward description = klass.description 774f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward except AttributeError: 775f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward description = "(no description available)" 776f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward rv.append((cmd, description)) 777f6fc875831d0cfbf4077b4d2e1800365a78f7c2eGreg Ward return rv 778fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 779fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # -- Command class/object methods ---------------------------------- 780fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 781ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_command_packages(self): 782d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake """Return a list of packages from which commands are loaded.""" 783d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake pkgs = self.command_packages 784c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if not isinstance(pkgs, list): 785c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if pkgs is None: 786c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé pkgs = '' 787c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != ''] 788d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake if "distutils.command" not in pkgs: 789d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake pkgs.insert(0, "distutils.command") 790d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake self.command_packages = pkgs 791d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake return pkgs 792d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 793ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_command_class(self, command): 794d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """Return the class that implements the Distutils command named by 795d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 'command'. First we check the 'cmdclass' dictionary; if the 796d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward command is mentioned there, we fetch the class object from the 797d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward dictionary and return it. Otherwise we load the command module 798d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward ("distutils.command." + command) and fetch the command class from 799d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward the module. The loaded class is also stored in 'cmdclass' 800d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward to speed future calls to 'get_command_class()'. 8011426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith 8021426354cf649546a2437df75f2c319ff0b456c53Gregory P. Smith Raises DistutilsModuleError if the expected module could not be 803d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward found, or if that module does not define the expected class. 804d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 805d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward klass = self.cmdclass.get(command) 806d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if klass: 807d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward return klass 808fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 809d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake for pkgname in self.get_command_packages(): 810d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake module_name = "%s.%s" % (pkgname, command) 811d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake klass_name = command 812fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 813d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake try: 814d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake __import__ (module_name) 815d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake module = sys.modules[module_name] 816d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake except ImportError: 817d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake continue 818d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 819d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake try: 820d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake klass = getattr(module, klass_name) 821d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake except AttributeError: 822d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake raise DistutilsModuleError, \ 823d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake "invalid command '%s' (no class '%s' in module '%s')" \ 824d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake % (command, klass_name, module_name) 825d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 826d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake self.cmdclass[command] = klass 827d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake return klass 828d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake 829d04573fef0346ee9a131e0c63d18ab9fbd12ea63Fred Drake raise DistutilsModuleError("invalid command '%s'" % command) 830fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 831fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 832ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_command_obj(self, command, create=1): 833d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """Return the command object for 'command'. Normally this object 834612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward is cached on a previous call to 'get_command_obj()'; if no command 835d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward object for 'command' is in the cache, then we either create and 836d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward return it (if 'create' is true) or return None. 837d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 838d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward cmd_obj = self.command_obj.get(command) 839fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward if not cmd_obj and create: 8402bd3f4250d59cabc0dda29fc3289beda315ce06aGreg Ward if DEBUG: 841c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce("Distribution.get_command_obj(): " \ 842c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé "creating '%s' command object" % command) 843474607777d10562679b1640d3831290b0c4284f7Greg Ward 844d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward klass = self.get_command_class(command) 845474607777d10562679b1640d3831290b0c4284f7Greg Ward cmd_obj = self.command_obj[command] = klass(self) 846474607777d10562679b1640d3831290b0c4284f7Greg Ward self.have_run[command] = 0 847474607777d10562679b1640d3831290b0c4284f7Greg Ward 848474607777d10562679b1640d3831290b0c4284f7Greg Ward # Set any options that were supplied in config files 849474607777d10562679b1640d3831290b0c4284f7Greg Ward # or on the command line. (NB. support for error 850474607777d10562679b1640d3831290b0c4284f7Greg Ward # reporting is lame here: any errors aren't reported 851474607777d10562679b1640d3831290b0c4284f7Greg Ward # until 'finalize_options()' is called, which means 852474607777d10562679b1640d3831290b0c4284f7Greg Ward # we won't report the source of the error.) 853474607777d10562679b1640d3831290b0c4284f7Greg Ward options = self.command_options.get(command) 854474607777d10562679b1640d3831290b0c4284f7Greg Ward if options: 855c32d9a69527af6d2823650ea7674e207c975f090Greg Ward self._set_command_options(cmd_obj, options) 856fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 857fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return cmd_obj 858fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 859ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def _set_command_options(self, command_obj, option_dict=None): 860c32d9a69527af6d2823650ea7674e207c975f090Greg Ward """Set the options for 'command_obj' from 'option_dict'. Basically 861c32d9a69527af6d2823650ea7674e207c975f090Greg Ward this means copying elements of a dictionary ('option_dict') to 862c32d9a69527af6d2823650ea7674e207c975f090Greg Ward attributes of an instance ('command'). 863c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 864ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward 'command_obj' must be a Command instance. If 'option_dict' is not 865c32d9a69527af6d2823650ea7674e207c975f090Greg Ward supplied, uses the standard option dictionary for this command 866c32d9a69527af6d2823650ea7674e207c975f090Greg Ward (from 'self.command_options'). 867c32d9a69527af6d2823650ea7674e207c975f090Greg Ward """ 868c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command_name = command_obj.get_command_name() 869c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if option_dict is None: 870c32d9a69527af6d2823650ea7674e207c975f090Greg Ward option_dict = self.get_option_dict(command_name) 871c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 872c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if DEBUG: 873c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(" setting options for '%s' command:" % command_name) 874c32d9a69527af6d2823650ea7674e207c975f090Greg Ward for (option, (source, value)) in option_dict.items(): 875c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé if DEBUG: 876c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé self.announce(" %s = %s (from %s)" % (option, value, 877c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé source)) 878ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward try: 8792f2b6c62baf42e06c06f0dcae4879cf88dd6a916Greg Ward bool_opts = map(translate_longopt, command_obj.boolean_options) 880ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward except AttributeError: 881ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward bool_opts = [] 882ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward try: 883ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward neg_opt = command_obj.negative_opt 884ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward except AttributeError: 885ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward neg_opt = {} 886ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward 887ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward try: 888c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé is_string = isinstance(value, str) 8898bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum if option in neg_opt and is_string: 890ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward setattr(command_obj, neg_opt[option], not strtobool(value)) 8912c08cf0ffacdd450e24eeca1f58dfca571538449Greg Ward elif option in bool_opts and is_string: 892ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward setattr(command_obj, option, strtobool(value)) 893ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward elif hasattr(command_obj, option): 894ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward setattr(command_obj, option, value) 895ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward else: 896ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward raise DistutilsOptionError, \ 897ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward ("error in %s: command '%s' has no such option '%s'" 898ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward % (source, command_name, option)) 899ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward except ValueError, msg: 900ceb9e226a638301e68420d7b6728bdc86fd30f0cGreg Ward raise DistutilsOptionError, msg 901c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 902ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def reinitialize_command(self, command, reinit_subcommands=0): 903c32d9a69527af6d2823650ea7674e207c975f090Greg Ward """Reinitializes a command to the state it was in when first 904c32d9a69527af6d2823650ea7674e207c975f090Greg Ward returned by 'get_command_obj()': ie., initialized but not yet 9057d9c705b234ad2ad013db1649e5fd2ffc2a59a75Greg Ward finalized. This provides the opportunity to sneak option 906c32d9a69527af6d2823650ea7674e207c975f090Greg Ward values in programmatically, overriding or supplementing 907c32d9a69527af6d2823650ea7674e207c975f090Greg Ward user-supplied values from the config files and command line. 908c32d9a69527af6d2823650ea7674e207c975f090Greg Ward You'll have to re-finalize the command object (by calling 909c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 'finalize_options()' or 'ensure_finalized()') before using it for 910b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake real. 911c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 912f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward 'command' should be a command name (string) or command object. If 913f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward 'reinit_subcommands' is true, also reinitializes the command's 914f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward sub-commands, as declared by the 'sub_commands' class attribute (if 915f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward it has one). See the "install" command for an example. Only 916f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward reinitializes the sub-commands that actually matter, ie. those 917f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward whose test predicates return true. 918f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward 919c32d9a69527af6d2823650ea7674e207c975f090Greg Ward Returns the reinitialized command object. 920c32d9a69527af6d2823650ea7674e207c975f090Greg Ward """ 921c32d9a69527af6d2823650ea7674e207c975f090Greg Ward from distutils.cmd import Command 922c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if not isinstance(command, Command): 923c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command_name = command 924c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command = self.get_command_obj(command_name) 925c32d9a69527af6d2823650ea7674e207c975f090Greg Ward else: 926c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command_name = command.get_command_name() 927c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 928c32d9a69527af6d2823650ea7674e207c975f090Greg Ward if not command.finalized: 929282c7a0230b578147a89a18ec22410b830edddfeGreg Ward return command 930c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command.initialize_options() 931c32d9a69527af6d2823650ea7674e207c975f090Greg Ward command.finalized = 0 93243955c9a023ea7b50b28052112dbdc914c090a27Greg Ward self.have_run[command_name] = 0 933c32d9a69527af6d2823650ea7674e207c975f090Greg Ward self._set_command_options(command) 934f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward 935f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward if reinit_subcommands: 936f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward for sub in command.get_sub_commands(): 937b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake self.reinitialize_command(sub, reinit_subcommands) 938f449ea51aa9b72bf8d8ea7a19e87c5a169fc9605Greg Ward 939c32d9a69527af6d2823650ea7674e207c975f090Greg Ward return command 940c32d9a69527af6d2823650ea7674e207c975f090Greg Ward 941fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # -- Methods that operate on the Distribution ---------------------- 942fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 94363f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé def announce(self, msg, level=log.INFO): 94463f1738d4bb904992afb748b3b2734d37cd7fdecTarek Ziadé log.log(level, msg) 945fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 946ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def run_commands(self): 94782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward """Run each command that was seen on the setup script command line. 948d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward Uses the list of commands found and cache of command objects 949fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward created by 'get_command_obj()'. 950fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward """ 951fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward for cmd in self.commands: 952fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward self.run_command(cmd) 953fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 954fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # -- Methods that operate on its Commands -------------------------- 955fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 956ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def run_command(self, command): 957fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward """Do whatever it takes to run a command (including nothing at all, 958d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward if the command has already been run). Specifically: if we have 959d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward already created and run the command named by 'command', return 960d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward silently without doing anything. If the command named by 'command' 961d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward doesn't even have a command object yet, create one. Then invoke 962d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward 'run()' on that command object (or an existing one). 963d5d8a9982b77ef54fcacf8ff7bfa449a2eab35dbGreg Ward """ 964fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # Already been here, done that? then return silently. 965fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward if self.have_run.get(command): 966fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return 967fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 968cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton log.info("running %s", command) 969fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward cmd_obj = self.get_command_obj(command) 970fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward cmd_obj.ensure_finalized() 971fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward cmd_obj.run() 972fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward self.have_run[command] = 1 973fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 974fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 975fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward # -- Distribution query methods ------------------------------------ 976fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 977ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_pure_modules(self): 978fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward return len(self.packages or self.py_modules or []) > 0 979fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 980ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_ext_modules(self): 981fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward return self.ext_modules and len(self.ext_modules) > 0 982fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 983ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_c_libraries(self): 984fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward return self.libraries and len(self.libraries) > 0 985fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 986ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_modules(self): 987fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return self.has_pure_modules() or self.has_ext_modules() 988fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 989ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_headers(self): 99051def7d667a42eac177690e1fe00eab7f2102319Greg Ward return self.headers and len(self.headers) > 0 99151def7d667a42eac177690e1fe00eab7f2102319Greg Ward 992ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_scripts(self): 99344a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward return self.scripts and len(self.scripts) > 0 99444a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward 995ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def has_data_files(self): 99644a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward return self.data_files and len(self.data_files) > 0 99744a61bbb66cfc6a0821d591ccf33fbc209aab112Greg Ward 998ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def is_pure(self): 999fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return (self.has_pure_modules() and 1000fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward not self.has_ext_modules() and 1001fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward not self.has_c_libraries()) 1002fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 100382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # -- Metadata query methods ---------------------------------------- 100482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 100582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # If you're looking for 'get_name()', 'get_version()', and so forth, 100682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # they are defined in a sneaky way: the constructor binds self.get_XXX 100782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # to self.metadata.get_XXX. The actual code is in the 100882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # DistributionMetadata class, below. 100982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 1010a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadéclass _MetadataMessage(rfc822.Message): 1011a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1012a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé def read_field(self, name): 1013a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé value = self[name] 1014a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if value == 'UNKNOWN': 1015a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé return None 1016a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé return value 1017a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1018a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé def getheaders(self, name, default): 1019a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé values = rfc822.Message.getheaders(self, name) 1020a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if values == []: 1021a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé return None 1022a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé return values 1023a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 102482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Wardclass DistributionMetadata: 102582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward """Dummy class to hold the distribution meta-data: name, version, 1026fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward author, and so forth. 1027fd7b91eff98d4e5fafbe50be0c875d1644bcfa6fGreg Ward """ 102882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 1029a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer _METHOD_BASENAMES = ("name", "version", "author", "author_email", 1030a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer "maintainer", "maintainer_email", "url", 1031a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer "license", "description", "long_description", 1032a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer "keywords", "platforms", "fullname", "contact", 1033a52b85262ae7c0ce3ba92ee7e933f5a449690b8cAndrew M. Kuchling "contact_email", "license", "classifiers", 1034db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake "download_url", 1035db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake # PEP 314 1036db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake "provides", "requires", "obsoletes", 1037db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake ) 1038a8aefe535c879c8b0f5201961648a89c8e3d7887Neil Schemenauer 1039a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé def __init__(self, path=None): 1040a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if path is not None: 1041a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.read_pkg_file(open(path)) 1042a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé else: 1043a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.name = None 1044a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.version = None 1045a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.author = None 1046a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.author_email = None 1047a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.maintainer = None 1048a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.maintainer_email = None 1049a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.url = None 1050a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.license = None 1051a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.description = None 1052a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.long_description = None 1053a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.keywords = None 1054a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.platforms = None 1055a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.classifiers = None 1056a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.download_url = None 1057a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé # PEP 314 1058a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.provides = None 1059a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.requires = None 1060a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.obsoletes = None 1061a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1062a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé def read_pkg_file(self, file): 1063a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé """Reads the metadata values from a file object.""" 1064a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé msg = _MetadataMessage(file) 1065a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé metadata_version = msg['metadata-version'] 1066a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.name = msg.read_field('name') 1067a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.version = msg.read_field('version') 1068a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.description = msg.read_field('summary') 1069a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé # we are filling author only. 1070a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.author = msg.read_field('author') 107182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward self.maintainer = None 1072a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.author_email = msg.read_field('author-email') 107382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward self.maintainer_email = None 1074a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.url = msg.read_field('home-page') 1075a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.license = msg.read_field('license') 1076a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1077a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if 'download-url' in msg: 1078a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.download_url = msg.read_field('download-url') 1079a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé else: 1080a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.download_url = None 1081a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1082a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.long_description = msg.read_field('description') 1083a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.description = msg.read_field('summary') 1084a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1085a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if 'keywords' in msg: 1086a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.keywords = msg.read_field('keywords').split(',') 1087a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1088a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.platforms = msg.getheaders('platform', None) 1089a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.classifiers = msg.getheaders('classifier', None) 1090a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé 1091a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé # PEP 314 - these fields only exist in 1.1 1092a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé if metadata_version == '1.1': 1093a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.requires = msg.getheaders('requires', None) 1094a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.provides = msg.getheaders('provides', None) 1095a939ecd95bada6552e86ac57c08b757efb01ab40Tarek Ziadé self.obsoletes = msg.getheaders('obsoletes', None) 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 """ 1104a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w') 1105db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self.write_pkg_file(pkg_info) 1106db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake pkg_info.close() 1107db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1108ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def write_pkg_file(self, file): 1109db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake """Write the PKG-INFO format data to a file object. 1110db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake """ 1111db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake version = '1.0' 1112db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake if self.provides or self.requires or self.obsoletes: 1113db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake version = '1.1' 1114db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1115b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Metadata-Version', version) 1116b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Name', self.get_name()) 1117b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Version', self.get_version()) 1118b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Summary', self.get_description()) 1119b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Home-page', self.get_url()) 1120b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Author', self.get_contact()) 1121b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Author-email', self.get_contact_email()) 1122b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'License', self.get_license()) 1123188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling if self.download_url: 1124b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Download-URL', self.download_url) 1125a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 1126c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé long_desc = rfc822_escape(self.get_long_description()) 1127b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Description', long_desc) 1128a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 1129c01cbc42aafb814d4f09d8add8a45effc18efb7aTarek Ziadé keywords = ','.join(self.get_keywords()) 1130a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling if keywords: 1131b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, 'Keywords', keywords) 1132a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 1133db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self._write_list(file, 'Platform', self.get_platforms()) 1134db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self._write_list(file, 'Classifier', self.get_classifiers()) 1135282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling 1136db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake # PEP 314 1137db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self._write_list(file, 'Requires', self.get_requires()) 1138db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self._write_list(file, 'Provides', self.get_provides()) 1139db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self._write_list(file, 'Obsoletes', self.get_obsoletes()) 1140b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 1141b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg def _write_field(self, file, name, value): 1142b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg if isinstance(value, unicode): 1143b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg value = value.encode(PKG_INFO_ENCODING) 1144b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg else: 1145b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg value = str(value) 1146b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg file.write('%s: %s\n' % (name, value)) 1147b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg 1148db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def _write_list (self, file, name, values): 1149db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake for value in values: 1150b339b2aa6f722cd81f374a6dca62f862caa42748Marc-André Lemburg self._write_field(file, name, value) 1151b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 115282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward # -- Metadata query methods ---------------------------------------- 115382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 1154ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_name(self): 1155fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward return self.name or "UNKNOWN" 1156fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 115782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_version(self): 1158bcd8975740da47e7d1c8a5d2839ad4bf214fe34bThomas Heller return self.version or "0.0.0" 115982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 1160ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé def get_fullname(self): 116182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return "%s-%s" % (self.get_name(), self.get_version()) 116282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 116382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_author(self): 116482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.author or "UNKNOWN" 1165fe6462c1f3206dd69659d20b5babab515fc6d4c3Greg Ward 116682715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_author_email(self): 116782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.author_email or "UNKNOWN" 116882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 116982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_maintainer(self): 117082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.maintainer or "UNKNOWN" 117182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 117282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_maintainer_email(self): 117382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.maintainer_email or "UNKNOWN" 117482715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 117582715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_contact(self): 1176ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé return self.maintainer or self.author or "UNKNOWN" 117782715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 117882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_contact_email(self): 1179ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadé return self.maintainer_email or self.author_email or "UNKNOWN" 118082715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 118182715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_url(self): 118282715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.url or "UNKNOWN" 118382715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward 1184fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling def get_license(self): 1185fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling return self.license or "UNKNOWN" 1186fa7dc57d6c9023a5028aacb802438527ab2cfaceAndrew M. Kuchling get_licence = get_license 1187b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake 118882715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward def get_description(self): 118982715e1f11ec1f4c7b13b07ca55f56850c4c3dabGreg Ward return self.description or "UNKNOWN" 1190e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward 1191e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward def get_long_description(self): 1192e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward return self.long_description or "UNKNOWN" 1193e5a584e86572a1ae85d99bc2a77b439d7024934fGreg Ward 1194a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling def get_keywords(self): 1195a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling return self.keywords or [] 1196a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 1197a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling def get_platforms(self): 1198a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling return self.platforms or ["UNKNOWN"] 1199a7210ed2728faefdcc440fb359ff1a1abdca998eAndrew M. Kuchling 1200282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling def get_classifiers(self): 1201282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling return self.classifiers or [] 1202282e2c36ba630aeeedb16a97aa6e881ca27b1a4dAndrew M. Kuchling 1203188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling def get_download_url(self): 1204188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling return self.download_url or "UNKNOWN" 1205188d85f475ff611ca09c1355610185f68e7236d3Andrew M. Kuchling 1206db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake # PEP 314 1207db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def get_requires(self): 1208db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake return self.requires or [] 1209db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1210db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def set_requires(self, value): 1211db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake import distutils.versionpredicate 1212db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake for v in value: 1213db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake distutils.versionpredicate.VersionPredicate(v) 1214db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self.requires = value 1215db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1216db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def get_provides(self): 1217db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake return self.provides or [] 1218db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1219db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def set_provides(self, value): 1220db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake value = [v.strip() for v in value] 1221db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake for v in value: 1222db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake import distutils.versionpredicate 1223227e8ffa20f7c2c3c1d1080da20c397bca51976dFred Drake distutils.versionpredicate.split_provision(v) 1224db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self.provides = value 1225db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1226db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def get_obsoletes(self): 1227db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake return self.obsoletes or [] 1228db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1229db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake def set_obsoletes(self, value): 1230db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake import distutils.versionpredicate 1231db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake for v in value: 1232db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake distutils.versionpredicate.VersionPredicate(v) 1233db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake self.obsoletes = value 1234db7b0027dcebca13d193db09d7f266d871fe67b9Fred Drake 1235ae6acfc9a108a1e304f1227bcfc92d96c6a9233eTarek Ziadédef fix_help_options(options): 12362ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward """Convert a 4-tuple 'help_options' list as found in various command 12372ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward classes to the 3-tuple form required by FancyGetopt. 12382ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward """ 12392ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward new_options = [] 12402ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward for help_tuple in options: 12412ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward new_options.append(help_tuple[0:3]) 12422ff7887270385bd6dddc2d5461486334b4fec8bcGreg Ward return new_options 1243