From 60cda3ce22c01c8d9398eff56e01eef64f714589 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Tue, 20 Oct 2020 14:07:44 +0700 Subject: [PATCH] Add substitution {/} to os.sep Closes https://github.com/tox-dev/tox/issues/1700 --- docs/changelog/1700.feature.rst | 1 + docs/config.rst | 6 ++++++ src/tox/config/__init__.py | 2 ++ tests/unit/config/test_config.py | 26 +++++++++++++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/1700.feature.rst diff --git a/docs/changelog/1700.feature.rst b/docs/changelog/1700.feature.rst new file mode 100644 index 000000000..73ea3216f --- /dev/null +++ b/docs/changelog/1700.feature.rst @@ -0,0 +1 @@ +Allow {/} to refer to os.sep. - by :user:`jayvdb` diff --git a/docs/config.rst b/docs/config.rst index bd218d392..9986fa039 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -669,6 +669,12 @@ Globally available substitutions OS-specific path separator (``:`` os \*nix family, ``;`` on Windows). May be used in ``setenv``, when target variable is path variable (e.g. PATH or PYTHONPATH). +``{/}`` + OS-specific directory separator (``/`` os \*nix family, ``\\`` on Windows). + Useful for deriving filenames from preset paths, as arguments for commands + that requires ``\\`` on Windows. e.g. ``{distdir}{/}file.txt``. + It is not usually needed when using commands written in Python. + Substitutions for virtualenv-related sections +++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/tox/config/__init__.py b/src/tox/config/__init__.py index ea37bdc11..23f4e90a6 100644 --- a/src/tox/config/__init__.py +++ b/src/tox/config/__init__.py @@ -1811,6 +1811,8 @@ def _replace_match(self, match): "Malformed substitution; no substitution type provided", ) + if not sub_type and not g["default_value"] and sub_value == "/": + return os.sep if sub_type == "env": return self._replace_env(match) if sub_type == "tty": diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index b61f6e254..994ccff59 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -2792,7 +2792,8 @@ def test_multiple_homedir_relative_local_indexservers(self, newconfig): class TestConfigConstSubstitutions: @pytest.mark.parametrize("pathsep", [":", ";"]) - def test_replace_pathsep_unix(self, monkeypatch, newconfig, pathsep): + def test_replace_pathsep(self, monkeypatch, newconfig, pathsep): + """Replace {:} with OS path separator.""" monkeypatch.setattr("os.pathsep", pathsep) config = newconfig( """ @@ -2813,6 +2814,29 @@ def test_pathsep_regex(self): assert mdict["substitution_value"] == "" assert mdict["default_value"] == "" + @pytest.mark.parametrize("dirsep", ["\\", "\\\\"]) + def test_dirsep_replace(self, monkeypatch, newconfig, dirsep): + """Replace {/} with OS directory separator.""" + monkeypatch.setattr("os.sep", dirsep) + config = newconfig( + """ + [testenv] + setenv = + VAR = dira{/}subdirb{/}subdirc + """, + ) + envconfig = config.envconfigs["python"] + assert envconfig.setenv["VAR"] == dirsep.join(["dira", "subdirb", "subdirc"]) + + def test_dirsep_regex(self): + """Sanity check for regex behavior for directory separator.""" + regex = tox.config.Replacer.RE_ITEM_REF + match = next(regex.finditer("{/}")) + mdict = match.groupdict() + assert mdict["sub_type"] is None + assert mdict["substitution_value"] == "/" + assert mdict["default_value"] is None + class TestParseEnv: def test_parse_recreate(self, newconfig):