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