Under 2.7, use pipes.quote instead of hand-rolled (h/t @j4james).
Chris Pressey
2 years ago
8 | 8 | unicode = unicode |
9 | 9 | except NameError: |
10 | 10 | unicode = str |
11 | ||
12 | try: | |
13 | from shlex import quote as shlex_quote | |
14 | except ImportError: | |
15 | from pipes import quote as shlex_quote | |
11 | 16 | |
12 | 17 | # Note: the __str__ method of all the classes defined herein should |
13 | 18 | # produce a short, human-readable summary of the contents of the object, |
566 | 571 | def subst(self, command, var_name, value): |
567 | 572 | """Replace all occurrences of `var_name` in `command` with |
568 | 573 | `value`, but make sure `value` is properly shell-escaped first.""" |
569 | ||
570 | # We could do this with shlex.quote, but that only appeared in 3.3. | |
571 | # To support Python 2.7, we just take every character that is a | |
572 | # shell metacharacter, and escape it. Note that we have to handle | |
573 | # backslashes first, lest we escape backslashes we just added in. | |
574 | ||
575 | value = value.replace('\\', '\\\\') | |
576 | for c in """ ><*?[]'"`$()|;&#""": | |
577 | value = value.replace(c, '\\' + c) | |
578 | ||
579 | # Note that, to handle putting multi-line strings into a single | |
580 | # command line, we need to escape newlines. Note, however, that | |
581 | # shells don't understand escape sequence like "\n"! Instead, we | |
582 | # put an actual newline in single quotes. We do this for tabs too. | |
583 | ||
584 | value = value.replace("\n", "'\n'") | |
585 | value = value.replace("\t", "'\t'") | |
586 | ||
587 | return command.replace(var_name, value) | |
574 | return command.replace(var_name, shlex_quote(value)) | |
588 | 575 | |
589 | 576 | def run(self, body=None, input=None): |
590 | 577 | # first, expand all known variables in the command, using subst(). |