blob: a0c6c9ea3d5e4d4b22ef6a22191e77fabaaf1573 [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 Ward82715e12000-04-21 02:28:14 +000015from distutils.fancy_getopt import FancyGetopt, longopt_xlate
Gregory P. Smith14263542000-05-12 00:41:33 +000016from distutils.util import check_environ
Greg Wardfe6462c2000-04-04 01:40:52 +000017
18
19# Regex to define acceptable Distutils command names. This is not *quite*
20# the same as a Python NAME -- I don't allow leading underscores. The fact
21# that they're very similar is no coincidence; the default naming scheme is
22# to look for a Python module named after the command.
23command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
24
25
26class Distribution:
27 """The core of the Distutils. Most of the work hiding behind
28 'setup' is really done within a Distribution instance, which
29 farms the work out to the Distutils commands specified on the
30 command line.
31
32 Clients will almost never instantiate Distribution directly,
33 unless the 'setup' function is totally inadequate to their needs.
34 However, it is conceivable that a client might wish to subclass
35 Distribution for some specialized purpose, and then pass the
36 subclass to 'setup' as the 'distclass' keyword argument. If so,
37 it is necessary to respect the expectations that 'setup' has of
38 Distribution: it must have a constructor and methods
39 'parse_command_line()' and 'run_commands()' with signatures like
40 those described below."""
41
42
43 # 'global_options' describes the command-line options that may be
Greg Ward82715e12000-04-21 02:28:14 +000044 # supplied to the setup script prior to any actual commands.
45 # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
Greg Wardfe6462c2000-04-04 01:40:52 +000046 # these global options. This list should be kept to a bare minimum,
47 # since every global option is also valid as a command option -- and we
48 # don't want to pollute the commands with too many options that they
49 # have minimal control over.
50 global_options = [('verbose', 'v',
51 "run verbosely (default)"),
52 ('quiet', 'q',
53 "run quietly (turns verbosity off)"),
54 ('dry-run', 'n',
55 "don't actually do anything"),
Greg Wardfe6462c2000-04-04 01:40:52 +000056 ('help', 'h',
Greg Ward82715e12000-04-21 02:28:14 +000057 "show this help message, plus help for any commands " +
58 "given on the command-line"),
Greg Wardfe6462c2000-04-04 01:40:52 +000059 ]
Greg Ward82715e12000-04-21 02:28:14 +000060
61 # options that are not propagated to the commands
62 display_options = [
63 ('help-commands', None,
64 "list all available commands"),
65 ('name', None,
66 "print package name"),
67 ('version', 'V',
68 "print package version"),
69 ('fullname', None,
70 "print <package name>-<version>"),
71 ('author', None,
72 "print the author's name"),
73 ('author-email', None,
74 "print the author's email address"),
75 ('maintainer', None,
76 "print the maintainer's name"),
77 ('maintainer-email', None,
78 "print the maintainer's email address"),
79 ('contact', None,
80 "print the name of the maintainer if present, "
81 "else author"),
82 ('contact-email', None,
83 "print the email of the maintainer if present, "
84 "else author"),
85 ('url', None,
86 "print the URL for this package"),
87 ('licence', None,
88 "print the licence of the package"),
89 ('license', None,
90 "alias for --licence"),
91 ('description', None,
92 "print the package description"),
Greg Warde5a584e2000-04-26 02:26:55 +000093 ('long-description', None,
94 "print the long package description"),
Greg Ward82715e12000-04-21 02:28:14 +000095 ]
96 display_option_names = map(lambda x: string.translate(x[0], longopt_xlate),
97 display_options)
98
99 # negative options are options that exclude other options
Greg Wardfe6462c2000-04-04 01:40:52 +0000100 negative_opt = {'quiet': 'verbose'}
101
102
103 # -- Creation/initialization methods -------------------------------
104
105 def __init__ (self, attrs=None):
106 """Construct a new Distribution instance: initialize all the
107 attributes of a Distribution, and then uses 'attrs' (a
108 dictionary mapping attribute names to values) to assign
109 some of those attributes their "real" values. (Any attributes
110 not mentioned in 'attrs' will be assigned to some null
111 value: 0, None, an empty list or dictionary, etc.) Most
112 importantly, initialize the 'command_obj' attribute
113 to the empty dictionary; this will be filled in with real
114 command objects by 'parse_command_line()'."""
115
116 # Default values for our command-line options
117 self.verbose = 1
118 self.dry_run = 0
Greg Wardfe6462c2000-04-04 01:40:52 +0000119 self.help = 0
Greg Ward82715e12000-04-21 02:28:14 +0000120 for attr in self.display_option_names:
121 setattr(self, attr, 0)
Greg Wardfe6462c2000-04-04 01:40:52 +0000122
Greg Ward82715e12000-04-21 02:28:14 +0000123 # Store the distribution meta-data (name, version, author, and so
124 # forth) in a separate object -- we're getting to have enough
125 # information here (and enough command-line options) that it's
126 # worth it. Also delegate 'get_XXX()' methods to the 'metadata'
127 # object in a sneaky and underhanded (but efficient!) way.
128 self.metadata = DistributionMetadata ()
Greg Ward4982f982000-04-22 02:52:44 +0000129 method_basenames = dir(self.metadata) + \
130 ['fullname', 'contact', 'contact_email']
131 for basename in method_basenames:
132 method_name = "get_" + basename
133 setattr(self, method_name, getattr(self.metadata, method_name))
Greg Wardfe6462c2000-04-04 01:40:52 +0000134
135 # 'cmdclass' maps command names to class objects, so we
136 # can 1) quickly figure out which class to instantiate when
137 # we need to create a new command object, and 2) have a way
Greg Ward82715e12000-04-21 02:28:14 +0000138 # for the setup script to override command classes
Greg Wardfe6462c2000-04-04 01:40:52 +0000139 self.cmdclass = {}
140
Gregory P. Smith14263542000-05-12 00:41:33 +0000141 # Store options for commands here between parsing them (from config
142 # files, the command-line, etc.) and actually putting them into the
143 # command object that needs them.
144 self.command_options = {}
145
Greg Wardfe6462c2000-04-04 01:40:52 +0000146 # These options are really the business of various commands, rather
147 # than of the Distribution itself. We provide aliases for them in
148 # Distribution as a convenience to the developer.
Greg Wardfe6462c2000-04-04 01:40:52 +0000149 self.packages = None
150 self.package_dir = None
151 self.py_modules = None
152 self.libraries = None
153 self.ext_modules = None
154 self.ext_package = None
155 self.include_dirs = None
156 self.extra_path = None
157
158 # And now initialize bookkeeping stuff that can't be supplied by
159 # the caller at all. 'command_obj' maps command names to
160 # Command instances -- that's how we enforce that every command
161 # class is a singleton.
162 self.command_obj = {}
163
164 # 'have_run' maps command names to boolean values; it keeps track
165 # of whether we have actually run a particular command, to make it
166 # cheap to "run" a command whenever we think we might need to -- if
167 # it's already been done, no need for expensive filesystem
168 # operations, we just check the 'have_run' dictionary and carry on.
169 # It's only safe to query 'have_run' for a command class that has
170 # been instantiated -- a false value will be inserted when the
171 # command object is created, and replaced with a true value when
172 # the command is succesfully run. Thus it's probably best to use
173 # '.get()' rather than a straight lookup.
174 self.have_run = {}
175
176 # Now we'll use the attrs dictionary (ultimately, keyword args from
Greg Ward82715e12000-04-21 02:28:14 +0000177 # the setup script) to possibly override any or all of these
178 # distribution options.
179
Greg Wardfe6462c2000-04-04 01:40:52 +0000180 if attrs:
181
182 # Pull out the set of command options and work on them
183 # specifically. Note that this order guarantees that aliased
184 # command options will override any supplied redundantly
185 # through the general options dictionary.
186 options = attrs.get ('options')
187 if options:
188 del attrs['options']
189 for (command, cmd_options) in options.items():
190 cmd_obj = self.find_command_obj (command)
191 for (key, val) in cmd_options.items():
192 cmd_obj.set_option (key, val)
193 # loop over commands
194 # if any command options
195
196 # Now work on the rest of the attributes. Any attribute that's
197 # not already defined is invalid!
198 for (key,val) in attrs.items():
Greg Ward82715e12000-04-21 02:28:14 +0000199 if hasattr (self.metadata, key):
200 setattr (self.metadata, key, val)
201 elif hasattr (self, key):
Greg Wardfe6462c2000-04-04 01:40:52 +0000202 setattr (self, key, val)
203 else:
Greg Ward02a1a2b2000-04-15 22:15:07 +0000204 raise DistutilsSetupError, \
Greg Wardfe6462c2000-04-04 01:40:52 +0000205 "invalid distribution option '%s'" % key
206
207 # __init__ ()
208
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)
223 and setup.cfg in the current directory."""
224
225 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
261 parser = ConfigParser()
262 parser.read(filenames)
263 for section in parser.sections():
264 options = parser.options(section)
265 if not self.command_options.has_key(section) is None:
266 self.command_options[section] = {}
267 cmd_opts = self.command_options[section]
268
269 for opt in options:
270 if opt != '__name__':
271 cmd_opts[opt] = parser.get(section,opt)
272
273 from pprint import pprint
274 print "configuration options:"
275 pprint (self.command_options)
276
277
Greg Wardfe6462c2000-04-04 01:40:52 +0000278 def parse_command_line (self, args):
279 """Parse the setup script's command line: set any Distribution
280 attributes tied to command-line options, create all command
281 objects, and set their options from the command-line. 'args'
282 must be a list of command-line arguments, most likely
283 'sys.argv[1:]' (see the 'setup()' function). This list is first
284 processed for "global options" -- options that set attributes of
285 the Distribution instance. Then, it is alternately scanned for
286 Distutils command and options for that command. Each new
287 command terminates the options for the previous command. The
288 allowed options for a command are determined by the 'options'
289 attribute of the command object -- thus, we instantiate (and
290 cache) every command object here, in order to access its
291 'options' attribute. Any error in that 'options' attribute
292 raises DistutilsGetoptError; any error on the command-line
293 raises DistutilsArgError. If no Distutils commands were found
294 on the command line, raises DistutilsArgError. Return true if
295 command-line successfully parsed and we should carry on with
296 executing commands; false if no errors but we shouldn't execute
297 commands (currently, this only happens if user asks for
298 help)."""
299
Greg Ward7d508fe2000-04-06 02:07:41 +0000300 # late import because of mutual dependence between these modules
Greg Wardfe6462c2000-04-04 01:40:52 +0000301 from distutils.cmd import Command
Greg Ward7d508fe2000-04-06 02:07:41 +0000302 from distutils.core import usage
Greg Wardfe6462c2000-04-04 01:40:52 +0000303
304 # We have to parse the command line a bit at a time -- global
305 # options, then the first command, then its options, and so on --
306 # because each command will be handled by a different class, and
307 # the options that are valid for a particular class aren't
308 # known until we instantiate the command class, which doesn't
309 # happen until we know what the command is.
310
311 self.commands = []
Greg Ward82715e12000-04-21 02:28:14 +0000312 parser = FancyGetopt (self.global_options + self.display_options)
313 parser.set_negative_aliases (self.negative_opt)
Greg Ward58ec6ed2000-04-21 04:22:49 +0000314 parser.set_aliases ({'license': 'licence'})
Greg Ward82715e12000-04-21 02:28:14 +0000315 args = parser.getopt (object=self)
316 option_order = parser.get_option_order()
Greg Wardfe6462c2000-04-04 01:40:52 +0000317
Greg Ward82715e12000-04-21 02:28:14 +0000318 # for display options we return immediately
319 if self.handle_display_options(option_order):
Greg Wardfe6462c2000-04-04 01:40:52 +0000320 return
321
322 while args:
323 # Pull the current command from the head of the command line
324 command = args[0]
325 if not command_re.match (command):
326 raise SystemExit, "invalid command name '%s'" % command
327 self.commands.append (command)
328
329 # Make sure we have a command object to put the options into
330 # (this either pulls it out of a cache of command objects,
331 # or finds and instantiates the command class).
332 try:
333 cmd_obj = self.find_command_obj (command)
334 except DistutilsModuleError, msg:
335 raise DistutilsArgError, msg
336
337 # Require that the command class be derived from Command --
Greg Wardc4537ac2000-05-07 15:30:31 +0000338 # want to be sure that the basic "command" interface is
339 # implemented.
Greg Wardfe6462c2000-04-04 01:40:52 +0000340 if not isinstance (cmd_obj, Command):
341 raise DistutilsClassError, \
342 "command class %s must subclass Command" % \
343 cmd_obj.__class__
344
345 # Also make sure that the command object provides a list of its
346 # known options
347 if not (hasattr (cmd_obj, 'user_options') and
348 type (cmd_obj.user_options) is ListType):
349 raise DistutilsClassError, \
350 ("command class %s must provide " +
351 "'user_options' attribute (a list of tuples)") % \
352 cmd_obj.__class__
353
354 # Poof! like magic, all commands support the global
355 # options too, just by adding in 'global_options'.
356 negative_opt = self.negative_opt
357 if hasattr (cmd_obj, 'negative_opt'):
358 negative_opt = copy (negative_opt)
359 negative_opt.update (cmd_obj.negative_opt)
360
Greg Ward82715e12000-04-21 02:28:14 +0000361 parser.set_option_table (self.global_options +
362 cmd_obj.user_options)
363 parser.set_negative_aliases (negative_opt)
364 args = parser.getopt (args[1:], cmd_obj)
Greg Wardfe6462c2000-04-04 01:40:52 +0000365 if cmd_obj.help:
Greg Ward82715e12000-04-21 02:28:14 +0000366 parser.set_option_table (self.global_options)
367 parser.print_help ("Global options:")
Greg Wardfe6462c2000-04-04 01:40:52 +0000368 print
Greg Ward82715e12000-04-21 02:28:14 +0000369
370 parser.set_option_table (cmd_obj.user_options)
371 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000372 print
373 print usage
374 return
375
376 self.command_obj[command] = cmd_obj
377 self.have_run[command] = 0
378
379 # while args
380
381 # If the user wants help -- ie. they gave the "--help" option --
382 # give it to 'em. We do this *after* processing the commands in
383 # case they want help on any particular command, eg.
384 # "setup.py --help foo". (This isn't the documented way to
385 # get help on a command, but I support it because that's how
386 # CVS does it -- might as well be consistent.)
387 if self.help:
Greg Ward82715e12000-04-21 02:28:14 +0000388 parser.set_option_table (self.global_options)
389 parser.print_help (
390 "Global options (apply to all commands, " +
391 "or can be used per command):")
Greg Wardfe6462c2000-04-04 01:40:52 +0000392 print
393
Greg Ward82715e12000-04-21 02:28:14 +0000394 if not self.commands:
395 parser.set_option_table (self.display_options)
396 parser.print_help (
397 "Information display options (just display " +
398 "information, ignore any commands)")
399 print
400
Greg Wardfe6462c2000-04-04 01:40:52 +0000401 for command in self.commands:
402 klass = self.find_command_class (command)
Greg Ward82715e12000-04-21 02:28:14 +0000403 parser.set_option_table (klass.user_options)
404 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000405 print
406
407 print usage
408 return
409
410 # Oops, no commands found -- an end-user error
411 if not self.commands:
412 raise DistutilsArgError, "no commands supplied"
413
414 # All is well: return true
415 return 1
416
417 # parse_command_line()
418
Greg Ward82715e12000-04-21 02:28:14 +0000419 def handle_display_options (self, option_order):
420 """If there were any non-global "display-only" options
421 (--help-commands or the metadata display options) on the command
422 line, display the requested info and return true; else return
423 false."""
424
425 from distutils.core import usage
426
427 # User just wants a list of commands -- we'll print it out and stop
428 # processing now (ie. if they ran "setup --help-commands foo bar",
429 # we ignore "foo bar").
430 if self.help_commands:
431 self.print_commands ()
432 print
433 print usage
434 return 1
435
436 # If user supplied any of the "display metadata" options, then
437 # display that metadata in the order in which the user supplied the
438 # metadata options.
439 any_display_options = 0
440 is_display_option = {}
441 for option in self.display_options:
442 is_display_option[option[0]] = 1
443
444 for (opt, val) in option_order:
445 if val and is_display_option.get(opt):
446 opt = string.translate (opt, longopt_xlate)
447 print getattr(self.metadata, "get_"+opt)()
448 any_display_options = 1
449
450 return any_display_options
451
452 # handle_display_options()
Greg Wardfe6462c2000-04-04 01:40:52 +0000453
454 def print_command_list (self, commands, header, max_length):
455 """Print a subset of the list of all commands -- used by
456 'print_commands()'."""
457
458 print header + ":"
459
460 for cmd in commands:
461 klass = self.cmdclass.get (cmd)
462 if not klass:
463 klass = self.find_command_class (cmd)
464 try:
465 description = klass.description
466 except AttributeError:
467 description = "(no description available)"
468
469 print " %-*s %s" % (max_length, cmd, description)
470
471 # print_command_list ()
472
473
474 def print_commands (self):
475 """Print out a help message listing all available commands with
476 a description of each. The list is divided into "standard
477 commands" (listed in distutils.command.__all__) and "extra
478 commands" (mentioned in self.cmdclass, but not a standard
479 command). The descriptions come from the command class
480 attribute 'description'."""
481
482 import distutils.command
483 std_commands = distutils.command.__all__
484 is_std = {}
485 for cmd in std_commands:
486 is_std[cmd] = 1
487
488 extra_commands = []
489 for cmd in self.cmdclass.keys():
490 if not is_std.get(cmd):
491 extra_commands.append (cmd)
492
493 max_length = 0
494 for cmd in (std_commands + extra_commands):
495 if len (cmd) > max_length:
496 max_length = len (cmd)
497
498 self.print_command_list (std_commands,
499 "Standard commands",
500 max_length)
501 if extra_commands:
502 print
503 self.print_command_list (extra_commands,
504 "Extra commands",
505 max_length)
506
507 # print_commands ()
508
509
510
511 # -- Command class/object methods ----------------------------------
512
Greg Wardfe6462c2000-04-04 01:40:52 +0000513 def find_command_class (self, command):
Gregory P. Smith14263542000-05-12 00:41:33 +0000514 """Given a command name, attempts to load the module and class that
515 implements that command. This is done by importing a module
516 "distutils.command." + command, and a class named 'command' in that
517 module.
Greg Wardfe6462c2000-04-04 01:40:52 +0000518
Gregory P. Smith14263542000-05-12 00:41:33 +0000519 Raises DistutilsModuleError if the expected module could not be
520 found, or if that module does not define the expected class."""
Greg Wardfe6462c2000-04-04 01:40:52 +0000521
522 module_name = 'distutils.command.' + command
523 klass_name = command
524
525 try:
526 __import__ (module_name)
527 module = sys.modules[module_name]
528 except ImportError:
529 raise DistutilsModuleError, \
530 "invalid command '%s' (no module named '%s')" % \
531 (command, module_name)
532
533 try:
534 klass = vars(module)[klass_name]
535 except KeyError:
536 raise DistutilsModuleError, \
537 "invalid command '%s' (no class '%s' in module '%s')" \
538 % (command, klass_name, module_name)
539
540 return klass
541
542 # find_command_class ()
543
544
545 def create_command_obj (self, command):
546 """Figure out the class that should implement a command,
547 instantiate it, cache and return the new "command object".
548 The "command class" is determined either by looking it up in
549 the 'cmdclass' attribute (this is the mechanism whereby
550 clients may override default Distutils commands or add their
551 own), or by calling the 'find_command_class()' method (if the
552 command name is not in 'cmdclass'."""
553
554 # Determine the command class -- either it's in the command_class
555 # dictionary, or we have to divine the module and class name
556 klass = self.cmdclass.get(command)
557 if not klass:
558 klass = self.find_command_class (command)
559 self.cmdclass[command] = klass
560
561 # Found the class OK -- instantiate it
562 cmd_obj = klass (self)
563 return cmd_obj
564
565
566 def find_command_obj (self, command, create=1):
567 """Look up and return a command object in the cache maintained by
568 'create_command_obj()'. If none found, the action taken
569 depends on 'create': if true (the default), create a new
570 command object by calling 'create_command_obj()' and return
571 it; otherwise, return None. If 'command' is an invalid
572 command name, then DistutilsModuleError will be raised."""
573
574 cmd_obj = self.command_obj.get (command)
575 if not cmd_obj and create:
576 cmd_obj = self.create_command_obj (command)
577 self.command_obj[command] = cmd_obj
578
579 return cmd_obj
580
581
582 # -- Methods that operate on the Distribution ----------------------
583
584 def announce (self, msg, level=1):
585 """Print 'msg' if 'level' is greater than or equal to the verbosity
586 level recorded in the 'verbose' attribute (which, currently,
587 can be only 0 or 1)."""
588
589 if self.verbose >= level:
590 print msg
591
592
593 def run_commands (self):
Greg Ward82715e12000-04-21 02:28:14 +0000594 """Run each command that was seen on the setup script command line.
Greg Wardfe6462c2000-04-04 01:40:52 +0000595 Uses the list of commands found and cache of command objects
596 created by 'create_command_obj()'."""
597
598 for cmd in self.commands:
599 self.run_command (cmd)
600
601
Greg Wardfe6462c2000-04-04 01:40:52 +0000602 # -- Methods that operate on its Commands --------------------------
603
604 def run_command (self, command):
605
606 """Do whatever it takes to run a command (including nothing at all,
607 if the command has already been run). Specifically: if we have
608 already created and run the command named by 'command', return
609 silently without doing anything. If the command named by
610 'command' doesn't even have a command object yet, create one.
611 Then invoke 'run()' on that command object (or an existing
612 one)."""
613
614 # Already been here, done that? then return silently.
615 if self.have_run.get (command):
616 return
617
618 self.announce ("running " + command)
619 cmd_obj = self.find_command_obj (command)
620 cmd_obj.ensure_ready ()
621 cmd_obj.run ()
622 self.have_run[command] = 1
623
624
Greg Wardfe6462c2000-04-04 01:40:52 +0000625 # -- Distribution query methods ------------------------------------
626
627 def has_pure_modules (self):
628 return len (self.packages or self.py_modules or []) > 0
629
630 def has_ext_modules (self):
631 return self.ext_modules and len (self.ext_modules) > 0
632
633 def has_c_libraries (self):
634 return self.libraries and len (self.libraries) > 0
635
636 def has_modules (self):
637 return self.has_pure_modules() or self.has_ext_modules()
638
639 def is_pure (self):
640 return (self.has_pure_modules() and
641 not self.has_ext_modules() and
642 not self.has_c_libraries())
643
Greg Ward82715e12000-04-21 02:28:14 +0000644 # -- Metadata query methods ----------------------------------------
645
646 # If you're looking for 'get_name()', 'get_version()', and so forth,
647 # they are defined in a sneaky way: the constructor binds self.get_XXX
648 # to self.metadata.get_XXX. The actual code is in the
649 # DistributionMetadata class, below.
650
651# class Distribution
652
653
654class DistributionMetadata:
655 """Dummy class to hold the distribution meta-data: name, version,
656 author, and so forth."""
657
658 def __init__ (self):
659 self.name = None
660 self.version = None
661 self.author = None
662 self.author_email = None
663 self.maintainer = None
664 self.maintainer_email = None
665 self.url = None
666 self.licence = None
667 self.description = None
Greg Warde5a584e2000-04-26 02:26:55 +0000668 self.long_description = None
Greg Ward82715e12000-04-21 02:28:14 +0000669
670 # -- Metadata query methods ----------------------------------------
671
Greg Wardfe6462c2000-04-04 01:40:52 +0000672 def get_name (self):
673 return self.name or "UNKNOWN"
674
Greg Ward82715e12000-04-21 02:28:14 +0000675 def get_version(self):
676 return self.version or "???"
Greg Wardfe6462c2000-04-04 01:40:52 +0000677
Greg Ward82715e12000-04-21 02:28:14 +0000678 def get_fullname (self):
679 return "%s-%s" % (self.get_name(), self.get_version())
680
681 def get_author(self):
682 return self.author or "UNKNOWN"
683
684 def get_author_email(self):
685 return self.author_email or "UNKNOWN"
686
687 def get_maintainer(self):
688 return self.maintainer or "UNKNOWN"
689
690 def get_maintainer_email(self):
691 return self.maintainer_email or "UNKNOWN"
692
693 def get_contact(self):
694 return (self.maintainer or
695 self.author or
696 "UNKNOWN")
697
698 def get_contact_email(self):
699 return (self.maintainer_email or
700 self.author_email or
701 "UNKNOWN")
702
703 def get_url(self):
704 return self.url or "UNKNOWN"
705
706 def get_licence(self):
707 return self.licence or "UNKNOWN"
708
709 def get_description(self):
710 return self.description or "UNKNOWN"
Greg Warde5a584e2000-04-26 02:26:55 +0000711
712 def get_long_description(self):
713 return self.long_description or "UNKNOWN"
714
Greg Ward82715e12000-04-21 02:28:14 +0000715# class DistributionMetadata
Greg Wardfe6462c2000-04-04 01:40:52 +0000716
717if __name__ == "__main__":
718 dist = Distribution ()
719 print "ok"