Updated for 2.1a3
[python/dscho.git] / Lib / distutils / cmd.py
blobcec4bff237ef76c7b856ccb312b28ec5a60a214b
1 """distutils.cmd
3 Provides the Command class, the base class for the command classes
4 in the distutils.command package.
5 """
7 # created 2000/04/03, Greg Ward
8 # (extricated from core.py; actually dates back to the beginning)
10 __revision__ = "$Id$"
12 import sys, os, re
13 from types import *
14 from distutils.errors import *
15 from distutils import util, dir_util, file_util, archive_util, dep_util
18 class Command:
19 """Abstract base class for defining command classes, the "worker bees"
20 of the Distutils. A useful analogy for command classes is to think of
21 them as subroutines with local variables called "options". The options
22 are "declared" in 'initialize_options()' and "defined" (given their
23 final values, aka "finalized") in 'finalize_options()', both of which
24 must be defined by every command class. The distinction between the
25 two is necessary because option values might come from the outside
26 world (command line, config file, ...), and any options dependent on
27 other options must be computed *after* these outside influences have
28 been processed -- hence 'finalize_options()'. The "body" of the
29 subroutine, where it does all its work based on the values of its
30 options, is the 'run()' method, which must also be implemented by every
31 command class.
32 """
34 # 'sub_commands' formalizes the notion of a "family" of commands,
35 # eg. "install" as the parent with sub-commands "install_lib",
36 # "install_headers", etc. The parent of a family of commands
37 # defines 'sub_commands' as a class attribute; it's a list of
38 # (command_name : string, predicate : unbound_method | string | None)
39 # tuples, where 'predicate' is a method of the parent command that
40 # determines whether the corresponding command is applicable in the
41 # current situation. (Eg. we "install_headers" is only applicable if
42 # we have any C header files to install.) If 'predicate' is None,
43 # that command is always applicable.
45 # 'sub_commands' is usually defined at the *end* of a class, because
46 # predicates can be unbound methods, so they must already have been
47 # defined. The canonical example is the "install" command.
48 sub_commands = []
51 # -- Creation/initialization methods -------------------------------
53 def __init__ (self, dist):
54 """Create and initialize a new Command object. Most importantly,
55 invokes the 'initialize_options()' method, which is the real
56 initializer and depends on the actual command being
57 instantiated.
58 """
59 # late import because of mutual dependence between these classes
60 from distutils.dist import Distribution
62 if not isinstance(dist, Distribution):
63 raise TypeError, "dist must be a Distribution instance"
64 if self.__class__ is Command:
65 raise RuntimeError, "Command is an abstract class"
67 self.distribution = dist
68 self.initialize_options()
70 # Per-command versions of the global flags, so that the user can
71 # customize Distutils' behaviour command-by-command and let some
72 # commands fallback on the Distribution's behaviour. None means
73 # "not defined, check self.distribution's copy", while 0 or 1 mean
74 # false and true (duh). Note that this means figuring out the real
75 # value of each flag is a touch complicated -- hence "self.verbose"
76 # (etc.) will be handled by __getattr__, below.
77 self._verbose = None
78 self._dry_run = None
80 # Some commands define a 'self.force' option to ignore file
81 # timestamps, but methods defined *here* assume that
82 # 'self.force' exists for all commands. So define it here
83 # just to be safe.
84 self.force = None
86 # The 'help' flag is just used for command-line parsing, so
87 # none of that complicated bureaucracy is needed.
88 self.help = 0
90 # 'finalized' records whether or not 'finalize_options()' has been
91 # called. 'finalize_options()' itself should not pay attention to
92 # this flag: it is the business of 'ensure_finalized()', which
93 # always calls 'finalize_options()', to respect/update it.
94 self.finalized = 0
96 # __init__ ()
99 def __getattr__ (self, attr):
100 if attr in ('verbose', 'dry_run'):
101 myval = getattr(self, "_" + attr)
102 if myval is None:
103 return getattr(self.distribution, attr)
104 else:
105 return myval
106 else:
107 raise AttributeError, attr
110 def ensure_finalized (self):
111 if not self.finalized:
112 self.finalize_options()
113 self.finalized = 1
116 # Subclasses must define:
117 # initialize_options()
118 # provide default values for all options; may be customized by
119 # setup script, by options from config file(s), or by command-line
120 # options
121 # finalize_options()
122 # decide on the final values for all options; this is called
123 # after all possible intervention from the outside world
124 # (command-line, option file, etc.) has been processed
125 # run()
126 # run the command: do whatever it is we're here to do,
127 # controlled by the command's various option values
129 def initialize_options (self):
130 """Set default values for all the options that this command
131 supports. Note that these defaults may be overridden by other
132 commands, by the setup script, by config files, or by the
133 command-line. Thus, this is not the place to code dependencies
134 between options; generally, 'initialize_options()' implementations
135 are just a bunch of "self.foo = None" assignments.
137 This method must be implemented by all command classes.
139 raise RuntimeError, \
140 "abstract method -- subclass %s must override" % self.__class__
142 def finalize_options (self):
143 """Set final values for all the options that this command supports.
144 This is always called as late as possible, ie. after any option
145 assignments from the command-line or from other commands have been
146 done. Thus, this is the place to to code option dependencies: if
147 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
148 long as 'foo' still has the same value it was assigned in
149 'initialize_options()'.
151 This method must be implemented by all command classes.
153 raise RuntimeError, \
154 "abstract method -- subclass %s must override" % self.__class__
157 def dump_options (self, header=None, indent=""):
158 from distutils.fancy_getopt import longopt_xlate
159 if header is None:
160 header = "command options for '%s':" % self.get_command_name()
161 print indent + header
162 indent = indent + " "
163 for (option, _, _) in self.user_options:
164 option = option.translate(longopt_xlate)
165 if option[-1] == "=":
166 option = option[:-1]
167 value = getattr(self, option)
168 print indent + "%s = %s" % (option, value)
171 def run (self):
172 """A command's raison d'etre: carry out the action it exists to
173 perform, controlled by the options initialized in
174 'initialize_options()', customized by other commands, the setup
175 script, the command-line, and config files, and finalized in
176 'finalize_options()'. All terminal output and filesystem
177 interaction should be done by 'run()'.
179 This method must be implemented by all command classes.
182 raise RuntimeError, \
183 "abstract method -- subclass %s must override" % self.__class__
185 def announce (self, msg, level=1):
186 """If the current verbosity level is of greater than or equal to
187 'level' print 'msg' to stdout.
189 if self.verbose >= level:
190 print msg
192 def debug_print (self, msg):
193 """Print 'msg' to stdout if the global DEBUG (taken from the
194 DISTUTILS_DEBUG environment variable) flag is true.
196 from distutils.core import DEBUG
197 if DEBUG:
198 print msg
202 # -- Option validation methods -------------------------------------
203 # (these are very handy in writing the 'finalize_options()' method)
205 # NB. the general philosophy here is to ensure that a particular option
206 # value meets certain type and value constraints. If not, we try to
207 # force it into conformance (eg. if we expect a list but have a string,
208 # split the string on comma and/or whitespace). If we can't force the
209 # option into conformance, raise DistutilsOptionError. Thus, command
210 # classes need do nothing more than (eg.)
211 # self.ensure_string_list('foo')
212 # and they can be guaranteed that thereafter, self.foo will be
213 # a list of strings.
215 def _ensure_stringlike (self, option, what, default=None):
216 val = getattr(self, option)
217 if val is None:
218 setattr(self, option, default)
219 return default
220 elif type(val) is not StringType:
221 raise DistutilsOptionError, \
222 "'%s' must be a %s (got `%s`)" % (option, what, val)
223 return val
225 def ensure_string (self, option, default=None):
226 """Ensure that 'option' is a string; if not defined, set it to
227 'default'.
229 self._ensure_stringlike(option, "string", default)
231 def ensure_string_list (self, option):
232 """Ensure that 'option' is a list of strings. If 'option' is
233 currently a string, we split it either on /,\s*/ or /\s+/, so
234 "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
235 ["foo", "bar", "baz"].
237 val = getattr(self, option)
238 if val is None:
239 return
240 elif type(val) is StringType:
241 setattr(self, option, re.split(r',\s*|\s+', val))
242 else:
243 if type(val) is ListType:
244 types = map(type, val)
245 ok = (types == [StringType] * len(val))
246 else:
247 ok = 0
249 if not ok:
250 raise DistutilsOptionError, \
251 "'%s' must be a list of strings (got %s)" % \
252 (option, `val`)
254 def _ensure_tested_string (self, option, tester,
255 what, error_fmt, default=None):
256 val = self._ensure_stringlike(option, what, default)
257 if val is not None and not tester(val):
258 raise DistutilsOptionError, \
259 ("error in '%s' option: " + error_fmt) % (option, val)
261 def ensure_filename (self, option):
262 """Ensure that 'option' is the name of an existing file."""
263 self._ensure_tested_string(option, os.path.isfile,
264 "filename",
265 "'%s' does not exist or is not a file")
267 def ensure_dirname (self, option):
268 self._ensure_tested_string(option, os.path.isdir,
269 "directory name",
270 "'%s' does not exist or is not a directory")
273 # -- Convenience methods for commands ------------------------------
275 def get_command_name (self):
276 if hasattr(self, 'command_name'):
277 return self.command_name
278 else:
279 return self.__class__.__name__
282 def set_undefined_options (self, src_cmd, *option_pairs):
283 """Set the values of any "undefined" options from corresponding
284 option values in some other command object. "Undefined" here means
285 "is None", which is the convention used to indicate that an option
286 has not been changed between 'initialize_options()' and
287 'finalize_options()'. Usually called from 'finalize_options()' for
288 options that depend on some other command rather than another
289 option of the same command. 'src_cmd' is the other command from
290 which option values will be taken (a command object will be created
291 for it if necessary); the remaining arguments are
292 '(src_option,dst_option)' tuples which mean "take the value of
293 'src_option' in the 'src_cmd' command object, and copy it to
294 'dst_option' in the current command object".
297 # Option_pairs: list of (src_option, dst_option) tuples
299 src_cmd_obj = self.distribution.get_command_obj(src_cmd)
300 src_cmd_obj.ensure_finalized()
301 for (src_option, dst_option) in option_pairs:
302 if getattr(self, dst_option) is None:
303 setattr(self, dst_option,
304 getattr(src_cmd_obj, src_option))
307 def get_finalized_command (self, command, create=1):
308 """Wrapper around Distribution's 'get_command_obj()' method: find
309 (create if necessary and 'create' is true) the command object for
310 'command', call its 'ensure_finalized()' method, and return the
311 finalized command object.
313 cmd_obj = self.distribution.get_command_obj(command, create)
314 cmd_obj.ensure_finalized()
315 return cmd_obj
317 # XXX rename to 'get_reinitialized_command()'? (should do the
318 # same in dist.py, if so)
319 def reinitialize_command (self, command, reinit_subcommands=0):
320 return self.distribution.reinitialize_command(
321 command, reinit_subcommands)
323 def run_command (self, command):
324 """Run some other command: uses the 'run_command()' method of
325 Distribution, which creates and finalizes the command object if
326 necessary and then invokes its 'run()' method.
328 self.distribution.run_command(command)
331 def get_sub_commands (self):
332 """Determine the sub-commands that are relevant in the current
333 distribution (ie., that need to be run). This is based on the
334 'sub_commands' class attribute: each tuple in that list may include
335 a method that we call to determine if the subcommand needs to be
336 run for the current distribution. Return a list of command names.
338 commands = []
339 for (cmd_name, method) in self.sub_commands:
340 if method is None or method(self):
341 commands.append(cmd_name)
342 return commands
345 # -- External world manipulation -----------------------------------
347 def warn (self, msg):
348 sys.stderr.write("warning: %s: %s\n" %
349 (self.get_command_name(), msg))
352 def execute (self, func, args, msg=None, level=1):
353 util.execute(func, args, msg, self.verbose >= level, self.dry_run)
356 def mkpath (self, name, mode=0777):
357 dir_util.mkpath(name, mode,
358 self.verbose, self.dry_run)
361 def copy_file (self, infile, outfile,
362 preserve_mode=1, preserve_times=1, link=None, level=1):
363 """Copy a file respecting verbose, dry-run and force flags. (The
364 former two default to whatever is in the Distribution object, and
365 the latter defaults to false for commands that don't define it.)"""
367 return file_util.copy_file(
368 infile, outfile,
369 preserve_mode, preserve_times,
370 not self.force,
371 link,
372 self.verbose >= level,
373 self.dry_run)
376 def copy_tree (self, infile, outfile,
377 preserve_mode=1, preserve_times=1, preserve_symlinks=0,
378 level=1):
379 """Copy an entire directory tree respecting verbose, dry-run,
380 and force flags.
382 return dir_util.copy_tree(
383 infile, outfile,
384 preserve_mode,preserve_times,preserve_symlinks,
385 not self.force,
386 self.verbose >= level,
387 self.dry_run)
390 def move_file (self, src, dst, level=1):
391 """Move a file respecting verbose and dry-run flags."""
392 return file_util.move_file(src, dst,
393 self.verbose >= level,
394 self.dry_run)
397 def spawn (self, cmd, search_path=1, level=1):
398 """Spawn an external command respecting verbose and dry-run flags."""
399 from distutils.spawn import spawn
400 spawn(cmd, search_path,
401 self.verbose >= level,
402 self.dry_run)
405 def make_archive (self, base_name, format,
406 root_dir=None, base_dir=None):
407 return archive_util.make_archive(
408 base_name, format, root_dir, base_dir,
409 self.verbose, self.dry_run)
412 def make_file (self, infiles, outfile, func, args,
413 exec_msg=None, skip_msg=None, level=1):
414 """Special case of 'execute()' for operations that process one or
415 more input files and generate one output file. Works just like
416 'execute()', except the operation is skipped and a different
417 message printed if 'outfile' already exists and is newer than all
418 files listed in 'infiles'. If the command defined 'self.force',
419 and it is true, then the command is unconditionally run -- does no
420 timestamp checks.
422 if exec_msg is None:
423 exec_msg = "generating %s from %s" % \
424 (outfile, ', '.join(infiles))
425 if skip_msg is None:
426 skip_msg = "skipping %s (inputs unchanged)" % outfile
429 # Allow 'infiles' to be a single string
430 if type(infiles) is StringType:
431 infiles = (infiles,)
432 elif type(infiles) not in (ListType, TupleType):
433 raise TypeError, \
434 "'infiles' must be a string, or a list or tuple of strings"
436 # If 'outfile' must be regenerated (either because it doesn't
437 # exist, is out-of-date, or the 'force' flag is true) then
438 # perform the action that presumably regenerates it
439 if self.force or dep_util.newer_group (infiles, outfile):
440 self.execute(func, args, exec_msg, level)
442 # Otherwise, print the "skip" message
443 else:
444 self.announce(skip_msg, level)
446 # make_file ()
448 # class Command
451 # XXX 'install_misc' class not currently used -- it was the base class for
452 # both 'install_scripts' and 'install_data', but they outgrew it. It might
453 # still be useful for 'install_headers', though, so I'm keeping it around
454 # for the time being.
456 class install_misc (Command):
457 """Common base class for installing some files in a subdirectory.
458 Currently used by install_data and install_scripts.
461 user_options = [('install-dir=', 'd', "directory to install the files to")]
463 def initialize_options (self):
464 self.install_dir = None
465 self.outfiles = []
467 def _install_dir_from (self, dirname):
468 self.set_undefined_options('install', (dirname, 'install_dir'))
470 def _copy_files (self, filelist):
471 self.outfiles = []
472 if not filelist:
473 return
474 self.mkpath(self.install_dir)
475 for f in filelist:
476 self.copy_file(f, self.install_dir)
477 self.outfiles.append(os.path.join(self.install_dir, f))
479 def get_outputs (self):
480 return self.outfiles
483 if __name__ == "__main__":
484 print "ok"