Home | History | Annotate | Download | only in distutils
      1 """distutils.dist
      2 
      3 Provides the Distribution class, which represents the module distribution
      4 being built/installed/distributed.
      5 """
      6 
      7 import sys
      8 import os
      9 import re
     10 from email import message_from_file
     11 
     12 try:
     13     import warnings
     14 except ImportError:
     15     warnings = None
     16 
     17 from distutils.errors import *
     18 from distutils.fancy_getopt import FancyGetopt, translate_longopt
     19 from distutils.util import check_environ, strtobool, rfc822_escape
     20 from distutils import log
     21 from distutils.debug import DEBUG
     22 
     23 # Regex to define acceptable Distutils command names.  This is not *quite*
     24 # the same as a Python NAME -- I don't allow leading underscores.  The fact
     25 # that they're very similar is no coincidence; the default naming scheme is
     26 # to look for a Python module named after the command.
     27 command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
     28 
     29 
     30 class Distribution:
     31     """The core of the Distutils.  Most of the work hiding behind 'setup'
     32     is really done within a Distribution instance, which farms the work out
     33     to the Distutils commands specified on the command line.
     34 
     35     Setup scripts will almost never instantiate Distribution directly,
     36     unless the 'setup()' function is totally inadequate to their needs.
     37     However, it is conceivable that a setup script might wish to subclass
     38     Distribution for some specialized purpose, and then pass the subclass
     39     to 'setup()' as the 'distclass' keyword argument.  If so, it is
     40     necessary to respect the expectations that 'setup' has of Distribution.
     41     See the code for 'setup()', in core.py, for details.
     42     """
     43 
     44     # 'global_options' describes the command-line options that may be
     45     # supplied to the setup script prior to any actual commands.
     46     # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
     47     # these global options.  This list should be kept to a bare minimum,
     48     # since every global option is also valid as a command option -- and we
     49     # don't want to pollute the commands with too many options that they
     50     # have minimal control over.
     51     # The fourth entry for verbose means that it can be repeated.
     52     global_options = [
     53         ('verbose', 'v', "run verbosely (default)", 1),
     54         ('quiet', 'q', "run quietly (turns verbosity off)"),
     55         ('dry-run', 'n', "don't actually do anything"),
     56         ('help', 'h', "show detailed help message"),
     57         ('no-user-cfg', None,
     58             'ignore pydistutils.cfg in your home directory'),
     59     ]
     60 
     61     # 'common_usage' is a short (2-3 line) string describing the common
     62     # usage of the setup script.
     63     common_usage = """\
     64 Common commands: (see '--help-commands' for more)
     65 
     66   setup.py build      will build the package underneath 'build/'
     67   setup.py install    will install the package
     68 """
     69 
     70     # options that are not propagated to the commands
     71     display_options = [
     72         ('help-commands', None,
     73          "list all available commands"),
     74         ('name', None,
     75          "print package name"),
     76         ('version', 'V',
     77          "print package version"),
     78         ('fullname', None,
     79          "print <package name>-<version>"),
     80         ('author', None,
     81          "print the author's name"),
     82         ('author-email', None,
     83          "print the author's email address"),
     84         ('maintainer', None,
     85          "print the maintainer's name"),
     86         ('maintainer-email', None,
     87          "print the maintainer's email address"),
     88         ('contact', None,
     89          "print the maintainer's name if known, else the author's"),
     90         ('contact-email', None,
     91          "print the maintainer's email address if known, else the author's"),
     92         ('url', None,
     93          "print the URL for this package"),
     94         ('license', None,
     95          "print the license of the package"),
     96         ('licence', None,
     97          "alias for --license"),
     98         ('description', None,
     99          "print the package description"),
    100         ('long-description', None,
    101          "print the long package description"),
    102         ('platforms', None,
    103          "print the list of platforms"),
    104         ('classifiers', None,
    105          "print the list of classifiers"),
    106         ('keywords', None,
    107          "print the list of keywords"),
    108         ('provides', None,
    109          "print the list of packages/modules provided"),
    110         ('requires', None,
    111          "print the list of packages/modules required"),
    112         ('obsoletes', None,
    113          "print the list of packages/modules made obsolete")
    114         ]
    115     display_option_names = [translate_longopt(x[0]) for x in display_options]
    116 
    117     # negative options are options that exclude other options
    118     negative_opt = {'quiet': 'verbose'}
    119 
    120     # -- Creation/initialization methods -------------------------------
    121 
    122     def __init__(self, attrs=None):
    123         """Construct a new Distribution instance: initialize all the
    124         attributes of a Distribution, and then use 'attrs' (a dictionary
    125         mapping attribute names to values) to assign some of those
    126         attributes their "real" values.  (Any attributes not mentioned in
    127         'attrs' will be assigned to some null value: 0, None, an empty list
    128         or dictionary, etc.)  Most importantly, initialize the
    129         'command_obj' attribute to the empty dictionary; this will be
    130         filled in with real command objects by 'parse_command_line()'.
    131         """
    132 
    133         # Default values for our command-line options
    134         self.verbose = 1
    135         self.dry_run = 0
    136         self.help = 0
    137         for attr in self.display_option_names:
    138             setattr(self, attr, 0)
    139 
    140         # Store the distribution meta-data (name, version, author, and so
    141         # forth) in a separate object -- we're getting to have enough
    142         # information here (and enough command-line options) that it's
    143         # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
    144         # object in a sneaky and underhanded (but efficient!) way.
    145         self.metadata = DistributionMetadata()
    146         for basename in self.metadata._METHOD_BASENAMES:
    147             method_name = "get_" + basename
    148             setattr(self, method_name, getattr(self.metadata, method_name))
    149 
    150         # 'cmdclass' maps command names to class objects, so we
    151         # can 1) quickly figure out which class to instantiate when
    152         # we need to create a new command object, and 2) have a way
    153         # for the setup script to override command classes
    154         self.cmdclass = {}
    155 
    156         # 'command_packages' is a list of packages in which commands
    157         # are searched for.  The factory for command 'foo' is expected
    158         # to be named 'foo' in the module 'foo' in one of the packages
    159         # named here.  This list is searched from the left; an error
    160         # is raised if no named package provides the command being
    161         # searched for.  (Always access using get_command_packages().)
    162         self.command_packages = None
    163 
    164         # 'script_name' and 'script_args' are usually set to sys.argv[0]
    165         # and sys.argv[1:], but they can be overridden when the caller is
    166         # not necessarily a setup script run from the command-line.
    167         self.script_name = None
    168         self.script_args = None
    169 
    170         # 'command_options' is where we store command options between
    171         # parsing them (from config files, the command-line, etc.) and when
    172         # they are actually needed -- ie. when the command in question is
    173         # instantiated.  It is a dictionary of dictionaries of 2-tuples:
    174         #   command_options = { command_name : { option : (source, value) } }
    175         self.command_options = {}
    176 
    177         # 'dist_files' is the list of (command, pyversion, file) that
    178         # have been created by any dist commands run so far. This is
    179         # filled regardless of whether the run is dry or not. pyversion
    180         # gives sysconfig.get_python_version() if the dist file is
    181         # specific to a Python version, 'any' if it is good for all
    182         # Python versions on the target platform, and '' for a source
    183         # file. pyversion should not be used to specify minimum or
    184         # maximum required Python versions; use the metainfo for that
    185         # instead.
    186         self.dist_files = []
    187 
    188         # These options are really the business of various commands, rather
    189         # than of the Distribution itself.  We provide aliases for them in
    190         # Distribution as a convenience to the developer.
    191         self.packages = None
    192         self.package_data = {}
    193         self.package_dir = None
    194         self.py_modules = None
    195         self.libraries = None
    196         self.headers = None
    197         self.ext_modules = None
    198         self.ext_package = None
    199         self.include_dirs = None
    200         self.extra_path = None
    201         self.scripts = None
    202         self.data_files = None
    203         self.password = ''
    204 
    205         # And now initialize bookkeeping stuff that can't be supplied by
    206         # the caller at all.  'command_obj' maps command names to
    207         # Command instances -- that's how we enforce that every command
    208         # class is a singleton.
    209         self.command_obj = {}
    210 
    211         # 'have_run' maps command names to boolean values; it keeps track
    212         # of whether we have actually run a particular command, to make it
    213         # cheap to "run" a command whenever we think we might need to -- if
    214         # it's already been done, no need for expensive filesystem
    215         # operations, we just check the 'have_run' dictionary and carry on.
    216         # It's only safe to query 'have_run' for a command class that has
    217         # been instantiated -- a false value will be inserted when the
    218         # command object is created, and replaced with a true value when
    219         # the command is successfully run.  Thus it's probably best to use
    220         # '.get()' rather than a straight lookup.
    221         self.have_run = {}
    222 
    223         # Now we'll use the attrs dictionary (ultimately, keyword args from
    224         # the setup script) to possibly override any or all of these
    225         # distribution options.
    226 
    227         if attrs:
    228             # Pull out the set of command options and work on them
    229             # specifically.  Note that this order guarantees that aliased
    230             # command options will override any supplied redundantly
    231             # through the general options dictionary.
    232             options = attrs.get('options')
    233             if options is not None:
    234                 del attrs['options']
    235                 for (command, cmd_options) in options.items():
    236                     opt_dict = self.get_option_dict(command)
    237                     for (opt, val) in cmd_options.items():
    238                         opt_dict[opt] = ("setup script", val)
    239 
    240             if 'licence' in attrs:
    241                 attrs['license'] = attrs['licence']
    242                 del attrs['licence']
    243                 msg = "'licence' distribution option is deprecated; use 'license'"
    244                 if warnings is not None:
    245                     warnings.warn(msg)
    246                 else:
    247                     sys.stderr.write(msg + "\n")
    248 
    249             # Now work on the rest of the attributes.  Any attribute that's
    250             # not already defined is invalid!
    251             for (key, val) in attrs.items():
    252                 if hasattr(self.metadata, "set_" + key):
    253                     getattr(self.metadata, "set_" + key)(val)
    254                 elif hasattr(self.metadata, key):
    255                     setattr(self.metadata, key, val)
    256                 elif hasattr(self, key):
    257                     setattr(self, key, val)
    258                 else:
    259                     msg = "Unknown distribution option: %s" % repr(key)
    260                     if warnings is not None:
    261                         warnings.warn(msg)
    262                     else:
    263                         sys.stderr.write(msg + "\n")
    264 
    265         # no-user-cfg is handled before other command line args
    266         # because other args override the config files, and this
    267         # one is needed before we can load the config files.
    268         # If attrs['script_args'] wasn't passed, assume false.
    269         #
    270         # This also make sure we just look at the global options
    271         self.want_user_cfg = True
    272 
    273         if self.script_args is not None:
    274             for arg in self.script_args:
    275                 if not arg.startswith('-'):
    276                     break
    277                 if arg == '--no-user-cfg':
    278                     self.want_user_cfg = False
    279                     break
    280 
    281         self.finalize_options()
    282 
    283     def get_option_dict(self, command):
    284         """Get the option dictionary for a given command.  If that
    285         command's option dictionary hasn't been created yet, then create it
    286         and return the new dictionary; otherwise, return the existing
    287         option dictionary.
    288         """
    289         dict = self.command_options.get(command)
    290         if dict is None:
    291             dict = self.command_options[command] = {}
    292         return dict
    293 
    294     def dump_option_dicts(self, header=None, commands=None, indent=""):
    295         from pprint import pformat
    296 
    297         if commands is None:             # dump all command option dicts
    298             commands = sorted(self.command_options.keys())
    299 
    300         if header is not None:
    301             self.announce(indent + header)
    302             indent = indent + "  "
    303 
    304         if not commands:
    305             self.announce(indent + "no commands known yet")
    306             return
    307 
    308         for cmd_name in commands:
    309             opt_dict = self.command_options.get(cmd_name)
    310             if opt_dict is None:
    311                 self.announce(indent +
    312                               "no option dict for '%s' command" % cmd_name)
    313             else:
    314                 self.announce(indent +
    315                               "option dict for '%s' command:" % cmd_name)
    316                 out = pformat(opt_dict)
    317                 for line in out.split('\n'):
    318                     self.announce(indent + "  " + line)
    319 
    320     # -- Config file finding/parsing methods ---------------------------
    321 
    322     def find_config_files(self):
    323         """Find as many configuration files as should be processed for this
    324         platform, and return a list of filenames in the order in which they
    325         should be parsed.  The filenames returned are guaranteed to exist
    326         (modulo nasty race conditions).
    327 
    328         There are three possible config files: distutils.cfg in the
    329         Distutils installation directory (ie. where the top-level
    330         Distutils __inst__.py file lives), a file in the user's home
    331         directory named .pydistutils.cfg on Unix and pydistutils.cfg
    332         on Windows/Mac; and setup.cfg in the current directory.
    333 
    334         The file in the user's home directory can be disabled with the
    335         --no-user-cfg option.
    336         """
    337         files = []
    338         check_environ()
    339 
    340         # Where to look for the system-wide Distutils config file
    341         sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
    342 
    343         # Look for the system config file
    344         sys_file = os.path.join(sys_dir, "distutils.cfg")
    345         if os.path.isfile(sys_file):
    346             files.append(sys_file)
    347 
    348         # What to call the per-user config file
    349         if os.name == 'posix':
    350             user_filename = ".pydistutils.cfg"
    351         else:
    352             user_filename = "pydistutils.cfg"
    353 
    354         # And look for the user config file
    355         if self.want_user_cfg:
    356             user_file = os.path.join(os.path.expanduser('~'), user_filename)
    357             if os.path.isfile(user_file):
    358                 files.append(user_file)
    359 
    360         # All platforms support local setup.cfg
    361         local_file = "setup.cfg"
    362         if os.path.isfile(local_file):
    363             files.append(local_file)
    364 
    365         if DEBUG:
    366             self.announce("using config files: %s" % ', '.join(files))
    367 
    368         return files
    369 
    370     def parse_config_files(self, filenames=None):
    371         from configparser import ConfigParser
    372 
    373         # Ignore install directory options if we have a venv
    374         if sys.prefix != sys.base_prefix:
    375             ignore_options = [
    376                 'install-base', 'install-platbase', 'install-lib',
    377                 'install-platlib', 'install-purelib', 'install-headers',
    378                 'install-scripts', 'install-data', 'prefix', 'exec-prefix',
    379                 'home', 'user', 'root']
    380         else:
    381             ignore_options = []
    382 
    383         ignore_options = frozenset(ignore_options)
    384 
    385         if filenames is None:
    386             filenames = self.find_config_files()
    387 
    388         if DEBUG:
    389             self.announce("Distribution.parse_config_files():")
    390 
    391         parser = ConfigParser()
    392         for filename in filenames:
    393             if DEBUG:
    394                 self.announce("  reading %s" % filename)
    395             parser.read(filename)
    396             for section in parser.sections():
    397                 options = parser.options(section)
    398                 opt_dict = self.get_option_dict(section)
    399 
    400                 for opt in options:
    401                     if opt != '__name__' and opt not in ignore_options:
    402                         val = parser.get(section,opt)
    403                         opt = opt.replace('-', '_')
    404                         opt_dict[opt] = (filename, val)
    405 
    406             # Make the ConfigParser forget everything (so we retain
    407             # the original filenames that options come from)
    408             parser.__init__()
    409 
    410         # If there was a "global" section in the config file, use it
    411         # to set Distribution options.
    412 
    413         if 'global' in self.command_options:
    414             for (opt, (src, val)) in self.command_options['global'].items():
    415                 alias = self.negative_opt.get(opt)
    416                 try:
    417                     if alias:
    418                         setattr(self, alias, not strtobool(val))
    419                     elif opt in ('verbose', 'dry_run'): # ugh!
    420                         setattr(self, opt, strtobool(val))
    421                     else:
    422                         setattr(self, opt, val)
    423                 except ValueError as msg:
    424                     raise DistutilsOptionError(msg)
    425 
    426     # -- Command-line parsing methods ----------------------------------
    427 
    428     def parse_command_line(self):
    429         """Parse the setup script's command line, taken from the
    430         'script_args' instance attribute (which defaults to 'sys.argv[1:]'
    431         -- see 'setup()' in core.py).  This list is first processed for
    432         "global options" -- options that set attributes of the Distribution
    433         instance.  Then, it is alternately scanned for Distutils commands
    434         and options for that command.  Each new command terminates the
    435         options for the previous command.  The allowed options for a
    436         command are determined by the 'user_options' attribute of the
    437         command class -- thus, we have to be able to load command classes
    438         in order to parse the command line.  Any error in that 'options'
    439         attribute raises DistutilsGetoptError; any error on the
    440         command-line raises DistutilsArgError.  If no Distutils commands
    441         were found on the command line, raises DistutilsArgError.  Return
    442         true if command-line was successfully parsed and we should carry
    443         on with executing commands; false if no errors but we shouldn't
    444         execute commands (currently, this only happens if user asks for
    445         help).
    446         """
    447         #
    448         # We now have enough information to show the Macintosh dialog
    449         # that allows the user to interactively specify the "command line".
    450         #
    451         toplevel_options = self._get_toplevel_options()
    452 
    453         # We have to parse the command line a bit at a time -- global
    454         # options, then the first command, then its options, and so on --
    455         # because each command will be handled by a different class, and
    456         # the options that are valid for a particular class aren't known
    457         # until we have loaded the command class, which doesn't happen
    458         # until we know what the command is.
    459 
    460         self.commands = []
    461         parser = FancyGetopt(toplevel_options + self.display_options)
    462         parser.set_negative_aliases(self.negative_opt)
    463         parser.set_aliases({'licence': 'license'})
    464         args = parser.getopt(args=self.script_args, object=self)
    465         option_order = parser.get_option_order()
    466         log.set_verbosity(self.verbose)
    467 
    468         # for display options we return immediately
    469         if self.handle_display_options(option_order):
    470             return
    471         while args:
    472             args = self._parse_command_opts(parser, args)
    473             if args is None:            # user asked for help (and got it)
    474                 return
    475 
    476         # Handle the cases of --help as a "global" option, ie.
    477         # "setup.py --help" and "setup.py --help command ...".  For the
    478         # former, we show global options (--verbose, --dry-run, etc.)
    479         # and display-only options (--name, --version, etc.); for the
    480         # latter, we omit the display-only options and show help for
    481         # each command listed on the command line.
    482         if self.help:
    483             self._show_help(parser,
    484                             display_options=len(self.commands) == 0,
    485                             commands=self.commands)
    486             return
    487 
    488         # Oops, no commands found -- an end-user error
    489         if not self.commands:
    490             raise DistutilsArgError("no commands supplied")
    491 
    492         # All is well: return true
    493         return True
    494 
    495     def _get_toplevel_options(self):
    496         """Return the non-display options recognized at the top level.
    497 
    498         This includes options that are recognized *only* at the top
    499         level as well as options recognized for commands.
    500         """
    501         return self.global_options + [
    502             ("command-packages=", None,
    503              "list of packages that provide distutils commands"),
    504             ]
    505 
    506     def _parse_command_opts(self, parser, args):
    507         """Parse the command-line options for a single command.
    508         'parser' must be a FancyGetopt instance; 'args' must be the list
    509         of arguments, starting with the current command (whose options
    510         we are about to parse).  Returns a new version of 'args' with
    511         the next command at the front of the list; will be the empty
    512         list if there are no more commands on the command line.  Returns
    513         None if the user asked for help on this command.
    514         """
    515         # late import because of mutual dependence between these modules
    516         from distutils.cmd import Command
    517 
    518         # Pull the current command from the head of the command line
    519         command = args[0]
    520         if not command_re.match(command):
    521             raise SystemExit("invalid command name '%s'" % command)
    522         self.commands.append(command)
    523 
    524         # Dig up the command class that implements this command, so we
    525         # 1) know that it's a valid command, and 2) know which options
    526         # it takes.
    527         try:
    528             cmd_class = self.get_command_class(command)
    529         except DistutilsModuleError as msg:
    530             raise DistutilsArgError(msg)
    531 
    532         # Require that the command class be derived from Command -- want
    533         # to be sure that the basic "command" interface is implemented.
    534         if not issubclass(cmd_class, Command):
    535             raise DistutilsClassError(
    536                 "command class %s must subclass Command" % cmd_class)
    537 
    538         # Also make sure that the command object provides a list of its
    539         # known options.
    540         if not (hasattr(cmd_class, 'user_options') and
    541                 isinstance(cmd_class.user_options, list)):
    542             msg = ("command class %s must provide "
    543                 "'user_options' attribute (a list of tuples)")
    544             raise DistutilsClassError(msg % cmd_class)
    545 
    546         # If the command class has a list of negative alias options,
    547         # merge it in with the global negative aliases.
    548         negative_opt = self.negative_opt
    549         if hasattr(cmd_class, 'negative_opt'):
    550             negative_opt = negative_opt.copy()
    551             negative_opt.update(cmd_class.negative_opt)
    552 
    553         # Check for help_options in command class.  They have a different
    554         # format (tuple of four) so we need to preprocess them here.
    555         if (hasattr(cmd_class, 'help_options') and
    556                 isinstance(cmd_class.help_options, list)):
    557             help_options = fix_help_options(cmd_class.help_options)
    558         else:
    559             help_options = []
    560 
    561         # All commands support the global options too, just by adding
    562         # in 'global_options'.
    563         parser.set_option_table(self.global_options +
    564                                 cmd_class.user_options +
    565                                 help_options)
    566         parser.set_negative_aliases(negative_opt)
    567         (args, opts) = parser.getopt(args[1:])
    568         if hasattr(opts, 'help') and opts.help:
    569             self._show_help(parser, display_options=0, commands=[cmd_class])
    570             return
    571 
    572         if (hasattr(cmd_class, 'help_options') and
    573                 isinstance(cmd_class.help_options, list)):
    574             help_option_found=0
    575             for (help_option, short, desc, func) in cmd_class.help_options:
    576                 if hasattr(opts, parser.get_attr_name(help_option)):
    577                     help_option_found=1
    578                     if callable(func):
    579                         func()
    580                     else:
    581                         raise DistutilsClassError(
    582                             "invalid help function %r for help option '%s': "
    583                             "must be a callable object (function, etc.)"
    584                             % (func, help_option))
    585 
    586             if help_option_found:
    587                 return
    588 
    589         # Put the options from the command-line into their official
    590         # holding pen, the 'command_options' dictionary.
    591         opt_dict = self.get_option_dict(command)
    592         for (name, value) in vars(opts).items():
    593             opt_dict[name] = ("command line", value)
    594 
    595         return args
    596 
    597     def finalize_options(self):
    598         """Set final values for all the options on the Distribution
    599         instance, analogous to the .finalize_options() method of Command
    600         objects.
    601         """
    602         for attr in ('keywords', 'platforms'):
    603             value = getattr(self.metadata, attr)
    604             if value is None:
    605                 continue
    606             if isinstance(value, str):
    607                 value = [elm.strip() for elm in value.split(',')]
    608                 setattr(self.metadata, attr, value)
    609 
    610     def _show_help(self, parser, global_options=1, display_options=1,
    611                    commands=[]):
    612         """Show help for the setup script command-line in the form of
    613         several lists of command-line options.  'parser' should be a
    614         FancyGetopt instance; do not expect it to be returned in the
    615         same state, as its option table will be reset to make it
    616         generate the correct help text.
    617 
    618         If 'global_options' is true, lists the global options:
    619         --verbose, --dry-run, etc.  If 'display_options' is true, lists
    620         the "display-only" options: --name, --version, etc.  Finally,
    621         lists per-command help for every command name or command class
    622         in 'commands'.
    623         """
    624         # late import because of mutual dependence between these modules
    625         from distutils.core import gen_usage
    626         from distutils.cmd import Command
    627 
    628         if global_options:
    629             if display_options:
    630                 options = self._get_toplevel_options()
    631             else:
    632                 options = self.global_options
    633             parser.set_option_table(options)
    634             parser.print_help(self.common_usage + "\nGlobal options:")
    635             print('')
    636 
    637         if display_options:
    638             parser.set_option_table(self.display_options)
    639             parser.print_help(
    640                 "Information display options (just display " +
    641                 "information, ignore any commands)")
    642             print('')
    643 
    644         for command in self.commands:
    645             if isinstance(command, type) and issubclass(command, Command):
    646                 klass = command
    647             else:
    648                 klass = self.get_command_class(command)
    649             if (hasattr(klass, 'help_options') and
    650                     isinstance(klass.help_options, list)):
    651                 parser.set_option_table(klass.user_options +
    652                                         fix_help_options(klass.help_options))
    653             else:
    654                 parser.set_option_table(klass.user_options)
    655             parser.print_help("Options for '%s' command:" % klass.__name__)
    656             print('')
    657 
    658         print(gen_usage(self.script_name))
    659 
    660     def handle_display_options(self, option_order):
    661         """If there were any non-global "display-only" options
    662         (--help-commands or the metadata display options) on the command
    663         line, display the requested info and return true; else return
    664         false.
    665         """
    666         from distutils.core import gen_usage
    667 
    668         # User just wants a list of commands -- we'll print it out and stop
    669         # processing now (ie. if they ran "setup --help-commands foo bar",
    670         # we ignore "foo bar").
    671         if self.help_commands:
    672             self.print_commands()
    673             print('')
    674             print(gen_usage(self.script_name))
    675             return 1
    676 
    677         # If user supplied any of the "display metadata" options, then
    678         # display that metadata in the order in which the user supplied the
    679         # metadata options.
    680         any_display_options = 0
    681         is_display_option = {}
    682         for option in self.display_options:
    683             is_display_option[option[0]] = 1
    684 
    685         for (opt, val) in option_order:
    686             if val and is_display_option.get(opt):
    687                 opt = translate_longopt(opt)
    688                 value = getattr(self.metadata, "get_"+opt)()
    689                 if opt in ['keywords', 'platforms']:
    690                     print(','.join(value))
    691                 elif opt in ('classifiers', 'provides', 'requires',
    692                              'obsoletes'):
    693                     print('\n'.join(value))
    694                 else:
    695                     print(value)
    696                 any_display_options = 1
    697 
    698         return any_display_options
    699 
    700     def print_command_list(self, commands, header, max_length):
    701         """Print a subset of the list of all commands -- used by
    702         'print_commands()'.
    703         """
    704         print(header + ":")
    705 
    706         for cmd in commands:
    707             klass = self.cmdclass.get(cmd)
    708             if not klass:
    709                 klass = self.get_command_class(cmd)
    710             try:
    711                 description = klass.description
    712             except AttributeError:
    713                 description = "(no description available)"
    714 
    715             print("  %-*s  %s" % (max_length, cmd, description))
    716 
    717     def print_commands(self):
    718         """Print out a help message listing all available commands with a
    719         description of each.  The list is divided into "standard commands"
    720         (listed in distutils.command.__all__) and "extra commands"
    721         (mentioned in self.cmdclass, but not a standard command).  The
    722         descriptions come from the command class attribute
    723         'description'.
    724         """
    725         import distutils.command
    726         std_commands = distutils.command.__all__
    727         is_std = {}
    728         for cmd in std_commands:
    729             is_std[cmd] = 1
    730 
    731         extra_commands = []
    732         for cmd in self.cmdclass.keys():
    733             if not is_std.get(cmd):
    734                 extra_commands.append(cmd)
    735 
    736         max_length = 0
    737         for cmd in (std_commands + extra_commands):
    738             if len(cmd) > max_length:
    739                 max_length = len(cmd)
    740 
    741         self.print_command_list(std_commands,
    742                                 "Standard commands",
    743                                 max_length)
    744         if extra_commands:
    745             print()
    746             self.print_command_list(extra_commands,
    747                                     "Extra commands",
    748                                     max_length)
    749 
    750     def get_command_list(self):
    751         """Get a list of (command, description) tuples.
    752         The list is divided into "standard commands" (listed in
    753         distutils.command.__all__) and "extra commands" (mentioned in
    754         self.cmdclass, but not a standard command).  The descriptions come
    755         from the command class attribute 'description'.
    756         """
    757         # Currently this is only used on Mac OS, for the Mac-only GUI
    758         # Distutils interface (by Jack Jansen)
    759         import distutils.command
    760         std_commands = distutils.command.__all__
    761         is_std = {}
    762         for cmd in std_commands:
    763             is_std[cmd] = 1
    764 
    765         extra_commands = []
    766         for cmd in self.cmdclass.keys():
    767             if not is_std.get(cmd):
    768                 extra_commands.append(cmd)
    769 
    770         rv = []
    771         for cmd in (std_commands + extra_commands):
    772             klass = self.cmdclass.get(cmd)
    773             if not klass:
    774                 klass = self.get_command_class(cmd)
    775             try:
    776                 description = klass.description
    777             except AttributeError:
    778                 description = "(no description available)"
    779             rv.append((cmd, description))
    780         return rv
    781 
    782     # -- Command class/object methods ----------------------------------
    783 
    784     def get_command_packages(self):
    785         """Return a list of packages from which commands are loaded."""
    786         pkgs = self.command_packages
    787         if not isinstance(pkgs, list):
    788             if pkgs is None:
    789                 pkgs = ''
    790             pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
    791             if "distutils.command" not in pkgs:
    792                 pkgs.insert(0, "distutils.command")
    793             self.command_packages = pkgs
    794         return pkgs
    795 
    796     def get_command_class(self, command):
    797         """Return the class that implements the Distutils command named by
    798         'command'.  First we check the 'cmdclass' dictionary; if the
    799         command is mentioned there, we fetch the class object from the
    800         dictionary and return it.  Otherwise we load the command module
    801         ("distutils.command." + command) and fetch the command class from
    802         the module.  The loaded class is also stored in 'cmdclass'
    803         to speed future calls to 'get_command_class()'.
    804 
    805         Raises DistutilsModuleError if the expected module could not be
    806         found, or if that module does not define the expected class.
    807         """
    808         klass = self.cmdclass.get(command)
    809         if klass:
    810             return klass
    811 
    812         for pkgname in self.get_command_packages():
    813             module_name = "%s.%s" % (pkgname, command)
    814             klass_name = command
    815 
    816             try:
    817                 __import__(module_name)
    818                 module = sys.modules[module_name]
    819             except ImportError:
    820                 continue
    821 
    822             try:
    823                 klass = getattr(module, klass_name)
    824             except AttributeError:
    825                 raise DistutilsModuleError(
    826                     "invalid command '%s' (no class '%s' in module '%s')"
    827                     % (command, klass_name, module_name))
    828 
    829             self.cmdclass[command] = klass
    830             return klass
    831 
    832         raise DistutilsModuleError("invalid command '%s'" % command)
    833 
    834     def get_command_obj(self, command, create=1):
    835         """Return the command object for 'command'.  Normally this object
    836         is cached on a previous call to 'get_command_obj()'; if no command
    837         object for 'command' is in the cache, then we either create and
    838         return it (if 'create' is true) or return None.
    839         """
    840         cmd_obj = self.command_obj.get(command)
    841         if not cmd_obj and create:
    842             if DEBUG:
    843                 self.announce("Distribution.get_command_obj(): "
    844                               "creating '%s' command object" % command)
    845 
    846             klass = self.get_command_class(command)
    847             cmd_obj = self.command_obj[command] = klass(self)
    848             self.have_run[command] = 0
    849 
    850             # Set any options that were supplied in config files
    851             # or on the command line.  (NB. support for error
    852             # reporting is lame here: any errors aren't reported
    853             # until 'finalize_options()' is called, which means
    854             # we won't report the source of the error.)
    855             options = self.command_options.get(command)
    856             if options:
    857                 self._set_command_options(cmd_obj, options)
    858 
    859         return cmd_obj
    860 
    861     def _set_command_options(self, command_obj, option_dict=None):
    862         """Set the options for 'command_obj' from 'option_dict'.  Basically
    863         this means copying elements of a dictionary ('option_dict') to
    864         attributes of an instance ('command').
    865 
    866         'command_obj' must be a Command instance.  If 'option_dict' is not
    867         supplied, uses the standard option dictionary for this command
    868         (from 'self.command_options').
    869         """
    870         command_name = command_obj.get_command_name()
    871         if option_dict is None:
    872             option_dict = self.get_option_dict(command_name)
    873 
    874         if DEBUG:
    875             self.announce("  setting options for '%s' command:" % command_name)
    876         for (option, (source, value)) in option_dict.items():
    877             if DEBUG:
    878                 self.announce("    %s = %s (from %s)" % (option, value,
    879                                                          source))
    880             try:
    881                 bool_opts = [translate_longopt(o)
    882                              for o in command_obj.boolean_options]
    883             except AttributeError:
    884                 bool_opts = []
    885             try:
    886                 neg_opt = command_obj.negative_opt
    887             except AttributeError:
    888                 neg_opt = {}
    889 
    890             try:
    891                 is_string = isinstance(value, str)
    892                 if option in neg_opt and is_string:
    893                     setattr(command_obj, neg_opt[option], not strtobool(value))
    894                 elif option in bool_opts and is_string:
    895                     setattr(command_obj, option, strtobool(value))
    896                 elif hasattr(command_obj, option):
    897                     setattr(command_obj, option, value)
    898                 else:
    899                     raise DistutilsOptionError(
    900                         "error in %s: command '%s' has no such option '%s'"
    901                         % (source, command_name, option))
    902             except ValueError as msg:
    903                 raise DistutilsOptionError(msg)
    904 
    905     def reinitialize_command(self, command, reinit_subcommands=0):
    906         """Reinitializes a command to the state it was in when first
    907         returned by 'get_command_obj()': ie., initialized but not yet
    908         finalized.  This provides the opportunity to sneak option
    909         values in programmatically, overriding or supplementing
    910         user-supplied values from the config files and command line.
    911         You'll have to re-finalize the command object (by calling
    912         'finalize_options()' or 'ensure_finalized()') before using it for
    913         real.
    914 
    915         'command' should be a command name (string) or command object.  If
    916         'reinit_subcommands' is true, also reinitializes the command's
    917         sub-commands, as declared by the 'sub_commands' class attribute (if
    918         it has one).  See the "install" command for an example.  Only
    919         reinitializes the sub-commands that actually matter, ie. those
    920         whose test predicates return true.
    921 
    922         Returns the reinitialized command object.
    923         """
    924         from distutils.cmd import Command
    925         if not isinstance(command, Command):
    926             command_name = command
    927             command = self.get_command_obj(command_name)
    928         else:
    929             command_name = command.get_command_name()
    930 
    931         if not command.finalized:
    932             return command
    933         command.initialize_options()
    934         command.finalized = 0
    935         self.have_run[command_name] = 0
    936         self._set_command_options(command)
    937 
    938         if reinit_subcommands:
    939             for sub in command.get_sub_commands():
    940                 self.reinitialize_command(sub, reinit_subcommands)
    941 
    942         return command
    943 
    944     # -- Methods that operate on the Distribution ----------------------
    945 
    946     def announce(self, msg, level=log.INFO):
    947         log.log(level, msg)
    948 
    949     def run_commands(self):
    950         """Run each command that was seen on the setup script command line.
    951         Uses the list of commands found and cache of command objects
    952         created by 'get_command_obj()'.
    953         """
    954         for cmd in self.commands:
    955             self.run_command(cmd)
    956 
    957     # -- Methods that operate on its Commands --------------------------
    958 
    959     def run_command(self, command):
    960         """Do whatever it takes to run a command (including nothing at all,
    961         if the command has already been run).  Specifically: if we have
    962         already created and run the command named by 'command', return
    963         silently without doing anything.  If the command named by 'command'
    964         doesn't even have a command object yet, create one.  Then invoke
    965         'run()' on that command object (or an existing one).
    966         """
    967         # Already been here, done that? then return silently.
    968         if self.have_run.get(command):
    969             return
    970 
    971         log.info("running %s", command)
    972         cmd_obj = self.get_command_obj(command)
    973         cmd_obj.ensure_finalized()
    974         cmd_obj.run()
    975         self.have_run[command] = 1
    976 
    977     # -- Distribution query methods ------------------------------------
    978 
    979     def has_pure_modules(self):
    980         return len(self.packages or self.py_modules or []) > 0
    981 
    982     def has_ext_modules(self):
    983         return self.ext_modules and len(self.ext_modules) > 0
    984 
    985     def has_c_libraries(self):
    986         return self.libraries and len(self.libraries) > 0
    987 
    988     def has_modules(self):
    989         return self.has_pure_modules() or self.has_ext_modules()
    990 
    991     def has_headers(self):
    992         return self.headers and len(self.headers) > 0
    993 
    994     def has_scripts(self):
    995         return self.scripts and len(self.scripts) > 0
    996 
    997     def has_data_files(self):
    998         return self.data_files and len(self.data_files) > 0
    999 
   1000     def is_pure(self):
   1001         return (self.has_pure_modules() and
   1002                 not self.has_ext_modules() and
   1003                 not self.has_c_libraries())
   1004 
   1005     # -- Metadata query methods ----------------------------------------
   1006 
   1007     # If you're looking for 'get_name()', 'get_version()', and so forth,
   1008     # they are defined in a sneaky way: the constructor binds self.get_XXX
   1009     # to self.metadata.get_XXX.  The actual code is in the
   1010     # DistributionMetadata class, below.
   1011 
   1012 class DistributionMetadata:
   1013     """Dummy class to hold the distribution meta-data: name, version,
   1014     author, and so forth.
   1015     """
   1016 
   1017     _METHOD_BASENAMES = ("name", "version", "author", "author_email",
   1018                          "maintainer", "maintainer_email", "url",
   1019                          "license", "description", "long_description",
   1020                          "keywords", "platforms", "fullname", "contact",
   1021                          "contact_email", "classifiers", "download_url",
   1022                          # PEP 314
   1023                          "provides", "requires", "obsoletes",
   1024                          )
   1025 
   1026     def __init__(self, path=None):
   1027         if path is not None:
   1028             self.read_pkg_file(open(path))
   1029         else:
   1030             self.name = None
   1031             self.version = None
   1032             self.author = None
   1033             self.author_email = None
   1034             self.maintainer = None
   1035             self.maintainer_email = None
   1036             self.url = None
   1037             self.license = None
   1038             self.description = None
   1039             self.long_description = None
   1040             self.keywords = None
   1041             self.platforms = None
   1042             self.classifiers = None
   1043             self.download_url = None
   1044             # PEP 314
   1045             self.provides = None
   1046             self.requires = None
   1047             self.obsoletes = None
   1048 
   1049     def read_pkg_file(self, file):
   1050         """Reads the metadata values from a file object."""
   1051         msg = message_from_file(file)
   1052 
   1053         def _read_field(name):
   1054             value = msg[name]
   1055             if value == 'UNKNOWN':
   1056                 return None
   1057             return value
   1058 
   1059         def _read_list(name):
   1060             values = msg.get_all(name, None)
   1061             if values == []:
   1062                 return None
   1063             return values
   1064 
   1065         metadata_version = msg['metadata-version']
   1066         self.name = _read_field('name')
   1067         self.version = _read_field('version')
   1068         self.description = _read_field('summary')
   1069         # we are filling author only.
   1070         self.author = _read_field('author')
   1071         self.maintainer = None
   1072         self.author_email = _read_field('author-email')
   1073         self.maintainer_email = None
   1074         self.url = _read_field('home-page')
   1075         self.license = _read_field('license')
   1076 
   1077         if 'download-url' in msg:
   1078             self.download_url = _read_field('download-url')
   1079         else:
   1080             self.download_url = None
   1081 
   1082         self.long_description = _read_field('description')
   1083         self.description = _read_field('summary')
   1084 
   1085         if 'keywords' in msg:
   1086             self.keywords = _read_field('keywords').split(',')
   1087 
   1088         self.platforms = _read_list('platform')
   1089         self.classifiers = _read_list('classifier')
   1090 
   1091         # PEP 314 - these fields only exist in 1.1
   1092         if metadata_version == '1.1':
   1093             self.requires = _read_list('requires')
   1094             self.provides = _read_list('provides')
   1095             self.obsoletes = _read_list('obsoletes')
   1096         else:
   1097             self.requires = None
   1098             self.provides = None
   1099             self.obsoletes = None
   1100 
   1101     def write_pkg_info(self, base_dir):
   1102         """Write the PKG-INFO file into the release tree.
   1103         """
   1104         with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
   1105                   encoding='UTF-8') as pkg_info:
   1106             self.write_pkg_file(pkg_info)
   1107 
   1108     def write_pkg_file(self, file):
   1109         """Write the PKG-INFO format data to a file object.
   1110         """
   1111         version = '1.0'
   1112         if (self.provides or self.requires or self.obsoletes or
   1113                 self.classifiers or self.download_url):
   1114             version = '1.1'
   1115 
   1116         file.write('Metadata-Version: %s\n' % version)
   1117         file.write('Name: %s\n' % self.get_name())
   1118         file.write('Version: %s\n' % self.get_version())
   1119         file.write('Summary: %s\n' % self.get_description())
   1120         file.write('Home-page: %s\n' % self.get_url())
   1121         file.write('Author: %s\n' % self.get_contact())
   1122         file.write('Author-email: %s\n' % self.get_contact_email())
   1123         file.write('License: %s\n' % self.get_license())
   1124         if self.download_url:
   1125             file.write('Download-URL: %s\n' % self.download_url)
   1126 
   1127         long_desc = rfc822_escape(self.get_long_description())
   1128         file.write('Description: %s\n' % long_desc)
   1129 
   1130         keywords = ','.join(self.get_keywords())
   1131         if keywords:
   1132             file.write('Keywords: %s\n' % keywords)
   1133 
   1134         self._write_list(file, 'Platform', self.get_platforms())
   1135         self._write_list(file, 'Classifier', self.get_classifiers())
   1136 
   1137         # PEP 314
   1138         self._write_list(file, 'Requires', self.get_requires())
   1139         self._write_list(file, 'Provides', self.get_provides())
   1140         self._write_list(file, 'Obsoletes', self.get_obsoletes())
   1141 
   1142     def _write_list(self, file, name, values):
   1143         for value in values:
   1144             file.write('%s: %s\n' % (name, value))
   1145 
   1146     # -- Metadata query methods ----------------------------------------
   1147 
   1148     def get_name(self):
   1149         return self.name or "UNKNOWN"
   1150 
   1151     def get_version(self):
   1152         return self.version or "0.0.0"
   1153 
   1154     def get_fullname(self):
   1155         return "%s-%s" % (self.get_name(), self.get_version())
   1156 
   1157     def get_author(self):
   1158         return self.author or "UNKNOWN"
   1159 
   1160     def get_author_email(self):
   1161         return self.author_email or "UNKNOWN"
   1162 
   1163     def get_maintainer(self):
   1164         return self.maintainer or "UNKNOWN"
   1165 
   1166     def get_maintainer_email(self):
   1167         return self.maintainer_email or "UNKNOWN"
   1168 
   1169     def get_contact(self):
   1170         return self.maintainer or self.author or "UNKNOWN"
   1171 
   1172     def get_contact_email(self):
   1173         return self.maintainer_email or self.author_email or "UNKNOWN"
   1174 
   1175     def get_url(self):
   1176         return self.url or "UNKNOWN"
   1177 
   1178     def get_license(self):
   1179         return self.license or "UNKNOWN"
   1180     get_licence = get_license
   1181 
   1182     def get_description(self):
   1183         return self.description or "UNKNOWN"
   1184 
   1185     def get_long_description(self):
   1186         return self.long_description or "UNKNOWN"
   1187 
   1188     def get_keywords(self):
   1189         return self.keywords or []
   1190 
   1191     def get_platforms(self):
   1192         return self.platforms or ["UNKNOWN"]
   1193 
   1194     def get_classifiers(self):
   1195         return self.classifiers or []
   1196 
   1197     def get_download_url(self):
   1198         return self.download_url or "UNKNOWN"
   1199 
   1200     # PEP 314
   1201     def get_requires(self):
   1202         return self.requires or []
   1203 
   1204     def set_requires(self, value):
   1205         import distutils.versionpredicate
   1206         for v in value:
   1207             distutils.versionpredicate.VersionPredicate(v)
   1208         self.requires = value
   1209 
   1210     def get_provides(self):
   1211         return self.provides or []
   1212 
   1213     def set_provides(self, value):
   1214         value = [v.strip() for v in value]
   1215         for v in value:
   1216             import distutils.versionpredicate
   1217             distutils.versionpredicate.split_provision(v)
   1218         self.provides = value
   1219 
   1220     def get_obsoletes(self):
   1221         return self.obsoletes or []
   1222 
   1223     def set_obsoletes(self, value):
   1224         import distutils.versionpredicate
   1225         for v in value:
   1226             distutils.versionpredicate.VersionPredicate(v)
   1227         self.obsoletes = value
   1228 
   1229 def fix_help_options(options):
   1230     """Convert a 4-tuple 'help_options' list as found in various command
   1231     classes to the 3-tuple form required by FancyGetopt.
   1232     """
   1233     new_options = []
   1234     for help_tuple in options:
   1235         new_options.append(help_tuple[0:3])
   1236     return new_options
   1237