parent
328c6708c1
commit
1c269861a6
@ -1,93 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Clark Boylan <clark.boylan@gmail.com>
|
||||
# Date 1391830704 28800
|
||||
# Node ID 62fe57a8fd3f8f44be8957e59846387d2f505227
|
||||
# Parent b0360a54ab368ef428c7f83601ba6b64f6fec64f
|
||||
Fix command expansion and parsing.
|
||||
|
||||
Tox testenv commands are parsed to expand variable substitutions and
|
||||
construct the argv list that will be passed to exec. Prior to this
|
||||
commit this parsing ate quotes surrounding variables and treated
|
||||
multiword variables as single argv items. Neither behavior was correct.
|
||||
To fix this create the expanded command before handing it off to shlex
|
||||
to do the tokenization of the argv list. Doing the parsing in this
|
||||
order ensures it is correct.
|
||||
|
||||
diff --git a/tests/test_config.py b/tests/test_config.py
|
||||
--- a/tests/test_config.py
|
||||
+++ b/tests/test_config.py
|
||||
@@ -278,7 +278,7 @@
|
||||
# "reader.getargvlist('section', 'key1')")
|
||||
assert reader.getargvlist('section', 'key1') == []
|
||||
x = reader.getargvlist("section", "key2")
|
||||
- assert x == [["cmd1", "with space", "grr"],
|
||||
+ assert x == [["cmd1", "with", "space", "grr"],
|
||||
["cmd2", "grr"]]
|
||||
|
||||
def test_argvlist_windows_escaping(self, tmpdir, newconfig):
|
||||
@@ -304,7 +304,7 @@
|
||||
# "reader.getargvlist('section', 'key1')")
|
||||
assert reader.getargvlist('section', 'key1') == []
|
||||
x = reader.getargvlist("section", "key2")
|
||||
- assert x == [["cmd1", "with space", "grr"]]
|
||||
+ assert x == [["cmd1", "with", "space", "grr"]]
|
||||
|
||||
|
||||
def test_argvlist_quoting_in_command(self, tmpdir, newconfig):
|
||||
diff --git a/tox/_config.py b/tox/_config.py
|
||||
--- a/tox/_config.py
|
||||
+++ b/tox/_config.py
|
||||
@@ -527,30 +527,35 @@
|
||||
def _processcommand(self, command):
|
||||
posargs = getattr(self, "posargs", None)
|
||||
|
||||
- # special treat posargs which might contain multiple arguments
|
||||
- # in their defaults
|
||||
+ # Iterate through each word of the command substituting as
|
||||
+ # appropriate to construct the new command string. This
|
||||
+ # string is then broken up into exec argv components using
|
||||
+ # shlex.
|
||||
newcommand = ""
|
||||
for word in CommandParser(command).words():
|
||||
- if word.startswith("{posargs:") and word.endswith("}"):
|
||||
+ if word == "{posargs}" or word == "[]":
|
||||
if posargs:
|
||||
- word = "{posargs}"
|
||||
+ newcommand += " ".join(posargs)
|
||||
+ continue
|
||||
+ elif word.startswith("{posargs:") and word.endswith("}"):
|
||||
+ if posargs:
|
||||
+ newcommand += " ".join(posargs)
|
||||
+ continue
|
||||
else:
|
||||
word = word[9:-1]
|
||||
- newcommand += word
|
||||
+ new_arg = ""
|
||||
+ new_word = self._replace(word)
|
||||
+ new_word = self._replace(new_word)
|
||||
+ new_arg += new_word
|
||||
+ newcommand += new_arg
|
||||
|
||||
- # now we can properly parse the command
|
||||
- argv = []
|
||||
- for arg in shlex.split(newcommand):
|
||||
- if arg in ('[]', "{posargs}"):
|
||||
- if posargs:
|
||||
- argv.extend(posargs)
|
||||
- continue
|
||||
- new_arg = ""
|
||||
- for word in CommandParser(arg).words():
|
||||
- new_word = self._replace(word)
|
||||
- new_word = self._replace(new_word)
|
||||
- new_arg += new_word
|
||||
- argv.append(new_arg)
|
||||
+ # Construct shlex object that will not escape any values,
|
||||
+ # use all values as is in argv.
|
||||
+ shlexer = shlex.shlex(newcommand, posix=True)
|
||||
+ shlexer.whitespace_split = True
|
||||
+ shlexer.escape = ''
|
||||
+ shlexer.commenters = ''
|
||||
+ argv = list(shlexer)
|
||||
return argv
|
||||
|
||||
def getargv(self, section, name, default=None, replace=True):
|
Loading…
Reference in new issue