Skip to content

Commit

Permalink
Unescaped comma in substitution should not be replaced during INI exp…
Browse files Browse the repository at this point in the history
…ansion (#2626)

Resolves #2616
  • Loading branch information
gaborbernat committed Dec 8, 2022
1 parent 3661b94 commit 98830e4
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/changelog/2616.bugfix.rst
@@ -0,0 +1 @@
Unescaped comma in substitution should not be replaced during INI expansion - by :user:`gaborbernat`.
9 changes: 5 additions & 4 deletions src/tox/config/loader/ini/replace.py
Expand Up @@ -54,14 +54,14 @@ def replace(conf: Config, loader: IniLoader, value: str, args: ConfigLoadArgs) -

REPLACE_PART = re.compile(
r"""
(?<! \\) { # Unescaped {
( [^{}] | \\ { | \\ } )* # Anything except an unescaped { or }
(?<!\\) { # Unescaped {
( [^{},] | \\ { | \\ } )* # Anything except an unescaped { or }
(?<! \\) } # Unescaped }
|
(?<! \\) \[ ] # Unescaped []
""",
re.VERBOSE,
) # simplified - not verbose version (?<!\\)([^{}]|\\\{|\\\})*(?<!\\)\}|(?<!\\)\[\]
)


def find_replace_part(value: str, end: int) -> tuple[int, int, str | None]:
Expand All @@ -70,7 +70,8 @@ def find_replace_part(value: str, end: int) -> tuple[int, int, str | None]:
return -1, -1, None
if match.group() == "[]":
return match.start(), match.end() - 1, "posargs" # brackets is an alias for positional arguments
return match.start(), match.end() - 1, match.group()[1:-1]
matched_part = match.group()[1:-1]
return match.start(), match.end() - 1, matched_part


def _replace_match(conf: Config, loader: IniLoader, value: str, conf_args: ConfigLoadArgs) -> str | None:
Expand Down
5 changes: 5 additions & 0 deletions tests/config/loader/ini/test_factor.py
Expand Up @@ -136,6 +136,11 @@ def test_factor_config(tox_ini_conf: ToxIniCreator) -> None:
assert "Django>=1.6,<1.7" in deps


def test_factor_config_do_not_replace_unescaped_comma(tox_ini_conf: ToxIniCreator) -> None:
config = tox_ini_conf("[tox]\nenv_list = py37-{base,i18n},b")
assert list(config) == ["py37-base", "py37-i18n", "b"]


def test_factor_config_no_env_list_creates_env(tox_ini_conf: ToxIniCreator) -> None:
"""If we have a factor that is not specified within the core env-list then that's also an environment"""
config = tox_ini_conf(
Expand Down

0 comments on commit 98830e4

Please sign in to comment.