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