[Pytest-commit] commit/tox: 3 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Thu May 15 11:33:32 CEST 2014


3 new commits in tox:

https://bitbucket.org/hpk42/tox/commits/62fe57a8fd3f/
Changeset:   62fe57a8fd3f
User:        cboylan
Date:        2014-02-08 04:38:24
Summary:     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.
Affected #:  2 files

diff -r b0360a54ab368ef428c7f83601ba6b64f6fec64f -r 62fe57a8fd3f8f44be8957e59846387d2f505227 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 -r b0360a54ab368ef428c7f83601ba6b64f6fec64f -r 62fe57a8fd3f8f44be8957e59846387d2f505227 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):


https://bitbucket.org/hpk42/tox/commits/a5be60e9e68c/
Changeset:   a5be60e9e68c
User:        cboylan
Date:        2014-02-08 05:33:48
Summary:     Add tests for posargs quoting.

Two new tests ensure posargs quoting works as expected. When {posargs}
is surrounded by quotes in the commands list the contents of posargs
should be a single entry in the argv list for the commands. When the
posargs themselves include quotes the same behavior should occur.
Affected #:  1 file

diff -r 62fe57a8fd3f8f44be8957e59846387d2f505227 -r a5be60e9e68ccde0f0d6e7a180923d16bcb8a350 tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -346,6 +346,34 @@
         assert argvlist[0] == ["cmd1"]
         assert argvlist[1] == ["cmd2", "value2", "other"]
 
+    def test_argvlist_quoted_posargs(self, tmpdir, newconfig):
+        config = newconfig("""
+            [section]
+            key2=
+                cmd1 --foo-args='{posargs}'
+                cmd2 -f '{posargs}'
+                cmd3 -f {posargs}
+        """)
+        reader = IniReader(config._cfg)
+        reader.addsubstitutions(["foo", "bar"])
+        assert reader.getargvlist('section', 'key1') == []
+        x = reader.getargvlist("section", "key2")
+        assert x == [["cmd1", "--foo-args=foo bar"],
+                     ["cmd2", "-f", "foo bar"],
+                     ["cmd3", "-f", "foo", "bar"]]
+
+    def test_argvlist_posargs_with_quotes(self, tmpdir, newconfig):
+        config = newconfig("""
+            [section]
+            key2=
+                cmd1 -f {posargs}
+        """)
+        reader = IniReader(config._cfg)
+        reader.addsubstitutions(["foo", "'bar", "baz'"])
+        assert reader.getargvlist('section', 'key1') == []
+        x = reader.getargvlist("section", "key2")
+        assert x == [["cmd1", "-f", "foo", "bar baz"]]
+
     def test_positional_arguments_are_only_replaced_when_standing_alone(self,
         tmpdir, newconfig):
         config = newconfig("""


https://bitbucket.org/hpk42/tox/commits/169574bf58a4/
Changeset:   169574bf58a4
User:        hpk42
Date:        2014-05-15 11:33:28
Summary:     Merged in cboylan/tox (pull request #85)

Fix command expansion and parsing.
Affected #:  2 files

diff -r 65be9669e403386305e091ff55c2b3e9fb8c6410 -r 169574bf58a499d179ece389b75a83ee8b6fba4a tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -293,7 +293,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):
@@ -319,7 +319,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):
@@ -361,6 +361,34 @@
         assert argvlist[0] == ["cmd1"]
         assert argvlist[1] == ["cmd2", "value2", "other"]
 
+    def test_argvlist_quoted_posargs(self, tmpdir, newconfig):
+        config = newconfig("""
+            [section]
+            key2=
+                cmd1 --foo-args='{posargs}'
+                cmd2 -f '{posargs}'
+                cmd3 -f {posargs}
+        """)
+        reader = IniReader(config._cfg)
+        reader.addsubstitutions(["foo", "bar"])
+        assert reader.getargvlist('section', 'key1') == []
+        x = reader.getargvlist("section", "key2")
+        assert x == [["cmd1", "--foo-args=foo bar"],
+                     ["cmd2", "-f", "foo bar"],
+                     ["cmd3", "-f", "foo", "bar"]]
+
+    def test_argvlist_posargs_with_quotes(self, tmpdir, newconfig):
+        config = newconfig("""
+            [section]
+            key2=
+                cmd1 -f {posargs}
+        """)
+        reader = IniReader(config._cfg)
+        reader.addsubstitutions(["foo", "'bar", "baz'"])
+        assert reader.getargvlist('section', 'key1') == []
+        x = reader.getargvlist("section", "key2")
+        assert x == [["cmd1", "-f", "foo", "bar baz"]]
+
     def test_positional_arguments_are_only_replaced_when_standing_alone(self,
         tmpdir, newconfig):
         config = newconfig("""

diff -r 65be9669e403386305e091ff55c2b3e9fb8c6410 -r 169574bf58a499d179ece389b75a83ee8b6fba4a tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -530,30 +530,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):

Repository URL: https://bitbucket.org/hpk42/tox/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.


More information about the pytest-commit mailing list