blob: 33b3b657b187542987c1a9195a72ea95ce89f382 [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 Ward0e48cfd2000-05-26 01:00:15 +0000188 opt_dict = self.get_option_dict(command)
189 for (opt, val) in cmd_options.items():
190 opt_dict[opt] = ("setup script", val)
Greg Wardfe6462c2000-04-04 01:40:52 +0000191
192 # Now work on the rest of the attributes. Any attribute that's
193 # not already defined is invalid!
194 for (key,val) in attrs.items():
Greg Ward82715e12000-04-21 02:28:14 +0000195 if hasattr (self.metadata, key):
196 setattr (self.metadata, key, val)
197 elif hasattr (self, key):
Greg Wardfe6462c2000-04-04 01:40:52 +0000198 setattr (self, key, val)
199 else:
Greg Ward02a1a2b2000-04-15 22:15:07 +0000200 raise DistutilsSetupError, \
Greg Wardfe6462c2000-04-04 01:40:52 +0000201 "invalid distribution option '%s'" % key
202
203 # __init__ ()
204
205
Greg Ward0e48cfd2000-05-26 01:00:15 +0000206 def get_option_dict (self, command):
207 """Get the option dictionary for a given command. If that
208 command's option dictionary hasn't been created yet, then create it
209 and return the new dictionary; otherwise, return the existing
210 option dictionary.
211 """
212
213 dict = self.command_options.get(command)
214 if dict is None:
215 dict = self.command_options[command] = {}
216 return dict
217
218
Greg Wardd5d8a992000-05-23 01:42:17 +0000219 # -- Config file finding/parsing methods ---------------------------
220
Gregory P. Smith14263542000-05-12 00:41:33 +0000221 def find_config_files (self):
222 """Find as many configuration files as should be processed for this
223 platform, and return a list of filenames in the order in which they
224 should be parsed. The filenames returned are guaranteed to exist
225 (modulo nasty race conditions).
226
227 On Unix, there are three possible config files: pydistutils.cfg in
228 the Distutils installation directory (ie. where the top-level
229 Distutils __inst__.py file lives), .pydistutils.cfg in the user's
230 home directory, and setup.cfg in the current directory.
231
232 On Windows and Mac OS, there are two possible config files:
233 pydistutils.cfg in the Python installation directory (sys.prefix)
Greg Wardd5d8a992000-05-23 01:42:17 +0000234 and setup.cfg in the current directory.
235 """
Gregory P. Smith14263542000-05-12 00:41:33 +0000236 files = []
237 if os.name == "posix":
238 check_environ()
239
240 sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
241 sys_file = os.path.join(sys_dir, "pydistutils.cfg")
242 if os.path.isfile(sys_file):
243 files.append(sys_file)
244
245 user_file = os.path.join(os.environ.get('HOME'),
246 ".pydistutils.cfg")
247 if os.path.isfile(user_file):
248 files.append(user_file)
249
250 else:
251 sys_file = os.path.join (sysconfig.PREFIX, "pydistutils.cfg")
252 if os.path.isfile(sys_file):
253 files.append(sys_file)
254
255 # All platforms support local setup.cfg
256 local_file = "setup.cfg"
257 if os.path.isfile(local_file):
258 files.append(local_file)
259
260 return files
261
262 # find_config_files ()
263
264
265 def parse_config_files (self, filenames=None):
266
267 from ConfigParser import ConfigParser
268
269 if filenames is None:
270 filenames = self.find_config_files()
271
Greg Ward47460772000-05-23 03:47:35 +0000272 print "Distribution.parse_config_files():"
273
Gregory P. Smith14263542000-05-12 00:41:33 +0000274 parser = ConfigParser()
Greg Wardd5d8a992000-05-23 01:42:17 +0000275 for filename in filenames:
Greg Ward47460772000-05-23 03:47:35 +0000276 print " reading", filename
Greg Wardd5d8a992000-05-23 01:42:17 +0000277 parser.read(filename)
278 for section in parser.sections():
279 options = parser.options(section)
Greg Ward0e48cfd2000-05-26 01:00:15 +0000280 opt_dict = self.get_option_dict(section)
Gregory P. Smith14263542000-05-12 00:41:33 +0000281
Greg Wardd5d8a992000-05-23 01:42:17 +0000282 for opt in options:
283 if opt != '__name__':
Greg Ward0e48cfd2000-05-26 01:00:15 +0000284 opt_dict[opt] = (filename, parser.get(section,opt))
Gregory P. Smith14263542000-05-12 00:41:33 +0000285
Greg Ward47460772000-05-23 03:47:35 +0000286 # Make the ConfigParser forget everything (so we retain
287 # the original filenames that options come from) -- gag,
288 # retch, puke -- another good reason for a distutils-
289 # specific config parser (sigh...)
290 parser.__init__()
Gregory P. Smith14263542000-05-12 00:41:33 +0000291
292
Greg Wardd5d8a992000-05-23 01:42:17 +0000293 # -- Command-line parsing methods ----------------------------------
294
Greg Wardfe6462c2000-04-04 01:40:52 +0000295 def parse_command_line (self, args):
Greg Wardd5d8a992000-05-23 01:42:17 +0000296 """Parse the setup script's command line. 'args' must be a list
297 of command-line arguments, most likely 'sys.argv[1:]' (see the
298 'setup()' function). This list is first processed for "global
299 options" -- options that set attributes of the Distribution
300 instance. Then, it is alternately scanned for Distutils
301 commands and options for that command. Each new command
302 terminates the options for the previous command. The allowed
303 options for a command are determined by the 'user_options'
304 attribute of the command class -- thus, we have to be able to
305 load command classes in order to parse the command line. Any
306 error in that 'options' attribute raises DistutilsGetoptError;
307 any error on the command-line raises DistutilsArgError. If no
308 Distutils commands were found on the command line, raises
309 DistutilsArgError. Return true if command-line were
310 successfully parsed and we should carry on with executing
311 commands; false if no errors but we shouldn't execute commands
312 (currently, this only happens if user asks for help).
313 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000314 # We have to parse the command line a bit at a time -- global
315 # options, then the first command, then its options, and so on --
316 # because each command will be handled by a different class, and
Greg Wardd5d8a992000-05-23 01:42:17 +0000317 # the options that are valid for a particular class aren't known
318 # until we have loaded the command class, which doesn't happen
319 # until we know what the command is.
Greg Wardfe6462c2000-04-04 01:40:52 +0000320
321 self.commands = []
Greg Ward82715e12000-04-21 02:28:14 +0000322 parser = FancyGetopt (self.global_options + self.display_options)
323 parser.set_negative_aliases (self.negative_opt)
Greg Ward58ec6ed2000-04-21 04:22:49 +0000324 parser.set_aliases ({'license': 'licence'})
Greg Ward82715e12000-04-21 02:28:14 +0000325 args = parser.getopt (object=self)
326 option_order = parser.get_option_order()
Greg Wardfe6462c2000-04-04 01:40:52 +0000327
Greg Ward82715e12000-04-21 02:28:14 +0000328 # for display options we return immediately
329 if self.handle_display_options(option_order):
Greg Wardfe6462c2000-04-04 01:40:52 +0000330 return
331
332 while args:
Greg Wardd5d8a992000-05-23 01:42:17 +0000333 args = self._parse_command_opts(parser, args)
334 if args is None: # user asked for help (and got it)
Greg Wardfe6462c2000-04-04 01:40:52 +0000335 return
Greg Wardfe6462c2000-04-04 01:40:52 +0000336
Greg Wardd5d8a992000-05-23 01:42:17 +0000337 # Handle the cases of --help as a "global" option, ie.
338 # "setup.py --help" and "setup.py --help command ...". For the
339 # former, we show global options (--verbose, --dry-run, etc.)
340 # and display-only options (--name, --version, etc.); for the
341 # latter, we omit the display-only options and show help for
342 # each command listed on the command line.
Greg Wardfe6462c2000-04-04 01:40:52 +0000343 if self.help:
Greg Wardd5d8a992000-05-23 01:42:17 +0000344 print "showing 'global' help; commands=", self.commands
345 self._show_help(parser,
346 display_options=len(self.commands) == 0,
347 commands=self.commands)
Greg Wardfe6462c2000-04-04 01:40:52 +0000348 return
349
350 # Oops, no commands found -- an end-user error
351 if not self.commands:
352 raise DistutilsArgError, "no commands supplied"
353
354 # All is well: return true
355 return 1
356
357 # parse_command_line()
358
Greg Wardd5d8a992000-05-23 01:42:17 +0000359 def _parse_command_opts (self, parser, args):
360
361 """Parse the command-line options for a single command.
362 'parser' must be a FancyGetopt instance; 'args' must be the list
363 of arguments, starting with the current command (whose options
364 we are about to parse). Returns a new version of 'args' with
365 the next command at the front of the list; will be the empty
366 list if there are no more commands on the command line. Returns
367 None if the user asked for help on this command.
368 """
369 # late import because of mutual dependence between these modules
370 from distutils.cmd import Command
371
372 # Pull the current command from the head of the command line
373 command = args[0]
374 if not command_re.match (command):
375 raise SystemExit, "invalid command name '%s'" % command
376 self.commands.append (command)
377
378 # Dig up the command class that implements this command, so we
379 # 1) know that it's a valid command, and 2) know which options
380 # it takes.
381 try:
382 cmd_class = self.get_command_class (command)
383 except DistutilsModuleError, msg:
384 raise DistutilsArgError, msg
385
386 # Require that the command class be derived from Command -- want
387 # to be sure that the basic "command" interface is implemented.
388 if not issubclass (cmd_class, Command):
389 raise DistutilsClassError, \
390 "command class %s must subclass Command" % cmd_class
391
392 # Also make sure that the command object provides a list of its
393 # known options.
394 if not (hasattr (cmd_class, 'user_options') and
395 type (cmd_class.user_options) is ListType):
396 raise DistutilsClassError, \
397 ("command class %s must provide " +
398 "'user_options' attribute (a list of tuples)") % \
399 cmd_class
400
401 # If the command class has a list of negative alias options,
402 # merge it in with the global negative aliases.
403 negative_opt = self.negative_opt
404 if hasattr (cmd_class, 'negative_opt'):
405 negative_opt = copy (negative_opt)
406 negative_opt.update (cmd_class.negative_opt)
407
408 # All commands support the global options too, just by adding
409 # in 'global_options'.
410 parser.set_option_table (self.global_options +
411 cmd_class.user_options)
412 parser.set_negative_aliases (negative_opt)
413 (args, opts) = parser.getopt (args[1:])
Greg Ward47460772000-05-23 03:47:35 +0000414 if hasattr(opts, 'help') and opts.help:
Greg Wardd5d8a992000-05-23 01:42:17 +0000415 print "showing help for command", cmd_class
416 self._show_help(parser, display_options=0, commands=[cmd_class])
417 return
418
419 # Put the options from the command-line into their official
420 # holding pen, the 'command_options' dictionary.
Greg Ward0e48cfd2000-05-26 01:00:15 +0000421 opt_dict = self.get_option_dict(command)
Greg Wardd5d8a992000-05-23 01:42:17 +0000422 for (name, value) in vars(opts).items():
Greg Ward0e48cfd2000-05-26 01:00:15 +0000423 opt_dict[name] = ("command line", value)
Greg Wardd5d8a992000-05-23 01:42:17 +0000424
425 return args
426
427 # _parse_command_opts ()
428
429
430 def _show_help (self,
431 parser,
432 global_options=1,
433 display_options=1,
434 commands=[]):
435 """Show help for the setup script command-line in the form of
436 several lists of command-line options. 'parser' should be a
437 FancyGetopt instance; do not expect it to be returned in the
438 same state, as its option table will be reset to make it
439 generate the correct help text.
440
441 If 'global_options' is true, lists the global options:
442 --verbose, --dry-run, etc. If 'display_options' is true, lists
443 the "display-only" options: --name, --version, etc. Finally,
444 lists per-command help for every command name or command class
445 in 'commands'.
446 """
447 # late import because of mutual dependence between these modules
448 from distutils.core import usage
449 from distutils.cmd import Command
450
451 if global_options:
452 parser.set_option_table (self.global_options)
453 parser.print_help ("Global options:")
454 print
455
456 if display_options:
457 parser.set_option_table (self.display_options)
458 parser.print_help (
459 "Information display options (just display " +
460 "information, ignore any commands)")
461 print
462
463 for command in self.commands:
464 if type(command) is ClassType and issubclass(klass, Command):
465 klass = command
466 else:
467 klass = self.get_command_class (command)
468 parser.set_option_table (klass.user_options)
469 parser.print_help ("Options for '%s' command:" % klass.__name__)
470 print
471
472 print usage
473 return
474
475 # _show_help ()
476
477
Greg Ward82715e12000-04-21 02:28:14 +0000478 def handle_display_options (self, option_order):
479 """If there were any non-global "display-only" options
Greg Wardd5d8a992000-05-23 01:42:17 +0000480 (--help-commands or the metadata display options) on the command
481 line, display the requested info and return true; else return
482 false.
483 """
Greg Ward82715e12000-04-21 02:28:14 +0000484 from distutils.core import usage
485
486 # User just wants a list of commands -- we'll print it out and stop
487 # processing now (ie. if they ran "setup --help-commands foo bar",
488 # we ignore "foo bar").
489 if self.help_commands:
490 self.print_commands ()
491 print
492 print usage
493 return 1
494
495 # If user supplied any of the "display metadata" options, then
496 # display that metadata in the order in which the user supplied the
497 # metadata options.
498 any_display_options = 0
499 is_display_option = {}
500 for option in self.display_options:
501 is_display_option[option[0]] = 1
502
503 for (opt, val) in option_order:
504 if val and is_display_option.get(opt):
505 opt = string.translate (opt, longopt_xlate)
506 print getattr(self.metadata, "get_"+opt)()
507 any_display_options = 1
508
509 return any_display_options
510
511 # handle_display_options()
Greg Wardfe6462c2000-04-04 01:40:52 +0000512
513 def print_command_list (self, commands, header, max_length):
514 """Print a subset of the list of all commands -- used by
Greg Wardd5d8a992000-05-23 01:42:17 +0000515 'print_commands()'.
516 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000517
518 print header + ":"
519
520 for cmd in commands:
521 klass = self.cmdclass.get (cmd)
522 if not klass:
Greg Wardd5d8a992000-05-23 01:42:17 +0000523 klass = self.get_command_class (cmd)
Greg Wardfe6462c2000-04-04 01:40:52 +0000524 try:
525 description = klass.description
526 except AttributeError:
527 description = "(no description available)"
528
529 print " %-*s %s" % (max_length, cmd, description)
530
531 # print_command_list ()
532
533
534 def print_commands (self):
Greg Wardd5d8a992000-05-23 01:42:17 +0000535 """Print out a help message listing all available commands with a
536 description of each. The list is divided into "standard commands"
537 (listed in distutils.command.__all__) and "extra commands"
538 (mentioned in self.cmdclass, but not a standard command). The
539 descriptions come from the command class attribute
540 'description'.
541 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000542
543 import distutils.command
544 std_commands = distutils.command.__all__
545 is_std = {}
546 for cmd in std_commands:
547 is_std[cmd] = 1
548
549 extra_commands = []
550 for cmd in self.cmdclass.keys():
551 if not is_std.get(cmd):
552 extra_commands.append (cmd)
553
554 max_length = 0
555 for cmd in (std_commands + extra_commands):
556 if len (cmd) > max_length:
557 max_length = len (cmd)
558
559 self.print_command_list (std_commands,
560 "Standard commands",
561 max_length)
562 if extra_commands:
563 print
564 self.print_command_list (extra_commands,
565 "Extra commands",
566 max_length)
567
568 # print_commands ()
Greg Wardfe6462c2000-04-04 01:40:52 +0000569
570
571 # -- Command class/object methods ----------------------------------
572
Greg Wardd5d8a992000-05-23 01:42:17 +0000573 def get_command_class (self, command):
574 """Return the class that implements the Distutils command named by
575 'command'. First we check the 'cmdclass' dictionary; if the
576 command is mentioned there, we fetch the class object from the
577 dictionary and return it. Otherwise we load the command module
578 ("distutils.command." + command) and fetch the command class from
579 the module. The loaded class is also stored in 'cmdclass'
580 to speed future calls to 'get_command_class()'.
Greg Wardfe6462c2000-04-04 01:40:52 +0000581
Gregory P. Smith14263542000-05-12 00:41:33 +0000582 Raises DistutilsModuleError if the expected module could not be
Greg Wardd5d8a992000-05-23 01:42:17 +0000583 found, or if that module does not define the expected class.
584 """
585 klass = self.cmdclass.get(command)
586 if klass:
587 return klass
Greg Wardfe6462c2000-04-04 01:40:52 +0000588
589 module_name = 'distutils.command.' + command
590 klass_name = command
591
592 try:
593 __import__ (module_name)
594 module = sys.modules[module_name]
595 except ImportError:
596 raise DistutilsModuleError, \
597 "invalid command '%s' (no module named '%s')" % \
598 (command, module_name)
599
600 try:
Greg Wardd5d8a992000-05-23 01:42:17 +0000601 klass = getattr(module, klass_name)
602 except AttributeError:
Greg Wardfe6462c2000-04-04 01:40:52 +0000603 raise DistutilsModuleError, \
604 "invalid command '%s' (no class '%s' in module '%s')" \
605 % (command, klass_name, module_name)
606
Greg Wardd5d8a992000-05-23 01:42:17 +0000607 self.cmdclass[command] = klass
Greg Wardfe6462c2000-04-04 01:40:52 +0000608 return klass
609
Greg Wardd5d8a992000-05-23 01:42:17 +0000610 # get_command_class ()
Greg Wardfe6462c2000-04-04 01:40:52 +0000611
Greg Wardd5d8a992000-05-23 01:42:17 +0000612 def get_command_obj (self, command, create=1):
613 """Return the command object for 'command'. Normally this object
614 is cached on a previous call to 'get_command_obj()'; if no comand
615 object for 'command' is in the cache, then we either create and
616 return it (if 'create' is true) or return None.
617 """
618 cmd_obj = self.command_obj.get(command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000619 if not cmd_obj and create:
Greg Ward47460772000-05-23 03:47:35 +0000620 print "Distribution.get_command_obj(): " \
621 "creating '%s' command object" % command
622
Greg Wardd5d8a992000-05-23 01:42:17 +0000623 klass = self.get_command_class(command)
Greg Ward47460772000-05-23 03:47:35 +0000624 cmd_obj = self.command_obj[command] = klass(self)
625 self.have_run[command] = 0
626
627 # Set any options that were supplied in config files
628 # or on the command line. (NB. support for error
629 # reporting is lame here: any errors aren't reported
630 # until 'finalize_options()' is called, which means
631 # we won't report the source of the error.)
632 options = self.command_options.get(command)
633 if options:
634 print " setting options:"
635 for (option, (source, value)) in options.items():
636 print " %s = %s (from %s)" % (option, value, source)
Greg Ward40313cf2000-05-23 04:11:14 +0000637 if not hasattr(cmd_obj, option):
638 raise DistutilsOptionError, \
639 ("%s: command '%s' has no such option '%s'") % \
640 (source, command, option)
Greg Ward47460772000-05-23 03:47:35 +0000641 setattr(cmd_obj, option, value)
Greg Wardfe6462c2000-04-04 01:40:52 +0000642
643 return cmd_obj
644
645
646 # -- Methods that operate on the Distribution ----------------------
647
648 def announce (self, msg, level=1):
649 """Print 'msg' if 'level' is greater than or equal to the verbosity
Greg Wardd5d8a992000-05-23 01:42:17 +0000650 level recorded in the 'verbose' attribute (which, currently, can be
651 only 0 or 1).
652 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000653 if self.verbose >= level:
654 print msg
655
656
657 def run_commands (self):
Greg Ward82715e12000-04-21 02:28:14 +0000658 """Run each command that was seen on the setup script command line.
Greg Wardd5d8a992000-05-23 01:42:17 +0000659 Uses the list of commands found and cache of command objects
660 created by 'get_command_obj()'."""
Greg Wardfe6462c2000-04-04 01:40:52 +0000661
662 for cmd in self.commands:
663 self.run_command (cmd)
664
665
Greg Wardfe6462c2000-04-04 01:40:52 +0000666 # -- Methods that operate on its Commands --------------------------
667
668 def run_command (self, command):
Greg Wardfe6462c2000-04-04 01:40:52 +0000669 """Do whatever it takes to run a command (including nothing at all,
Greg Wardd5d8a992000-05-23 01:42:17 +0000670 if the command has already been run). Specifically: if we have
671 already created and run the command named by 'command', return
672 silently without doing anything. If the command named by 'command'
673 doesn't even have a command object yet, create one. Then invoke
674 'run()' on that command object (or an existing one).
675 """
Greg Wardfe6462c2000-04-04 01:40:52 +0000676
677 # Already been here, done that? then return silently.
678 if self.have_run.get (command):
679 return
680
681 self.announce ("running " + command)
Greg Wardd5d8a992000-05-23 01:42:17 +0000682 cmd_obj = self.get_command_obj (command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000683 cmd_obj.ensure_ready ()
684 cmd_obj.run ()
685 self.have_run[command] = 1
686
687
Greg Wardfe6462c2000-04-04 01:40:52 +0000688 # -- Distribution query methods ------------------------------------
689
690 def has_pure_modules (self):
691 return len (self.packages or self.py_modules or []) > 0
692
693 def has_ext_modules (self):
694 return self.ext_modules and len (self.ext_modules) > 0
695
696 def has_c_libraries (self):
697 return self.libraries and len (self.libraries) > 0
698
699 def has_modules (self):
700 return self.has_pure_modules() or self.has_ext_modules()
701
Greg Ward44a61bb2000-05-20 15:06:48 +0000702 def has_scripts (self):
703 return self.scripts and len(self.scripts) > 0
704
705 def has_data_files (self):
706 return self.data_files and len(self.data_files) > 0
707
Greg Wardfe6462c2000-04-04 01:40:52 +0000708 def is_pure (self):
709 return (self.has_pure_modules() and
710 not self.has_ext_modules() and
711 not self.has_c_libraries())
712
Greg Ward82715e12000-04-21 02:28:14 +0000713 # -- Metadata query methods ----------------------------------------
714
715 # If you're looking for 'get_name()', 'get_version()', and so forth,
716 # they are defined in a sneaky way: the constructor binds self.get_XXX
717 # to self.metadata.get_XXX. The actual code is in the
718 # DistributionMetadata class, below.
719
720# class Distribution
721
722
723class DistributionMetadata:
724 """Dummy class to hold the distribution meta-data: name, version,
725 author, and so forth."""
726
727 def __init__ (self):
728 self.name = None
729 self.version = None
730 self.author = None
731 self.author_email = None
732 self.maintainer = None
733 self.maintainer_email = None
734 self.url = None
735 self.licence = None
736 self.description = None
Greg Warde5a584e2000-04-26 02:26:55 +0000737 self.long_description = None
Greg Ward82715e12000-04-21 02:28:14 +0000738
739 # -- Metadata query methods ----------------------------------------
740
Greg Wardfe6462c2000-04-04 01:40:52 +0000741 def get_name (self):
742 return self.name or "UNKNOWN"
743
Greg Ward82715e12000-04-21 02:28:14 +0000744 def get_version(self):
745 return self.version or "???"
Greg Wardfe6462c2000-04-04 01:40:52 +0000746
Greg Ward82715e12000-04-21 02:28:14 +0000747 def get_fullname (self):
748 return "%s-%s" % (self.get_name(), self.get_version())
749
750 def get_author(self):
751 return self.author or "UNKNOWN"
752
753 def get_author_email(self):
754 return self.author_email or "UNKNOWN"
755
756 def get_maintainer(self):
757 return self.maintainer or "UNKNOWN"
758
759 def get_maintainer_email(self):
760 return self.maintainer_email or "UNKNOWN"
761
762 def get_contact(self):
763 return (self.maintainer or
764 self.author or
765 "UNKNOWN")
766
767 def get_contact_email(self):
768 return (self.maintainer_email or
769 self.author_email or
770 "UNKNOWN")
771
772 def get_url(self):
773 return self.url or "UNKNOWN"
774
775 def get_licence(self):
776 return self.licence or "UNKNOWN"
777
778 def get_description(self):
779 return self.description or "UNKNOWN"
Greg Warde5a584e2000-04-26 02:26:55 +0000780
781 def get_long_description(self):
782 return self.long_description or "UNKNOWN"
783
Greg Ward82715e12000-04-21 02:28:14 +0000784# class DistributionMetadata
Greg Wardfe6462c2000-04-04 01:40:52 +0000785
786if __name__ == "__main__":
787 dist = Distribution ()
788 print "ok"