blob: a20921277842defad575493138377247f8c532f4 [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)
Greg Ward58ec6ed2000-04-21 04:22:49 +0000236 parser.set_aliases ({'license': 'licence'})
Greg Ward82715e12000-04-21 02:28:14 +0000237 args = parser.getopt (object=self)
238 option_order = parser.get_option_order()
Greg Wardfe6462c2000-04-04 01:40:52 +0000239
Greg Ward82715e12000-04-21 02:28:14 +0000240 # for display options we return immediately
241 if self.handle_display_options(option_order):
Greg Wardfe6462c2000-04-04 01:40:52 +0000242 return
243
244 while args:
245 # Pull the current command from the head of the command line
246 command = args[0]
247 if not command_re.match (command):
248 raise SystemExit, "invalid command name '%s'" % command
249 self.commands.append (command)
250
251 # Make sure we have a command object to put the options into
252 # (this either pulls it out of a cache of command objects,
253 # or finds and instantiates the command class).
254 try:
255 cmd_obj = self.find_command_obj (command)
256 except DistutilsModuleError, msg:
257 raise DistutilsArgError, msg
258
259 # Require that the command class be derived from Command --
260 # that way, we can be sure that we at least have the 'run'
261 # and 'get_option' methods.
262 if not isinstance (cmd_obj, Command):
263 raise DistutilsClassError, \
264 "command class %s must subclass Command" % \
265 cmd_obj.__class__
266
267 # Also make sure that the command object provides a list of its
268 # known options
269 if not (hasattr (cmd_obj, 'user_options') and
270 type (cmd_obj.user_options) is ListType):
271 raise DistutilsClassError, \
272 ("command class %s must provide " +
273 "'user_options' attribute (a list of tuples)") % \
274 cmd_obj.__class__
275
276 # Poof! like magic, all commands support the global
277 # options too, just by adding in 'global_options'.
278 negative_opt = self.negative_opt
279 if hasattr (cmd_obj, 'negative_opt'):
280 negative_opt = copy (negative_opt)
281 negative_opt.update (cmd_obj.negative_opt)
282
Greg Ward82715e12000-04-21 02:28:14 +0000283 parser.set_option_table (self.global_options +
284 cmd_obj.user_options)
285 parser.set_negative_aliases (negative_opt)
286 args = parser.getopt (args[1:], cmd_obj)
Greg Wardfe6462c2000-04-04 01:40:52 +0000287 if cmd_obj.help:
Greg Ward82715e12000-04-21 02:28:14 +0000288 parser.set_option_table (self.global_options)
289 parser.print_help ("Global options:")
Greg Wardfe6462c2000-04-04 01:40:52 +0000290 print
Greg Ward82715e12000-04-21 02:28:14 +0000291
292 parser.set_option_table (cmd_obj.user_options)
293 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000294 print
295 print usage
296 return
297
298 self.command_obj[command] = cmd_obj
299 self.have_run[command] = 0
300
301 # while args
302
303 # If the user wants help -- ie. they gave the "--help" option --
304 # give it to 'em. We do this *after* processing the commands in
305 # case they want help on any particular command, eg.
306 # "setup.py --help foo". (This isn't the documented way to
307 # get help on a command, but I support it because that's how
308 # CVS does it -- might as well be consistent.)
309 if self.help:
Greg Ward82715e12000-04-21 02:28:14 +0000310 parser.set_option_table (self.global_options)
311 parser.print_help (
312 "Global options (apply to all commands, " +
313 "or can be used per command):")
Greg Wardfe6462c2000-04-04 01:40:52 +0000314 print
315
Greg Ward82715e12000-04-21 02:28:14 +0000316 if not self.commands:
317 parser.set_option_table (self.display_options)
318 parser.print_help (
319 "Information display options (just display " +
320 "information, ignore any commands)")
321 print
322
Greg Wardfe6462c2000-04-04 01:40:52 +0000323 for command in self.commands:
324 klass = self.find_command_class (command)
Greg Ward82715e12000-04-21 02:28:14 +0000325 parser.set_option_table (klass.user_options)
326 parser.print_help ("Options for '%s' command:" % command)
Greg Wardfe6462c2000-04-04 01:40:52 +0000327 print
328
329 print usage
330 return
331
332 # Oops, no commands found -- an end-user error
333 if not self.commands:
334 raise DistutilsArgError, "no commands supplied"
335
336 # All is well: return true
337 return 1
338
339 # parse_command_line()
340
Greg Ward82715e12000-04-21 02:28:14 +0000341 def handle_display_options (self, option_order):
342 """If there were any non-global "display-only" options
343 (--help-commands or the metadata display options) on the command
344 line, display the requested info and return true; else return
345 false."""
346
347 from distutils.core import usage
348
349 # User just wants a list of commands -- we'll print it out and stop
350 # processing now (ie. if they ran "setup --help-commands foo bar",
351 # we ignore "foo bar").
352 if self.help_commands:
353 self.print_commands ()
354 print
355 print usage
356 return 1
357
358 # If user supplied any of the "display metadata" options, then
359 # display that metadata in the order in which the user supplied the
360 # metadata options.
361 any_display_options = 0
362 is_display_option = {}
363 for option in self.display_options:
364 is_display_option[option[0]] = 1
365
366 for (opt, val) in option_order:
367 if val and is_display_option.get(opt):
368 opt = string.translate (opt, longopt_xlate)
369 print getattr(self.metadata, "get_"+opt)()
370 any_display_options = 1
371
372 return any_display_options
373
374 # handle_display_options()
Greg Wardfe6462c2000-04-04 01:40:52 +0000375
376 def print_command_list (self, commands, header, max_length):
377 """Print a subset of the list of all commands -- used by
378 'print_commands()'."""
379
380 print header + ":"
381
382 for cmd in commands:
383 klass = self.cmdclass.get (cmd)
384 if not klass:
385 klass = self.find_command_class (cmd)
386 try:
387 description = klass.description
388 except AttributeError:
389 description = "(no description available)"
390
391 print " %-*s %s" % (max_length, cmd, description)
392
393 # print_command_list ()
394
395
396 def print_commands (self):
397 """Print out a help message listing all available commands with
398 a description of each. The list is divided into "standard
399 commands" (listed in distutils.command.__all__) and "extra
400 commands" (mentioned in self.cmdclass, but not a standard
401 command). The descriptions come from the command class
402 attribute 'description'."""
403
404 import distutils.command
405 std_commands = distutils.command.__all__
406 is_std = {}
407 for cmd in std_commands:
408 is_std[cmd] = 1
409
410 extra_commands = []
411 for cmd in self.cmdclass.keys():
412 if not is_std.get(cmd):
413 extra_commands.append (cmd)
414
415 max_length = 0
416 for cmd in (std_commands + extra_commands):
417 if len (cmd) > max_length:
418 max_length = len (cmd)
419
420 self.print_command_list (std_commands,
421 "Standard commands",
422 max_length)
423 if extra_commands:
424 print
425 self.print_command_list (extra_commands,
426 "Extra commands",
427 max_length)
428
429 # print_commands ()
430
431
432
433 # -- Command class/object methods ----------------------------------
434
435 # This is a method just so it can be overridden if desired; it doesn't
436 # actually use or change any attributes of the Distribution instance.
437 def find_command_class (self, command):
438 """Given a command, derives the names of the module and class
439 expected to implement the command: eg. 'foo_bar' becomes
440 'distutils.command.foo_bar' (the module) and 'FooBar' (the
441 class within that module). Loads the module, extracts the
442 class from it, and returns the class object.
443
444 Raises DistutilsModuleError with a semi-user-targeted error
445 message if the expected module could not be loaded, or the
446 expected class was not found in it."""
447
448 module_name = 'distutils.command.' + command
449 klass_name = command
450
451 try:
452 __import__ (module_name)
453 module = sys.modules[module_name]
454 except ImportError:
455 raise DistutilsModuleError, \
456 "invalid command '%s' (no module named '%s')" % \
457 (command, module_name)
458
459 try:
460 klass = vars(module)[klass_name]
461 except KeyError:
462 raise DistutilsModuleError, \
463 "invalid command '%s' (no class '%s' in module '%s')" \
464 % (command, klass_name, module_name)
465
466 return klass
467
468 # find_command_class ()
469
470
471 def create_command_obj (self, command):
472 """Figure out the class that should implement a command,
473 instantiate it, cache and return the new "command object".
474 The "command class" is determined either by looking it up in
475 the 'cmdclass' attribute (this is the mechanism whereby
476 clients may override default Distutils commands or add their
477 own), or by calling the 'find_command_class()' method (if the
478 command name is not in 'cmdclass'."""
479
480 # Determine the command class -- either it's in the command_class
481 # dictionary, or we have to divine the module and class name
482 klass = self.cmdclass.get(command)
483 if not klass:
484 klass = self.find_command_class (command)
485 self.cmdclass[command] = klass
486
487 # Found the class OK -- instantiate it
488 cmd_obj = klass (self)
489 return cmd_obj
490
491
492 def find_command_obj (self, command, create=1):
493 """Look up and return a command object in the cache maintained by
494 'create_command_obj()'. If none found, the action taken
495 depends on 'create': if true (the default), create a new
496 command object by calling 'create_command_obj()' and return
497 it; otherwise, return None. If 'command' is an invalid
498 command name, then DistutilsModuleError will be raised."""
499
500 cmd_obj = self.command_obj.get (command)
501 if not cmd_obj and create:
502 cmd_obj = self.create_command_obj (command)
503 self.command_obj[command] = cmd_obj
504
505 return cmd_obj
506
507
508 # -- Methods that operate on the Distribution ----------------------
509
510 def announce (self, msg, level=1):
511 """Print 'msg' if 'level' is greater than or equal to the verbosity
512 level recorded in the 'verbose' attribute (which, currently,
513 can be only 0 or 1)."""
514
515 if self.verbose >= level:
516 print msg
517
518
519 def run_commands (self):
Greg Ward82715e12000-04-21 02:28:14 +0000520 """Run each command that was seen on the setup script command line.
Greg Wardfe6462c2000-04-04 01:40:52 +0000521 Uses the list of commands found and cache of command objects
522 created by 'create_command_obj()'."""
523
524 for cmd in self.commands:
525 self.run_command (cmd)
526
527
528 def get_option (self, option):
529 """Return the value of a distribution option. Raise
Greg Ward02a1a2b2000-04-15 22:15:07 +0000530 AttributeError if 'option' is not known."""
531 return getattr (self, opt)
Greg Wardfe6462c2000-04-04 01:40:52 +0000532
533
534 def get_options (self, *options):
535 """Return (as a tuple) the values of several distribution
Greg Ward02a1a2b2000-04-15 22:15:07 +0000536 options. Raise AttributeError if any element of
Greg Wardfe6462c2000-04-04 01:40:52 +0000537 'options' is not known."""
538
539 values = []
Greg Ward02a1a2b2000-04-15 22:15:07 +0000540 for opt in options:
541 values.append (getattr (self, opt))
Greg Wardfe6462c2000-04-04 01:40:52 +0000542
543 return tuple (values)
544
545
546 # -- Methods that operate on its Commands --------------------------
547
548 def run_command (self, command):
549
550 """Do whatever it takes to run a command (including nothing at all,
551 if the command has already been run). Specifically: if we have
552 already created and run the command named by 'command', return
553 silently without doing anything. If the command named by
554 'command' doesn't even have a command object yet, create one.
555 Then invoke 'run()' on that command object (or an existing
556 one)."""
557
558 # Already been here, done that? then return silently.
559 if self.have_run.get (command):
560 return
561
562 self.announce ("running " + command)
563 cmd_obj = self.find_command_obj (command)
564 cmd_obj.ensure_ready ()
565 cmd_obj.run ()
566 self.have_run[command] = 1
567
568
569 def get_command_option (self, command, option):
570 """Create a command object for 'command' if necessary, ensure that
571 its option values are all set to their final values, and return
Greg Ward02a1a2b2000-04-15 22:15:07 +0000572 the value of its 'option' option. Raise AttributeError if
Greg Wardfe6462c2000-04-04 01:40:52 +0000573 'option' is not known for that 'command'."""
574
575 cmd_obj = self.find_command_obj (command)
576 cmd_obj.ensure_ready ()
577 return cmd_obj.get_option (option)
Greg Wardfe6462c2000-04-04 01:40:52 +0000578
579
580 def get_command_options (self, command, *options):
581 """Create a command object for 'command' if necessary, ensure that
582 its option values are all set to their final values, and return
583 a tuple containing the values of all the options listed in
584 'options' for that command. Raise DistutilsOptionError if any
585 invalid option is supplied in 'options'."""
586
587 cmd_obj = self.find_command_obj (command)
588 cmd_obj.ensure_ready ()
589 values = []
Greg Ward02a1a2b2000-04-15 22:15:07 +0000590 for opt in options:
591 values.append (getattr (cmd_obj, option))
Greg Wardfe6462c2000-04-04 01:40:52 +0000592
593 return tuple (values)
594
595
596 # -- Distribution query methods ------------------------------------
597
598 def has_pure_modules (self):
599 return len (self.packages or self.py_modules or []) > 0
600
601 def has_ext_modules (self):
602 return self.ext_modules and len (self.ext_modules) > 0
603
604 def has_c_libraries (self):
605 return self.libraries and len (self.libraries) > 0
606
607 def has_modules (self):
608 return self.has_pure_modules() or self.has_ext_modules()
609
610 def is_pure (self):
611 return (self.has_pure_modules() and
612 not self.has_ext_modules() and
613 not self.has_c_libraries())
614
Greg Ward82715e12000-04-21 02:28:14 +0000615 # -- Metadata query methods ----------------------------------------
616
617 # If you're looking for 'get_name()', 'get_version()', and so forth,
618 # they are defined in a sneaky way: the constructor binds self.get_XXX
619 # to self.metadata.get_XXX. The actual code is in the
620 # DistributionMetadata class, below.
621
622# class Distribution
623
624
625class DistributionMetadata:
626 """Dummy class to hold the distribution meta-data: name, version,
627 author, and so forth."""
628
629 def __init__ (self):
630 self.name = None
631 self.version = None
632 self.author = None
633 self.author_email = None
634 self.maintainer = None
635 self.maintainer_email = None
636 self.url = None
637 self.licence = None
638 self.description = None
639
640 # -- Metadata query methods ----------------------------------------
641
Greg Wardfe6462c2000-04-04 01:40:52 +0000642 def get_name (self):
643 return self.name or "UNKNOWN"
644
Greg Ward82715e12000-04-21 02:28:14 +0000645 def get_version(self):
646 return self.version or "???"
Greg Wardfe6462c2000-04-04 01:40:52 +0000647
Greg Ward82715e12000-04-21 02:28:14 +0000648 def get_fullname (self):
649 return "%s-%s" % (self.get_name(), self.get_version())
650
651 def get_author(self):
652 return self.author or "UNKNOWN"
653
654 def get_author_email(self):
655 return self.author_email or "UNKNOWN"
656
657 def get_maintainer(self):
658 return self.maintainer or "UNKNOWN"
659
660 def get_maintainer_email(self):
661 return self.maintainer_email or "UNKNOWN"
662
663 def get_contact(self):
664 return (self.maintainer or
665 self.author or
666 "UNKNOWN")
667
668 def get_contact_email(self):
669 return (self.maintainer_email or
670 self.author_email or
671 "UNKNOWN")
672
673 def get_url(self):
674 return self.url or "UNKNOWN"
675
676 def get_licence(self):
677 return self.licence or "UNKNOWN"
678
679 def get_description(self):
680 return self.description or "UNKNOWN"
681
682# class DistributionMetadata
Greg Wardfe6462c2000-04-04 01:40:52 +0000683
684if __name__ == "__main__":
685 dist = Distribution ()
686 print "ok"