blob: e53392133d4408f1a7e8cbec0d38a0391e97143c [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
Greg Ward42926dd1999-09-08 02:41:09 +0000419 # XXX currently, this is the only place where we invoke a
420 # command object's 'run()' method -- so it might make sense to
421 # put the 'set_final_options()' call here, too, instead of
422 # requiring every command's 'run()' to call it first.
423
Greg Wardc9973341999-06-08 02:02:00 +0000424 # Already been here, done that? then return silently.
425 if self.have_run.get (command):
426 return
Greg Ward2689e3d1999-03-22 14:52:19 +0000427
428 self.announce ("running " + command)
429 cmd_obj = self.find_command_obj (command)
430 cmd_obj.run ()
Greg Wardc9973341999-06-08 02:02:00 +0000431 self.have_run[command] = 1
Greg Ward2689e3d1999-03-22 14:52:19 +0000432
433
434 def get_command_option (self, command, option):
435 """Create a command object for 'command' if necessary, finalize
436 its option values by invoking its 'set_final_options()'
437 method, and return the value of its 'option' option. Raise
438 DistutilsOptionError if 'option' is not known for
439 that 'command'."""
440
441 cmd_obj = self.find_command_obj (command)
442 cmd_obj.set_final_options ()
443 return cmd_obj.get_option (option)
444 try:
445 return getattr (cmd_obj, option)
446 except AttributeError:
447 raise DistutilsOptionError, \
448 "command %s: no such option %s" % (command, option)
449
450
451 def get_command_options (self, command, *options):
452 """Create a command object for 'command' if necessary, finalize
453 its option values by invoking its 'set_final_options()'
454 method, and return the values of all the options listed in
455 'options' for that command. Raise DistutilsOptionError if
456 'option' is not known for that 'command'."""
457
458 cmd_obj = self.find_command_obj (command)
459 cmd_obj.set_final_options ()
460 values = []
461 try:
462 for opt in options:
463 values.append (getattr (cmd_obj, option))
464 except AttributeError, name:
465 raise DistutilsOptionError, \
466 "command %s: no such option %s" % (command, name)
467
468 return tuple (values)
469
470# end class Distribution
471
472
473class Command:
474 """Abstract base class for defining command classes, the "worker bees"
475 of the Distutils. A useful analogy for command classes is to
476 think of them as subroutines with local variables called
477 "options". The options are "declared" in 'set_initial_options()'
478 and "initialized" (given their real values) in
479 'set_final_options()', both of which must be defined by every
480 command class. The distinction between the two is necessary
481 because option values might come from the outside world (command
482 line, option file, ...), and any options dependent on other
483 options must be computed *after* these outside influences have
484 been processed -- hence 'set_final_values()'. The "body" of the
485 subroutine, where it does all its work based on the values of its
486 options, is the 'run()' method, which must also be implemented by
487 every command class."""
488
489 # -- Creation/initialization methods -------------------------------
490
491 def __init__ (self, dist):
492 """Create and initialize a new Command object. Most importantly,
493 invokes the 'set_default_options()' method, which is the
494 real initializer and depends on the actual command being
495 instantiated."""
496
497 if not isinstance (dist, Distribution):
498 raise TypeError, "dist must be a Distribution instance"
499 if self.__class__ is Command:
500 raise RuntimeError, "Command is an abstract class"
501
502 self.distribution = dist
503 self.set_default_options ()
504
505 # end __init__ ()
506
507 # Subclasses must define:
508 # set_default_options()
509 # provide default values for all options; may be overridden
510 # by Distutils client, by command-line options, or by options
511 # from option file
512 # set_final_options()
513 # decide on the final values for all options; this is called
514 # after all possible intervention from the outside world
515 # (command-line, option file, etc.) has been processed
516 # run()
517 # run the command: do whatever it is we're here to do,
518 # controlled by the command's various option values
519
520 def set_default_options (self):
521 """Set default values for all the options that this command
522 supports. Note that these defaults may be overridden
523 by the command-line supplied by the user; thus, this is
524 not the place to code dependencies between options; generally,
525 'set_default_options()' implementations are just a bunch
526 of "self.foo = None" assignments.
527
528 This method must be implemented by all command classes."""
529
530 raise RuntimeError, \
531 "abstract method -- subclass %s must override" % self.__class__
532
533 def set_final_options (self):
534 """Set final values for all the options that this command
535 supports. This is always called as late as possible, ie.
536 after any option assignments from the command-line or from
537 other commands have been done. Thus, this is the place to to
538 code option dependencies: if 'foo' depends on 'bar', then it
539 is safe to set 'foo' from 'bar' as long as 'foo' still has
540 the same value it was assigned in 'set_default_options()'.
541
542 This method must be implemented by all command classes."""
543
544 raise RuntimeError, \
545 "abstract method -- subclass %s must override" % self.__class__
546
547 def run (self):
548 """A command's raison d'etre: carry out the action it exists
549 to perform, controlled by the options initialized in
550 'set_initial_options()', customized by the user and other
551 commands, and finalized in 'set_final_options()'. All
552 terminal output and filesystem interaction should be done by
553 'run()'.
554
555 This method must be implemented by all command classes."""
556
557 raise RuntimeError, \
558 "abstract method -- subclass %s must override" % self.__class__
559
560 def announce (self, msg, level=1):
561 """If the Distribution instance to which this command belongs
562 has a verbosity level of greater than or equal to 'level'
563 print 'msg' to stdout."""
564 if self.distribution.verbose >= level:
565 print msg
566
567
568 # -- Option query/set methods --------------------------------------
569
570 def get_option (self, option):
571 """Return the value of a single option for this command. Raise
572 DistutilsOptionError if 'option' is not known."""
573 try:
574 return getattr (self, option)
575 except AttributeError:
576 raise DistutilsOptionError, \
577 "command %s: no such option %s" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000578 (self.get_command_name(), option)
Greg Ward2689e3d1999-03-22 14:52:19 +0000579
580
581 def get_options (self, *options):
582 """Return (as a tuple) the values of several options for this
583 command. Raise DistutilsOptionError if any of the options in
584 'options' are not known."""
585
586 values = []
587 try:
588 for opt in options:
589 values.append (getattr (self, opt))
590 except AttributeError, name:
591 raise DistutilsOptionError, \
592 "command %s: no such option %s" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000593 (self.get_command_name(), name)
Greg Ward2689e3d1999-03-22 14:52:19 +0000594
595 return tuple (values)
596
597
598 def set_option (self, option, value):
599 """Set the value of a single option for this command. Raise
600 DistutilsOptionError if 'option' is not known."""
601
602 if not hasattr (self, option):
603 raise DistutilsOptionError, \
Greg Ward1ae32461999-09-13 03:03:01 +0000604 "command '%s': no such option '%s'" % \
Greg Ward42926dd1999-09-08 02:41:09 +0000605 (self.get_command_name(), option)
Greg Ward2689e3d1999-03-22 14:52:19 +0000606 if value is not None:
607 setattr (self, option, value)
608
609 def set_options (self, **optval):
610 """Set the values of several options for this command. Raise
611 DistutilsOptionError if any of the options specified as
612 keyword arguments are not known."""
613
614 for k in optval.keys():
615 if optval[k] is not None:
616 self.set_option (k, optval[k])
617
618
619 # -- Convenience methods for commands ------------------------------
620
Greg Ward42926dd1999-09-08 02:41:09 +0000621 def get_command_name (self):
622 if hasattr (self, 'command_name'):
623 return self.command_name
624 else:
625 class_name = self.__class__.__name__
626
627 # The re.split here returs empty strings delimited by the
628 # words we're actually interested in -- e.g. "FooBarBaz"
629 # splits to ['', 'Foo', '', 'Bar', '', 'Baz', '']. Hence
630 # the 'filter' to strip out the empties.
631 words = filter (None, re.split (r'([A-Z][a-z]+)', class_name))
Greg Warddf0d3351999-09-21 18:41:36 +0000632 self.command_name = string.join (map (string.lower, words), "_")
633 return self.command_name
Greg Ward42926dd1999-09-08 02:41:09 +0000634
635
Greg Ward2689e3d1999-03-22 14:52:19 +0000636 def set_undefined_options (self, src_cmd, *option_pairs):
637 """Set the values of any "undefined" options from corresponding
638 option values in some other command object. "Undefined" here
639 means "is None", which is the convention used to indicate
640 that an option has not been changed between
641 'set_initial_values()' and 'set_final_values()'. Usually
642 called from 'set_final_values()' for options that depend on
643 some other command rather than another option of the same
644 command. 'src_cmd' is the other command from which option
645 values will be taken (a command object will be created for it
646 if necessary); the remaining arguments are
647 '(src_option,dst_option)' tuples which mean "take the value
648 of 'src_option' in the 'src_cmd' command object, and copy it
649 to 'dst_option' in the current command object"."""
650
651 # Option_pairs: list of (src_option, dst_option) tuples
652
653 src_cmd_obj = self.distribution.find_command_obj (src_cmd)
654 src_cmd_obj.set_final_options ()
655 try:
656 for (src_option, dst_option) in option_pairs:
657 if getattr (self, dst_option) is None:
658 self.set_option (dst_option,
659 src_cmd_obj.get_option (src_option))
660 except AttributeError, name:
661 # duh, which command?
662 raise DistutilsOptionError, "unknown option %s" % name
663
664
665 def set_peer_option (self, command, option, value):
666 """Attempt to simulate a command-line override of some option
667 value in another command. Creates a command object for
668 'command' if necessary, sets 'option' to 'value', and invokes
669 'set_final_options()' on that command object. This will only
670 have the desired effect if the command object for 'command'
671 has not previously been created. Generally this is used to
672 ensure that the options in 'command' dependent on 'option'
673 are computed, hopefully (but not necessarily) deriving from
674 'value'. It might be more accurate to call this method
675 'influence_dependent_peer_options()'."""
676
677 cmd_obj = self.distribution.find_command_obj (command)
678 cmd_obj.set_option (option, value)
679 cmd_obj.set_final_options ()
680
681
Greg Ward1ae32461999-09-13 03:03:01 +0000682 def get_peer_option (self, command, option):
683 cmd_obj = self.distribution.find_command_obj (command)
684 return cmd_obj.get_option (option)
685
686
Greg Ward2689e3d1999-03-22 14:52:19 +0000687 def run_peer (self, command):
688 """Run some other command: uses the 'run_command()' method of
689 Distribution, which creates the command object if necessary
690 and then invokes its 'run()' method."""
691
692 self.distribution.run_command (command)
693
Greg Ward06ca9481999-04-04 02:58:07 +0000694
695 # -- External world manipulation -----------------------------------
696
Greg Warddf0d3351999-09-21 18:41:36 +0000697 def warn (self, msg):
698 sys.stderr.write ("warning: %s: %s\n" %
699 (self.get_command_name(), msg))
700
701
Greg Ward06ca9481999-04-04 02:58:07 +0000702 def execute (self, func, args, msg=None, level=1):
703 """Perform some action that affects the outside world (eg.
704 by writing to the filesystem). Such actions are special because
705 they should be disabled by the "dry run" flag (carried around by
706 the Command's Distribution), and should announce themselves if
707 the current verbosity level is high enough. This method takes
708 care of all that bureaucracy for you; all you have to do is
709 supply the funtion to call and an argument tuple for it (to
710 embody the "external action" being performed), a message to
711 print if the verbosity level is high enough, and an optional
712 verbosity threshold."""
713
714
715 # Generate a message if we weren't passed one
716 if msg is None:
717 msg = "%s %s" % (func.__name__, `args`)
718 if msg[-2:] == ',)': # correct for singleton tuple
719 msg = msg[0:-2] + ')'
720
721 # Print it if verbosity level is high enough
722 self.announce (msg, level)
723
724 # And do it, as long as we're not in dry-run mode
725 if not self.distribution.dry_run:
726 apply (func, args)
727
728 # execute()
729
730
731 def mkpath (self, name, mode=0777):
732 util.mkpath (name, mode,
733 self.distribution.verbose, self.distribution.dry_run)
734
735
736 def copy_file (self, infile, outfile,
737 preserve_mode=1, preserve_times=1, update=1, level=1):
738 """Copy a file respecting verbose and dry-run flags."""
739
Greg Ward884df451999-05-02 21:42:05 +0000740 return util.copy_file (infile, outfile,
741 preserve_mode, preserve_times,
742 update, self.distribution.verbose >= level,
743 self.distribution.dry_run)
Greg Ward06ca9481999-04-04 02:58:07 +0000744
745
746 def copy_tree (self, infile, outfile,
747 preserve_mode=1, preserve_times=1, preserve_symlinks=0,
748 update=1, level=1):
749 """Copy an entire directory tree respecting verbose and dry-run
750 flags."""
751
Greg Ward884df451999-05-02 21:42:05 +0000752 return util.copy_tree (infile, outfile,
753 preserve_mode,preserve_times,preserve_symlinks,
754 update, self.distribution.verbose >= level,
755 self.distribution.dry_run)
Greg Ward06ca9481999-04-04 02:58:07 +0000756
757
Greg Ward1ae32461999-09-13 03:03:01 +0000758 def move_file (self, src, dst, level=1):
759 """Move a file respecting verbose and dry-run flags."""
760 return util.move_file (src, dst,
761 self.distribution.verbose >= level,
762 self.distribution.dry_run)
763
764
Greg Ward06ca9481999-04-04 02:58:07 +0000765 def make_file (self, infiles, outfile, func, args,
766 exec_msg=None, skip_msg=None, level=1):
767
768 """Special case of 'execute()' for operations that process one or
769 more input files and generate one output file. Works just like
770 'execute()', except the operation is skipped and a different
771 message printed if 'outfile' already exists and is newer than
772 all files listed in 'infiles'."""
773
774
775 if exec_msg is None:
776 exec_msg = "generating %s from %s" % \
777 (outfile, string.join (infiles, ', '))
778 if skip_msg is None:
779 skip_msg = "skipping %s (inputs unchanged)" % outfile
780
781
782 # Allow 'infiles' to be a single string
783 if type (infiles) is StringType:
784 infiles = (infiles,)
785 elif type (infiles) not in (ListType, TupleType):
786 raise TypeError, \
787 "'infiles' must be a string, or a list or tuple of strings"
788
789 # XXX this stuff should probably be moved off to a function
790 # in 'distutils.util'
791 from stat import *
792
793 if os.path.exists (outfile):
794 out_mtime = os.stat (outfile)[ST_MTIME]
795
796 # Loop over all infiles. If any infile is newer than outfile,
797 # then we'll have to regenerate outfile
798 for f in infiles:
799 in_mtime = os.stat (f)[ST_MTIME]
800 if in_mtime > out_mtime:
801 runit = 1
802 break
803 else:
804 runit = 0
805
806 else:
807 runit = 1
808
809 # If we determined that 'outfile' must be regenerated, then
810 # perform the action that presumably regenerates it
811 if runit:
812 self.execute (func, args, exec_msg, level)
813
814 # Otherwise, print the "skip" message
815 else:
816 self.announce (skip_msg, level)
817
818 # make_file ()
819
820
821# def make_files (self, infiles, outfiles, func, args,
822# exec_msg=None, skip_msg=None, level=1):
823
824# """Special case of 'execute()' for operations that process one or
825# more input files and generate one or more output files. Works
826# just like 'execute()', except the operation is skipped and a
827# different message printed if all files listed in 'outfiles'
828# already exist and are newer than all files listed in
829# 'infiles'."""
830
831# pass
832
833
834
Greg Ward2689e3d1999-03-22 14:52:19 +0000835# end class Command