blob: f0c97aa3caccdf0562fe97aa45d425ace5eaf424 [file] [log] [blame]
Greg Ward2689e3d1999-03-22 14:52:19 +00001"""distutils.core
2
3The only module that needs to be imported to use the Distutils; provides
4the 'setup' function (which must be called); the 'Distribution' class
5(which may be subclassed if additional functionality is desired), and
6the 'Command' class (which is used both internally by Distutils, and
7may be subclassed by clients for still more flexibility)."""
8
9# created 1999/03/01, Greg Ward
10
11__rcsid__ = "$Id$"
12
Greg Ward06ca9481999-04-04 02:58:07 +000013import sys, os
Greg Ward2689e3d1999-03-22 14:52:19 +000014import string, re
Greg Ward1ea8af21999-08-29 18:20:32 +000015from types import *
Greg Ward2689e3d1999-03-22 14:52:19 +000016from distutils.errors import *
17from distutils.fancy_getopt import fancy_getopt
Greg Ward06ca9481999-04-04 02:58:07 +000018from distutils import util
Greg Ward2689e3d1999-03-22 14:52:19 +000019
20# This is not *quite* the same as a Python NAME; I don't allow leading
21# underscores. The fact that they're very similar is no coincidence...
22command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
23
24# Defining this as a global is probably inadequate -- what about
25# listing the available options (or even commands, which can vary
26# quite late as well)
27usage = '%s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]' % sys.argv[0]
28
29
30
31def setup (**attrs):
32 """The gateway to the Distutils: do everything your setup script
33 needs to do, in a highly flexible and user-driven way. Briefly:
34 create a Distribution instance; parse the command-line, creating
35 and customizing instances of the command class for each command
36 found on the command-line; run each of those commands.
37
38 The Distribution instance might be an instance of a class
39 supplied via the 'distclass' keyword argument to 'setup'; if no
40 such class is supplied, then the 'Distribution' class (also in
41 this module) is instantiated. All other arguments to 'setup'
42 (except for 'cmdclass') are used to set attributes of the
43 Distribution instance.
44
45 The 'cmdclass' argument, if supplied, is a dictionary mapping
46 command names to command classes. Each command encountered on the
47 command line will be turned into a command class, which is in turn
48 instantiated; any class found in 'cmdclass' is used in place of the
49 default, which is (for command 'foo_bar') class 'FooBar' in module
50 'distutils.command.foo_bar'. The command object must provide an
51 'options' attribute which is a list of option specifiers for
52 'distutils.fancy_getopt'. Any command-line options between the
53 current and the next command are used to set attributes in the
54 current command object.
55
56 When the entire command-line has been successfully parsed, calls the
57 'run' method on each command object in turn. This method will be
58 driven entirely by the Distribution object (which each command
59 object has a reference to, thanks to its constructor), and the
60 command-specific options that became attributes of each command
61 object."""
62
63 # Determine the distribution class -- either caller-supplied or
64 # our Distribution (see below).
65 klass = attrs.get ('distclass')
66 if klass:
67 del attrs['distclass']
68 else:
69 klass = Distribution
70
71 # Create the Distribution instance, using the remaining arguments
72 # (ie. everything except distclass) to initialize it
73 dist = klass (attrs)
74
Greg Ward42926dd1999-09-08 02:41:09 +000075 # If we had a config file, this is where we would parse it: override
76 # the client-supplied command options, but be overridden by the
77 # command line.
78
79 # Parse the command line; any command-line errors are the end-users
80 # fault, so turn them into SystemExit to suppress tracebacks.
Greg Ward2689e3d1999-03-22 14:52:19 +000081 try:
82 dist.parse_command_line (sys.argv[1:])
83 except DistutilsArgError, msg:
84 raise SystemExit, msg
85
86 # And finally, run all the commands found on the command line.
87 dist.run_commands ()
88
89# setup ()
90
91
92class Distribution:
93 """The core of the Distutils. Most of the work hiding behind
94 'setup' is really done within a Distribution instance, which
95 farms the work out to the Distutils commands specified on the
96 command line.
97
98 Clients will almost never instantiate Distribution directly,
99 unless the 'setup' function is totally inadequate to their needs.
100 However, it is conceivable that a client might wish to subclass
101 Distribution for some specialized purpose, and then pass the
102 subclass to 'setup' as the 'distclass' keyword argument. If so,
103 it is necessary to respect the expectations that 'setup' has of
104 Distribution: it must have a constructor and methods
105 'parse_command_line()' and 'run_commands()' with signatures like
106 those described below."""
107
108
109 # 'global_options' describes the command-line options that may
110 # be supplied to the client (setup.py) prior to any actual
111 # commands. Eg. "./setup.py -nv" or "./setup.py --verbose"
112 # both take advantage of these global options.
113 global_options = [('verbose', 'v', "run verbosely"),
114 ('dry-run', 'n', "don't actually do anything"),
115 ]
116
117
118 # -- Creation/initialization methods -------------------------------
119
120 def __init__ (self, attrs=None):
121 """Construct a new Distribution instance: initialize all the
122 attributes of a Distribution, and then uses 'attrs' (a
123 dictionary mapping attribute names to values) to assign
124 some of those attributes their "real" values. (Any attributes
125 not mentioned in 'attrs' will be assigned to some null
126 value: 0, None, an empty list or dictionary, etc.) Most
127 importantly, initialize the 'command_obj' attribute
128 to the empty dictionary; this will be filled in with real
129 command objects by 'parse_command_line()'."""
130
131 # Default values for our command-line options
132 self.verbose = 0
133 self.dry_run = 0
134
Greg Ward42926dd1999-09-08 02:41:09 +0000135 # And the "distribution meta-data" options -- these can only
136 # come from setup.py (the caller), not the command line
137 # (or a hypothetical config file)..
Greg Ward2689e3d1999-03-22 14:52:19 +0000138 self.name = None
139 self.version = None
140 self.author = None
Greg Warddf0d3351999-09-21 18:41:36 +0000141 self.author_email = None
Greg Ward42926dd1999-09-08 02:41:09 +0000142 self.url = None
Greg Ward2689e3d1999-03-22 14:52:19 +0000143 self.licence = None
144 self.description = None
145
Greg Wardc9973341999-06-08 02:02:00 +0000146 # 'cmdclass' maps command names to class objects, so we
147 # can 1) quickly figure out which class to instantiate when
148 # we need to create a new command object, and 2) have a way
149 # for the client to override command classes
Greg Ward2689e3d1999-03-22 14:52:19 +0000150 self.cmdclass = {}
151
Greg Ward42926dd1999-09-08 02:41:09 +0000152 # These options are really the business of various commands, rather
153 # than of the Distribution itself. We provide aliases for them in
154 # Distribution as a convenience to the developer.
155 # dictionary.
Greg Warddf0d3351999-09-21 18:41:36 +0000156 self.packages = None
157 self.package_dir = None
158 self.py_modules = None
159 self.ext_modules = None
160 self.ext_package = None
161 self.include_dirs = None
162 self.install_path = None
Greg Ward2689e3d1999-03-22 14:52:19 +0000163
164 # And now initialize bookkeeping stuff that can't be supplied by
Greg Wardc9973341999-06-08 02:02:00 +0000165 # the caller at all. 'command_obj' maps command names to
166 # Command instances -- that's how we enforce that every command
167 # class is a singleton.
Greg Ward2689e3d1999-03-22 14:52:19 +0000168 self.command_obj = {}
169
Greg Wardc9973341999-06-08 02:02:00 +0000170 # 'have_run' maps command names to boolean values; it keeps track
171 # of whether we have actually run a particular command, to make it
172 # cheap to "run" a command whenever we think we might need to -- if
173 # it's already been done, no need for expensive filesystem
174 # operations, we just check the 'have_run' dictionary and carry on.
Greg Ward7f65c651999-08-14 23:47:21 +0000175 # It's only safe to query 'have_run' for a command class that has
176 # been instantiated -- a false value will be inserted when the
177 # command object is created, and replaced with a true value when
178 # the command is succesfully run. Thus it's probably best to use
179 # '.get()' rather than a straight lookup.
Greg Wardc9973341999-06-08 02:02:00 +0000180 self.have_run = {}
181
Greg Warddf0d3351999-09-21 18:41:36 +0000182 # Now we'll use the attrs dictionary (ultimately, keyword args from
183 # the client) to possibly override any or all of these distribution
184 # options.
Greg Ward42926dd1999-09-08 02:41:09 +0000185 if attrs:
186
187 # Pull out the set of command options and work on them
188 # specifically. Note that this order guarantees that aliased
189 # command options will override any supplied redundantly
190 # through the general options dictionary.
191 options = attrs.get ('options')
192 if options:
193 del attrs['options']
194 for (command, cmd_options) in options.items():
195 cmd_obj = self.find_command_obj (command)
196 for (key, val) in cmd_options.items():
197 cmd_obj.set_option (key, val)
198 # loop over commands
199 # if any command options
200
Greg Warddf0d3351999-09-21 18:41:36 +0000201 # Now work on the rest of the attributes. Any attribute that's
202 # not already defined is invalid!
Greg Ward42926dd1999-09-08 02:41:09 +0000203 for (key,val) in attrs.items():
Greg Warddf0d3351999-09-21 18:41:36 +0000204 if hasattr (self, key):
Greg Ward42926dd1999-09-08 02:41:09 +0000205 setattr (self, key, val)
206 else:
207 raise DistutilsOptionError, \
208 "invalid distribution option '%s'" % key
209
Greg Ward2689e3d1999-03-22 14:52:19 +0000210 # __init__ ()
211
212
213 def parse_command_line (self, args):
214 """Parse the client's command line: set any Distribution
215 attributes tied to command-line options, create all command
216 objects, and set their options from the command-line. 'args'
217 must be a list of command-line arguments, most likely
218 'sys.argv[1:]' (see the 'setup()' function). This list is
219 first processed for "global options" -- options that set
220 attributes of the Distribution instance. Then, it is
221 alternately scanned for Distutils command and options for
222 that command. Each new command terminates the options for
223 the previous command. The allowed options for a command are
224 determined by the 'options' attribute of the command object
225 -- thus, we instantiate (and cache) every command object
226 here, in order to access its 'options' attribute. Any error
227 in that 'options' attribute raises DistutilsGetoptError; any
228 error on the command-line raises DistutilsArgError. If no
229 Distutils commands were found on the command line, raises
230 DistutilsArgError."""
231
232 # We have to parse the command line a bit at a time -- global
233 # options, then the first command, then its options, and so on --
234 # because each command will be handled by a different class, and
235 # the options that are valid for a particular class aren't
236 # known until we instantiate the command class, which doesn't
237 # happen until we know what the command is.
238
239 self.commands = []
240 args = fancy_getopt (self.global_options, self, sys.argv[1:])
241
242 while args:
243 # Pull the current command from the head of the command line
244 command = args[0]
245 if not command_re.match (command):
246 raise SystemExit, "invalid command name '%s'" % command
247 self.commands.append (command)
248
Greg Ward42926dd1999-09-08 02:41:09 +0000249 # Make sure we have a command object to put the options into
250 # (this either pulls it out of a cache of command objects,
251 # or finds and instantiates the command class).
252 cmd_obj = self.find_command_obj (command)
Greg Ward2689e3d1999-03-22 14:52:19 +0000253
254 # Require that the command class be derived from Command --
255 # that way, we can be sure that we at least have the 'run'
256 # and 'get_option' methods.
257 if not isinstance (cmd_obj, Command):
258 raise DistutilsClassError, \
259 "command class %s must subclass Command" % \
260 cmd_obj.__class__
261
Greg Ward42926dd1999-09-08 02:41:09 +0000262 # Also make sure that the command object provides a list of its
263 # known options
264 if not (hasattr (cmd_obj, 'options') and
265 type (cmd_obj.options) is ListType):
266 raise DistutilsClasserror, \
267 ("command class %s must provide an 'options' attribute "+
268 "(a list of tuples)") % \
269 cmd_obj.__class__
270
Greg Ward2689e3d1999-03-22 14:52:19 +0000271 args = fancy_getopt (cmd_obj.options, cmd_obj, args[1:])
272 self.command_obj[command] = cmd_obj
Greg Wardc9973341999-06-08 02:02:00 +0000273 self.have_run[command] = 0
Greg Ward2689e3d1999-03-22 14:52:19 +0000274
275 # while args
276
277 # Oops, no commands found -- an end-user error
278 if not self.commands:
279 sys.stderr.write (usage + "\n")
280 raise DistutilsArgError, "no commands supplied"
281
282 # parse_command_line()
283
284
285 # -- Command class/object methods ----------------------------------
286
287 # This is a method just so it can be overridden if desired; it doesn't
288 # actually use or change any attributes of the Distribution instance.
289 def find_command_class (self, command):
290 """Given a command, derives the names of the module and class
291 expected to implement the command: eg. 'foo_bar' becomes
292 'distutils.command.foo_bar' (the module) and 'FooBar' (the
293 class within that module). Loads the module, extracts the
294 class from it, and returns the class object.
295
296 Raises DistutilsModuleError with a semi-user-targeted error
297 message if the expected module could not be loaded, or the
298 expected class was not found in it."""
299
300 module_name = 'distutils.command.' + command
301 klass_name = string.join \
302 (map (string.capitalize, string.split (command, '_')), '')
303
304 try:
305 __import__ (module_name)
306 module = sys.modules[module_name]
307 except ImportError:
308 raise DistutilsModuleError, \
309 "invalid command '%s' (no module named %s)" % \
310 (command, module_name)
311
312 try:
313 klass = vars(module)[klass_name]
314 except KeyError:
315 raise DistutilsModuleError, \
316 "invalid command '%s' (no class '%s' in module '%s')" \
317 % (command, klass_name, module_name)
318
319 return klass
320
321 # find_command_class ()
322
323
324 def create_command_obj (self, command):
325 """Figure out the class that should implement a command,
326 instantiate it, cache and return the new "command object".
327 The "command class" is determined either by looking it up in
328 the 'cmdclass' attribute (this is the mechanism whereby
329 clients may override default Distutils commands or add their
330 own), or by calling the 'find_command_class()' method (if the
331 command name is not in 'cmdclass'."""
332
333 # Determine the command class -- either it's in the command_class
334 # dictionary, or we have to divine the module and class name
335 klass = self.cmdclass.get(command)
336 if not klass:
337 klass = self.find_command_class (command)
338 self.cmdclass[command] = klass
339
340 # Found the class OK -- instantiate it
341 cmd_obj = klass (self)
342 return cmd_obj
343
344
345 def find_command_obj (self, command, create=1):
346 """Look up and return a command object in the cache maintained by
347 'create_command_obj()'. If none found, the action taken
348 depends on 'create': if true (the default), create a new
349 command object by calling 'create_command_obj()' and return
350 it; otherwise, return None."""
351
352 cmd_obj = self.command_obj.get (command)
353 if not cmd_obj and create:
354 cmd_obj = self.create_command_obj (command)
355 self.command_obj[command] = cmd_obj
356
357 return cmd_obj
358
359
360 # -- Methods that operate on the Distribution ----------------------
361
362 def announce (self, msg, level=1):
363 """Print 'msg' if 'level' is greater than or equal to the verbosity
364 level recorded in the 'verbose' attribute (which, currently,
365 can be only 0 or 1)."""
366
367 if self.verbose >= level:
368 print msg
369
370
371 def run_commands (self):
372 """Run each command that was seen on the client command line.
373 Uses the list of commands found and cache of command objects
374 created by 'create_command_obj()'."""
375
376 for cmd in self.commands:
377 self.run_command (cmd)
378
379
380 def get_option (self, option):
381 """Return the value of a distribution option. Raise
382 DistutilsOptionError if 'option' is not known."""
383
384 try:
385 return getattr (self, opt)
386 except AttributeError:
387 raise DistutilsOptionError, \
388 "unknown distribution option %s" % option
389
390
391 def get_options (self, *options):
392 """Return (as a tuple) the values of several distribution
393 options. Raise DistutilsOptionError if any element of
394 'options' is not known."""
395
396 values = []
397 try:
398 for opt in options:
399 values.append (getattr (self, opt))
400 except AttributeError, name:
401 raise DistutilsOptionError, \
402 "unknown distribution option %s" % name
403
404 return tuple (values)
405
406
407 # -- Methods that operate on its Commands --------------------------
408
409 def run_command (self, command):
Greg Wardc9973341999-06-08 02:02:00 +0000410
411 """Do whatever it takes to run a command (including nothing at all,
412 if the command has already been run). Specifically: if we have
413 already created and run the command named by 'command', return
414 silently without doing anything. If the command named by
415 'command' doesn't even have a command object yet, create one.
416 Then invoke 'run()' on that command object (or an existing
417 one)."""
418
419 # Already been here, done that? then return silently.
420 if self.have_run.get (command):
421 return
Greg Ward2689e3d1999-03-22 14:52:19 +0000422
423 self.announce ("running " + command)
424 cmd_obj = self.find_command_obj (command)
Greg Ward3868eb91999-09-29 12:12:19 +0000425 cmd_obj.ensure_ready ()
Greg Ward2689e3d1999-03-22 14:52:19 +0000426 cmd_obj.run ()
Greg Wardc9973341999-06-08 02:02:00 +0000427 self.have_run[command] = 1
Greg Ward2689e3d1999-03-22 14:52:19 +0000428
429
430 def get_command_option (self, command, option):
Greg Ward3868eb91999-09-29 12:12:19 +0000431 """Create a command object for 'command' if necessary, ensure that
432 its option values are all set to their final values, and return
433 the value of its 'option' option. Raise DistutilsOptionError if
434 'option' is not known for that 'command'."""
Greg Ward2689e3d1999-03-22 14:52:19 +0000435
436 cmd_obj = self.find_command_obj (command)
Greg Ward3868eb91999-09-29 12:12:19 +0000437 cmd_obj.ensure_ready ()
Greg Ward2689e3d1999-03-22 14:52:19 +0000438 return cmd_obj.get_option (option)
439 try:
440 return getattr (cmd_obj, option)
441 except AttributeError:
442 raise DistutilsOptionError, \
443 "command %s: no such option %s" % (command, option)
444
445
446 def get_command_options (self, command, *options):
Greg Ward3868eb91999-09-29 12:12:19 +0000447 """Create a command object for 'command' if necessary, ensure that
448 its option values are all set to their final values, and return
449 a tuple containing the values of all the options listed in
450 'options' for that command. Raise DistutilsOptionError if any
451 invalid option is supplied in 'options'."""
Greg Ward2689e3d1999-03-22 14:52:19 +0000452
453 cmd_obj = self.find_command_obj (command)
Greg Ward3868eb91999-09-29 12:12:19 +0000454 cmd_obj.ensure_ready ()
Greg Ward2689e3d1999-03-22 14:52:19 +0000455 values = []
456 try:
457 for opt in options:
458 values.append (getattr (cmd_obj, option))
459 except AttributeError, name:
460 raise DistutilsOptionError, \
461 "command %s: no such option %s" % (command, name)
462
463 return tuple (values)
464
465# end class Distribution
466
467
468class Command:
469 """Abstract base class for defining command classes, the "worker bees"
470 of the Distutils. A useful analogy for command classes is to
471 think of them as subroutines with local variables called
Greg Ward3868eb91999-09-29 12:12:19 +0000472 "options". The options are "declared" in 'set_default_options()'
Greg Ward2689e3d1999-03-22 14:52:19 +0000473 and "initialized" (given their real values) in
474 'set_final_options()', both of which must be defined by every
475 command class. The distinction between the two is necessary
476 because option values might come from the outside world (command
477 line, option file, ...), and any options dependent on other
478 options must be computed *after* these outside influences have
Greg Ward3868eb91999-09-29 12:12:19 +0000479 been processed -- hence 'set_final_options()'. The "body" of the
Greg Ward2689e3d1999-03-22 14:52:19 +0000480 subroutine, where it does all its work based on the values of its
481 options, is the 'run()' method, which must also be implemented by
482 every command class."""
483
484 # -- Creation/initialization methods -------------------------------
485
486 def __init__ (self, dist):
487 """Create and initialize a new Command object. Most importantly,
488 invokes the 'set_default_options()' method, which is the
489 real initializer and depends on the actual command being
490 instantiated."""
491
492 if not isinstance (dist, Distribution):
493 raise TypeError, "dist must be a Distribution instance"
494 if self.__class__ is Command:
495 raise RuntimeError, "Command is an abstract class"
496
497 self.distribution = dist
498 self.set_default_options ()
499
Greg Ward3868eb91999-09-29 12:12:19 +0000500 # 'ready' records whether or not 'set_final_options()' has been
501 # called. 'set_final_options()' itself should not pay attention to
502 # this flag: it is the business of 'ensure_ready()', which always
503 # calls 'set_final_options()', to respect/update it.
504 self.ready = 0
505
Greg Ward2689e3d1999-03-22 14:52:19 +0000506 # end __init__ ()
507
Greg Ward3868eb91999-09-29 12:12:19 +0000508
509 def ensure_ready (self):
510 if not self.ready:
511 self.set_final_options ()
512 self.ready = 1
513
514
Greg Ward2689e3d1999-03-22 14:52:19 +0000515 # Subclasses must define:
516 # set_default_options()
517 # provide default values for all options; may be overridden
518 # by Distutils client, by command-line options, or by options
519 # from option file
520 # set_final_options()
521 # decide on the final values for all options; this is called
522 # after all possible intervention from the outside world
523 # (command-line, option file, etc.) has been processed
524 # run()
525 # run the command: do whatever it is we're here to do,
526 # controlled by the command's various option values
527
528 def set_default_options (self):
529 """Set default values for all the options that this command
530 supports. Note that these defaults may be overridden
531 by the command-line supplied by the user; thus, this is
532 not the place to code dependencies between options; generally,
533 'set_default_options()' implementations are just a bunch
534 of "self.foo = None" assignments.
535
536 This method must be implemented by all command classes."""
537
538 raise RuntimeError, \
539 "abstract method -- subclass %s must override" % self.__class__
540
541 def set_final_options (self):
542 """Set final values for all the options that this command
543 supports. This is always called as late as possible, ie.
544 after any option assignments from the command-line or from
545 other commands have been done. Thus, this is the place to to
546 code option dependencies: if 'foo' depends on 'bar', then it
547 is safe to set 'foo' from 'bar' as long as 'foo' still has
548 the same value it was assigned in 'set_default_options()'.
549
550 This method must be implemented by all command classes."""
551
552 raise RuntimeError, \
553 "abstract method -- subclass %s must override" % self.__class__
554
555 def run (self):
556 """A command's raison d'etre: carry out the action it exists
557 to perform, controlled by the options initialized in
558 'set_initial_options()', customized by the user and other
559 commands, and finalized in 'set_final_options()'. All
560 terminal output and filesystem interaction should be done by
561 'run()'.
562
563 This method must be implemented by all command classes."""
564
565 raise RuntimeError, \
566 "abstract method -- subclass %s must override" % self.__class__
567
568 def announce (self, msg, level=1):
569 """If the Distribution instance to which this command belongs
570 has a verbosity level of greater than or equal to 'level'
571 print 'msg' to stdout."""
572 if self.distribution.verbose >= level:
573 print msg
574
575
576 # -- Option query/set methods --------------------------------------
577
578 def get_option (self, option):
579 """Return the value of a single option for this command. Raise
580 DistutilsOptionError if 'option' is not known."""
581 try:
582 return getattr (self, option)
583 except AttributeError:
584 raise DistutilsOptionError, \
585 "command %s: no such option %s" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000586 (self.get_command_name(), option)
Greg Ward2689e3d1999-03-22 14:52:19 +0000587
588
589 def get_options (self, *options):
590 """Return (as a tuple) the values of several options for this
591 command. Raise DistutilsOptionError if any of the options in
592 'options' are not known."""
593
594 values = []
595 try:
596 for opt in options:
597 values.append (getattr (self, opt))
598 except AttributeError, name:
599 raise DistutilsOptionError, \
600 "command %s: no such option %s" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000601 (self.get_command_name(), name)
Greg Ward2689e3d1999-03-22 14:52:19 +0000602
603 return tuple (values)
604
605
606 def set_option (self, option, value):
607 """Set the value of a single option for this command. Raise
608 DistutilsOptionError if 'option' is not known."""
609
610 if not hasattr (self, option):
611 raise DistutilsOptionError, \
Greg Ward1ae32461999-09-13 03:03:01 +0000612 "command '%s': no such option '%s'" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000613 (self.get_command_name(), option)
Greg Ward2689e3d1999-03-22 14:52:19 +0000614 if value is not None:
615 setattr (self, option, value)
616
617 def set_options (self, **optval):
618 """Set the values of several options for this command. Raise
619 DistutilsOptionError if any of the options specified as
620 keyword arguments are not known."""
621
622 for k in optval.keys():
623 if optval[k] is not None:
624 self.set_option (k, optval[k])
625
626
627 # -- Convenience methods for commands ------------------------------
628
Greg Ward42926dd1999-09-08 02:41:09 +0000629 def get_command_name (self):
630 if hasattr (self, 'command_name'):
631 return self.command_name
632 else:
633 class_name = self.__class__.__name__
634
635 # The re.split here returs empty strings delimited by the
636 # words we're actually interested in -- e.g. "FooBarBaz"
637 # splits to ['', 'Foo', '', 'Bar', '', 'Baz', '']. Hence
638 # the 'filter' to strip out the empties.
639 words = filter (None, re.split (r'([A-Z][a-z]+)', class_name))
Greg Warddf0d3351999-09-21 18:41:36 +0000640 self.command_name = string.join (map (string.lower, words), "_")
641 return self.command_name
Greg Ward42926dd1999-09-08 02:41:09 +0000642
643
Greg Ward2689e3d1999-03-22 14:52:19 +0000644 def set_undefined_options (self, src_cmd, *option_pairs):
645 """Set the values of any "undefined" options from corresponding
646 option values in some other command object. "Undefined" here
647 means "is None", which is the convention used to indicate
648 that an option has not been changed between
649 'set_initial_values()' and 'set_final_values()'. Usually
650 called from 'set_final_values()' for options that depend on
651 some other command rather than another option of the same
652 command. 'src_cmd' is the other command from which option
653 values will be taken (a command object will be created for it
654 if necessary); the remaining arguments are
655 '(src_option,dst_option)' tuples which mean "take the value
656 of 'src_option' in the 'src_cmd' command object, and copy it
657 to 'dst_option' in the current command object"."""
658
659 # Option_pairs: list of (src_option, dst_option) tuples
660
661 src_cmd_obj = self.distribution.find_command_obj (src_cmd)
662 src_cmd_obj.set_final_options ()
663 try:
664 for (src_option, dst_option) in option_pairs:
665 if getattr (self, dst_option) is None:
666 self.set_option (dst_option,
667 src_cmd_obj.get_option (src_option))
668 except AttributeError, name:
669 # duh, which command?
670 raise DistutilsOptionError, "unknown option %s" % name
671
672
673 def set_peer_option (self, command, option, value):
674 """Attempt to simulate a command-line override of some option
Greg Ward3868eb91999-09-29 12:12:19 +0000675 value in another command. Finds the command object for
676 'command', sets its 'option' to 'value', and unconditionally
677 calls 'set_final_options()' on it: this means that some command
678 objects may have 'set_final_options()' invoked more than once.
679 Even so, this is not entirely reliable: the other command may
680 already be initialized to its satisfaction, in which case the
681 second 'set_final_options()' invocation will have little or no
682 effect."""
Greg Ward2689e3d1999-03-22 14:52:19 +0000683
684 cmd_obj = self.distribution.find_command_obj (command)
685 cmd_obj.set_option (option, value)
686 cmd_obj.set_final_options ()
687
688
Greg Ward3868eb91999-09-29 12:12:19 +0000689 def find_peer (self, command, create=1):
690 """Wrapper around Distribution's 'find_command_obj()' method:
691 find (create if necessary and 'create' is true) the command
692 object for 'command'.."""
693
694 return self.distribution.find_command_obj (command, create)
695
696
Greg Ward1ae32461999-09-13 03:03:01 +0000697 def get_peer_option (self, command, option):
Greg Ward3868eb91999-09-29 12:12:19 +0000698 """Find or create the command object for 'command', and return
699 its 'option' option."""
700
Greg Ward1ae32461999-09-13 03:03:01 +0000701 cmd_obj = self.distribution.find_command_obj (command)
702 return cmd_obj.get_option (option)
703
704
Greg Ward2689e3d1999-03-22 14:52:19 +0000705 def run_peer (self, command):
706 """Run some other command: uses the 'run_command()' method of
707 Distribution, which creates the command object if necessary
708 and then invokes its 'run()' method."""
709
710 self.distribution.run_command (command)
711
Greg Ward06ca9481999-04-04 02:58:07 +0000712
713 # -- External world manipulation -----------------------------------
714
Greg Warddf0d3351999-09-21 18:41:36 +0000715 def warn (self, msg):
716 sys.stderr.write ("warning: %s: %s\n" %
717 (self.get_command_name(), msg))
718
719
Greg Ward06ca9481999-04-04 02:58:07 +0000720 def execute (self, func, args, msg=None, level=1):
721 """Perform some action that affects the outside world (eg.
722 by writing to the filesystem). Such actions are special because
723 they should be disabled by the "dry run" flag (carried around by
724 the Command's Distribution), and should announce themselves if
725 the current verbosity level is high enough. This method takes
726 care of all that bureaucracy for you; all you have to do is
727 supply the funtion to call and an argument tuple for it (to
728 embody the "external action" being performed), a message to
729 print if the verbosity level is high enough, and an optional
730 verbosity threshold."""
731
732
733 # Generate a message if we weren't passed one
734 if msg is None:
735 msg = "%s %s" % (func.__name__, `args`)
736 if msg[-2:] == ',)': # correct for singleton tuple
737 msg = msg[0:-2] + ')'
738
739 # Print it if verbosity level is high enough
740 self.announce (msg, level)
741
742 # And do it, as long as we're not in dry-run mode
743 if not self.distribution.dry_run:
744 apply (func, args)
745
746 # execute()
747
748
749 def mkpath (self, name, mode=0777):
750 util.mkpath (name, mode,
751 self.distribution.verbose, self.distribution.dry_run)
752
753
754 def copy_file (self, infile, outfile,
755 preserve_mode=1, preserve_times=1, update=1, level=1):
756 """Copy a file respecting verbose and dry-run flags."""
757
Greg Ward884df451999-05-02 21:42:05 +0000758 return util.copy_file (infile, outfile,
759 preserve_mode, preserve_times,
760 update, self.distribution.verbose >= level,
761 self.distribution.dry_run)
Greg Ward06ca9481999-04-04 02:58:07 +0000762
763
764 def copy_tree (self, infile, outfile,
765 preserve_mode=1, preserve_times=1, preserve_symlinks=0,
766 update=1, level=1):
767 """Copy an entire directory tree respecting verbose and dry-run
768 flags."""
769
Greg Ward884df451999-05-02 21:42:05 +0000770 return util.copy_tree (infile, outfile,
771 preserve_mode,preserve_times,preserve_symlinks,
772 update, self.distribution.verbose >= level,
773 self.distribution.dry_run)
Greg Ward06ca9481999-04-04 02:58:07 +0000774
775
Greg Ward1ae32461999-09-13 03:03:01 +0000776 def move_file (self, src, dst, level=1):
777 """Move a file respecting verbose and dry-run flags."""
778 return util.move_file (src, dst,
779 self.distribution.verbose >= level,
780 self.distribution.dry_run)
781
782
Greg Ward3868eb91999-09-29 12:12:19 +0000783 def spawn (self, cmd, search_path=1, level=1):
784 from distutils.spawn import spawn
785 spawn (cmd, search_path,
786 self.distribution.verbose >= level,
787 self.distribution.dry_run)
788
789
Greg Ward06ca9481999-04-04 02:58:07 +0000790 def make_file (self, infiles, outfile, func, args,
791 exec_msg=None, skip_msg=None, level=1):
792
793 """Special case of 'execute()' for operations that process one or
794 more input files and generate one output file. Works just like
795 'execute()', except the operation is skipped and a different
796 message printed if 'outfile' already exists and is newer than
797 all files listed in 'infiles'."""
798
799
800 if exec_msg is None:
801 exec_msg = "generating %s from %s" % \
802 (outfile, string.join (infiles, ', '))
803 if skip_msg is None:
804 skip_msg = "skipping %s (inputs unchanged)" % outfile
805
806
807 # Allow 'infiles' to be a single string
808 if type (infiles) is StringType:
809 infiles = (infiles,)
810 elif type (infiles) not in (ListType, TupleType):
811 raise TypeError, \
812 "'infiles' must be a string, or a list or tuple of strings"
813
814 # XXX this stuff should probably be moved off to a function
815 # in 'distutils.util'
816 from stat import *
817
818 if os.path.exists (outfile):
819 out_mtime = os.stat (outfile)[ST_MTIME]
820
821 # Loop over all infiles. If any infile is newer than outfile,
822 # then we'll have to regenerate outfile
823 for f in infiles:
824 in_mtime = os.stat (f)[ST_MTIME]
825 if in_mtime > out_mtime:
826 runit = 1
827 break
828 else:
829 runit = 0
830
831 else:
832 runit = 1
833
834 # If we determined that 'outfile' must be regenerated, then
835 # perform the action that presumably regenerates it
836 if runit:
837 self.execute (func, args, exec_msg, level)
838
839 # Otherwise, print the "skip" message
840 else:
841 self.announce (skip_msg, level)
842
843 # make_file ()
844
845
846# def make_files (self, infiles, outfiles, func, args,
847# exec_msg=None, skip_msg=None, level=1):
848
849# """Special case of 'execute()' for operations that process one or
850# more input files and generate one or more output files. Works
851# just like 'execute()', except the operation is skipped and a
852# different message printed if all files listed in 'outfiles'
853# already exist and are newer than all files listed in
854# 'infiles'."""
855
856# pass
857
858
859
Greg Ward2689e3d1999-03-22 14:52:19 +0000860# end class Command