]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/distutils/dist.py
   3 Provides the Distribution class, which represents the module distribution 
   4 being built/installed/distributed. 
   7 # This module should be kept compatible with Python 1.5.2. 
  11 import sys
, os
, string
, re
 
  20 from distutils
.errors 
import * 
  21 from distutils
.fancy_getopt 
import FancyGetopt
, translate_longopt
 
  22 from distutils
.util 
import check_environ
, strtobool
, rfc822_escape
 
  23 from distutils 
import log
 
  24 from distutils
.debug 
import DEBUG
 
  26 # Regex to define acceptable Distutils command names.  This is not *quite* 
  27 # the same as a Python NAME -- I don't allow leading underscores.  The fact 
  28 # that they're very similar is no coincidence; the default naming scheme is 
  29 # to look for a Python module named after the command. 
  30 command_re 
= re
.compile (r
'^[a-zA-Z]([a-zA-Z0-9_]*)$') 
  34     """The core of the Distutils.  Most of the work hiding behind 'setup' 
  35     is really done within a Distribution instance, which farms the work out 
  36     to the Distutils commands specified on the command line. 
  38     Setup scripts will almost never instantiate Distribution directly, 
  39     unless the 'setup()' function is totally inadequate to their needs. 
  40     However, it is conceivable that a setup script might wish to subclass 
  41     Distribution for some specialized purpose, and then pass the subclass 
  42     to 'setup()' as the 'distclass' keyword argument.  If so, it is 
  43     necessary to respect the expectations that 'setup' has of Distribution. 
  44     See the code for 'setup()', in core.py, for details. 
  48     # 'global_options' describes the command-line options that may be 
  49     # supplied to the setup script prior to any actual commands. 
  50     # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of 
  51     # these global options.  This list should be kept to a bare minimum, 
  52     # since every global option is also valid as a command option -- and we 
  53     # don't want to pollute the commands with too many options that they 
  54     # have minimal control over. 
  55     # The fourth entry for verbose means that it can be repeated. 
  56     global_options 
= [('verbose', 'v', "run verbosely (default)", 1), 
  57                       ('quiet', 'q', "run quietly (turns verbosity off)"), 
  58                       ('dry-run', 'n', "don't actually do anything"), 
  59                       ('help', 'h', "show detailed help message"), 
  62     # options that are not propagated to the commands 
  64         ('help-commands', None, 
  65          "list all available commands"), 
  67          "print package name"), 
  69          "print package version"), 
  71          "print <package name>-<version>"), 
  73          "print the author's name"), 
  74         ('author-email', None, 
  75          "print the author's email address"), 
  77          "print the maintainer's name"), 
  78         ('maintainer-email', None, 
  79          "print the maintainer's email address"), 
  81          "print the maintainer's name if known, else the author's"), 
  82         ('contact-email', None, 
  83          "print the maintainer's email address if known, else the author's"), 
  85          "print the URL for this package"), 
  87          "print the license of the package"), 
  89          "alias for --license"), 
  91          "print the package description"), 
  92         ('long-description', None, 
  93          "print the long package description"), 
  95          "print the list of platforms"), 
  97          "print the list of classifiers"), 
  99          "print the list of keywords"), 
 101     display_option_names 
= map(lambda x
: translate_longopt(x
[0]), 
 104     # negative options are options that exclude other options 
 105     negative_opt 
= {'quiet': 'verbose'}
 
 108     # -- Creation/initialization methods ------------------------------- 
 110     def __init__ (self
, attrs
=None): 
 111         """Construct a new Distribution instance: initialize all the 
 112         attributes of a Distribution, and then use 'attrs' (a dictionary 
 113         mapping attribute names to values) to assign some of those 
 114         attributes their "real" values.  (Any attributes not mentioned in 
 115         'attrs' will be assigned to some null value: 0, None, an empty list 
 116         or dictionary, etc.)  Most importantly, initialize the 
 117         'command_obj' attribute to the empty dictionary; this will be 
 118         filled in with real command objects by 'parse_command_line()'. 
 121         # Default values for our command-line options 
 125         for attr 
in self
.display_option_names
: 
 126             setattr(self
, attr
, 0) 
 128         # Store the distribution meta-data (name, version, author, and so 
 129         # forth) in a separate object -- we're getting to have enough 
 130         # information here (and enough command-line options) that it's 
 131         # worth it.  Also delegate 'get_XXX()' methods to the 'metadata' 
 132         # object in a sneaky and underhanded (but efficient!) way. 
 133         self
.metadata 
= DistributionMetadata() 
 134         for basename 
in self
.metadata
._METHOD
_BASENAMES
: 
 135             method_name 
= "get_" + basename
 
 136             setattr(self
, method_name
, getattr(self
.metadata
, method_name
)) 
 138         # 'cmdclass' maps command names to class objects, so we 
 139         # can 1) quickly figure out which class to instantiate when 
 140         # we need to create a new command object, and 2) have a way 
 141         # for the setup script to override command classes 
 144         # 'script_name' and 'script_args' are usually set to sys.argv[0] 
 145         # and sys.argv[1:], but they can be overridden when the caller is 
 146         # not necessarily a setup script run from the command-line. 
 147         self
.script_name 
= None 
 148         self
.script_args 
= None 
 150         # 'command_options' is where we store command options between 
 151         # parsing them (from config files, the command-line, etc.) and when 
 152         # they are actually needed -- ie. when the command in question is 
 153         # instantiated.  It is a dictionary of dictionaries of 2-tuples: 
 154         #   command_options = { command_name : { option : (source, value) } } 
 155         self
.command_options 
= {} 
 157         # These options are really the business of various commands, rather 
 158         # than of the Distribution itself.  We provide aliases for them in 
 159         # Distribution as a convenience to the developer. 
 161         self
.package_dir 
= None 
 162         self
.py_modules 
= None 
 163         self
.libraries 
= None 
 165         self
.ext_modules 
= None 
 166         self
.ext_package 
= None 
 167         self
.include_dirs 
= None 
 168         self
.extra_path 
= None 
 170         self
.data_files 
= None 
 172         # And now initialize bookkeeping stuff that can't be supplied by 
 173         # the caller at all.  'command_obj' maps command names to 
 174         # Command instances -- that's how we enforce that every command 
 175         # class is a singleton. 
 176         self
.command_obj 
= {} 
 178         # 'have_run' maps command names to boolean values; it keeps track 
 179         # of whether we have actually run a particular command, to make it 
 180         # cheap to "run" a command whenever we think we might need to -- if 
 181         # it's already been done, no need for expensive filesystem 
 182         # operations, we just check the 'have_run' dictionary and carry on. 
 183         # It's only safe to query 'have_run' for a command class that has 
 184         # been instantiated -- a false value will be inserted when the 
 185         # command object is created, and replaced with a true value when 
 186         # the command is successfully run.  Thus it's probably best to use 
 187         # '.get()' rather than a straight lookup. 
 190         # Now we'll use the attrs dictionary (ultimately, keyword args from 
 191         # the setup script) to possibly override any or all of these 
 192         # distribution options. 
 196             # Pull out the set of command options and work on them 
 197             # specifically.  Note that this order guarantees that aliased 
 198             # command options will override any supplied redundantly 
 199             # through the general options dictionary. 
 200             options 
= attrs
.get('options') 
 203                 for (command
, cmd_options
) in options
.items(): 
 204                     opt_dict 
= self
.get_option_dict(command
) 
 205                     for (opt
, val
) in cmd_options
.items(): 
 206                         opt_dict
[opt
] = ("setup script", val
) 
 208             # Now work on the rest of the attributes.  Any attribute that's 
 209             # not already defined is invalid! 
 210             for (key
,val
) in attrs
.items(): 
 211                 if hasattr(self
.metadata
, key
): 
 212                     setattr(self
.metadata
, key
, val
) 
 213                 elif hasattr(self
, key
): 
 214                     setattr(self
, key
, val
) 
 216                     msg 
= "Unknown distribution option: %s" % repr(key
) 
 217                     if warnings 
is not None: 
 220                         sys
.stderr
.write(msg 
+ "\n") 
 222         self
.finalize_options() 
 227     def get_option_dict (self
, command
): 
 228         """Get the option dictionary for a given command.  If that 
 229         command's option dictionary hasn't been created yet, then create it 
 230         and return the new dictionary; otherwise, return the existing 
 234         dict = self
.command_options
.get(command
) 
 236             dict = self
.command_options
[command
] = {} 
 240     def dump_option_dicts (self
, header
=None, commands
=None, indent
=""): 
 241         from pprint 
import pformat
 
 243         if commands 
is None:             # dump all command option dicts 
 244             commands 
= self
.command_options
.keys() 
 247         if header 
is not None: 
 248             print indent 
+ header
 
 249             indent 
= indent 
+ "  " 
 252             print indent 
+ "no commands known yet" 
 255         for cmd_name 
in commands
: 
 256             opt_dict 
= self
.command_options
.get(cmd_name
) 
 258                 print indent 
+ "no option dict for '%s' command" % cmd_name
 
 260                 print indent 
+ "option dict for '%s' command:" % cmd_name
 
 261                 out 
= pformat(opt_dict
) 
 262                 for line 
in string
.split(out
, "\n"): 
 263                     print indent 
+ "  " + line
 
 265     # dump_option_dicts () 
 269     # -- Config file finding/parsing methods --------------------------- 
 271     def find_config_files (self
): 
 272         """Find as many configuration files as should be processed for this 
 273         platform, and return a list of filenames in the order in which they 
 274         should be parsed.  The filenames returned are guaranteed to exist 
 275         (modulo nasty race conditions). 
 277         There are three possible config files: distutils.cfg in the 
 278         Distutils installation directory (ie. where the top-level 
 279         Distutils __inst__.py file lives), a file in the user's home 
 280         directory named .pydistutils.cfg on Unix and pydistutils.cfg 
 281         on Windows/Mac, and setup.cfg in the current directory. 
 286         # Where to look for the system-wide Distutils config file 
 287         sys_dir 
= os
.path
.dirname(sys
.modules
['distutils'].__file
__) 
 289         # Look for the system config file 
 290         sys_file 
= os
.path
.join(sys_dir
, "distutils.cfg") 
 291         if os
.path
.isfile(sys_file
): 
 292             files
.append(sys_file
) 
 294         # What to call the per-user config file 
 295         if os
.name 
== 'posix': 
 296             user_filename 
= ".pydistutils.cfg" 
 298             user_filename 
= "pydistutils.cfg" 
 300         # And look for the user config file 
 301         if os
.environ
.has_key('HOME'): 
 302             user_file 
= os
.path
.join(os
.environ
.get('HOME'), user_filename
) 
 303             if os
.path
.isfile(user_file
): 
 304                 files
.append(user_file
) 
 306         # All platforms support local setup.cfg 
 307         local_file 
= "setup.cfg" 
 308         if os
.path
.isfile(local_file
): 
 309             files
.append(local_file
) 
 313     # find_config_files () 
 316     def parse_config_files (self
, filenames
=None): 
 318         from ConfigParser 
import ConfigParser
 
 320         if filenames 
is None: 
 321             filenames 
= self
.find_config_files() 
 323         if DEBUG
: print "Distribution.parse_config_files():" 
 325         parser 
= ConfigParser() 
 326         for filename 
in filenames
: 
 327             if DEBUG
: print "  reading", filename
 
 328             parser
.read(filename
) 
 329             for section 
in parser
.sections(): 
 330                 options 
= parser
.options(section
) 
 331                 opt_dict 
= self
.get_option_dict(section
) 
 334                     if opt 
!= '__name__': 
 335                         val 
= parser
.get(section
,opt
) 
 336                         opt 
= string
.replace(opt
, '-', '_') 
 337                         opt_dict
[opt
] = (filename
, val
) 
 339             # Make the ConfigParser forget everything (so we retain 
 340             # the original filenames that options come from) -- gag, 
 341             # retch, puke -- another good reason for a distutils- 
 342             # specific config parser (sigh...) 
 345         # If there was a "global" section in the config file, use it 
 346         # to set Distribution options. 
 348         if self
.command_options
.has_key('global'): 
 349             for (opt
, (src
, val
)) in self
.command_options
['global'].items(): 
 350                 alias 
= self
.negative_opt
.get(opt
) 
 353                         setattr(self
, alias
, not strtobool(val
)) 
 354                     elif opt 
in ('verbose', 'dry_run'): # ugh! 
 355                         setattr(self
, opt
, strtobool(val
)) 
 356                 except ValueError, msg
: 
 357                     raise DistutilsOptionError
, msg
 
 359     # parse_config_files () 
 362     # -- Command-line parsing methods ---------------------------------- 
 364     def parse_command_line (self
): 
 365         """Parse the setup script's command line, taken from the 
 366         'script_args' instance attribute (which defaults to 'sys.argv[1:]' 
 367         -- see 'setup()' in core.py).  This list is first processed for 
 368         "global options" -- options that set attributes of the Distribution 
 369         instance.  Then, it is alternately scanned for Distutils commands 
 370         and options for that command.  Each new command terminates the 
 371         options for the previous command.  The allowed options for a 
 372         command are determined by the 'user_options' attribute of the 
 373         command class -- thus, we have to be able to load command classes 
 374         in order to parse the command line.  Any error in that 'options' 
 375         attribute raises DistutilsGetoptError; any error on the 
 376         command-line raises DistutilsArgError.  If no Distutils commands 
 377         were found on the command line, raises DistutilsArgError.  Return 
 378         true if command-line was successfully parsed and we should carry 
 379         on with executing commands; false if no errors but we shouldn't 
 380         execute commands (currently, this only happens if user asks for 
 384         # We now have enough information to show the Macintosh dialog 
 385         # that allows the user to interactively specify the "command line". 
 387         if sys
.platform 
== 'mac': 
 389             cmdlist 
= self
.get_command_list() 
 390             self
.script_args 
= EasyDialogs
.GetArgv( 
 391                 self
.global_options 
+ self
.display_options
, cmdlist
) 
 393         # We have to parse the command line a bit at a time -- global 
 394         # options, then the first command, then its options, and so on -- 
 395         # because each command will be handled by a different class, and 
 396         # the options that are valid for a particular class aren't known 
 397         # until we have loaded the command class, which doesn't happen 
 398         # until we know what the command is. 
 401         parser 
= FancyGetopt(self
.global_options 
+ self
.display_options
) 
 402         parser
.set_negative_aliases(self
.negative_opt
) 
 403         parser
.set_aliases({'licence': 'license'}
) 
 404         args 
= parser
.getopt(args
=self
.script_args
, object=self
) 
 405         option_order 
= parser
.get_option_order() 
 406         log
.set_verbosity(self
.verbose
) 
 408         # for display options we return immediately 
 409         if self
.handle_display_options(option_order
): 
 413             args 
= self
._parse
_command
_opts
(parser
, args
) 
 414             if args 
is None:            # user asked for help (and got it) 
 417         # Handle the cases of --help as a "global" option, ie. 
 418         # "setup.py --help" and "setup.py --help command ...".  For the 
 419         # former, we show global options (--verbose, --dry-run, etc.) 
 420         # and display-only options (--name, --version, etc.); for the 
 421         # latter, we omit the display-only options and show help for 
 422         # each command listed on the command line. 
 424             self
._show
_help
(parser
, 
 425                             display_options
=len(self
.commands
) == 0, 
 426                             commands
=self
.commands
) 
 429         # Oops, no commands found -- an end-user error 
 430         if not self
.commands
: 
 431             raise DistutilsArgError
, "no commands supplied" 
 433         # All is well: return true 
 436     # parse_command_line() 
 438     def _parse_command_opts (self
, parser
, args
): 
 439         """Parse the command-line options for a single command. 
 440         'parser' must be a FancyGetopt instance; 'args' must be the list 
 441         of arguments, starting with the current command (whose options 
 442         we are about to parse).  Returns a new version of 'args' with 
 443         the next command at the front of the list; will be the empty 
 444         list if there are no more commands on the command line.  Returns 
 445         None if the user asked for help on this command. 
 447         # late import because of mutual dependence between these modules 
 448         from distutils
.cmd 
import Command
 
 450         # Pull the current command from the head of the command line 
 452         if not command_re
.match(command
): 
 453             raise SystemExit, "invalid command name '%s'" % command
 
 454         self
.commands
.append(command
) 
 456         # Dig up the command class that implements this command, so we 
 457         # 1) know that it's a valid command, and 2) know which options 
 460             cmd_class 
= self
.get_command_class(command
) 
 461         except DistutilsModuleError
, msg
: 
 462             raise DistutilsArgError
, msg
 
 464         # Require that the command class be derived from Command -- want 
 465         # to be sure that the basic "command" interface is implemented. 
 466         if not issubclass(cmd_class
, Command
): 
 467             raise DistutilsClassError
, \
 
 468                   "command class %s must subclass Command" % cmd_class
 
 470         # Also make sure that the command object provides a list of its 
 472         if not (hasattr(cmd_class
, 'user_options') and 
 473                 type(cmd_class
.user_options
) is ListType
): 
 474             raise DistutilsClassError
, \
 
 475                   ("command class %s must provide " + 
 476                    "'user_options' attribute (a list of tuples)") % \
 
 479         # If the command class has a list of negative alias options, 
 480         # merge it in with the global negative aliases. 
 481         negative_opt 
= self
.negative_opt
 
 482         if hasattr(cmd_class
, 'negative_opt'): 
 483             negative_opt 
= copy(negative_opt
) 
 484             negative_opt
.update(cmd_class
.negative_opt
) 
 486         # Check for help_options in command class.  They have a different 
 487         # format (tuple of four) so we need to preprocess them here. 
 488         if (hasattr(cmd_class
, 'help_options') and 
 489             type(cmd_class
.help_options
) is ListType
): 
 490             help_options 
= fix_help_options(cmd_class
.help_options
) 
 495         # All commands support the global options too, just by adding 
 496         # in 'global_options'. 
 497         parser
.set_option_table(self
.global_options 
+ 
 498                                 cmd_class
.user_options 
+ 
 500         parser
.set_negative_aliases(negative_opt
) 
 501         (args
, opts
) = parser
.getopt(args
[1:]) 
 502         if hasattr(opts
, 'help') and opts
.help: 
 503             self
._show
_help
(parser
, display_options
=0, commands
=[cmd_class
]) 
 506         if (hasattr(cmd_class
, 'help_options') and 
 507             type(cmd_class
.help_options
) is ListType
): 
 509             for (help_option
, short
, desc
, func
) in cmd_class
.help_options
: 
 510                 if hasattr(opts
, parser
.get_attr_name(help_option
)): 
 512                     #print "showing help for option %s of command %s" % \ 
 513                     #      (help_option[0],cmd_class) 
 518                         raise DistutilsClassError( 
 519                             "invalid help function %s for help option '%s': " 
 520                             "must be a callable object (function, etc.)" 
 521                             % (`func`
, help_option
)) 
 523             if help_option_found
: 
 526         # Put the options from the command-line into their official 
 527         # holding pen, the 'command_options' dictionary. 
 528         opt_dict 
= self
.get_option_dict(command
) 
 529         for (name
, value
) in vars(opts
).items(): 
 530             opt_dict
[name
] = ("command line", value
) 
 534     # _parse_command_opts () 
 537     def finalize_options (self
): 
 538         """Set final values for all the options on the Distribution 
 539         instance, analogous to the .finalize_options() method of Command 
 543         keywords 
= self
.metadata
.keywords
 
 544         if keywords 
is not None: 
 545             if type(keywords
) is StringType
: 
 546                 keywordlist 
= string
.split(keywords
, ',') 
 547                 self
.metadata
.keywords 
= map(string
.strip
, keywordlist
) 
 549         platforms 
= self
.metadata
.platforms
 
 550         if platforms 
is not None: 
 551             if type(platforms
) is StringType
: 
 552                 platformlist 
= string
.split(platforms
, ',') 
 553                 self
.metadata
.platforms 
= map(string
.strip
, platformlist
) 
 555     def _show_help (self
, 
 560         """Show help for the setup script command-line in the form of 
 561         several lists of command-line options.  'parser' should be a 
 562         FancyGetopt instance; do not expect it to be returned in the 
 563         same state, as its option table will be reset to make it 
 564         generate the correct help text. 
 566         If 'global_options' is true, lists the global options: 
 567         --verbose, --dry-run, etc.  If 'display_options' is true, lists 
 568         the "display-only" options: --name, --version, etc.  Finally, 
 569         lists per-command help for every command name or command class 
 572         # late import because of mutual dependence between these modules 
 573         from distutils
.core 
import gen_usage
 
 574         from distutils
.cmd 
import Command
 
 577             parser
.set_option_table(self
.global_options
) 
 578             parser
.print_help("Global options:") 
 582             parser
.set_option_table(self
.display_options
) 
 584                 "Information display options (just display " + 
 585                 "information, ignore any commands)") 
 588         for command 
in self
.commands
: 
 589             if type(command
) is ClassType 
and issubclass(command
, Command
): 
 592                 klass 
= self
.get_command_class(command
) 
 593             if (hasattr(klass
, 'help_options') and 
 594                 type(klass
.help_options
) is ListType
): 
 595                 parser
.set_option_table(klass
.user_options 
+ 
 596                                         fix_help_options(klass
.help_options
)) 
 598                 parser
.set_option_table(klass
.user_options
) 
 599             parser
.print_help("Options for '%s' command:" % klass
.__name
__) 
 602         print gen_usage(self
.script_name
) 
 608     def handle_display_options (self
, option_order
): 
 609         """If there were any non-global "display-only" options 
 610         (--help-commands or the metadata display options) on the command 
 611         line, display the requested info and return true; else return 
 614         from distutils
.core 
import gen_usage
 
 616         # User just wants a list of commands -- we'll print it out and stop 
 617         # processing now (ie. if they ran "setup --help-commands foo bar", 
 618         # we ignore "foo bar"). 
 619         if self
.help_commands
: 
 620             self
.print_commands() 
 622             print gen_usage(self
.script_name
) 
 625         # If user supplied any of the "display metadata" options, then 
 626         # display that metadata in the order in which the user supplied the 
 628         any_display_options 
= 0 
 629         is_display_option 
= {} 
 630         for option 
in self
.display_options
: 
 631             is_display_option
[option
[0]] = 1 
 633         for (opt
, val
) in option_order
: 
 634             if val 
and is_display_option
.get(opt
): 
 635                 opt 
= translate_longopt(opt
) 
 636                 value 
= getattr(self
.metadata
, "get_"+opt
)() 
 637                 if opt 
in ['keywords', 'platforms']: 
 638                     print string
.join(value
, ',') 
 639                 elif opt 
== 'classifiers': 
 640                     print string
.join(value
, '\n') 
 643                 any_display_options 
= 1 
 645         return any_display_options
 
 647     # handle_display_options() 
 649     def print_command_list (self
, commands
, header
, max_length
): 
 650         """Print a subset of the list of all commands -- used by 
 657             klass 
= self
.cmdclass
.get(cmd
) 
 659                 klass 
= self
.get_command_class(cmd
) 
 661                 description 
= klass
.description
 
 662             except AttributeError: 
 663                 description 
= "(no description available)" 
 665             print "  %-*s  %s" % (max_length
, cmd
, description
) 
 667     # print_command_list () 
 670     def print_commands (self
): 
 671         """Print out a help message listing all available commands with a 
 672         description of each.  The list is divided into "standard commands" 
 673         (listed in distutils.command.__all__) and "extra commands" 
 674         (mentioned in self.cmdclass, but not a standard command).  The 
 675         descriptions come from the command class attribute 
 679         import distutils
.command
 
 680         std_commands 
= distutils
.command
.__all
__ 
 682         for cmd 
in std_commands
: 
 686         for cmd 
in self
.cmdclass
.keys(): 
 687             if not is_std
.get(cmd
): 
 688                 extra_commands
.append(cmd
) 
 691         for cmd 
in (std_commands 
+ extra_commands
): 
 692             if len(cmd
) > max_length
: 
 693                 max_length 
= len(cmd
) 
 695         self
.print_command_list(std_commands
, 
 700             self
.print_command_list(extra_commands
, 
 706     def get_command_list (self
): 
 707         """Get a list of (command, description) tuples. 
 708         The list is divided into "standard commands" (listed in 
 709         distutils.command.__all__) and "extra commands" (mentioned in 
 710         self.cmdclass, but not a standard command).  The descriptions come 
 711         from the command class attribute 'description'. 
 713         # Currently this is only used on Mac OS, for the Mac-only GUI 
 714         # Distutils interface (by Jack Jansen) 
 716         import distutils
.command
 
 717         std_commands 
= distutils
.command
.__all
__ 
 719         for cmd 
in std_commands
: 
 723         for cmd 
in self
.cmdclass
.keys(): 
 724             if not is_std
.get(cmd
): 
 725                 extra_commands
.append(cmd
) 
 728         for cmd 
in (std_commands 
+ extra_commands
): 
 729             klass 
= self
.cmdclass
.get(cmd
) 
 731                 klass 
= self
.get_command_class(cmd
) 
 733                 description 
= klass
.description
 
 734             except AttributeError: 
 735                 description 
= "(no description available)" 
 736             rv
.append((cmd
, description
)) 
 739     # -- Command class/object methods ---------------------------------- 
 741     def get_command_class (self
, command
): 
 742         """Return the class that implements the Distutils command named by 
 743         'command'.  First we check the 'cmdclass' dictionary; if the 
 744         command is mentioned there, we fetch the class object from the 
 745         dictionary and return it.  Otherwise we load the command module 
 746         ("distutils.command." + command) and fetch the command class from 
 747         the module.  The loaded class is also stored in 'cmdclass' 
 748         to speed future calls to 'get_command_class()'. 
 750         Raises DistutilsModuleError if the expected module could not be 
 751         found, or if that module does not define the expected class. 
 753         klass 
= self
.cmdclass
.get(command
) 
 757         module_name 
= 'distutils.command.' + command
 
 761             __import__ (module_name
) 
 762             module 
= sys
.modules
[module_name
] 
 764             raise DistutilsModuleError
, \
 
 765                   "invalid command '%s' (no module named '%s')" % \
 
 766                   (command
, module_name
) 
 769             klass 
= getattr(module
, klass_name
) 
 770         except AttributeError: 
 771             raise DistutilsModuleError
, \
 
 772                   "invalid command '%s' (no class '%s' in module '%s')" \
 
 773                   % (command
, klass_name
, module_name
) 
 775         self
.cmdclass
[command
] = klass
 
 778     # get_command_class () 
 780     def get_command_obj (self
, command
, create
=1): 
 781         """Return the command object for 'command'.  Normally this object 
 782         is cached on a previous call to 'get_command_obj()'; if no command 
 783         object for 'command' is in the cache, then we either create and 
 784         return it (if 'create' is true) or return None. 
 786         cmd_obj 
= self
.command_obj
.get(command
) 
 787         if not cmd_obj 
and create
: 
 789                 print "Distribution.get_command_obj(): " \
 
 790                       "creating '%s' command object" % command
 
 792             klass 
= self
.get_command_class(command
) 
 793             cmd_obj 
= self
.command_obj
[command
] = klass(self
) 
 794             self
.have_run
[command
] = 0 
 796             # Set any options that were supplied in config files 
 797             # or on the command line.  (NB. support for error 
 798             # reporting is lame here: any errors aren't reported 
 799             # until 'finalize_options()' is called, which means 
 800             # we won't report the source of the error.) 
 801             options 
= self
.command_options
.get(command
) 
 803                 self
._set
_command
_options
(cmd_obj
, options
) 
 807     def _set_command_options (self
, command_obj
, option_dict
=None): 
 808         """Set the options for 'command_obj' from 'option_dict'.  Basically 
 809         this means copying elements of a dictionary ('option_dict') to 
 810         attributes of an instance ('command'). 
 812         'command_obj' must be a Command instance.  If 'option_dict' is not 
 813         supplied, uses the standard option dictionary for this command 
 814         (from 'self.command_options'). 
 816         command_name 
= command_obj
.get_command_name() 
 817         if option_dict 
is None: 
 818             option_dict 
= self
.get_option_dict(command_name
) 
 820         if DEBUG
: print "  setting options for '%s' command:" % command_name
 
 821         for (option
, (source
, value
)) in option_dict
.items(): 
 822             if DEBUG
: print "    %s = %s (from %s)" % (option
, value
, source
) 
 824                 bool_opts 
= map(translate_longopt
, command_obj
.boolean_options
) 
 825             except AttributeError: 
 828                 neg_opt 
= command_obj
.negative_opt
 
 829             except AttributeError: 
 833                 is_string 
= type(value
) is StringType
 
 834                 if neg_opt
.has_key(option
) and is_string
: 
 835                     setattr(command_obj
, neg_opt
[option
], not strtobool(value
)) 
 836                 elif option 
in bool_opts 
and is_string
: 
 837                     setattr(command_obj
, option
, strtobool(value
)) 
 838                 elif hasattr(command_obj
, option
): 
 839                     setattr(command_obj
, option
, value
) 
 841                     raise DistutilsOptionError
, \
 
 842                           ("error in %s: command '%s' has no such option '%s'" 
 843                            % (source
, command_name
, option
)) 
 844             except ValueError, msg
: 
 845                 raise DistutilsOptionError
, msg
 
 847     def reinitialize_command (self
, command
, reinit_subcommands
=0): 
 848         """Reinitializes a command to the state it was in when first 
 849         returned by 'get_command_obj()': ie., initialized but not yet 
 850         finalized.  This provides the opportunity to sneak option 
 851         values in programmatically, overriding or supplementing 
 852         user-supplied values from the config files and command line. 
 853         You'll have to re-finalize the command object (by calling 
 854         'finalize_options()' or 'ensure_finalized()') before using it for 
 857         'command' should be a command name (string) or command object.  If 
 858         'reinit_subcommands' is true, also reinitializes the command's 
 859         sub-commands, as declared by the 'sub_commands' class attribute (if 
 860         it has one).  See the "install" command for an example.  Only 
 861         reinitializes the sub-commands that actually matter, ie. those 
 862         whose test predicates return true. 
 864         Returns the reinitialized command object. 
 866         from distutils
.cmd 
import Command
 
 867         if not isinstance(command
, Command
): 
 868             command_name 
= command
 
 869             command 
= self
.get_command_obj(command_name
) 
 871             command_name 
= command
.get_command_name() 
 873         if not command
.finalized
: 
 875         command
.initialize_options() 
 876         command
.finalized 
= 0 
 877         self
.have_run
[command_name
] = 0 
 878         self
._set
_command
_options
(command
) 
 880         if reinit_subcommands
: 
 881             for sub 
in command
.get_sub_commands(): 
 882                 self
.reinitialize_command(sub
, reinit_subcommands
) 
 887     # -- Methods that operate on the Distribution ---------------------- 
 889     def announce (self
, msg
, level
=1): 
 892     def run_commands (self
): 
 893         """Run each command that was seen on the setup script command line. 
 894         Uses the list of commands found and cache of command objects 
 895         created by 'get_command_obj()'. 
 897         for cmd 
in self
.commands
: 
 898             self
.run_command(cmd
) 
 901     # -- Methods that operate on its Commands -------------------------- 
 903     def run_command (self
, command
): 
 904         """Do whatever it takes to run a command (including nothing at all, 
 905         if the command has already been run).  Specifically: if we have 
 906         already created and run the command named by 'command', return 
 907         silently without doing anything.  If the command named by 'command' 
 908         doesn't even have a command object yet, create one.  Then invoke 
 909         'run()' on that command object (or an existing one). 
 911         # Already been here, done that? then return silently. 
 912         if self
.have_run
.get(command
): 
 915         log
.info("running %s", command
) 
 916         cmd_obj 
= self
.get_command_obj(command
) 
 917         cmd_obj
.ensure_finalized() 
 919         self
.have_run
[command
] = 1 
 922     # -- Distribution query methods ------------------------------------ 
 924     def has_pure_modules (self
): 
 925         return len(self
.packages 
or self
.py_modules 
or []) > 0 
 927     def has_ext_modules (self
): 
 928         return self
.ext_modules 
and len(self
.ext_modules
) > 0 
 930     def has_c_libraries (self
): 
 931         return self
.libraries 
and len(self
.libraries
) > 0 
 933     def has_modules (self
): 
 934         return self
.has_pure_modules() or self
.has_ext_modules() 
 936     def has_headers (self
): 
 937         return self
.headers 
and len(self
.headers
) > 0 
 939     def has_scripts (self
): 
 940         return self
.scripts 
and len(self
.scripts
) > 0 
 942     def has_data_files (self
): 
 943         return self
.data_files 
and len(self
.data_files
) > 0 
 946         return (self
.has_pure_modules() and 
 947                 not self
.has_ext_modules() and 
 948                 not self
.has_c_libraries()) 
 950     # -- Metadata query methods ---------------------------------------- 
 952     # If you're looking for 'get_name()', 'get_version()', and so forth, 
 953     # they are defined in a sneaky way: the constructor binds self.get_XXX 
 954     # to self.metadata.get_XXX.  The actual code is in the 
 955     # DistributionMetadata class, below. 
 960 class DistributionMetadata
: 
 961     """Dummy class to hold the distribution meta-data: name, version, 
 962     author, and so forth. 
 965     _METHOD_BASENAMES 
= ("name", "version", "author", "author_email", 
 966                          "maintainer", "maintainer_email", "url", 
 967                          "license", "description", "long_description", 
 968                          "keywords", "platforms", "fullname", "contact", 
 969                          "contact_email", "licence", "classifiers", 
 976         self
.author_email 
= None 
 977         self
.maintainer 
= None 
 978         self
.maintainer_email 
= None 
 981         self
.description 
= None 
 982         self
.long_description 
= None 
 984         self
.platforms 
= None 
 985         self
.classifiers 
= None 
 986         self
.download_url 
= None 
 988     def write_pkg_info (self
, base_dir
): 
 989         """Write the PKG-INFO file into the release tree. 
 992         pkg_info 
= open( os
.path
.join(base_dir
, 'PKG-INFO'), 'w') 
 994         pkg_info
.write('Metadata-Version: 1.0\n') 
 995         pkg_info
.write('Name: %s\n' % self
.get_name() ) 
 996         pkg_info
.write('Version: %s\n' % self
.get_version() ) 
 997         pkg_info
.write('Summary: %s\n' % self
.get_description() ) 
 998         pkg_info
.write('Home-page: %s\n' % self
.get_url() ) 
 999         pkg_info
.write('Author: %s\n' % self
.get_contact() ) 
1000         pkg_info
.write('Author-email: %s\n' % self
.get_contact_email() ) 
1001         pkg_info
.write('License: %s\n' % self
.get_license() ) 
1002         if self
.download_url
: 
1003             pkg_info
.write('Download-URL: %s\n' % self
.download_url
) 
1005         long_desc 
= rfc822_escape( self
.get_long_description() ) 
1006         pkg_info
.write('Description: %s\n' % long_desc
) 
1008         keywords 
= string
.join( self
.get_keywords(), ',') 
1010             pkg_info
.write('Keywords: %s\n' % keywords 
) 
1012         for platform 
in self
.get_platforms(): 
1013             pkg_info
.write('Platform: %s\n' % platform 
) 
1015         for classifier 
in self
.get_classifiers(): 
1016             pkg_info
.write('Classifier: %s\n' % classifier 
) 
1022     # -- Metadata query methods ---------------------------------------- 
1024     def get_name (self
): 
1025         return self
.name 
or "UNKNOWN" 
1027     def get_version(self
): 
1028         return self
.version 
or "0.0.0" 
1030     def get_fullname (self
): 
1031         return "%s-%s" % (self
.get_name(), self
.get_version()) 
1033     def get_author(self
): 
1034         return self
.author 
or "UNKNOWN" 
1036     def get_author_email(self
): 
1037         return self
.author_email 
or "UNKNOWN" 
1039     def get_maintainer(self
): 
1040         return self
.maintainer 
or "UNKNOWN" 
1042     def get_maintainer_email(self
): 
1043         return self
.maintainer_email 
or "UNKNOWN" 
1045     def get_contact(self
): 
1046         return (self
.maintainer 
or 
1050     def get_contact_email(self
): 
1051         return (self
.maintainer_email 
or 
1052                 self
.author_email 
or 
1056         return self
.url 
or "UNKNOWN" 
1058     def get_license(self
): 
1059         return self
.license 
or "UNKNOWN" 
1060     get_licence 
= get_license
 
1062     def get_description(self
): 
1063         return self
.description 
or "UNKNOWN" 
1065     def get_long_description(self
): 
1066         return self
.long_description 
or "UNKNOWN" 
1068     def get_keywords(self
): 
1069         return self
.keywords 
or [] 
1071     def get_platforms(self
): 
1072         return self
.platforms 
or ["UNKNOWN"] 
1074     def get_classifiers(self
): 
1075         return self
.classifiers 
or [] 
1077     def get_download_url(self
): 
1078         return self
.download_url 
or "UNKNOWN" 
1080 # class DistributionMetadata 
1083 def fix_help_options (options
): 
1084     """Convert a 4-tuple 'help_options' list as found in various command 
1085     classes to the 3-tuple form required by FancyGetopt. 
1088     for help_tuple 
in options
: 
1089         new_options
.append(help_tuple
[0:3]) 
1093 if __name__ 
== "__main__": 
1094     dist 
= Distribution()