blob: bedd9d252a35bcf0c27a4bf520325d7bcf973315 [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
11import sys, string, re
12from 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
Greg Wardfe6462c2000-04-04 01:40:52 +000016
17
18# Regex to define acceptable Distutils command names. This is not *quite*
19# the same as a Python NAME -- I don't allow leading underscores. The fact
20# that they're very similar is no coincidence; the default naming scheme is
21# to look for a Python module named after the command.
22command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
23
24
25class Distribution:
26 """The core of the Distutils. Most of the work hiding behind
27 'setup' is really done within a Distribution instance, which
28 farms the work out to the Distutils commands specified on the
29 command line.
30
31 Clients will almost never instantiate Distribution directly,
32 unless the 'setup' function is totally inadequate to their needs.
33 However, it is conceivable that a client might wish to subclass
34 Distribution for some specialized purpose, and then pass the
35 subclass to 'setup' as the 'distclass' keyword argument. If so,
36 it is necessary to respect the expectations that 'setup' has of
37 Distribution: it must have a constructor and methods
38 'parse_command_line()' and 'run_commands()' with signatures like
39 those described below."""
40
41
42 # 'global_options' describes the command-line options that may be
Greg Ward82715e12000-04-21 02:28:14 +000043 # supplied to the setup script prior to any actual commands.
44 # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
Greg Wardfe6462c2000-04-04 01:40:52 +000045 # these global options. This list should be kept to a bare minimum,
46 # since every global option is also valid as a command option -- and we
47 # don't want to pollute the commands with too many options that they
48 # have minimal control over.
49 global_options = [('verbose', 'v',
50 "run verbosely (default)"),
51 ('quiet', 'q',
52 "run quietly (turns verbosity off)"),
53 ('dry-run', 'n',
54 "don't actually do anything"),
Greg Wardfe6462c2000-04-04 01:40:52 +000055 ('help', 'h',
Greg Ward82715e12000-04-21 02:28:14 +000056 "show this help message, plus help for any commands " +
57 "given on the command-line"),
Greg Wardfe6462c2000-04-04 01:40:52 +000058 ]
Greg Ward82715e12000-04-21 02:28:14 +000059
60 # options that are not propagated to the commands
61 display_options = [
62 ('help-commands', None,
63 "list all available commands"),
64 ('name', None,
65 "print package name"),
66 ('version', 'V',
67 "print package version"),
68 ('fullname', None,
69 "print <package name>-<version>"),
70 ('author', None,
71 "print the author's name"),
72 ('author-email', None,
73 "print the author's email address"),
74 ('maintainer', None,
75 "print the maintainer's name"),
76 ('maintainer-email', None,
77 "print the maintainer's email address"),
78 ('contact', None,
79 "print the name of the maintainer if present, "
80 "else author"),
81 ('contact-email', None,
82 "print the email of the maintainer if present, "
83 "else author"),
84 ('url', None,
85 "print the URL for this package"),
86 ('licence', None,
87 "print the licence of the package"),
88 ('license', None,
89 "alias for --licence"),
90 ('description', None,
91 "print the package description"),
92 ]
93 display_option_names = map(lambda x: string.translate(x[0], longopt_xlate),
94 display_options)
95
96 # negative options are options that exclude other options
Greg Wardfe6462c2000-04-04 01:40:52 +000097 negative_opt = {'quiet': 'verbose'}
98
99
100 # -- Creation/initialization methods -------------------------------
101
102 def __init__ (self, attrs=None):
103 """Construct a new Distribution instance: initialize all the
104 attributes of a Distribution, and then uses 'attrs' (a
105 dictionary mapping attribute names to values) to assign
106 some of those attributes their "real" values. (Any attributes
107 not mentioned in 'attrs' will be assigned to some null
108 value: 0, None, an empty list or dictionary, etc.) Most
109 importantly, initialize the 'command_obj' attribute
110 to the empty dictionary; this will be filled in with real
111 command objects by 'parse_command_line()'."""
112
113 # Default values for our command-line options
114 self.verbose = 1
115 self.dry_run = 0
Greg Wardfe6462c2000-04-04 01:40:52 +0000116 self.help = 0
Greg Ward82715e12000-04-21 02:28:14 +0000117 for attr in self.display_option_names:
118 setattr(self, attr, 0)
Greg Wardfe6462c2000-04-04 01:40:52 +0000119
Greg Ward82715e12000-04-21 02:28:14 +0000120 # Store the distribution meta-data (name, version, author, and so
121 # forth) in a separate object -- we're getting to have enough
122 # information here (and enough command-line options) that it's
123 # worth it. Also delegate 'get_XXX()' methods to the 'metadata'
124 # object in a sneaky and underhanded (but efficient!) way.
125 self.metadata = DistributionMetadata ()
126 for attr in dir(self.metadata):
127 meth_name = "get_" + attr
128 setattr(self, meth_name, getattr(self.metadata, meth_name))
Greg Wardfe6462c2000-04-04 01:40:52 +0000129
130 # 'cmdclass' maps command names to class objects, so we
131 # can 1) quickly figure out which class to instantiate when
132 # we need to create a new command object, and 2) have a way
Greg Ward82715e12000-04-21 02:28:14 +0000133 # for the setup script to override command classes
Greg Wardfe6462c2000-04-04 01:40:52 +0000134 self.cmdclass = {}
135
136 # These options are really the business of various commands, rather
137 # than of the Distribution itself. We provide aliases for them in
138 # Distribution as a convenience to the developer.
Greg Wardfe6462c2000-04-04 01:40:52 +0000139 self.packages = None
140 self.package_dir = None
141 self.py_modules = None
142 self.libraries = None
143 self.ext_modules = None
144 self.ext_package = None
145 self.include_dirs = None
146 self.extra_path = None
147
148 # And now initialize bookkeeping stuff that can't be supplied by
149 # the caller at all. 'command_obj' maps command names to
150 # Command instances -- that's how we enforce that every command
151 # class is a singleton.
152 self.command_obj = {}
153
154 # 'have_run' maps command names to boolean values; it keeps track
155 # of whether we have actually run a particular command, to make it
156 # cheap to "run" a command whenever we think we might need to -- if
157 # it's already been done, no need for expensive filesystem
158 # operations, we just check the 'have_run' dictionary and carry on.
159 # It's only safe to query 'have_run' for a command class that has
160 # been instantiated -- a false value will be inserted when the
161 # command object is created, and replaced with a true value when
162 # the command is succesfully run. Thus it's probably best to use
163 # '.get()' rather than a straight lookup.
164 self.have_run = {}
165
166 # Now we'll use the attrs dictionary (ultimately, keyword args from
Greg Ward82715e12000-04-21 02:28:14 +0000167 # the setup script) to possibly override any or all of these
168 # distribution options.
169
Greg Wardfe6462c2000-04-04 01:40:52 +0000170 if attrs:
171
172 # Pull out the set of command options and work on them
173 # specifically. Note that this order guarantees that aliased
174 # command options will override any supplied redundantly
175 # through the general options dictionary.
176 options = attrs.get ('options')
177 if options:
178 del attrs['options']
179 for (command, cmd_options) in options.items():
180 cmd_obj = self.find_command_obj (command)
181 for (key, val) in cmd_options.items():
182 cmd_obj.set_option (key, val)
183 # loop over commands
184 # if any command options
185
186 # Now work on the rest of the attributes. Any attribute that's
187 # not already defined is invalid!
188 for (key,val) in attrs.items():
Greg Ward82715e12000-04-21 02:28:14 +0000189 if hasattr (self.metadata, key):
190 setattr (self.metadata, key, val)
191 elif hasattr (self, key):
Greg Wardfe6462c2000-04-04 01:40:52 +0000192 setattr (self, key, val)
193 else:
Greg Ward02a1a2b2000-04-15 22:15:07 +0000194 raise DistutilsSetupError, \
Greg Wardfe6462c2000-04-04 01:40:52 +0000195 "invalid distribution option '%s'" % key
196
197 # __init__ ()
198
199
200 def parse_command_line (self, args):
201 """Parse the setup script's command line: set any Distribution
202 attributes tied to command-line options, create all command
203 objects, and set their options from the command-line. 'args'
204 must be a list of command-line arguments, most likely
205 'sys.argv[1:]' (see the 'setup()' function). This list is first
206 processed for "global options" -- options that set attributes of
207 the Distribution instance. Then, it is alternately scanned for
208 Distutils command and options for that command. Each new
209 command terminates the options for the previous command. The
210 allowed options for a command are determined by the 'options'
211 attribute of the command object -- thus, we instantiate (and
212 cache) every command object here, in order to access its
213 'options' attribute. Any error in that 'options' attribute
214 raises DistutilsGetoptError; any error on the command-line
215 raises DistutilsArgError. If no Distutils commands were found
216 on the command line, raises DistutilsArgError. Return true if
217 command-line successfully parsed and we should carry on with
218 executing commands; false if no errors but we shouldn't execute
219 commands (currently, this only happens if user asks for
220 help)."""
221
Greg Ward7d508fe2000-04-06 02:07:41 +0000222 # late import because of mutual dependence between these modules
Greg Wardfe6462c2000-04-04 01:40:52 +0000223 from distutils.cmd import Command
Greg Ward7d508fe2000-04-06 02:07:41 +0000224 from distutils.core import usage
Greg Wardfe6462c2000-04-04 01:40:52 +0000225
226 # We have to parse the command line a bit at a time -- global
227 # options, then the first command, then its options, and so on --
228 # because each command will be handled by a different class, and
229 # the options that are valid for a particular class aren't
230 # known until we instantiate the command class, which doesn't
231 # happen until we know what the command is.
232
233 self.commands = []
Greg Ward82715e12000-04-21 02:28:14 +0000234 parser = FancyGetopt (self.global_options + self.display_options)
235 parser.set_negative_aliases (self.negative_opt)
236 args = parser.getopt (object=self)
237 option_order = parser.get_option_order()
Greg Wardfe6462c2000-04-04 01:40:52 +0000238
Greg Ward82715e12000-04-21 02:28:14 +0000239 # Handle aliases (license == licence)
240 if self.license:
241 self.licence = 1
242
243 # for display options we return immediately
244 if self.handle_display_options(option_order):
Greg Wardfe6462c2000-04-04 01:40:52 +0000245 return
246
247 while args:
248 # Pull the current command from the head of the command line
249 command = args[0]
250 if not command_re.match (command):
251 raise SystemExit, "invalid command name '%s'" % command
252 self.commands.append (command)
253
254 # Make sure we have a command object to put the options into
255 # (this either pulls it out of a cache of command objects,
256 # or finds and instantiates the command class).
257 try:
258 cmd_obj = self.find_command_obj (command)
259 except DistutilsModuleError, msg:
260 raise DistutilsArgError, msg
261
262 # Require that the command class be derived from Command --
263 # that way, we can be sure that we at least have the 'run'
264 # and 'get_option' methods.
265 if not isinstance (cmd_obj, Command):
266 raise DistutilsClassError, \
267 "command class %s must subclass Command" % \
268 cmd_obj.__class__
269
270 # Also make sure that the command object provides a list of its
271 # known options
272 if not (hasattr (cmd_obj, 'user_options') and
273 type (cmd_obj.user_options) is ListType):
274 raise DistutilsClassError, \
275 ("command class %s must provide " +
276 "'user_options' attribute (a list of tuples)") % \
277 cmd_obj.__class__
278
279 # Poof! like magic, all commands support the global
280 # options too, just by adding in 'global_options'.
281 negative_opt = self.negative_opt
282 if hasattr (cmd_obj, 'negative_opt'):
283 negative_opt = copy (negative_opt)
284 negative_opt.update (cmd_obj.negative_opt)
285
Greg Ward82715e12000-04-21 02:28:14 +0000286 parser.set_option_table (self.global_options +
287 cmd_obj.user_options)
288 parser.set_negative_aliases (negative_opt)
289 args = parser.getopt (args[1:], cmd_obj)
Greg Wardfe6462c2000-04-04 01:40:52 +0000290 if cmd_obj.help:
Greg Ward82715e12000-04-21 02:28:14 +0000291 parser.set_option_table (self.global_options)
292 parser.print_help ("Global options:")
Greg Wardfe6462c2000-04-04 01:40:52 +0000293 print
Greg Ward82715e12000-04-21 02:28:14 +0000294
295 parser.set_option_table (cmd_obj.user_options)
296 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000297 print
298 print usage
299 return
300
301 self.command_obj[command] = cmd_obj
302 self.have_run[command] = 0
303
304 # while args
305
306 # If the user wants help -- ie. they gave the "--help" option --
307 # give it to 'em. We do this *after* processing the commands in
308 # case they want help on any particular command, eg.
309 # "setup.py --help foo". (This isn't the documented way to
310 # get help on a command, but I support it because that's how
311 # CVS does it -- might as well be consistent.)
312 if self.help:
Greg Ward82715e12000-04-21 02:28:14 +0000313 parser.set_option_table (self.global_options)
314 parser.print_help (
315 "Global options (apply to all commands, " +
316 "or can be used per command):")
Greg Wardfe6462c2000-04-04 01:40:52 +0000317 print
318
Greg Ward82715e12000-04-21 02:28:14 +0000319 if not self.commands:
320 parser.set_option_table (self.display_options)
321 parser.print_help (
322 "Information display options (just display " +
323 "information, ignore any commands)")
324 print
325
Greg Wardfe6462c2000-04-04 01:40:52 +0000326 for command in self.commands:
327 klass = self.find_command_class (command)
Greg Ward82715e12000-04-21 02:28:14 +0000328 parser.set_option_table (klass.user_options)
329 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000330 print
331
332 print usage
333 return
334
335 # Oops, no commands found -- an end-user error
336 if not self.commands:
337 raise DistutilsArgError, "no commands supplied"
338
339 # All is well: return true
340 return 1
341
342 # parse_command_line()
343
Greg Ward82715e12000-04-21 02:28:14 +0000344 def handle_display_options (self, option_order):
345 """If there were any non-global "display-only" options
346 (--help-commands or the metadata display options) on the command
347 line, display the requested info and return true; else return
348 false."""
349
350 from distutils.core import usage
351
352 # User just wants a list of commands -- we'll print it out and stop
353 # processing now (ie. if they ran "setup --help-commands foo bar",
354 # we ignore "foo bar").
355 if self.help_commands:
356 self.print_commands ()
357 print
358 print usage
359 return 1
360
361 # If user supplied any of the "display metadata" options, then
362 # display that metadata in the order in which the user supplied the
363 # metadata options.
364 any_display_options = 0
365 is_display_option = {}
366 for option in self.display_options:
367 is_display_option[option[0]] = 1
368
369 for (opt, val) in option_order:
370 if val and is_display_option.get(opt):
371 opt = string.translate (opt, longopt_xlate)
372 print getattr(self.metadata, "get_"+opt)()
373 any_display_options = 1
374
375 return any_display_options
376
377 # handle_display_options()
Greg Wardfe6462c2000-04-04 01:40:52 +0000378
379 def print_command_list (self, commands, header, max_length):
380 """Print a subset of the list of all commands -- used by
381 'print_commands()'."""
382
383 print header + ":"
384
385 for cmd in commands:
386 klass = self.cmdclass.get (cmd)
387 if not klass:
388 klass = self.find_command_class (cmd)
389 try:
390 description = klass.description
391 except AttributeError:
392 description = "(no description available)"
393
394 print " %-*s %s" % (max_length, cmd, description)
395
396 # print_command_list ()
397
398
399 def print_commands (self):
400 """Print out a help message listing all available commands with
401 a description of each. The list is divided into "standard
402 commands" (listed in distutils.command.__all__) and "extra
403 commands" (mentioned in self.cmdclass, but not a standard
404 command). The descriptions come from the command class
405 attribute 'description'."""
406
407 import distutils.command
408 std_commands = distutils.command.__all__
409 is_std = {}
410 for cmd in std_commands:
411 is_std[cmd] = 1
412
413 extra_commands = []
414 for cmd in self.cmdclass.keys():
415 if not is_std.get(cmd):
416 extra_commands.append (cmd)
417
418 max_length = 0
419 for cmd in (std_commands + extra_commands):
420 if len (cmd) > max_length:
421 max_length = len (cmd)
422
423 self.print_command_list (std_commands,
424 "Standard commands",
425 max_length)
426 if extra_commands:
427 print
428 self.print_command_list (extra_commands,
429 "Extra commands",
430 max_length)
431
432 # print_commands ()
433
434
435
436 # -- Command class/object methods ----------------------------------
437
438 # This is a method just so it can be overridden if desired; it doesn't
439 # actually use or change any attributes of the Distribution instance.
440 def find_command_class (self, command):
441 """Given a command, derives the names of the module and class
442 expected to implement the command: eg. 'foo_bar' becomes
443 'distutils.command.foo_bar' (the module) and 'FooBar' (the
444 class within that module). Loads the module, extracts the
445 class from it, and returns the class object.
446
447 Raises DistutilsModuleError with a semi-user-targeted error
448 message if the expected module could not be loaded, or the
449 expected class was not found in it."""
450
451 module_name = 'distutils.command.' + command
452 klass_name = command
453
454 try:
455 __import__ (module_name)
456 module = sys.modules[module_name]
457 except ImportError:
458 raise DistutilsModuleError, \
459 "invalid command '%s' (no module named '%s')" % \
460 (command, module_name)
461
462 try:
463 klass = vars(module)[klass_name]
464 except KeyError:
465 raise DistutilsModuleError, \
466 "invalid command '%s' (no class '%s' in module '%s')" \
467 % (command, klass_name, module_name)
468
469 return klass
470
471 # find_command_class ()
472
473
474 def create_command_obj (self, command):
475 """Figure out the class that should implement a command,
476 instantiate it, cache and return the new "command object".
477 The "command class" is determined either by looking it up in
478 the 'cmdclass' attribute (this is the mechanism whereby
479 clients may override default Distutils commands or add their
480 own), or by calling the 'find_command_class()' method (if the
481 command name is not in 'cmdclass'."""
482
483 # Determine the command class -- either it's in the command_class
484 # dictionary, or we have to divine the module and class name
485 klass = self.cmdclass.get(command)
486 if not klass:
487 klass = self.find_command_class (command)
488 self.cmdclass[command] = klass
489
490 # Found the class OK -- instantiate it
491 cmd_obj = klass (self)
492 return cmd_obj
493
494
495 def find_command_obj (self, command, create=1):
496 """Look up and return a command object in the cache maintained by
497 'create_command_obj()'. If none found, the action taken
498 depends on 'create': if true (the default), create a new
499 command object by calling 'create_command_obj()' and return
500 it; otherwise, return None. If 'command' is an invalid
501 command name, then DistutilsModuleError will be raised."""
502
503 cmd_obj = self.command_obj.get (command)
504 if not cmd_obj and create:
505 cmd_obj = self.create_command_obj (command)
506 self.command_obj[command] = cmd_obj
507
508 return cmd_obj
509
510
511 # -- Methods that operate on the Distribution ----------------------
512
513 def announce (self, msg, level=1):
514 """Print 'msg' if 'level' is greater than or equal to the verbosity
515 level recorded in the 'verbose' attribute (which, currently,
516 can be only 0 or 1)."""
517
518 if self.verbose >= level:
519 print msg
520
521
522 def run_commands (self):
Greg Ward82715e12000-04-21 02:28:14 +0000523 """Run each command that was seen on the setup script command line.
Greg Wardfe6462c2000-04-04 01:40:52 +0000524 Uses the list of commands found and cache of command objects
525 created by 'create_command_obj()'."""
526
527 for cmd in self.commands:
528 self.run_command (cmd)
529
530
531 def get_option (self, option):
532 """Return the value of a distribution option. Raise
Greg Ward02a1a2b2000-04-15 22:15:07 +0000533 AttributeError if 'option' is not known."""
534 return getattr (self, opt)
Greg Wardfe6462c2000-04-04 01:40:52 +0000535
536
537 def get_options (self, *options):
538 """Return (as a tuple) the values of several distribution
Greg Ward02a1a2b2000-04-15 22:15:07 +0000539 options. Raise AttributeError if any element of
Greg Wardfe6462c2000-04-04 01:40:52 +0000540 'options' is not known."""
541
542 values = []
Greg Ward02a1a2b2000-04-15 22:15:07 +0000543 for opt in options:
544 values.append (getattr (self, opt))
Greg Wardfe6462c2000-04-04 01:40:52 +0000545
546 return tuple (values)
547
548
549 # -- Methods that operate on its Commands --------------------------
550
551 def run_command (self, command):
552
553 """Do whatever it takes to run a command (including nothing at all,
554 if the command has already been run). Specifically: if we have
555 already created and run the command named by 'command', return
556 silently without doing anything. If the command named by
557 'command' doesn't even have a command object yet, create one.
558 Then invoke 'run()' on that command object (or an existing
559 one)."""
560
561 # Already been here, done that? then return silently.
562 if self.have_run.get (command):
563 return
564
565 self.announce ("running " + command)
566 cmd_obj = self.find_command_obj (command)
567 cmd_obj.ensure_ready ()
568 cmd_obj.run ()
569 self.have_run[command] = 1
570
571
572 def get_command_option (self, command, option):
573 """Create a command object for 'command' if necessary, ensure that
574 its option values are all set to their final values, and return
Greg Ward02a1a2b2000-04-15 22:15:07 +0000575 the value of its 'option' option. Raise AttributeError if
Greg Wardfe6462c2000-04-04 01:40:52 +0000576 'option' is not known for that 'command'."""
577
578 cmd_obj = self.find_command_obj (command)
579 cmd_obj.ensure_ready ()
580 return cmd_obj.get_option (option)
Greg Wardfe6462c2000-04-04 01:40:52 +0000581
582
583 def get_command_options (self, command, *options):
584 """Create a command object for 'command' if necessary, ensure that
585 its option values are all set to their final values, and return
586 a tuple containing the values of all the options listed in
587 'options' for that command. Raise DistutilsOptionError if any
588 invalid option is supplied in 'options'."""
589
590 cmd_obj = self.find_command_obj (command)
591 cmd_obj.ensure_ready ()
592 values = []
Greg Ward02a1a2b2000-04-15 22:15:07 +0000593 for opt in options:
594 values.append (getattr (cmd_obj, option))
Greg Wardfe6462c2000-04-04 01:40:52 +0000595
596 return tuple (values)
597
598
599 # -- Distribution query methods ------------------------------------
600
601 def has_pure_modules (self):
602 return len (self.packages or self.py_modules or []) > 0
603
604 def has_ext_modules (self):
605 return self.ext_modules and len (self.ext_modules) > 0
606
607 def has_c_libraries (self):
608 return self.libraries and len (self.libraries) > 0
609
610 def has_modules (self):
611 return self.has_pure_modules() or self.has_ext_modules()
612
613 def is_pure (self):
614 return (self.has_pure_modules() and
615 not self.has_ext_modules() and
616 not self.has_c_libraries())
617
Greg Ward82715e12000-04-21 02:28:14 +0000618 # -- Metadata query methods ----------------------------------------
619
620 # If you're looking for 'get_name()', 'get_version()', and so forth,
621 # they are defined in a sneaky way: the constructor binds self.get_XXX
622 # to self.metadata.get_XXX. The actual code is in the
623 # DistributionMetadata class, below.
624
625# class Distribution
626
627
628class DistributionMetadata:
629 """Dummy class to hold the distribution meta-data: name, version,
630 author, and so forth."""
631
632 def __init__ (self):
633 self.name = None
634 self.version = None
635 self.author = None
636 self.author_email = None
637 self.maintainer = None
638 self.maintainer_email = None
639 self.url = None
640 self.licence = None
641 self.description = None
642
643 # -- Metadata query methods ----------------------------------------
644
Greg Wardfe6462c2000-04-04 01:40:52 +0000645 def get_name (self):
646 return self.name or "UNKNOWN"
647
Greg Ward82715e12000-04-21 02:28:14 +0000648 def get_version(self):
649 return self.version or "???"
Greg Wardfe6462c2000-04-04 01:40:52 +0000650
Greg Ward82715e12000-04-21 02:28:14 +0000651 def get_fullname (self):
652 return "%s-%s" % (self.get_name(), self.get_version())
653
654 def get_author(self):
655 return self.author or "UNKNOWN"
656
657 def get_author_email(self):
658 return self.author_email or "UNKNOWN"
659
660 def get_maintainer(self):
661 return self.maintainer or "UNKNOWN"
662
663 def get_maintainer_email(self):
664 return self.maintainer_email or "UNKNOWN"
665
666 def get_contact(self):
667 return (self.maintainer or
668 self.author or
669 "UNKNOWN")
670
671 def get_contact_email(self):
672 return (self.maintainer_email or
673 self.author_email or
674 "UNKNOWN")
675
676 def get_url(self):
677 return self.url or "UNKNOWN"
678
679 def get_licence(self):
680 return self.licence or "UNKNOWN"
681
682 def get_description(self):
683 return self.description or "UNKNOWN"
684
685# class DistributionMetadata
Greg Wardfe6462c2000-04-04 01:40:52 +0000686
687if __name__ == "__main__":
688 dist = Distribution ()
689 print "ok"