PyXR

c:\python24\lib \ distutils \ dist.py



0001 """distutils.dist
0002 
0003 Provides the Distribution class, which represents the module distribution
0004 being built/installed/distributed.
0005 """
0006 
0007 # This module should be kept compatible with Python 1.5.2.
0008 
0009 __revision__ = "$Id: dist.py,v 1.71 2004/10/13 13:22:34 anthonybaxter Exp $"
0010 
0011 import sys, os, string, re
0012 from types import *
0013 from copy import copy
0014 
0015 try:
0016     import warnings
0017 except ImportError:
0018     warnings = None
0019 
0020 from distutils.errors import *
0021 from distutils.fancy_getopt import FancyGetopt, translate_longopt
0022 from distutils.util import check_environ, strtobool, rfc822_escape
0023 from distutils import log
0024 from distutils.debug import DEBUG
0025 
0026 # Regex to define acceptable Distutils command names.  This is not *quite*
0027 # the same as a Python NAME -- I don't allow leading underscores.  The fact
0028 # that they're very similar is no coincidence; the default naming scheme is
0029 # to look for a Python module named after the command.
0030 command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
0031 
0032 
0033 class Distribution:
0034     """The core of the Distutils.  Most of the work hiding behind 'setup'
0035     is really done within a Distribution instance, which farms the work out
0036     to the Distutils commands specified on the command line.
0037 
0038     Setup scripts will almost never instantiate Distribution directly,
0039     unless the 'setup()' function is totally inadequate to their needs.
0040     However, it is conceivable that a setup script might wish to subclass
0041     Distribution for some specialized purpose, and then pass the subclass
0042     to 'setup()' as the 'distclass' keyword argument.  If so, it is
0043     necessary to respect the expectations that 'setup' has of Distribution.
0044     See the code for 'setup()', in core.py, for details.
0045     """
0046 
0047 
0048     # 'global_options' describes the command-line options that may be
0049     # supplied to the setup script prior to any actual commands.
0050     # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
0051     # these global options.  This list should be kept to a bare minimum,
0052     # since every global option is also valid as a command option -- and we
0053     # don't want to pollute the commands with too many options that they
0054     # have minimal control over.
0055     # The fourth entry for verbose means that it can be repeated.
0056     global_options = [('verbose', 'v', "run verbosely (default)", 1),
0057                       ('quiet', 'q', "run quietly (turns verbosity off)"),
0058                       ('dry-run', 'n', "don't actually do anything"),
0059                       ('help', 'h', "show detailed help message"),
0060                      ]
0061 
0062     # options that are not propagated to the commands
0063     display_options = [
0064         ('help-commands', None,
0065          "list all available commands"),
0066         ('name', None,
0067          "print package name"),
0068         ('version', 'V',
0069          "print package version"),
0070         ('fullname', None,
0071          "print <package name>-<version>"),
0072         ('author', None,
0073          "print the author's name"),
0074         ('author-email', None,
0075          "print the author's email address"),
0076         ('maintainer', None,
0077          "print the maintainer's name"),
0078         ('maintainer-email', None,
0079          "print the maintainer's email address"),
0080         ('contact', None,
0081          "print the maintainer's name if known, else the author's"),
0082         ('contact-email', None,
0083          "print the maintainer's email address if known, else the author's"),
0084         ('url', None,
0085          "print the URL for this package"),
0086         ('license', None,
0087          "print the license of the package"),
0088         ('licence', None,
0089          "alias for --license"),
0090         ('description', None,
0091          "print the package description"),
0092         ('long-description', None,
0093          "print the long package description"),
0094         ('platforms', None,
0095          "print the list of platforms"),
0096         ('classifiers', None,
0097          "print the list of classifiers"),
0098         ('keywords', None,
0099          "print the list of keywords"),
0100         ]
0101     display_option_names = map(lambda x: translate_longopt(x[0]),
0102                                display_options)
0103 
0104     # negative options are options that exclude other options
0105     negative_opt = {'quiet': 'verbose'}
0106 
0107 
0108     # -- Creation/initialization methods -------------------------------
0109 
0110     def __init__ (self, attrs=None):
0111         """Construct a new Distribution instance: initialize all the
0112         attributes of a Distribution, and then use 'attrs' (a dictionary
0113         mapping attribute names to values) to assign some of those
0114         attributes their "real" values.  (Any attributes not mentioned in
0115         'attrs' will be assigned to some null value: 0, None, an empty list
0116         or dictionary, etc.)  Most importantly, initialize the
0117         'command_obj' attribute to the empty dictionary; this will be
0118         filled in with real command objects by 'parse_command_line()'.
0119         """
0120 
0121         # Default values for our command-line options
0122         self.verbose = 1
0123         self.dry_run = 0
0124         self.help = 0
0125         for attr in self.display_option_names:
0126             setattr(self, attr, 0)
0127 
0128         # Store the distribution meta-data (name, version, author, and so
0129         # forth) in a separate object -- we're getting to have enough
0130         # information here (and enough command-line options) that it's
0131         # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
0132         # object in a sneaky and underhanded (but efficient!) way.
0133         self.metadata = DistributionMetadata()
0134         for basename in self.metadata._METHOD_BASENAMES:
0135             method_name = "get_" + basename
0136             setattr(self, method_name, getattr(self.metadata, method_name))
0137 
0138         # 'cmdclass' maps command names to class objects, so we
0139         # can 1) quickly figure out which class to instantiate when
0140         # we need to create a new command object, and 2) have a way
0141         # for the setup script to override command classes
0142         self.cmdclass = {}
0143 
0144         # 'command_packages' is a list of packages in which commands
0145         # are searched for.  The factory for command 'foo' is expected
0146         # to be named 'foo' in the module 'foo' in one of the packages
0147         # named here.  This list is searched from the left; an error
0148         # is raised if no named package provides the command being
0149         # searched for.  (Always access using get_command_packages().)
0150         self.command_packages = None
0151 
0152         # 'script_name' and 'script_args' are usually set to sys.argv[0]
0153         # and sys.argv[1:], but they can be overridden when the caller is
0154         # not necessarily a setup script run from the command-line.
0155         self.script_name = None
0156         self.script_args = None
0157 
0158         # 'command_options' is where we store command options between
0159         # parsing them (from config files, the command-line, etc.) and when
0160         # they are actually needed -- ie. when the command in question is
0161         # instantiated.  It is a dictionary of dictionaries of 2-tuples:
0162         #   command_options = { command_name : { option : (source, value) } }
0163         self.command_options = {}
0164 
0165         # These options are really the business of various commands, rather
0166         # than of the Distribution itself.  We provide aliases for them in
0167         # Distribution as a convenience to the developer.
0168         self.packages = None
0169         self.package_data = {}
0170         self.package_dir = None
0171         self.py_modules = None
0172         self.libraries = None
0173         self.headers = None
0174         self.ext_modules = None
0175         self.ext_package = None
0176         self.include_dirs = None
0177         self.extra_path = None
0178         self.scripts = None
0179         self.data_files = None
0180 
0181         # And now initialize bookkeeping stuff that can't be supplied by
0182         # the caller at all.  'command_obj' maps command names to
0183         # Command instances -- that's how we enforce that every command
0184         # class is a singleton.
0185         self.command_obj = {}
0186 
0187         # 'have_run' maps command names to boolean values; it keeps track
0188         # of whether we have actually run a particular command, to make it
0189         # cheap to "run" a command whenever we think we might need to -- if
0190         # it's already been done, no need for expensive filesystem
0191         # operations, we just check the 'have_run' dictionary and carry on.
0192         # It's only safe to query 'have_run' for a command class that has
0193         # been instantiated -- a false value will be inserted when the
0194         # command object is created, and replaced with a true value when
0195         # the command is successfully run.  Thus it's probably best to use
0196         # '.get()' rather than a straight lookup.
0197         self.have_run = {}
0198 
0199         # Now we'll use the attrs dictionary (ultimately, keyword args from
0200         # the setup script) to possibly override any or all of these
0201         # distribution options.
0202 
0203         if attrs:
0204 
0205             # Pull out the set of command options and work on them
0206             # specifically.  Note that this order guarantees that aliased
0207             # command options will override any supplied redundantly
0208             # through the general options dictionary.
0209             options = attrs.get('options')
0210             if options:
0211                 del attrs['options']
0212                 for (command, cmd_options) in options.items():
0213                     opt_dict = self.get_option_dict(command)
0214                     for (opt, val) in cmd_options.items():
0215                         opt_dict[opt] = ("setup script", val)
0216 
0217             if attrs.has_key('licence'):
0218                 attrs['license'] = attrs['licence']
0219                 del attrs['licence']
0220                 msg = "'licence' distribution option is deprecated; use 'license'"
0221                 if warnings is not None:
0222                     warnings.warn(msg)
0223                 else:
0224                     sys.stderr.write(msg + "\n")
0225 
0226             # Now work on the rest of the attributes.  Any attribute that's
0227             # not already defined is invalid!
0228             for (key,val) in attrs.items():
0229                 if hasattr(self.metadata, key):
0230                     setattr(self.metadata, key, val)
0231                 elif hasattr(self, key):
0232                     setattr(self, key, val)
0233                 else:
0234                     msg = "Unknown distribution option: %s" % repr(key)
0235                     if warnings is not None:
0236                         warnings.warn(msg)
0237                     else:
0238                         sys.stderr.write(msg + "\n")
0239 
0240         self.finalize_options()
0241 
0242     # __init__ ()
0243 
0244 
0245     def get_option_dict (self, command):
0246         """Get the option dictionary for a given command.  If that
0247         command's option dictionary hasn't been created yet, then create it
0248         and return the new dictionary; otherwise, return the existing
0249         option dictionary.
0250         """
0251 
0252         dict = self.command_options.get(command)
0253         if dict is None:
0254             dict = self.command_options[command] = {}
0255         return dict
0256 
0257 
0258     def dump_option_dicts (self, header=None, commands=None, indent=""):
0259         from pprint import pformat
0260 
0261         if commands is None:             # dump all command option dicts
0262             commands = self.command_options.keys()
0263             commands.sort()
0264 
0265         if header is not None:
0266             print indent + header
0267             indent = indent + "  "
0268 
0269         if not commands:
0270             print indent + "no commands known yet"
0271             return
0272 
0273         for cmd_name in commands:
0274             opt_dict = self.command_options.get(cmd_name)
0275             if opt_dict is None:
0276                 print indent + "no option dict for '%s' command" % cmd_name
0277             else:
0278                 print indent + "option dict for '%s' command:" % cmd_name
0279                 out = pformat(opt_dict)
0280                 for line in string.split(out, "\n"):
0281                     print indent + "  " + line
0282 
0283     # dump_option_dicts ()
0284 
0285 
0286 
0287     # -- Config file finding/parsing methods ---------------------------
0288 
0289     def find_config_files (self):
0290         """Find as many configuration files as should be processed for this
0291         platform, and return a list of filenames in the order in which they
0292         should be parsed.  The filenames returned are guaranteed to exist
0293         (modulo nasty race conditions).
0294 
0295         There are three possible config files: distutils.cfg in the
0296         Distutils installation directory (ie. where the top-level
0297         Distutils __inst__.py file lives), a file in the user's home
0298         directory named .pydistutils.cfg on Unix and pydistutils.cfg
0299         on Windows/Mac, and setup.cfg in the current directory.
0300         """
0301         files = []
0302         check_environ()
0303 
0304         # Where to look for the system-wide Distutils config file
0305         sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
0306 
0307         # Look for the system config file
0308         sys_file = os.path.join(sys_dir, "distutils.cfg")
0309         if os.path.isfile(sys_file):
0310             files.append(sys_file)
0311 
0312         # What to call the per-user config file
0313         if os.name == 'posix':
0314             user_filename = ".pydistutils.cfg"
0315         else:
0316             user_filename = "pydistutils.cfg"
0317 
0318         # And look for the user config file
0319         if os.environ.has_key('HOME'):
0320             user_file = os.path.join(os.environ.get('HOME'), user_filename)
0321             if os.path.isfile(user_file):
0322                 files.append(user_file)
0323 
0324         # All platforms support local setup.cfg
0325         local_file = "setup.cfg"
0326         if os.path.isfile(local_file):
0327             files.append(local_file)
0328 
0329         return files
0330 
0331     # find_config_files ()
0332 
0333 
0334     def parse_config_files (self, filenames=None):
0335 
0336         from ConfigParser import ConfigParser
0337 
0338         if filenames is None:
0339             filenames = self.find_config_files()
0340 
0341         if DEBUG: print "Distribution.parse_config_files():"
0342 
0343         parser = ConfigParser()
0344         for filename in filenames:
0345             if DEBUG: print "  reading", filename
0346             parser.read(filename)
0347             for section in parser.sections():
0348                 options = parser.options(section)
0349                 opt_dict = self.get_option_dict(section)
0350 
0351                 for opt in options:
0352                     if opt != '__name__':
0353                         val = parser.get(section,opt)
0354                         opt = string.replace(opt, '-', '_')
0355                         opt_dict[opt] = (filename, val)
0356 
0357             # Make the ConfigParser forget everything (so we retain
0358             # the original filenames that options come from)
0359             parser.__init__()
0360 
0361         # If there was a "global" section in the config file, use it
0362         # to set Distribution options.
0363 
0364         if self.command_options.has_key('global'):
0365             for (opt, (src, val)) in self.command_options['global'].items():
0366                 alias = self.negative_opt.get(opt)
0367                 try:
0368                     if alias:
0369                         setattr(self, alias, not strtobool(val))
0370                     elif opt in ('verbose', 'dry_run'): # ugh!
0371                         setattr(self, opt, strtobool(val))
0372                     else:
0373                         setattr(self, opt, val)
0374                 except ValueError, msg:
0375                     raise DistutilsOptionError, msg
0376 
0377     # parse_config_files ()
0378 
0379 
0380     # -- Command-line parsing methods ----------------------------------
0381 
0382     def parse_command_line (self):
0383         """Parse the setup script's command line, taken from the
0384         'script_args' instance attribute (which defaults to 'sys.argv[1:]'
0385         -- see 'setup()' in core.py).  This list is first processed for
0386         "global options" -- options that set attributes of the Distribution
0387         instance.  Then, it is alternately scanned for Distutils commands
0388         and options for that command.  Each new command terminates the
0389         options for the previous command.  The allowed options for a
0390         command are determined by the 'user_options' attribute of the
0391         command class -- thus, we have to be able to load command classes
0392         in order to parse the command line.  Any error in that 'options'
0393         attribute raises DistutilsGetoptError; any error on the
0394         command-line raises DistutilsArgError.  If no Distutils commands
0395         were found on the command line, raises DistutilsArgError.  Return
0396         true if command-line was successfully parsed and we should carry
0397         on with executing commands; false if no errors but we shouldn't
0398         execute commands (currently, this only happens if user asks for
0399         help).
0400         """
0401         #
0402         # We now have enough information to show the Macintosh dialog
0403         # that allows the user to interactively specify the "command line".
0404         #
0405         toplevel_options = self._get_toplevel_options()
0406         if sys.platform == 'mac':
0407             import EasyDialogs
0408             cmdlist = self.get_command_list()
0409             self.script_args = EasyDialogs.GetArgv(
0410                 toplevel_options + self.display_options, cmdlist)
0411 
0412         # We have to parse the command line a bit at a time -- global
0413         # options, then the first command, then its options, and so on --
0414         # because each command will be handled by a different class, and
0415         # the options that are valid for a particular class aren't known
0416         # until we have loaded the command class, which doesn't happen
0417         # until we know what the command is.
0418 
0419         self.commands = []
0420         parser = FancyGetopt(toplevel_options + self.display_options)
0421         parser.set_negative_aliases(self.negative_opt)
0422         parser.set_aliases({'licence': 'license'})
0423         args = parser.getopt(args=self.script_args, object=self)
0424         option_order = parser.get_option_order()
0425         log.set_verbosity(self.verbose)
0426 
0427         # for display options we return immediately
0428         if self.handle_display_options(option_order):
0429             return
0430 
0431         while args:
0432             args = self._parse_command_opts(parser, args)
0433             if args is None:            # user asked for help (and got it)
0434                 return
0435 
0436         # Handle the cases of --help as a "global" option, ie.
0437         # "setup.py --help" and "setup.py --help command ...".  For the
0438         # former, we show global options (--verbose, --dry-run, etc.)
0439         # and display-only options (--name, --version, etc.); for the
0440         # latter, we omit the display-only options and show help for
0441         # each command listed on the command line.
0442         if self.help:
0443             self._show_help(parser,
0444                             display_options=len(self.commands) == 0,
0445                             commands=self.commands)
0446             return
0447 
0448         # Oops, no commands found -- an end-user error
0449         if not self.commands:
0450             raise DistutilsArgError, "no commands supplied"
0451 
0452         # All is well: return true
0453         return 1
0454 
0455     # parse_command_line()
0456 
0457     def _get_toplevel_options (self):
0458         """Return the non-display options recognized at the top level.
0459 
0460         This includes options that are recognized *only* at the top
0461         level as well as options recognized for commands.
0462         """
0463         return self.global_options + [
0464             ("command-packages=", None,
0465              "list of packages that provide distutils commands"),
0466             ]
0467 
0468     def _parse_command_opts (self, parser, args):
0469         """Parse the command-line options for a single command.
0470         'parser' must be a FancyGetopt instance; 'args' must be the list
0471         of arguments, starting with the current command (whose options
0472         we are about to parse).  Returns a new version of 'args' with
0473         the next command at the front of the list; will be the empty
0474         list if there are no more commands on the command line.  Returns
0475         None if the user asked for help on this command.
0476         """
0477         # late import because of mutual dependence between these modules
0478         from distutils.cmd import Command
0479 
0480         # Pull the current command from the head of the command line
0481         command = args[0]
0482         if not command_re.match(command):
0483             raise SystemExit, "invalid command name '%s'" % command
0484         self.commands.append(command)
0485 
0486         # Dig up the command class that implements this command, so we
0487         # 1) know that it's a valid command, and 2) know which options
0488         # it takes.
0489         try:
0490             cmd_class = self.get_command_class(command)
0491         except DistutilsModuleError, msg:
0492             raise DistutilsArgError, msg
0493 
0494         # Require that the command class be derived from Command -- want
0495         # to be sure that the basic "command" interface is implemented.
0496         if not issubclass(cmd_class, Command):
0497             raise DistutilsClassError, \
0498                   "command class %s must subclass Command" % cmd_class
0499 
0500         # Also make sure that the command object provides a list of its
0501         # known options.
0502         if not (hasattr(cmd_class, 'user_options') and
0503                 type(cmd_class.user_options) is ListType):
0504             raise DistutilsClassError, \
0505                   ("command class %s must provide " +
0506                    "'user_options' attribute (a list of tuples)") % \
0507                   cmd_class
0508 
0509         # If the command class has a list of negative alias options,
0510         # merge it in with the global negative aliases.
0511         negative_opt = self.negative_opt
0512         if hasattr(cmd_class, 'negative_opt'):
0513             negative_opt = copy(negative_opt)
0514             negative_opt.update(cmd_class.negative_opt)
0515 
0516         # Check for help_options in command class.  They have a different
0517         # format (tuple of four) so we need to preprocess them here.
0518         if (hasattr(cmd_class, 'help_options') and
0519             type(cmd_class.help_options) is ListType):
0520             help_options = fix_help_options(cmd_class.help_options)
0521         else:
0522             help_options = []
0523 
0524 
0525         # All commands support the global options too, just by adding
0526         # in 'global_options'.
0527         parser.set_option_table(self.global_options +
0528                                 cmd_class.user_options +
0529                                 help_options)
0530         parser.set_negative_aliases(negative_opt)
0531         (args, opts) = parser.getopt(args[1:])
0532         if hasattr(opts, 'help') and opts.help:
0533             self._show_help(parser, display_options=0, commands=[cmd_class])
0534             return
0535 
0536         if (hasattr(cmd_class, 'help_options') and
0537             type(cmd_class.help_options) is ListType):
0538             help_option_found=0
0539             for (help_option, short, desc, func) in cmd_class.help_options:
0540                 if hasattr(opts, parser.get_attr_name(help_option)):
0541                     help_option_found=1
0542                     #print "showing help for option %s of command %s" % \
0543                     #      (help_option[0],cmd_class)
0544 
0545                     if callable(func):
0546                         func()
0547                     else:
0548                         raise DistutilsClassError(
0549                             "invalid help function %r for help option '%s': "
0550                             "must be a callable object (function, etc.)"
0551                             % (func, help_option))
0552 
0553             if help_option_found:
0554                 return
0555 
0556         # Put the options from the command-line into their official
0557         # holding pen, the 'command_options' dictionary.
0558         opt_dict = self.get_option_dict(command)
0559         for (name, value) in vars(opts).items():
0560             opt_dict[name] = ("command line", value)
0561 
0562         return args
0563 
0564     # _parse_command_opts ()
0565 
0566     def finalize_options (self):
0567         """Set final values for all the options on the Distribution
0568         instance, analogous to the .finalize_options() method of Command
0569         objects.
0570         """
0571 
0572         keywords = self.metadata.keywords
0573         if keywords is not None:
0574             if type(keywords) is StringType:
0575                 keywordlist = string.split(keywords, ',')
0576                 self.metadata.keywords = map(string.strip, keywordlist)
0577 
0578         platforms = self.metadata.platforms
0579         if platforms is not None:
0580             if type(platforms) is StringType:
0581                 platformlist = string.split(platforms, ',')
0582                 self.metadata.platforms = map(string.strip, platformlist)
0583 
0584     def _show_help (self,
0585                     parser,
0586                     global_options=1,
0587                     display_options=1,
0588                     commands=[]):
0589         """Show help for the setup script command-line in the form of
0590         several lists of command-line options.  'parser' should be a
0591         FancyGetopt instance; do not expect it to be returned in the
0592         same state, as its option table will be reset to make it
0593         generate the correct help text.
0594 
0595         If 'global_options' is true, lists the global options:
0596         --verbose, --dry-run, etc.  If 'display_options' is true, lists
0597         the "display-only" options: --name, --version, etc.  Finally,
0598         lists per-command help for every command name or command class
0599         in 'commands'.
0600         """
0601         # late import because of mutual dependence between these modules
0602         from distutils.core import gen_usage
0603         from distutils.cmd import Command
0604 
0605         if global_options:
0606             if display_options:
0607                 options = self._get_toplevel_options()
0608             else:
0609                 options = self.global_options
0610             parser.set_option_table(options)
0611             parser.print_help("Global options:")
0612             print
0613 
0614         if display_options:
0615             parser.set_option_table(self.display_options)
0616             parser.print_help(
0617                 "Information display options (just display " +
0618                 "information, ignore any commands)")
0619             print
0620 
0621         for command in self.commands:
0622             if type(command) is ClassType and issubclass(command, Command):
0623                 klass = command
0624             else:
0625                 klass = self.get_command_class(command)
0626             if (hasattr(klass, 'help_options') and
0627                 type(klass.help_options) is ListType):
0628                 parser.set_option_table(klass.user_options +
0629                                         fix_help_options(klass.help_options))
0630             else:
0631                 parser.set_option_table(klass.user_options)
0632             parser.print_help("Options for '%s' command:" % klass.__name__)
0633             print
0634 
0635         print gen_usage(self.script_name)
0636         return
0637 
0638     # _show_help ()
0639 
0640 
0641     def handle_display_options (self, option_order):
0642         """If there were any non-global "display-only" options
0643         (--help-commands or the metadata display options) on the command
0644         line, display the requested info and return true; else return
0645         false.
0646         """
0647         from distutils.core import gen_usage
0648 
0649         # User just wants a list of commands -- we'll print it out and stop
0650         # processing now (ie. if they ran "setup --help-commands foo bar",
0651         # we ignore "foo bar").
0652         if self.help_commands:
0653             self.print_commands()
0654             print
0655             print gen_usage(self.script_name)
0656             return 1
0657 
0658         # If user supplied any of the "display metadata" options, then
0659         # display that metadata in the order in which the user supplied the
0660         # metadata options.
0661         any_display_options = 0
0662         is_display_option = {}
0663         for option in self.display_options:
0664             is_display_option[option[0]] = 1
0665 
0666         for (opt, val) in option_order:
0667             if val and is_display_option.get(opt):
0668                 opt = translate_longopt(opt)
0669                 value = getattr(self.metadata, "get_"+opt)()
0670                 if opt in ['keywords', 'platforms']:
0671                     print string.join(value, ',')
0672                 elif opt == 'classifiers':
0673                     print string.join(value, '\n')
0674                 else:
0675                     print value
0676                 any_display_options = 1
0677 
0678         return any_display_options
0679 
0680     # handle_display_options()
0681 
0682     def print_command_list (self, commands, header, max_length):
0683         """Print a subset of the list of all commands -- used by
0684         'print_commands()'.
0685         """
0686 
0687         print header + ":"
0688 
0689         for cmd in commands:
0690             klass = self.cmdclass.get(cmd)
0691             if not klass:
0692                 klass = self.get_command_class(cmd)
0693             try:
0694                 description = klass.description
0695             except AttributeError:
0696                 description = "(no description available)"
0697 
0698             print "  %-*s  %s" % (max_length, cmd, description)
0699 
0700     # print_command_list ()
0701 
0702 
0703     def print_commands (self):
0704         """Print out a help message listing all available commands with a
0705         description of each.  The list is divided into "standard commands"
0706         (listed in distutils.command.__all__) and "extra commands"
0707         (mentioned in self.cmdclass, but not a standard command).  The
0708         descriptions come from the command class attribute
0709         'description'.
0710         """
0711 
0712         import distutils.command
0713         std_commands = distutils.command.__all__
0714         is_std = {}
0715         for cmd in std_commands:
0716             is_std[cmd] = 1
0717 
0718         extra_commands = []
0719         for cmd in self.cmdclass.keys():
0720             if not is_std.get(cmd):
0721                 extra_commands.append(cmd)
0722 
0723         max_length = 0
0724         for cmd in (std_commands + extra_commands):
0725             if len(cmd) > max_length:
0726                 max_length = len(cmd)
0727 
0728         self.print_command_list(std_commands,
0729                                 "Standard commands",
0730                                 max_length)
0731         if extra_commands:
0732             print
0733             self.print_command_list(extra_commands,
0734                                     "Extra commands",
0735                                     max_length)
0736 
0737     # print_commands ()
0738 
0739     def get_command_list (self):
0740         """Get a list of (command, description) tuples.
0741         The list is divided into "standard commands" (listed in
0742         distutils.command.__all__) and "extra commands" (mentioned in
0743         self.cmdclass, but not a standard command).  The descriptions come
0744         from the command class attribute 'description'.
0745         """
0746         # Currently this is only used on Mac OS, for the Mac-only GUI
0747         # Distutils interface (by Jack Jansen)
0748 
0749         import distutils.command
0750         std_commands = distutils.command.__all__
0751         is_std = {}
0752         for cmd in std_commands:
0753             is_std[cmd] = 1
0754 
0755         extra_commands = []
0756         for cmd in self.cmdclass.keys():
0757             if not is_std.get(cmd):
0758                 extra_commands.append(cmd)
0759 
0760         rv = []
0761         for cmd in (std_commands + extra_commands):
0762             klass = self.cmdclass.get(cmd)
0763             if not klass:
0764                 klass = self.get_command_class(cmd)
0765             try:
0766                 description = klass.description
0767             except AttributeError:
0768                 description = "(no description available)"
0769             rv.append((cmd, description))
0770         return rv
0771 
0772     # -- Command class/object methods ----------------------------------
0773 
0774     def get_command_packages (self):
0775         """Return a list of packages from which commands are loaded."""
0776         pkgs = self.command_packages
0777         if not isinstance(pkgs, type([])):
0778             pkgs = string.split(pkgs or "", ",")
0779             for i in range(len(pkgs)):
0780                 pkgs[i] = string.strip(pkgs[i])
0781             pkgs = filter(None, pkgs)
0782             if "distutils.command" not in pkgs:
0783                 pkgs.insert(0, "distutils.command")
0784             self.command_packages = pkgs
0785         return pkgs
0786 
0787     def get_command_class (self, command):
0788         """Return the class that implements the Distutils command named by
0789         'command'.  First we check the 'cmdclass' dictionary; if the
0790         command is mentioned there, we fetch the class object from the
0791         dictionary and return it.  Otherwise we load the command module
0792         ("distutils.command." + command) and fetch the command class from
0793         the module.  The loaded class is also stored in 'cmdclass'
0794         to speed future calls to 'get_command_class()'.
0795 
0796         Raises DistutilsModuleError if the expected module could not be
0797         found, or if that module does not define the expected class.
0798         """
0799         klass = self.cmdclass.get(command)
0800         if klass:
0801             return klass
0802 
0803         for pkgname in self.get_command_packages():
0804             module_name = "%s.%s" % (pkgname, command)
0805             klass_name = command
0806 
0807             try:
0808                 __import__ (module_name)
0809                 module = sys.modules[module_name]
0810             except ImportError:
0811                 continue
0812 
0813             try:
0814                 klass = getattr(module, klass_name)
0815             except AttributeError:
0816                 raise DistutilsModuleError, \
0817                       "invalid command '%s' (no class '%s' in module '%s')" \
0818                       % (command, klass_name, module_name)
0819 
0820             self.cmdclass[command] = klass
0821             return klass
0822 
0823         raise DistutilsModuleError("invalid command '%s'" % command)
0824 
0825 
0826     # get_command_class ()
0827 
0828     def get_command_obj (self, command, create=1):
0829         """Return the command object for 'command'.  Normally this object
0830         is cached on a previous call to 'get_command_obj()'; if no command
0831         object for 'command' is in the cache, then we either create and
0832         return it (if 'create' is true) or return None.
0833         """
0834         cmd_obj = self.command_obj.get(command)
0835         if not cmd_obj and create:
0836             if DEBUG:
0837                 print "Distribution.get_command_obj(): " \
0838                       "creating '%s' command object" % command
0839 
0840             klass = self.get_command_class(command)
0841             cmd_obj = self.command_obj[command] = klass(self)
0842             self.have_run[command] = 0
0843 
0844             # Set any options that were supplied in config files
0845             # or on the command line.  (NB. support for error
0846             # reporting is lame here: any errors aren't reported
0847             # until 'finalize_options()' is called, which means
0848             # we won't report the source of the error.)
0849             options = self.command_options.get(command)
0850             if options:
0851                 self._set_command_options(cmd_obj, options)
0852 
0853         return cmd_obj
0854 
0855     def _set_command_options (self, command_obj, option_dict=None):
0856         """Set the options for 'command_obj' from 'option_dict'.  Basically
0857         this means copying elements of a dictionary ('option_dict') to
0858         attributes of an instance ('command').
0859 
0860         'command_obj' must be a Command instance.  If 'option_dict' is not
0861         supplied, uses the standard option dictionary for this command
0862         (from 'self.command_options').
0863         """
0864         command_name = command_obj.get_command_name()
0865         if option_dict is None:
0866             option_dict = self.get_option_dict(command_name)
0867 
0868         if DEBUG: print "  setting options for '%s' command:" % command_name
0869         for (option, (source, value)) in option_dict.items():
0870             if DEBUG: print "    %s = %s (from %s)" % (option, value, source)
0871             try:
0872                 bool_opts = map(translate_longopt, command_obj.boolean_options)
0873             except AttributeError:
0874                 bool_opts = []
0875             try:
0876                 neg_opt = command_obj.negative_opt
0877             except AttributeError:
0878                 neg_opt = {}
0879 
0880             try:
0881                 is_string = type(value) is StringType
0882                 if neg_opt.has_key(option) and is_string:
0883                     setattr(command_obj, neg_opt[option], not strtobool(value))
0884                 elif option in bool_opts and is_string:
0885                     setattr(command_obj, option, strtobool(value))
0886                 elif hasattr(command_obj, option):
0887                     setattr(command_obj, option, value)
0888                 else:
0889                     raise DistutilsOptionError, \
0890                           ("error in %s: command '%s' has no such option '%s'"
0891                            % (source, command_name, option))
0892             except ValueError, msg:
0893                 raise DistutilsOptionError, msg
0894 
0895     def reinitialize_command (self, command, reinit_subcommands=0):
0896         """Reinitializes a command to the state it was in when first
0897         returned by 'get_command_obj()': ie., initialized but not yet
0898         finalized.  This provides the opportunity to sneak option
0899         values in programmatically, overriding or supplementing
0900         user-supplied values from the config files and command line.
0901         You'll have to re-finalize the command object (by calling
0902         'finalize_options()' or 'ensure_finalized()') before using it for
0903         real.
0904 
0905         'command' should be a command name (string) or command object.  If
0906         'reinit_subcommands' is true, also reinitializes the command's
0907         sub-commands, as declared by the 'sub_commands' class attribute (if
0908         it has one).  See the "install" command for an example.  Only
0909         reinitializes the sub-commands that actually matter, ie. those
0910         whose test predicates return true.
0911 
0912         Returns the reinitialized command object.
0913         """
0914         from distutils.cmd import Command
0915         if not isinstance(command, Command):
0916             command_name = command
0917             command = self.get_command_obj(command_name)
0918         else:
0919             command_name = command.get_command_name()
0920 
0921         if not command.finalized:
0922             return command
0923         command.initialize_options()
0924         command.finalized = 0
0925         self.have_run[command_name] = 0
0926         self._set_command_options(command)
0927 
0928         if reinit_subcommands:
0929             for sub in command.get_sub_commands():
0930                 self.reinitialize_command(sub, reinit_subcommands)
0931 
0932         return command
0933 
0934 
0935     # -- Methods that operate on the Distribution ----------------------
0936 
0937     def announce (self, msg, level=1):
0938         log.debug(msg)
0939 
0940     def run_commands (self):
0941         """Run each command that was seen on the setup script command line.
0942         Uses the list of commands found and cache of command objects
0943         created by 'get_command_obj()'.
0944         """
0945         for cmd in self.commands:
0946             self.run_command(cmd)
0947 
0948 
0949     # -- Methods that operate on its Commands --------------------------
0950 
0951     def run_command (self, command):
0952         """Do whatever it takes to run a command (including nothing at all,
0953         if the command has already been run).  Specifically: if we have
0954         already created and run the command named by 'command', return
0955         silently without doing anything.  If the command named by 'command'
0956         doesn't even have a command object yet, create one.  Then invoke
0957         'run()' on that command object (or an existing one).
0958         """
0959         # Already been here, done that? then return silently.
0960         if self.have_run.get(command):
0961             return
0962 
0963         log.info("running %s", command)
0964         cmd_obj = self.get_command_obj(command)
0965         cmd_obj.ensure_finalized()
0966         cmd_obj.run()
0967         self.have_run[command] = 1
0968 
0969 
0970     # -- Distribution query methods ------------------------------------
0971 
0972     def has_pure_modules (self):
0973         return len(self.packages or self.py_modules or []) > 0
0974 
0975     def has_ext_modules (self):
0976         return self.ext_modules and len(self.ext_modules) > 0
0977 
0978     def has_c_libraries (self):
0979         return self.libraries and len(self.libraries) > 0
0980 
0981     def has_modules (self):
0982         return self.has_pure_modules() or self.has_ext_modules()
0983 
0984     def has_headers (self):
0985         return self.headers and len(self.headers) > 0
0986 
0987     def has_scripts (self):
0988         return self.scripts and len(self.scripts) > 0
0989 
0990     def has_data_files (self):
0991         return self.data_files and len(self.data_files) > 0
0992 
0993     def is_pure (self):
0994         return (self.has_pure_modules() and
0995                 not self.has_ext_modules() and
0996                 not self.has_c_libraries())
0997 
0998     # -- Metadata query methods ----------------------------------------
0999 
1000     # If you're looking for 'get_name()', 'get_version()', and so forth,
1001     # they are defined in a sneaky way: the constructor binds self.get_XXX
1002     # to self.metadata.get_XXX.  The actual code is in the
1003     # DistributionMetadata class, below.
1004 
1005 # class Distribution
1006 
1007 
1008 class DistributionMetadata:
1009     """Dummy class to hold the distribution meta-data: name, version,
1010     author, and so forth.
1011     """
1012 
1013     _METHOD_BASENAMES = ("name", "version", "author", "author_email",
1014                          "maintainer", "maintainer_email", "url",
1015                          "license", "description", "long_description",
1016                          "keywords", "platforms", "fullname", "contact",
1017                          "contact_email", "license", "classifiers",
1018                          "download_url")
1019 
1020     def __init__ (self):
1021         self.name = None
1022         self.version = None
1023         self.author = None
1024         self.author_email = None
1025         self.maintainer = None
1026         self.maintainer_email = None
1027         self.url = None
1028         self.license = None
1029         self.description = None
1030         self.long_description = None
1031         self.keywords = None
1032         self.platforms = None
1033         self.classifiers = None
1034         self.download_url = None
1035 
1036     def write_pkg_info (self, base_dir):
1037         """Write the PKG-INFO file into the release tree.
1038         """
1039 
1040         pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
1041 
1042         pkg_info.write('Metadata-Version: 1.0\n')
1043         pkg_info.write('Name: %s\n' % self.get_name() )
1044         pkg_info.write('Version: %s\n' % self.get_version() )
1045         pkg_info.write('Summary: %s\n' % self.get_description() )
1046         pkg_info.write('Home-page: %s\n' % self.get_url() )
1047         pkg_info.write('Author: %s\n' % self.get_contact() )
1048         pkg_info.write('Author-email: %s\n' % self.get_contact_email() )
1049         pkg_info.write('License: %s\n' % self.get_license() )
1050         if self.download_url:
1051             pkg_info.write('Download-URL: %s\n' % self.download_url)
1052 
1053         long_desc = rfc822_escape( self.get_long_description() )
1054         pkg_info.write('Description: %s\n' % long_desc)
1055 
1056         keywords = string.join( self.get_keywords(), ',')
1057         if keywords:
1058             pkg_info.write('Keywords: %s\n' % keywords )
1059 
1060         for platform in self.get_platforms():
1061             pkg_info.write('Platform: %s\n' % platform )
1062 
1063         for classifier in self.get_classifiers():
1064             pkg_info.write('Classifier: %s\n' % classifier )
1065 
1066         pkg_info.close()
1067 
1068     # write_pkg_info ()
1069 
1070     # -- Metadata query methods ----------------------------------------
1071 
1072     def get_name (self):
1073         return self.name or "UNKNOWN"
1074 
1075     def get_version(self):
1076         return self.version or "0.0.0"
1077 
1078     def get_fullname (self):
1079         return "%s-%s" % (self.get_name(), self.get_version())
1080 
1081     def get_author(self):
1082         return self.author or "UNKNOWN"
1083 
1084     def get_author_email(self):
1085         return self.author_email or "UNKNOWN"
1086 
1087     def get_maintainer(self):
1088         return self.maintainer or "UNKNOWN"
1089 
1090     def get_maintainer_email(self):
1091         return self.maintainer_email or "UNKNOWN"
1092 
1093     def get_contact(self):
1094         return (self.maintainer or
1095                 self.author or
1096                 "UNKNOWN")
1097 
1098     def get_contact_email(self):
1099         return (self.maintainer_email or
1100                 self.author_email or
1101                 "UNKNOWN")
1102 
1103     def get_url(self):
1104         return self.url or "UNKNOWN"
1105 
1106     def get_license(self):
1107         return self.license or "UNKNOWN"
1108     get_licence = get_license
1109 
1110     def get_description(self):
1111         return self.description or "UNKNOWN"
1112 
1113     def get_long_description(self):
1114         return self.long_description or "UNKNOWN"
1115 
1116     def get_keywords(self):
1117         return self.keywords or []
1118 
1119     def get_platforms(self):
1120         return self.platforms or ["UNKNOWN"]
1121 
1122     def get_classifiers(self):
1123         return self.classifiers or []
1124 
1125     def get_download_url(self):
1126         return self.download_url or "UNKNOWN"
1127 
1128 # class DistributionMetadata
1129 
1130 
1131 def fix_help_options (options):
1132     """Convert a 4-tuple 'help_options' list as found in various command
1133     classes to the 3-tuple form required by FancyGetopt.
1134     """
1135     new_options = []
1136     for help_tuple in options:
1137         new_options.append(help_tuple[0:3])
1138     return new_options
1139 
1140 
1141 if __name__ == "__main__":
1142     dist = Distribution()
1143     print "ok"
1144 

Generated by PyXR 0.9.4
SourceForge.net Logo