Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix space not accepted in factor filter expression #2744

Merged
merged 2 commits into from Dec 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog/2718.bugfix.rst
@@ -0,0 +1 @@
Fix space not accepted in factor filter expression - by :user:`gaborbernat`.
24 changes: 13 additions & 11 deletions src/tox/config/loader/ini/factor.py
Expand Up @@ -46,18 +46,18 @@ def explode_factor(group: list[tuple[str, bool]]) -> str:
return "-".join([name for name, _ in group])


def expand_factors(value: str) -> Iterator[tuple[Iterator[list[tuple[str, bool]]] | None, str]]:
def expand_factors(value: str) -> Iterator[tuple[list[list[tuple[str, bool]]] | None, str]]:
for line in value.split("\n"):
match = re.match(r"^((?P<factor_expr>[\w{}.!,-]+):\s+)?(?P<content>.*?)$", line)
if match is None: # pragma: no cover
raise RuntimeError("for a valid factor regex this cannot happen")
groups = match.groupdict()
factor_expr, content = groups["factor_expr"], groups["content"]
if factor_expr is not None:
factors = find_factor_groups(factor_expr)
yield factors, content
else:
yield None, content
factors: list[list[tuple[str, bool]]] | None = None
marker_at, content = line.find(":"), line
if marker_at != -1:
try:
factors = list(find_factor_groups(line[:marker_at].strip()))
except ValueError:
pass # when cannot extract factors keep the entire line
else:
content = line[marker_at + 1 :].strip()
yield factors, content


def find_factor_groups(value: str) -> Iterator[list[tuple[str, bool]]]:
Expand All @@ -76,6 +76,8 @@ def expand_env_with_negation(value: str) -> Iterator[str]:
parts = [re.sub(r"\s+", "", elem).split(",") for elem in elements]
for variant in product(*parts):
variant_str = "".join(variant)
if not re.fullmatch(r"!?[\w._][\w._-]*", variant_str):
raise ValueError(variant_str)
yield variant_str


Expand Down
4 changes: 2 additions & 2 deletions tests/config/loader/ini/replace/test_replace_posargs.py
Expand Up @@ -37,8 +37,8 @@ def test_replace_pos_args(syntax: str, replace_one: ReplaceOne) -> None:
[
("magic", "magic"),
("magic:colon", "magic:colon"),
("magic\n b:c", "magic\nb:c"), # an unescaped newline keeps the newline
("magi\\\n c:d", "magic:d"), # an escaped newline merges the lines
("magic\n b c", "magic\nb c"), # an unescaped newline keeps the newline
("magi\\\n c d", "magic d"), # an escaped newline merges the lines
("\\{a\\}", "{a}"), # escaped curly braces
],
)
Expand Down
2 changes: 2 additions & 0 deletions tests/config/loader/ini/test_factor.py
Expand Up @@ -27,6 +27,7 @@ def complex_example() -> str:
py: py only
!py: not py
{py,!pi}-{a,b}{,-dev},c: complex
py, d: space
extra: extra
more-default
""",
Expand All @@ -46,6 +47,7 @@ def test_factor_env_discover(complex_example: str) -> None:
"pi-b",
"pi-b-dev",
"c",
"d",
"extra",
]

Expand Down
2 changes: 2 additions & 0 deletions tests/session/cmd/test_list_envs.py
Expand Up @@ -36,6 +36,7 @@ def test_list_env(project: ToxProject) -> None:

additional environments:
fix -> fix it
pypy -> with pypy
"""
outcome.assert_out_err(expected, "")

Expand All @@ -62,6 +63,7 @@ def test_list_env_quiet(project: ToxProject) -> None:
py31
py
fix
pypy
"""
outcome.assert_out_err(expected, "")

Expand Down