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