blob: 7bdd9aa09b6ce879fb49e05a00e28412db028016 [file] [log] [blame]
Greg Wardfe6462c2000-04-04 01:40:52 +00001"""distutils.dist
2
3Provides the Distribution class, which represents the module distribution
4being built/installed/distributed."""
5
6# created 2000/04/03, Greg Ward
7# (extricated from core.py; actually dates back to the beginning)
8
9__revision__ = "$Id$"
10
Gregory P. Smith14263542000-05-12 00:41:33 +000011import sys, os, string, re
Greg Wardfe6462c2000-04-04 01:40:52 +000012from types import *
13from copy import copy
14from distutils.errors import *
Greg Ward36c36fe2000-05-20 14:07:59 +000015from distutils import sysconfig
Greg Ward82715e12000-04-21 02:28:14 +000016from distutils.fancy_getopt import FancyGetopt, longopt_xlate
Gregory P. Smith14263542000-05-12 00:41:33 +000017from distutils.util import check_environ
Greg Wardfe6462c2000-04-04 01:40:52 +000018
19
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.
24command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
25
26
27class Distribution:
28 """The core of the Distutils. Most of the work hiding behind
29 'setup' is really done within a Distribution instance, which
30 farms the work out to the Distutils commands specified on the
31 command line.
32
33 Clients will almost never instantiate Distribution directly,
34 unless the 'setup' function is totally inadequate to their needs.
35 However, it is conceivable that a client might wish to subclass
36 Distribution for some specialized purpose, and then pass the
37 subclass to 'setup' as the 'distclass' keyword argument. If so,
38 it is necessary to respect the expectations that 'setup' has of
39 Distribution: it must have a constructor and methods
40 'parse_command_line()' and 'run_commands()' with signatures like
41 those described below."""
42
43
44 # 'global_options' describes the command-line options that may be
Greg Ward82715e12000-04-21 02:28:14 +000045 # supplied to the setup script prior to any actual commands.
46 # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
Greg Wardfe6462c2000-04-04 01:40:52 +000047 # these global options. This list should be kept to a bare minimum,
48 # since every global option is also valid as a command option -- and we
49 # don't want to pollute the commands with too many options that they
50 # have minimal control over.
Greg Wardd5d8a992000-05-23 01:42:17 +000051 global_options = [('verbose', 'v', "run verbosely (default)"),
52 ('quiet', 'q', "run quietly (turns verbosity off)"),
53 ('dry-run', 'n', "don't actually do anything"),
54 ('help', 'h', "show detailed help message"),
Greg Wardfe6462c2000-04-04 01:40:52 +000055 ]
Greg Ward82715e12000-04-21 02:28:14 +000056
57 # options that are not propagated to the commands
58 display_options = [
59 ('help-commands', None,
60 "list all available commands"),
61 ('name', None,
62 "print package name"),
63 ('version', 'V',
64 "print package version"),
65 ('fullname', None,
66 "print <package name>-<version>"),
67 ('author', None,
68 "print the author's name"),
69 ('author-email', None,
70 "print the author's email address"),
71 ('maintainer', None,
72 "print the maintainer's name"),
73 ('maintainer-email', None,
74 "print the maintainer's email address"),
75 ('contact', None,
Greg Wardd5d8a992000-05-23 01:42:17 +000076 "print the maintainer's name if known, else the author's"),
Greg Ward82715e12000-04-21 02:28:14 +000077 ('contact-email', None,
Greg Wardd5d8a992000-05-23 01:42:17 +000078 "print the maintainer's email address if known, else the author's"),
Greg Ward82715e12000-04-21 02:28:14 +000079 ('url', None,
80 "print the URL for this package"),
81 ('licence', None,
82 "print the licence of the package"),
83 ('license', None,
84 "alias for --licence"),
85 ('description', None,
86 "print the package description"),
Greg Warde5a584e2000-04-26 02:26:55 +000087 ('long-description', None,
88 "print the long package description"),
Greg Ward82715e12000-04-21 02:28:14 +000089 ]
90 display_option_names = map(lambda x: string.translate(x[0], longopt_xlate),
91 display_options)
92
93 # negative options are options that exclude other options
Greg Wardfe6462c2000-04-04 01:40:52 +000094 negative_opt = {'quiet': 'verbose'}
95
96
97 # -- Creation/initialization methods -------------------------------
98
99 def __init__ (self, attrs=None):
100 """Construct a new Distribution instance: initialize all the
101 attributes of a Distribution, and then uses 'attrs' (a
102 dictionary mapping attribute names to values) to assign
103 some of those attributes their "real" values. (Any attributes
104 not mentioned in 'attrs' will be assigned to some null
105 value: 0, None, an empty list or dictionary, etc.) Most
106 importantly, initialize the 'command_obj' attribute
107 to the empty dictionary; this will be filled in with real
108 command objects by 'parse_command_line()'."""
109
110 # Default values for our command-line options
111 self.verbose = 1
112 self.dry_run = 0
Greg Wardfe6462c2000-04-04 01:40:52 +0000113 self.help = 0
Greg Ward82715e12000-04-21 02:28:14 +0000114 for attr in self.display_option_names:
115 setattr(self, attr, 0)
Greg Wardfe6462c2000-04-04 01:40:52 +0000116
Greg Ward82715e12000-04-21 02:28:14 +0000117 # Store the distribution meta-data (name, version, author, and so
118 # forth) in a separate object -- we're getting to have enough
119 # information here (and enough command-line options) that it's
120 # worth it. Also delegate 'get_XXX()' methods to the 'metadata'
121 # object in a sneaky and underhanded (but efficient!) way.
122 self.metadata = DistributionMetadata ()
Greg Ward4982f982000-04-22 02:52:44 +0000123 method_basenames = dir(self.metadata) + \
124 ['fullname', 'contact', 'contact_email']
125 for basename in method_basenames:
126 method_name = "get_" + basename
127 setattr(self, method_name, getattr(self.metadata, method_name))
Greg Wardfe6462c2000-04-04 01:40:52 +0000128
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
Greg Ward82715e12000-04-21 02:28:14 +0000132 # for the setup script to override command classes
Greg Wardfe6462c2000-04-04 01:40:52 +0000133 self.cmdclass = {}
134
Greg Wardd5d8a992000-05-23 01:42:17 +0000135 # 'command_options' is where we store command options between
136 # parsing them (from config files, the command-line, etc.) and when
137 # they are actually needed -- ie. when the command in question is
138 # instantiated. It is a dictionary of dictionaries of 2-tuples:
139 # command_options = { command_name : { option : (source, value) } }
Gregory P. Smith14263542000-05-12 00:41:33 +0000140 self.command_options = {}
141
Greg Wardfe6462c2000-04-04 01:40:52 +0000142 # These options are really the business of various commands, rather
143 # than of the Distribution itself. We provide aliases for them in
144 # Distribution as a convenience to the developer.
Greg Wardfe6462c2000-04-04 01:40:52 +0000145 self.packages = None
146 self.package_dir = None
147 self.py_modules = None
148 self.libraries = None
149 self.ext_modules = None
150 self.ext_package = None
151 self.include_dirs = None
152 self.extra_path = None
Gregory P. Smithb2e3bb32000-05-12 00:52:23 +0000153 self.scripts = None
Gregory P. Smith6a901dd2000-05-13 03:09:50 +0000154 self.data_files = None
Greg Wardfe6462c2000-04-04 01:40:52 +0000155
156 # And now initialize bookkeeping stuff that can't be supplied by
157 # the caller at all. 'command_obj' maps command names to
158 # Command instances -- that's how we enforce that every command
159 # class is a singleton.
160 self.command_obj = {}
161
162 # 'have_run' maps command names to boolean values; it keeps track
163 # of whether we have actually run a particular command, to make it
164 # cheap to "run" a command whenever we think we might need to -- if
165 # it's already been done, no need for expensive filesystem
166 # operations, we just check the 'have_run' dictionary and carry on.
167 # It's only safe to query 'have_run' for a command class that has
168 # been instantiated -- a false value will be inserted when the
169 # command object is created, and replaced with a true value when
170 # the command is succesfully run. Thus it's probably best to use
171 # '.get()' rather than a straight lookup.
172 self.have_run = {}
173
174 # Now we'll use the attrs dictionary (ultimately, keyword args from
Greg Ward82715e12000-04-21 02:28:14 +0000175 # the setup script) to possibly override any or all of these
176 # distribution options.
177
Greg Wardfe6462c2000-04-04 01:40:52 +0000178 if attrs:
179
180 # Pull out the set of command options and work on them
181 # specifically. Note that this order guarantees that aliased
182 # command options will override any supplied redundantly
183 # through the general options dictionary.
184 options = attrs.get ('options')
185 if options:
186 del attrs['options']
187 for (command, cmd_options) in options.items():
Greg Wardd5d8a992000-05-23 01:42:17 +0000188 cmd_obj = self.get_command_obj (command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000189 for (key, val) in cmd_options.items():
190 cmd_obj.set_option (key, val)
191 # loop over commands
192 # if any command options
193
194 # Now work on the rest of the attributes. Any attribute that's
195 # not already defined is invalid!
196 for (key,val) in attrs.items():
Greg Ward82715e12000-04-21 02:28:14 +0000197 if hasattr (self.metadata, key):
198 setattr (self.metadata, key, val)
199 elif hasattr (self, key):
Greg Wardfe6462c2000-04-04 01:40:52 +0000200 setattr (self, key, val)
201 else:
Greg Ward02a1a2b2000-04-15 22:15:07 +0000202 raise DistutilsSetupError, \
Greg Wardfe6462c2000-04-04 01:40:52 +0000203 "invalid distribution option '%s'" % key
204
205 # __init__ ()
206
207
Greg Wardd5d8a992000-05-23 01:42:17 +0000208 # -- Config file finding/parsing methods ---------------------------
209
Gregory P. Smith14263542000-05-12 00:41:33 +0000210 def find_config_files (self):
211 """Find as many configuration files as should be processed for this
212 platform, and return a list of filenames in the order in which they
213 should be parsed. The filenames returned are guaranteed to exist
214 (modulo nasty race conditions).
215
216 On Unix, there are three possible config files: pydistutils.cfg in
217 the Distutils installation directory (ie. where the top-level
218 Distutils __inst__.py file lives), .pydistutils.cfg in the user's
219 home directory, and setup.cfg in the current directory.
220
221 On Windows and Mac OS, there are two possible config files:
222 pydistutils.cfg in the Python installation directory (sys.prefix)
Greg Wardd5d8a992000-05-23 01:42:17 +0000223 and setup.cfg in the current directory.
224 """
Gregory P. Smith14263542000-05-12 00:41:33 +0000225 files = []
226 if os.name == "posix":
227 check_environ()
228
229 sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
230 sys_file = os.path.join(sys_dir, "pydistutils.cfg")
231 if os.path.isfile(sys_file):
232 files.append(sys_file)
233
234 user_file = os.path.join(os.environ.get('HOME'),
235 ".pydistutils.cfg")
236 if os.path.isfile(user_file):
237 files.append(user_file)
238
239 else:
240 sys_file = os.path.join (sysconfig.PREFIX, "pydistutils.cfg")
241 if os.path.isfile(sys_file):
242 files.append(sys_file)
243
244 # All platforms support local setup.cfg
245 local_file = "setup.cfg"
246 if os.path.isfile(local_file):
247 files.append(local_file)
248
249 return files
250
251 # find_config_files ()
252
253
254 def parse_config_files (self, filenames=None):
255
256 from ConfigParser import ConfigParser
257
258 if filenames is None:
259 filenames = self.find_config_files()
260
Greg Ward47460772000-05-23 03:47:35 +0000261 print "Distribution.parse_config_files():"
262
Gregory P. Smith14263542000-05-12 00:41:33 +0000263 parser = ConfigParser()
Greg Wardd5d8a992000-05-23 01:42:17 +0000264 for filename in filenames:
Greg Ward47460772000-05-23 03:47:35 +0000265 print " reading", filename
Greg Wardd5d8a992000-05-23 01:42:17 +0000266 parser.read(filename)
267 for section in parser.sections():
268 options = parser.options(section)
269 if not self.command_options.has_key(section):
270 self.command_options[section] = {}
271 opts = self.command_options[section]
Gregory P. Smith14263542000-05-12 00:41:33 +0000272
Greg Wardd5d8a992000-05-23 01:42:17 +0000273 for opt in options:
274 if opt != '__name__':
275 opts[opt] = (filename, parser.get(section,opt))
Gregory P. Smith14263542000-05-12 00:41:33 +0000276
Greg Ward47460772000-05-23 03:47:35 +0000277 # Make the ConfigParser forget everything (so we retain
278 # the original filenames that options come from) -- gag,
279 # retch, puke -- another good reason for a distutils-
280 # specific config parser (sigh...)
281 parser.__init__()
Gregory P. Smith14263542000-05-12 00:41:33 +0000282
283
Greg Wardd5d8a992000-05-23 01:42:17 +0000284 # -- Command-line parsing methods ----------------------------------
285
Greg Wardfe6462c2000-04-04 01:40:52 +0000286 def parse_command_line (self, args):
Greg Wardd5d8a992000-05-23 01:42:17 +0000287 """Parse the setup script's command line. 'args' must be a list
288 of command-line arguments, most likely 'sys.argv[1:]' (see the
289 'setup()' function). This list is first processed for "global
290 options" -- options that set attributes of the Distribution
291 instance. Then, it is alternately scanned for Distutils
292 commands and options for that command. Each new command
293 terminates the options for the previous command. The allowed
294 options for a command are determined by the 'user_options'
295 attribute of the command class -- thus, we have to be able to
296 load command classes in order to parse the command line. Any
297 error in that 'options' attribute raises DistutilsGetoptError;
298 any error on the command-line raises DistutilsArgError. If no
299 Distutils commands were found on the command line, raises
300 DistutilsArgError. Return true if command-line were
301 successfully parsed and we should carry on with executing
302 commands; false if no errors but we shouldn't execute commands
303 (currently, this only happens if user asks for help).
304 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000305 # We have to parse the command line a bit at a time -- global
306 # options, then the first command, then its options, and so on --
307 # because each command will be handled by a different class, and
Greg Wardd5d8a992000-05-23 01:42:17 +0000308 # the options that are valid for a particular class aren't known
309 # until we have loaded the command class, which doesn't happen
310 # until we know what the command is.
Greg Wardfe6462c2000-04-04 01:40:52 +0000311
312 self.commands = []
Greg Ward82715e12000-04-21 02:28:14 +0000313 parser = FancyGetopt (self.global_options + self.display_options)
314 parser.set_negative_aliases (self.negative_opt)
Greg Ward58ec6ed2000-04-21 04:22:49 +0000315 parser.set_aliases ({'license': 'licence'})
Greg Ward82715e12000-04-21 02:28:14 +0000316 args = parser.getopt (object=self)
317 option_order = parser.get_option_order()
Greg Wardfe6462c2000-04-04 01:40:52 +0000318
Greg Ward82715e12000-04-21 02:28:14 +0000319 # for display options we return immediately
320 if self.handle_display_options(option_order):
Greg Wardfe6462c2000-04-04 01:40:52 +0000321 return
322
323 while args:
Greg Wardd5d8a992000-05-23 01:42:17 +0000324 args = self._parse_command_opts(parser, args)
325 if args is None: # user asked for help (and got it)
Greg Wardfe6462c2000-04-04 01:40:52 +0000326 return
Greg Wardfe6462c2000-04-04 01:40:52 +0000327
Greg Wardd5d8a992000-05-23 01:42:17 +0000328 # Handle the cases of --help as a "global" option, ie.
329 # "setup.py --help" and "setup.py --help command ...". For the
330 # former, we show global options (--verbose, --dry-run, etc.)
331 # and display-only options (--name, --version, etc.); for the
332 # latter, we omit the display-only options and show help for
333 # each command listed on the command line.
Greg Wardfe6462c2000-04-04 01:40:52 +0000334 if self.help:
Greg Wardd5d8a992000-05-23 01:42:17 +0000335 print "showing 'global' help; commands=", self.commands
336 self._show_help(parser,
337 display_options=len(self.commands) == 0,
338 commands=self.commands)
Greg Wardfe6462c2000-04-04 01:40:52 +0000339 return
340
341 # Oops, no commands found -- an end-user error
342 if not self.commands:
343 raise DistutilsArgError, "no commands supplied"
344
345 # All is well: return true
346 return 1
347
348 # parse_command_line()
349
Greg Wardd5d8a992000-05-23 01:42:17 +0000350 def _parse_command_opts (self, parser, args):
351
352 """Parse the command-line options for a single command.
353 'parser' must be a FancyGetopt instance; 'args' must be the list
354 of arguments, starting with the current command (whose options
355 we are about to parse). Returns a new version of 'args' with
356 the next command at the front of the list; will be the empty
357 list if there are no more commands on the command line. Returns
358 None if the user asked for help on this command.
359 """
360 # late import because of mutual dependence between these modules
361 from distutils.cmd import Command
362
363 # Pull the current command from the head of the command line
364 command = args[0]
365 if not command_re.match (command):
366 raise SystemExit, "invalid command name '%s'" % command
367 self.commands.append (command)
368
369 # Dig up the command class that implements this command, so we
370 # 1) know that it's a valid command, and 2) know which options
371 # it takes.
372 try:
373 cmd_class = self.get_command_class (command)
374 except DistutilsModuleError, msg:
375 raise DistutilsArgError, msg
376
377 # Require that the command class be derived from Command -- want
378 # to be sure that the basic "command" interface is implemented.
379 if not issubclass (cmd_class, Command):
380 raise DistutilsClassError, \
381 "command class %s must subclass Command" % cmd_class
382
383 # Also make sure that the command object provides a list of its
384 # known options.
385 if not (hasattr (cmd_class, 'user_options') and
386 type (cmd_class.user_options) is ListType):
387 raise DistutilsClassError, \
388 ("command class %s must provide " +
389 "'user_options' attribute (a list of tuples)") % \
390 cmd_class
391
392 # If the command class has a list of negative alias options,
393 # merge it in with the global negative aliases.
394 negative_opt = self.negative_opt
395 if hasattr (cmd_class, 'negative_opt'):
396 negative_opt = copy (negative_opt)
397 negative_opt.update (cmd_class.negative_opt)
398
399 # All commands support the global options too, just by adding
400 # in 'global_options'.
401 parser.set_option_table (self.global_options +
402 cmd_class.user_options)
403 parser.set_negative_aliases (negative_opt)
404 (args, opts) = parser.getopt (args[1:])
Greg Ward47460772000-05-23 03:47:35 +0000405 if hasattr(opts, 'help') and opts.help:
Greg Wardd5d8a992000-05-23 01:42:17 +0000406 print "showing help for command", cmd_class
407 self._show_help(parser, display_options=0, commands=[cmd_class])
408 return
409
410 # Put the options from the command-line into their official
411 # holding pen, the 'command_options' dictionary.
412 if not self.command_options.has_key(command):
413 self.command_options[command] = {}
414 cmd_opts = self.command_options[command]
415 for (name, value) in vars(opts).items():
Greg Ward47460772000-05-23 03:47:35 +0000416 cmd_opts[name] = ("command line", value)
Greg Wardd5d8a992000-05-23 01:42:17 +0000417
418 return args
419
420 # _parse_command_opts ()
421
422
423 def _show_help (self,
424 parser,
425 global_options=1,
426 display_options=1,
427 commands=[]):
428 """Show help for the setup script command-line in the form of
429 several lists of command-line options. 'parser' should be a
430 FancyGetopt instance; do not expect it to be returned in the
431 same state, as its option table will be reset to make it
432 generate the correct help text.
433
434 If 'global_options' is true, lists the global options:
435 --verbose, --dry-run, etc. If 'display_options' is true, lists
436 the "display-only" options: --name, --version, etc. Finally,
437 lists per-command help for every command name or command class
438 in 'commands'.
439 """
440 # late import because of mutual dependence between these modules
441 from distutils.core import usage
442 from distutils.cmd import Command
443
444 if global_options:
445 parser.set_option_table (self.global_options)
446 parser.print_help ("Global options:")
447 print
448
449 if display_options:
450 parser.set_option_table (self.display_options)
451 parser.print_help (
452 "Information display options (just display " +
453 "information, ignore any commands)")
454 print
455
456 for command in self.commands:
457 if type(command) is ClassType and issubclass(klass, Command):
458 klass = command
459 else:
460 klass = self.get_command_class (command)
461 parser.set_option_table (klass.user_options)
462 parser.print_help ("Options for '%s' command:" % klass.__name__)
463 print
464
465 print usage
466 return
467
468 # _show_help ()
469
470
Greg Ward82715e12000-04-21 02:28:14 +0000471 def handle_display_options (self, option_order):
472 """If there were any non-global "display-only" options
Greg Wardd5d8a992000-05-23 01:42:17 +0000473 (--help-commands or the metadata display options) on the command
474 line, display the requested info and return true; else return
475 false.
476 """
Greg Ward82715e12000-04-21 02:28:14 +0000477 from distutils.core import usage
478
479 # User just wants a list of commands -- we'll print it out and stop
480 # processing now (ie. if they ran "setup --help-commands foo bar",
481 # we ignore "foo bar").
482 if self.help_commands:
483 self.print_commands ()
484 print
485 print usage
486 return 1
487
488 # If user supplied any of the "display metadata" options, then
489 # display that metadata in the order in which the user supplied the
490 # metadata options.
491 any_display_options = 0
492 is_display_option = {}
493 for option in self.display_options:
494 is_display_option[option[0]] = 1
495
496 for (opt, val) in option_order:
497 if val and is_display_option.get(opt):
498 opt = string.translate (opt, longopt_xlate)
499 print getattr(self.metadata, "get_"+opt)()
500 any_display_options = 1
501
502 return any_display_options
503
504 # handle_display_options()
Greg Wardfe6462c2000-04-04 01:40:52 +0000505
506 def print_command_list (self, commands, header, max_length):
507 """Print a subset of the list of all commands -- used by
Greg Wardd5d8a992000-05-23 01:42:17 +0000508 'print_commands()'.
509 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000510
511 print header + ":"
512
513 for cmd in commands:
514 klass = self.cmdclass.get (cmd)
515 if not klass:
Greg Wardd5d8a992000-05-23 01:42:17 +0000516 klass = self.get_command_class (cmd)
Greg Wardfe6462c2000-04-04 01:40:52 +0000517 try:
518 description = klass.description
519 except AttributeError:
520 description = "(no description available)"
521
522 print " %-*s %s" % (max_length, cmd, description)
523
524 # print_command_list ()
525
526
527 def print_commands (self):
Greg Wardd5d8a992000-05-23 01:42:17 +0000528 """Print out a help message listing all available commands with a
529 description of each. The list is divided into "standard commands"
530 (listed in distutils.command.__all__) and "extra commands"
531 (mentioned in self.cmdclass, but not a standard command). The
532 descriptions come from the command class attribute
533 'description'.
534 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000535
536 import distutils.command
537 std_commands = distutils.command.__all__
538 is_std = {}
539 for cmd in std_commands:
540 is_std[cmd] = 1
541
542 extra_commands = []
543 for cmd in self.cmdclass.keys():
544 if not is_std.get(cmd):
545 extra_commands.append (cmd)
546
547 max_length = 0
548 for cmd in (std_commands + extra_commands):
549 if len (cmd) > max_length:
550 max_length = len (cmd)
551
552 self.print_command_list (std_commands,
553 "Standard commands",
554 max_length)
555 if extra_commands:
556 print
557 self.print_command_list (extra_commands,
558 "Extra commands",
559 max_length)
560
561 # print_commands ()
Greg Wardfe6462c2000-04-04 01:40:52 +0000562
563
564 # -- Command class/object methods ----------------------------------
565
Greg Wardd5d8a992000-05-23 01:42:17 +0000566 def get_command_class (self, command):
567 """Return the class that implements the Distutils command named by
568 'command'. First we check the 'cmdclass' dictionary; if the
569 command is mentioned there, we fetch the class object from the
570 dictionary and return it. Otherwise we load the command module
571 ("distutils.command." + command) and fetch the command class from
572 the module. The loaded class is also stored in 'cmdclass'
573 to speed future calls to 'get_command_class()'.
Greg Wardfe6462c2000-04-04 01:40:52 +0000574
Gregory P. Smith14263542000-05-12 00:41:33 +0000575 Raises DistutilsModuleError if the expected module could not be
Greg Wardd5d8a992000-05-23 01:42:17 +0000576 found, or if that module does not define the expected class.
577 """
578 klass = self.cmdclass.get(command)
579 if klass:
580 return klass
Greg Wardfe6462c2000-04-04 01:40:52 +0000581
582 module_name = 'distutils.command.' + command
583 klass_name = command
584
585 try:
586 __import__ (module_name)
587 module = sys.modules[module_name]
588 except ImportError:
589 raise DistutilsModuleError, \
590 "invalid command '%s' (no module named '%s')" % \
591 (command, module_name)
592
593 try:
Greg Wardd5d8a992000-05-23 01:42:17 +0000594 klass = getattr(module, klass_name)
595 except AttributeError:
Greg Wardfe6462c2000-04-04 01:40:52 +0000596 raise DistutilsModuleError, \
597 "invalid command '%s' (no class '%s' in module '%s')" \
598 % (command, klass_name, module_name)
599
Greg Wardd5d8a992000-05-23 01:42:17 +0000600 self.cmdclass[command] = klass
Greg Wardfe6462c2000-04-04 01:40:52 +0000601 return klass
602
Greg Wardd5d8a992000-05-23 01:42:17 +0000603 # get_command_class ()
Greg Wardfe6462c2000-04-04 01:40:52 +0000604
Greg Wardd5d8a992000-05-23 01:42:17 +0000605 def get_command_obj (self, command, create=1):
606 """Return the command object for 'command'. Normally this object
607 is cached on a previous call to 'get_command_obj()'; if no comand
608 object for 'command' is in the cache, then we either create and
609 return it (if 'create' is true) or return None.
610 """
611 cmd_obj = self.command_obj.get(command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000612 if not cmd_obj and create:
Greg Ward47460772000-05-23 03:47:35 +0000613 print "Distribution.get_command_obj(): " \
614 "creating '%s' command object" % command
615
Greg Wardd5d8a992000-05-23 01:42:17 +0000616 klass = self.get_command_class(command)
Greg Ward47460772000-05-23 03:47:35 +0000617 cmd_obj = self.command_obj[command] = klass(self)
618 self.have_run[command] = 0
619
620 # Set any options that were supplied in config files
621 # or on the command line. (NB. support for error
622 # reporting is lame here: any errors aren't reported
623 # until 'finalize_options()' is called, which means
624 # we won't report the source of the error.)
625 options = self.command_options.get(command)
626 if options:
627 print " setting options:"
628 for (option, (source, value)) in options.items():
629 print " %s = %s (from %s)" % (option, value, source)
Greg Ward40313cf2000-05-23 04:11:14 +0000630 if not hasattr(cmd_obj, option):
631 raise DistutilsOptionError, \
632 ("%s: command '%s' has no such option '%s'") % \
633 (source, command, option)
Greg Ward47460772000-05-23 03:47:35 +0000634 setattr(cmd_obj, option, value)
Greg Wardfe6462c2000-04-04 01:40:52 +0000635
636 return cmd_obj
637
638
639 # -- Methods that operate on the Distribution ----------------------
640
641 def announce (self, msg, level=1):
642 """Print 'msg' if 'level' is greater than or equal to the verbosity
Greg Wardd5d8a992000-05-23 01:42:17 +0000643 level recorded in the 'verbose' attribute (which, currently, can be
644 only 0 or 1).
645 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000646 if self.verbose >= level:
647 print msg
648
649
650 def run_commands (self):
Greg Ward82715e12000-04-21 02:28:14 +0000651 """Run each command that was seen on the setup script command line.
Greg Wardd5d8a992000-05-23 01:42:17 +0000652 Uses the list of commands found and cache of command objects
653 created by 'get_command_obj()'."""
Greg Wardfe6462c2000-04-04 01:40:52 +0000654
655 for cmd in self.commands:
656 self.run_command (cmd)
657
658
Greg Wardfe6462c2000-04-04 01:40:52 +0000659 # -- Methods that operate on its Commands --------------------------
660
661 def run_command (self, command):
Greg Wardfe6462c2000-04-04 01:40:52 +0000662 """Do whatever it takes to run a command (including nothing at all,
Greg Wardd5d8a992000-05-23 01:42:17 +0000663 if the command has already been run). Specifically: if we have
664 already created and run the command named by 'command', return
665 silently without doing anything. If the command named by 'command'
666 doesn't even have a command object yet, create one. Then invoke
667 'run()' on that command object (or an existing one).
668 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000669
670 # Already been here, done that? then return silently.
671 if self.have_run.get (command):
672 return
673
674 self.announce ("running " + command)
Greg Wardd5d8a992000-05-23 01:42:17 +0000675 cmd_obj = self.get_command_obj (command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000676 cmd_obj.ensure_ready ()
677 cmd_obj.run ()
678 self.have_run[command] = 1
679
680
Greg Wardfe6462c2000-04-04 01:40:52 +0000681 # -- Distribution query methods ------------------------------------
682
683 def has_pure_modules (self):
684 return len (self.packages or self.py_modules or []) > 0
685
686 def has_ext_modules (self):
687 return self.ext_modules and len (self.ext_modules) > 0
688
689 def has_c_libraries (self):
690 return self.libraries and len (self.libraries) > 0
691
692 def has_modules (self):
693 return self.has_pure_modules() or self.has_ext_modules()
694
Greg Ward44a61bb2000-05-20 15:06:48 +0000695 def has_scripts (self):
696 return self.scripts and len(self.scripts) > 0
697
698 def has_data_files (self):
699 return self.data_files and len(self.data_files) > 0
700
Greg Wardfe6462c2000-04-04 01:40:52 +0000701 def is_pure (self):
702 return (self.has_pure_modules() and
703 not self.has_ext_modules() and
704 not self.has_c_libraries())
705
Greg Ward82715e12000-04-21 02:28:14 +0000706 # -- Metadata query methods ----------------------------------------
707
708 # If you're looking for 'get_name()', 'get_version()', and so forth,
709 # they are defined in a sneaky way: the constructor binds self.get_XXX
710 # to self.metadata.get_XXX. The actual code is in the
711 # DistributionMetadata class, below.
712
713# class Distribution
714
715
716class DistributionMetadata:
717 """Dummy class to hold the distribution meta-data: name, version,
718 author, and so forth."""
719
720 def __init__ (self):
721 self.name = None
722 self.version = None
723 self.author = None
724 self.author_email = None
725 self.maintainer = None
726 self.maintainer_email = None
727 self.url = None
728 self.licence = None
729 self.description = None
Greg Warde5a584e2000-04-26 02:26:55 +0000730 self.long_description = None
Greg Ward82715e12000-04-21 02:28:14 +0000731
732 # -- Metadata query methods ----------------------------------------
733
Greg Wardfe6462c2000-04-04 01:40:52 +0000734 def get_name (self):
735 return self.name or "UNKNOWN"
736
Greg Ward82715e12000-04-21 02:28:14 +0000737 def get_version(self):
738 return self.version or "???"
Greg Wardfe6462c2000-04-04 01:40:52 +0000739
Greg Ward82715e12000-04-21 02:28:14 +0000740 def get_fullname (self):
741 return "%s-%s" % (self.get_name(), self.get_version())
742
743 def get_author(self):
744 return self.author or "UNKNOWN"
745
746 def get_author_email(self):
747 return self.author_email or "UNKNOWN"
748
749 def get_maintainer(self):
750 return self.maintainer or "UNKNOWN"
751
752 def get_maintainer_email(self):
753 return self.maintainer_email or "UNKNOWN"
754
755 def get_contact(self):
756 return (self.maintainer or
757 self.author or
758 "UNKNOWN")
759
760 def get_contact_email(self):
761 return (self.maintainer_email or
762 self.author_email or
763 "UNKNOWN")
764
765 def get_url(self):
766 return self.url or "UNKNOWN"
767
768 def get_licence(self):
769 return self.licence or "UNKNOWN"
770
771 def get_description(self):
772 return self.description or "UNKNOWN"
Greg Warde5a584e2000-04-26 02:26:55 +0000773
774 def get_long_description(self):
775 return self.long_description or "UNKNOWN"
776
Greg Ward82715e12000-04-21 02:28:14 +0000777# class DistributionMetadata
Greg Wardfe6462c2000-04-04 01:40:52 +0000778
779if __name__ == "__main__":
780 dist = Distribution ()
781 print "ok"