3 Provides the Distribution class, which represents the module distribution
4 being built/installed/distributed.
7 # created 2000/04/03, Greg Ward
8 # (extricated from core.py; actually dates back to the beginning)
12 import sys
, os
, string
, re
15 from distutils
.errors
import *
16 from distutils
.fancy_getopt
import FancyGetopt
, translate_longopt
17 from distutils
.util
import check_environ
, strtobool
, rfc822_escape
20 # Regex to define acceptable Distutils command names. This is not *quite*
21 # the same as a Python NAME -- I don't allow leading underscores. The fact
22 # that they're very similar is no coincidence; the default naming scheme is
23 # to look for a Python module named after the command.
24 command_re
= re
.compile (r
'^[a-zA-Z]([a-zA-Z0-9_]*)$')
28 """The core of the Distutils. Most of the work hiding behind 'setup'
29 is really done within a Distribution instance, which farms the work out
30 to the Distutils commands specified on the command line.
32 Setup scripts will almost never instantiate Distribution directly,
33 unless the 'setup()' function is totally inadequate to their needs.
34 However, it is conceivable that a setup script might wish to subclass
35 Distribution for some specialized purpose, and then pass the subclass
36 to 'setup()' as the 'distclass' keyword argument. If so, it is
37 necessary to respect the expectations that 'setup' has of Distribution.
38 See the code for 'setup()', in core.py, for details.
42 # 'global_options' describes the command-line options that may be
43 # supplied to the setup script prior to any actual commands.
44 # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
45 # these global options. This list should be kept to a bare minimum,
46 # since every global option is also valid as a command option -- and we
47 # don't want to pollute the commands with too many options that they
48 # have minimal control over.
49 global_options
= [('verbose', 'v', "run verbosely (default)"),
50 ('quiet', 'q', "run quietly (turns verbosity off)"),
51 ('dry-run', 'n', "don't actually do anything"),
52 ('help', 'h', "show detailed help message"),
55 # options that are not propagated to the commands
57 ('help-commands', None,
58 "list all available commands"),
60 "print package name"),
62 "print package version"),
64 "print <package name>-<version>"),
66 "print the author's name"),
67 ('author-email', None,
68 "print the author's email address"),
70 "print the maintainer's name"),
71 ('maintainer-email', None,
72 "print the maintainer's email address"),
74 "print the maintainer's name if known, else the author's"),
75 ('contact-email', None,
76 "print the maintainer's email address if known, else the author's"),
78 "print the URL for this package"),
80 "print the license of the package"),
82 "alias for --license"),
84 "print the package description"),
85 ('long-description', None,
86 "print the long package description"),
88 "print the list of platforms"),
90 "print the list of keywords"),
92 display_option_names
= map(lambda x
: translate_longopt(x
[0]),
95 # negative options are options that exclude other options
96 negative_opt
= {'quiet': 'verbose'}
99 # -- Creation/initialization methods -------------------------------
101 def __init__ (self
, attrs
=None):
102 """Construct a new Distribution instance: initialize all the
103 attributes of a Distribution, and then use 'attrs' (a dictionary
104 mapping attribute names to values) to assign some of those
105 attributes their "real" values. (Any attributes not mentioned in
106 'attrs' will be assigned to some null value: 0, None, an empty list
107 or dictionary, etc.) Most importantly, initialize the
108 'command_obj' attribute to the empty dictionary; this will be
109 filled in with real command objects by 'parse_command_line()'.
112 # Default values for our command-line options
116 for attr
in self
.display_option_names
:
117 setattr(self
, attr
, 0)
119 # Store the distribution meta-data (name, version, author, and so
120 # forth) in a separate object -- we're getting to have enough
121 # information here (and enough command-line options) that it's
122 # worth it. Also delegate 'get_XXX()' methods to the 'metadata'
123 # object in a sneaky and underhanded (but efficient!) way.
124 self
.metadata
= DistributionMetadata()
125 for basename
in self
.metadata
._METHOD
_BASENAMES
:
126 method_name
= "get_" + basename
127 setattr(self
, method_name
, getattr(self
.metadata
, method_name
))
129 # 'cmdclass' maps command names to class objects, so we
130 # can 1) quickly figure out which class to instantiate when
131 # we need to create a new command object, and 2) have a way
132 # for the setup script to override command classes
135 # 'script_name' and 'script_args' are usually set to sys.argv[0]
136 # and sys.argv[1:], but they can be overridden when the caller is
137 # not necessarily a setup script run from the command-line.
138 self
.script_name
= None
139 self
.script_args
= None
141 # 'command_options' is where we store command options between
142 # parsing them (from config files, the command-line, etc.) and when
143 # they are actually needed -- ie. when the command in question is
144 # instantiated. It is a dictionary of dictionaries of 2-tuples:
145 # command_options = { command_name : { option : (source, value) } }
146 self
.command_options
= {}
148 # These options are really the business of various commands, rather
149 # than of the Distribution itself. We provide aliases for them in
150 # Distribution as a convenience to the developer.
152 self
.package_dir
= None
153 self
.py_modules
= None
154 self
.libraries
= None
156 self
.ext_modules
= None
157 self
.ext_package
= None
158 self
.include_dirs
= None
159 self
.extra_path
= None
161 self
.data_files
= None
163 # And now initialize bookkeeping stuff that can't be supplied by
164 # the caller at all. 'command_obj' maps command names to
165 # Command instances -- that's how we enforce that every command
166 # class is a singleton.
167 self
.command_obj
= {}
169 # 'have_run' maps command names to boolean values; it keeps track
170 # of whether we have actually run a particular command, to make it
171 # cheap to "run" a command whenever we think we might need to -- if
172 # it's already been done, no need for expensive filesystem
173 # operations, we just check the 'have_run' dictionary and carry on.
174 # It's only safe to query 'have_run' for a command class that has
175 # been instantiated -- a false value will be inserted when the
176 # command object is created, and replaced with a true value when
177 # the command is successfully run. Thus it's probably best to use
178 # '.get()' rather than a straight lookup.
181 # Now we'll use the attrs dictionary (ultimately, keyword args from
182 # the setup script) to possibly override any or all of these
183 # distribution options.
187 # Pull out the set of command options and work on them
188 # specifically. Note that this order guarantees that aliased
189 # command options will override any supplied redundantly
190 # through the general options dictionary.
191 options
= attrs
.get('options')
194 for (command
, cmd_options
) in options
.items():
195 opt_dict
= self
.get_option_dict(command
)
196 for (opt
, val
) in cmd_options
.items():
197 opt_dict
[opt
] = ("setup script", val
)
199 # Now work on the rest of the attributes. Any attribute that's
200 # not already defined is invalid!
201 for (key
,val
) in attrs
.items():
202 if hasattr(self
.metadata
, key
):
203 setattr(self
.metadata
, key
, val
)
204 elif hasattr(self
, key
):
205 setattr(self
, key
, val
)
207 raise DistutilsSetupError
, \
208 "invalid distribution option '%s'" % key
210 self
.finalize_options()
215 def get_option_dict (self
, command
):
216 """Get the option dictionary for a given command. If that
217 command's option dictionary hasn't been created yet, then create it
218 and return the new dictionary; otherwise, return the existing
222 dict = self
.command_options
.get(command
)
224 dict = self
.command_options
[command
] = {}
228 def dump_option_dicts (self
, header
=None, commands
=None, indent
=""):
229 from pprint
import pformat
231 if commands
is None: # dump all command option dicts
232 commands
= self
.command_options
.keys()
235 if header
is not None:
236 print indent
+ header
237 indent
= indent
+ " "
240 print indent
+ "no commands known yet"
243 for cmd_name
in commands
:
244 opt_dict
= self
.command_options
.get(cmd_name
)
246 print indent
+ "no option dict for '%s' command" % cmd_name
248 print indent
+ "option dict for '%s' command:" % cmd_name
249 out
= pformat(opt_dict
)
250 for line
in string
.split(out
, "\n"):
251 print indent
+ " " + line
253 # dump_option_dicts ()
257 # -- Config file finding/parsing methods ---------------------------
259 def find_config_files (self
):
260 """Find as many configuration files as should be processed for this
261 platform, and return a list of filenames in the order in which they
262 should be parsed. The filenames returned are guaranteed to exist
263 (modulo nasty race conditions).
265 There are three possible config files: distutils.cfg in the
266 Distutils installation directory (ie. where the top-level
267 Distutils __inst__.py file lives), a file in the user's home
268 directory named .pydistutils.cfg on Unix and pydistutils.cfg
269 on Windows/Mac, and setup.cfg in the current directory.
274 # Where to look for the system-wide Distutils config file
275 sys_dir
= os
.path
.dirname(sys
.modules
['distutils'].__file
__)
277 # Look for the system config file
278 sys_file
= os
.path
.join(sys_dir
, "distutils.cfg")
279 if os
.path
.isfile(sys_file
):
280 files
.append(sys_file
)
282 # What to call the per-user config file
283 if os
.name
== 'posix':
284 user_filename
= ".pydistutils.cfg"
286 user_filename
= "pydistutils.cfg"
288 # And look for the user config file
289 if os
.environ
.has_key('HOME'):
290 user_file
= os
.path
.join(os
.environ
.get('HOME'), user_filename
)
291 if os
.path
.isfile(user_file
):
292 files
.append(user_file
)
294 # All platforms support local setup.cfg
295 local_file
= "setup.cfg"
296 if os
.path
.isfile(local_file
):
297 files
.append(local_file
)
301 # find_config_files ()
304 def parse_config_files (self
, filenames
=None):
306 from ConfigParser
import ConfigParser
307 from distutils
.core
import DEBUG
309 if filenames
is None:
310 filenames
= self
.find_config_files()
312 if DEBUG
: print "Distribution.parse_config_files():"
314 parser
= ConfigParser()
315 for filename
in filenames
:
316 if DEBUG
: print " reading", filename
317 parser
.read(filename
)
318 for section
in parser
.sections():
319 options
= parser
.options(section
)
320 opt_dict
= self
.get_option_dict(section
)
323 if opt
!= '__name__':
324 val
= parser
.get(section
,opt
)
325 opt
= string
.replace(opt
, '-', '_')
326 opt_dict
[opt
] = (filename
, val
)
328 # Make the ConfigParser forget everything (so we retain
329 # the original filenames that options come from) -- gag,
330 # retch, puke -- another good reason for a distutils-
331 # specific config parser (sigh...)
334 # If there was a "global" section in the config file, use it
335 # to set Distribution options.
337 if self
.command_options
.has_key('global'):
338 for (opt
, (src
, val
)) in self
.command_options
['global'].items():
339 alias
= self
.negative_opt
.get(opt
)
342 setattr(self
, alias
, not strtobool(val
))
343 elif opt
in ('verbose', 'dry_run'): # ugh!
344 setattr(self
, opt
, strtobool(val
))
345 except ValueError, msg
:
346 raise DistutilsOptionError
, msg
348 # parse_config_files ()
351 # -- Command-line parsing methods ----------------------------------
353 def parse_command_line (self
):
354 """Parse the setup script's command line, taken from the
355 'script_args' instance attribute (which defaults to 'sys.argv[1:]'
356 -- see 'setup()' in core.py). This list is first processed for
357 "global options" -- options that set attributes of the Distribution
358 instance. Then, it is alternately scanned for Distutils commands
359 and options for that command. Each new command terminates the
360 options for the previous command. The allowed options for a
361 command are determined by the 'user_options' attribute of the
362 command class -- thus, we have to be able to load command classes
363 in order to parse the command line. Any error in that 'options'
364 attribute raises DistutilsGetoptError; any error on the
365 command-line raises DistutilsArgError. If no Distutils commands
366 were found on the command line, raises DistutilsArgError. Return
367 true if command-line was successfully parsed and we should carry
368 on with executing commands; false if no errors but we shouldn't
369 execute commands (currently, this only happens if user asks for
373 # We now have enough information to show the Macintosh dialog
374 # that allows the user to interactively specify the "command line".
376 if sys
.platform
== 'mac':
378 cmdlist
= self
.get_command_list()
379 self
.script_args
= EasyDialogs
.GetArgv(
380 self
.global_options
+ self
.display_options
, cmdlist
)
382 # We have to parse the command line a bit at a time -- global
383 # options, then the first command, then its options, and so on --
384 # because each command will be handled by a different class, and
385 # the options that are valid for a particular class aren't known
386 # until we have loaded the command class, which doesn't happen
387 # until we know what the command is.
390 parser
= FancyGetopt(self
.global_options
+ self
.display_options
)
391 parser
.set_negative_aliases(self
.negative_opt
)
392 parser
.set_aliases({'licence': 'license'})
393 args
= parser
.getopt(args
=self
.script_args
, object=self
)
394 option_order
= parser
.get_option_order()
396 # for display options we return immediately
397 if self
.handle_display_options(option_order
):
401 args
= self
._parse
_command
_opts
(parser
, args
)
402 if args
is None: # user asked for help (and got it)
405 # Handle the cases of --help as a "global" option, ie.
406 # "setup.py --help" and "setup.py --help command ...". For the
407 # former, we show global options (--verbose, --dry-run, etc.)
408 # and display-only options (--name, --version, etc.); for the
409 # latter, we omit the display-only options and show help for
410 # each command listed on the command line.
412 self
._show
_help
(parser
,
413 display_options
=len(self
.commands
) == 0,
414 commands
=self
.commands
)
417 # Oops, no commands found -- an end-user error
418 if not self
.commands
:
419 raise DistutilsArgError
, "no commands supplied"
421 # All is well: return true
424 # parse_command_line()
426 def _parse_command_opts (self
, parser
, args
):
427 """Parse the command-line options for a single command.
428 'parser' must be a FancyGetopt instance; 'args' must be the list
429 of arguments, starting with the current command (whose options
430 we are about to parse). Returns a new version of 'args' with
431 the next command at the front of the list; will be the empty
432 list if there are no more commands on the command line. Returns
433 None if the user asked for help on this command.
435 # late import because of mutual dependence between these modules
436 from distutils
.cmd
import Command
438 # Pull the current command from the head of the command line
440 if not command_re
.match(command
):
441 raise SystemExit, "invalid command name '%s'" % command
442 self
.commands
.append(command
)
444 # Dig up the command class that implements this command, so we
445 # 1) know that it's a valid command, and 2) know which options
448 cmd_class
= self
.get_command_class(command
)
449 except DistutilsModuleError
, msg
:
450 raise DistutilsArgError
, msg
452 # Require that the command class be derived from Command -- want
453 # to be sure that the basic "command" interface is implemented.
454 if not issubclass(cmd_class
, Command
):
455 raise DistutilsClassError
, \
456 "command class %s must subclass Command" % cmd_class
458 # Also make sure that the command object provides a list of its
460 if not (hasattr(cmd_class
, 'user_options') and
461 type(cmd_class
.user_options
) is ListType
):
462 raise DistutilsClassError
, \
463 ("command class %s must provide " +
464 "'user_options' attribute (a list of tuples)") % \
467 # If the command class has a list of negative alias options,
468 # merge it in with the global negative aliases.
469 negative_opt
= self
.negative_opt
470 if hasattr(cmd_class
, 'negative_opt'):
471 negative_opt
= copy(negative_opt
)
472 negative_opt
.update(cmd_class
.negative_opt
)
474 # Check for help_options in command class. They have a different
475 # format (tuple of four) so we need to preprocess them here.
476 if (hasattr(cmd_class
, 'help_options') and
477 type(cmd_class
.help_options
) is ListType
):
478 help_options
= fix_help_options(cmd_class
.help_options
)
483 # All commands support the global options too, just by adding
484 # in 'global_options'.
485 parser
.set_option_table(self
.global_options
+
486 cmd_class
.user_options
+
488 parser
.set_negative_aliases(negative_opt
)
489 (args
, opts
) = parser
.getopt(args
[1:])
490 if hasattr(opts
, 'help') and opts
.help:
491 self
._show
_help
(parser
, display_options
=0, commands
=[cmd_class
])
494 if (hasattr(cmd_class
, 'help_options') and
495 type(cmd_class
.help_options
) is ListType
):
497 for (help_option
, short
, desc
, func
) in cmd_class
.help_options
:
498 if hasattr(opts
, parser
.get_attr_name(help_option
)):
500 #print "showing help for option %s of command %s" % \
501 # (help_option[0],cmd_class)
506 raise DistutilsClassError(
507 "invalid help function %s for help option '%s': "
508 "must be a callable object (function, etc.)"
509 % (`func`
, help_option
))
511 if help_option_found
:
514 # Put the options from the command-line into their official
515 # holding pen, the 'command_options' dictionary.
516 opt_dict
= self
.get_option_dict(command
)
517 for (name
, value
) in vars(opts
).items():
518 opt_dict
[name
] = ("command line", value
)
522 # _parse_command_opts ()
525 def finalize_options (self
):
526 """Set final values for all the options on the Distribution
527 instance, analogous to the .finalize_options() method of Command
531 keywords
= self
.metadata
.keywords
532 if keywords
is not None:
533 if type(keywords
) is StringType
:
534 keywordlist
= string
.split(keywords
, ',')
535 self
.metadata
.keywords
= map(string
.strip
, keywordlist
)
537 platforms
= self
.metadata
.platforms
538 if platforms
is not None:
539 if type(platforms
) is StringType
:
540 platformlist
= string
.split(platforms
, ',')
541 self
.metadata
.platforms
= map(string
.strip
, platformlist
)
543 def _show_help (self
,
548 """Show help for the setup script command-line in the form of
549 several lists of command-line options. 'parser' should be a
550 FancyGetopt instance; do not expect it to be returned in the
551 same state, as its option table will be reset to make it
552 generate the correct help text.
554 If 'global_options' is true, lists the global options:
555 --verbose, --dry-run, etc. If 'display_options' is true, lists
556 the "display-only" options: --name, --version, etc. Finally,
557 lists per-command help for every command name or command class
560 # late import because of mutual dependence between these modules
561 from distutils
.core
import gen_usage
562 from distutils
.cmd
import Command
565 parser
.set_option_table(self
.global_options
)
566 parser
.print_help("Global options:")
570 parser
.set_option_table(self
.display_options
)
572 "Information display options (just display " +
573 "information, ignore any commands)")
576 for command
in self
.commands
:
577 if type(command
) is ClassType
and issubclass(command
, Command
):
580 klass
= self
.get_command_class(command
)
581 if (hasattr(klass
, 'help_options') and
582 type(klass
.help_options
) is ListType
):
583 parser
.set_option_table(klass
.user_options
+
584 fix_help_options(klass
.help_options
))
586 parser
.set_option_table(klass
.user_options
)
587 parser
.print_help("Options for '%s' command:" % klass
.__name
__)
590 print gen_usage(self
.script_name
)
596 def handle_display_options (self
, option_order
):
597 """If there were any non-global "display-only" options
598 (--help-commands or the metadata display options) on the command
599 line, display the requested info and return true; else return
602 from distutils
.core
import gen_usage
604 # User just wants a list of commands -- we'll print it out and stop
605 # processing now (ie. if they ran "setup --help-commands foo bar",
606 # we ignore "foo bar").
607 if self
.help_commands
:
608 self
.print_commands()
610 print gen_usage(self
.script_name
)
613 # If user supplied any of the "display metadata" options, then
614 # display that metadata in the order in which the user supplied the
616 any_display_options
= 0
617 is_display_option
= {}
618 for option
in self
.display_options
:
619 is_display_option
[option
[0]] = 1
621 for (opt
, val
) in option_order
:
622 if val
and is_display_option
.get(opt
):
623 opt
= translate_longopt(opt
)
624 value
= getattr(self
.metadata
, "get_"+opt
)()
625 if opt
in ['keywords', 'platforms']:
626 print string
.join(value
, ',')
629 any_display_options
= 1
631 return any_display_options
633 # handle_display_options()
635 def print_command_list (self
, commands
, header
, max_length
):
636 """Print a subset of the list of all commands -- used by
643 klass
= self
.cmdclass
.get(cmd
)
645 klass
= self
.get_command_class(cmd
)
647 description
= klass
.description
648 except AttributeError:
649 description
= "(no description available)"
651 print " %-*s %s" % (max_length
, cmd
, description
)
653 # print_command_list ()
656 def print_commands (self
):
657 """Print out a help message listing all available commands with a
658 description of each. The list is divided into "standard commands"
659 (listed in distutils.command.__all__) and "extra commands"
660 (mentioned in self.cmdclass, but not a standard command). The
661 descriptions come from the command class attribute
665 import distutils
.command
666 std_commands
= distutils
.command
.__all
__
668 for cmd
in std_commands
:
672 for cmd
in self
.cmdclass
.keys():
673 if not is_std
.get(cmd
):
674 extra_commands
.append(cmd
)
677 for cmd
in (std_commands
+ extra_commands
):
678 if len(cmd
) > max_length
:
679 max_length
= len(cmd
)
681 self
.print_command_list(std_commands
,
686 self
.print_command_list(extra_commands
,
692 def get_command_list (self
):
693 """Get a list of (command, description) tuples.
694 The list is divided into "standard commands" (listed in
695 distutils.command.__all__) and "extra commands" (mentioned in
696 self.cmdclass, but not a standard command). The descriptions come
697 from the command class attribute 'description'.
699 # Currently this is only used on Mac OS, for the Mac-only GUI
700 # Distutils interface (by Jack Jansen)
702 import distutils
.command
703 std_commands
= distutils
.command
.__all
__
705 for cmd
in std_commands
:
709 for cmd
in self
.cmdclass
.keys():
710 if not is_std
.get(cmd
):
711 extra_commands
.append(cmd
)
714 for cmd
in (std_commands
+ extra_commands
):
715 klass
= self
.cmdclass
.get(cmd
)
717 klass
= self
.get_command_class(cmd
)
719 description
= klass
.description
720 except AttributeError:
721 description
= "(no description available)"
722 rv
.append((cmd
, description
))
725 # -- Command class/object methods ----------------------------------
727 def get_command_class (self
, command
):
728 """Return the class that implements the Distutils command named by
729 'command'. First we check the 'cmdclass' dictionary; if the
730 command is mentioned there, we fetch the class object from the
731 dictionary and return it. Otherwise we load the command module
732 ("distutils.command." + command) and fetch the command class from
733 the module. The loaded class is also stored in 'cmdclass'
734 to speed future calls to 'get_command_class()'.
736 Raises DistutilsModuleError if the expected module could not be
737 found, or if that module does not define the expected class.
739 klass
= self
.cmdclass
.get(command
)
743 module_name
= 'distutils.command.' + command
747 __import__ (module_name
)
748 module
= sys
.modules
[module_name
]
750 raise DistutilsModuleError
, \
751 "invalid command '%s' (no module named '%s')" % \
752 (command
, module_name
)
755 klass
= getattr(module
, klass_name
)
756 except AttributeError:
757 raise DistutilsModuleError
, \
758 "invalid command '%s' (no class '%s' in module '%s')" \
759 % (command
, klass_name
, module_name
)
761 self
.cmdclass
[command
] = klass
764 # get_command_class ()
766 def get_command_obj (self
, command
, create
=1):
767 """Return the command object for 'command'. Normally this object
768 is cached on a previous call to 'get_command_obj()'; if no command
769 object for 'command' is in the cache, then we either create and
770 return it (if 'create' is true) or return None.
772 from distutils
.core
import DEBUG
773 cmd_obj
= self
.command_obj
.get(command
)
774 if not cmd_obj
and create
:
776 print "Distribution.get_command_obj(): " \
777 "creating '%s' command object" % command
779 klass
= self
.get_command_class(command
)
780 cmd_obj
= self
.command_obj
[command
] = klass(self
)
781 self
.have_run
[command
] = 0
783 # Set any options that were supplied in config files
784 # or on the command line. (NB. support for error
785 # reporting is lame here: any errors aren't reported
786 # until 'finalize_options()' is called, which means
787 # we won't report the source of the error.)
788 options
= self
.command_options
.get(command
)
790 self
._set
_command
_options
(cmd_obj
, options
)
794 def _set_command_options (self
, command_obj
, option_dict
=None):
795 """Set the options for 'command_obj' from 'option_dict'. Basically
796 this means copying elements of a dictionary ('option_dict') to
797 attributes of an instance ('command').
799 'command_obj' must be a Command instance. If 'option_dict' is not
800 supplied, uses the standard option dictionary for this command
801 (from 'self.command_options').
803 from distutils
.core
import DEBUG
805 command_name
= command_obj
.get_command_name()
806 if option_dict
is None:
807 option_dict
= self
.get_option_dict(command_name
)
809 if DEBUG
: print " setting options for '%s' command:" % command_name
810 for (option
, (source
, value
)) in option_dict
.items():
811 if DEBUG
: print " %s = %s (from %s)" % (option
, value
, source
)
813 bool_opts
= map(translate_longopt
, command_obj
.boolean_options
)
814 except AttributeError:
817 neg_opt
= command_obj
.negative_opt
818 except AttributeError:
822 is_string
= type(value
) is StringType
823 if neg_opt
.has_key(option
) and is_string
:
824 setattr(command_obj
, neg_opt
[option
], not strtobool(value
))
825 elif option
in bool_opts
and is_string
:
826 setattr(command_obj
, option
, strtobool(value
))
827 elif hasattr(command_obj
, option
):
828 setattr(command_obj
, option
, value
)
830 raise DistutilsOptionError
, \
831 ("error in %s: command '%s' has no such option '%s'"
832 % (source
, command_name
, option
))
833 except ValueError, msg
:
834 raise DistutilsOptionError
, msg
836 def reinitialize_command (self
, command
, reinit_subcommands
=0):
837 """Reinitializes a command to the state it was in when first
838 returned by 'get_command_obj()': ie., initialized but not yet
839 finalized. This provides the opportunity to sneak option
840 values in programmatically, overriding or supplementing
841 user-supplied values from the config files and command line.
842 You'll have to re-finalize the command object (by calling
843 'finalize_options()' or 'ensure_finalized()') before using it for
846 'command' should be a command name (string) or command object. If
847 'reinit_subcommands' is true, also reinitializes the command's
848 sub-commands, as declared by the 'sub_commands' class attribute (if
849 it has one). See the "install" command for an example. Only
850 reinitializes the sub-commands that actually matter, ie. those
851 whose test predicates return true.
853 Returns the reinitialized command object.
855 from distutils
.cmd
import Command
856 if not isinstance(command
, Command
):
857 command_name
= command
858 command
= self
.get_command_obj(command_name
)
860 command_name
= command
.get_command_name()
862 if not command
.finalized
:
864 command
.initialize_options()
865 command
.finalized
= 0
866 self
.have_run
[command_name
] = 0
867 self
._set
_command
_options
(command
)
869 if reinit_subcommands
:
870 for sub
in command
.get_sub_commands():
871 self
.reinitialize_command(sub
, reinit_subcommands
)
876 # -- Methods that operate on the Distribution ----------------------
878 def announce (self
, msg
, level
=1):
879 """Print 'msg' if 'level' is greater than or equal to the verbosity
880 level recorded in the 'verbose' attribute (which, currently, can be
883 if self
.verbose
>= level
:
887 def run_commands (self
):
888 """Run each command that was seen on the setup script command line.
889 Uses the list of commands found and cache of command objects
890 created by 'get_command_obj()'.
892 for cmd
in self
.commands
:
893 self
.run_command(cmd
)
896 # -- Methods that operate on its Commands --------------------------
898 def run_command (self
, command
):
899 """Do whatever it takes to run a command (including nothing at all,
900 if the command has already been run). Specifically: if we have
901 already created and run the command named by 'command', return
902 silently without doing anything. If the command named by 'command'
903 doesn't even have a command object yet, create one. Then invoke
904 'run()' on that command object (or an existing one).
906 # Already been here, done that? then return silently.
907 if self
.have_run
.get(command
):
910 self
.announce("running " + command
)
911 cmd_obj
= self
.get_command_obj(command
)
912 cmd_obj
.ensure_finalized()
914 self
.have_run
[command
] = 1
917 # -- Distribution query methods ------------------------------------
919 def has_pure_modules (self
):
920 return len(self
.packages
or self
.py_modules
or []) > 0
922 def has_ext_modules (self
):
923 return self
.ext_modules
and len(self
.ext_modules
) > 0
925 def has_c_libraries (self
):
926 return self
.libraries
and len(self
.libraries
) > 0
928 def has_modules (self
):
929 return self
.has_pure_modules() or self
.has_ext_modules()
931 def has_headers (self
):
932 return self
.headers
and len(self
.headers
) > 0
934 def has_scripts (self
):
935 return self
.scripts
and len(self
.scripts
) > 0
937 def has_data_files (self
):
938 return self
.data_files
and len(self
.data_files
) > 0
941 return (self
.has_pure_modules() and
942 not self
.has_ext_modules() and
943 not self
.has_c_libraries())
945 # -- Metadata query methods ----------------------------------------
947 # If you're looking for 'get_name()', 'get_version()', and so forth,
948 # they are defined in a sneaky way: the constructor binds self.get_XXX
949 # to self.metadata.get_XXX. The actual code is in the
950 # DistributionMetadata class, below.
955 class DistributionMetadata
:
956 """Dummy class to hold the distribution meta-data: name, version,
957 author, and so forth.
960 _METHOD_BASENAMES
= ("name", "version", "author", "author_email",
961 "maintainer", "maintainer_email", "url",
962 "license", "description", "long_description",
963 "keywords", "platforms", "fullname", "contact",
964 "contact_email", "licence")
970 self
.author_email
= None
971 self
.maintainer
= None
972 self
.maintainer_email
= None
975 self
.description
= None
976 self
.long_description
= None
978 self
.platforms
= None
980 def write_pkg_info (self
, base_dir
):
981 """Write the PKG-INFO file into the release tree.
984 pkg_info
= open( os
.path
.join(base_dir
, 'PKG-INFO'), 'w')
986 pkg_info
.write('Metadata-Version: 1.0\n')
987 pkg_info
.write('Name: %s\n' % self
.get_name() )
988 pkg_info
.write('Version: %s\n' % self
.get_version() )
989 pkg_info
.write('Summary: %s\n' % self
.get_description() )
990 pkg_info
.write('Home-page: %s\n' % self
.get_url() )
991 pkg_info
.write('Author: %s\n' % self
.get_contact() )
992 pkg_info
.write('Author-email: %s\n' % self
.get_contact_email() )
993 pkg_info
.write('License: %s\n' % self
.get_license() )
995 long_desc
= rfc822_escape( self
.get_long_description() )
996 pkg_info
.write('Description: %s\n' % long_desc
)
998 keywords
= string
.join( self
.get_keywords(), ',')
1000 pkg_info
.write('Keywords: %s\n' % keywords
)
1002 for platform
in self
.get_platforms():
1003 pkg_info
.write('Platform: %s\n' % platform
)
1009 # -- Metadata query methods ----------------------------------------
1011 def get_name (self
):
1012 return self
.name
or "UNKNOWN"
1014 def get_version(self
):
1015 return self
.version
or "0.0.0"
1017 def get_fullname (self
):
1018 return "%s-%s" % (self
.get_name(), self
.get_version())
1020 def get_author(self
):
1021 return self
.author
or "UNKNOWN"
1023 def get_author_email(self
):
1024 return self
.author_email
or "UNKNOWN"
1026 def get_maintainer(self
):
1027 return self
.maintainer
or "UNKNOWN"
1029 def get_maintainer_email(self
):
1030 return self
.maintainer_email
or "UNKNOWN"
1032 def get_contact(self
):
1033 return (self
.maintainer
or
1037 def get_contact_email(self
):
1038 return (self
.maintainer_email
or
1039 self
.author_email
or
1043 return self
.url
or "UNKNOWN"
1045 def get_license(self
):
1046 return self
.license
or "UNKNOWN"
1047 get_licence
= get_license
1049 def get_description(self
):
1050 return self
.description
or "UNKNOWN"
1052 def get_long_description(self
):
1053 return self
.long_description
or "UNKNOWN"
1055 def get_keywords(self
):
1056 return self
.keywords
or []
1058 def get_platforms(self
):
1059 return self
.platforms
or ["UNKNOWN"]
1061 # class DistributionMetadata
1064 def fix_help_options (options
):
1065 """Convert a 4-tuple 'help_options' list as found in various command
1066 classes to the 3-tuple form required by FancyGetopt.
1069 for help_tuple
in options
:
1070 new_options
.append(help_tuple
[0:3])
1074 if __name__
== "__main__":
1075 dist
= Distribution()