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

Rewrite substitution parser #2861

Merged
merged 12 commits into from Jan 16, 2023

Conversation

masenf
Copy link
Collaborator

@masenf masenf commented Jan 15, 2023

  • Fix issue tox 3.27.1 to 4.0.9, environment var substitution failing #2732 by rewriting the regex-based substitution expression parser with a recursive-style parser.
  • Substitutions are processed left to right, inner-most to outer-most.
  • After a replacement is made in a string, the replaced part of the string will NOT affect characters after it. the result of a replacement will never be used in further substitution parsing.
    • On windows {/} will expand to a literal backslash \, which will NOT act as an escape for the next character.
  • Additional test cases and regression tests are added.
  • Migrate and update "Substitutions" section of the "Configuration" doc from tox 3

Thanks for contribution

Please, make sure you address all the checklists (for details on how see
development documentation)!

  • ran the linter to address style issues (tox -e fix)
  • wrote descriptive pull request text
  • ensured there are test(s) validating the fix
  • added news fragment in docs/changelog folder
  • updated/extended the documentation

The resulting escaped value should not then be
subsequently used as an escape in future replacement
rounds.

Additional friends, like triple backslash, which
should escape the following, and quad backslash,
which should escape to two single backslashes
and not escape the following characters.

The Quad backslash test case also has escaped
double backslash at the beginning and end of the
string for more edge coverage.
explicit test case for issue tox-dev#2732 which affects
{/} os.sep replacement on windows platform.

test_replace_os_sep_subexp_regression

WiP
When the replacement value is a backslash, it shouldn't escape the next
part of the value.

However, if the replacement contains a backslash, then it could affect
the next value.
go back and forth between mututally circular env vars
When the env var name is itself given by another env var
walk through the expression character by character, recursively
descending on left curly brace and breaking arguments along the way
should allow for arbitrarily complex nested expressions that do NOT
affect adjacent expressions.

enabling recursive replacement could be allowed on a per-expression
basis, but that is not currently done
test_replace: {toxinidir,}
	shouldn't be replaced with the trailing comma

test_replace: add test case for escaped colon arg sep

test_replace: additional cases for test_match

	Single capital letter variable
	Single backslash
	Backslash escape non-special character
	Windows path shouldn't be mangled
describe ini-style curly brace substitutions
@masenf
Copy link
Collaborator Author

masenf commented Jan 15, 2023

This is a rather large, fiddly PR. The more review I can get on this the better 🙏.

@@ -0,0 +1,7 @@
Rewrite substitution replacement parser - by :user:`masenf`

* ``\`` acts as a proper escape for ``\`` in ini-style substitutions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more a feature than bugfixe, as it changes behavior of the logic.

replace_value = replace_reference(conf, loader, value, conf_args)
return replace_value
class MatchError(Exception):
pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstring instead of pass.

(r"{foo:{bar}}", (5, 9, "bar")),
(r"{\{}", (0, 3, r"\{")),
(r"{\}}", (0, 3, r"\}")),
("[]", [MatchExpression([["posargs"]])]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my, because you've changed the tests makes this pr infinitely harder to review. How am I supposed to know you did not introduce a lot of breaking changes 😅

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm realizing now that find_replace_part was actually a public API of the tox.config.loader.ini.replace module, so I don't know if I can just "replace" it like this (even though the only caller in setenv was updated).

I took some time tonight to try to reimplement the find_replace_part API on top of the new find_replace_expr recursive implementation, and it's definitely possible, but the MatchExpression needs to track position information for where in the original value the match was found to allow reconstruction of the(start, end, replacement) tuple.

with that shim in place, I'd be able to bring back the original tests with no modification (only new tests, or those with clear behavior changes) to hopefully improve the reviewability here.

the other option would be keeping the regex parser, or at least the find_replace_expr part as it is currently and leave these tests in place... even though the ini-loader would actually be using the new parser under the hood.

thanks for looking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll accept this as is, for now; we don't have public API besides the plugin interface, but I ask you to stick around for any regression bug reports and help out with that please.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ask you to stick around for any regression bug reports and help out with that please.

100% please ping me if anything comes through that I don't notice and I'll jump on it.

this is a change in behavior, not merely a bugfix

changelog: mention API names added and removed from the replace module
to help people who might be searching for these names from error messages, etc
a first step at tracking enough position information to recreate the
find_replace_part API; this one also improves the typing and readability of the
class, so that the functions don't have to pass the term_pos in a tuple return
value.
@gaborbernat gaborbernat merged commit aff1d4d into tox-dev:main Jan 16, 2023
@masenf masenf deleted the rewrite-substitution-parser branch January 18, 2023 04:25
@masenf masenf mentioned this pull request Jan 19, 2023
descope bot added a commit to descope/django-descope that referenced this pull request Jan 30, 2023
This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [tox](https://togithub.com/tox-dev/tox)
([changelog](https://tox.wiki/en/latest/changelog.html)) | dev | minor |
`4.2.8` -> `4.3.0` | `4.4.2` (+7) |

---

### Release Notes

<details>
<summary>tox-dev/tox</summary>

### [`v4.3.0`](https://togithub.com/tox-dev/tox/releases/tag/4.3.0)

[Compare Source](https://togithub.com/tox-dev/tox/compare/4.2.8...4.3.0)

#### What's Changed

- Add Documentation URL for quick access via PyPI web by
[@&#8203;kerel-fs](https://togithub.com/kerel-fs) in
[tox-dev/tox#2854
- Document factors by
[@&#8203;stephenfin](https://togithub.com/stephenfin) in
[tox-dev/tox#2852
- Rewrite substitution parser by
[@&#8203;masenf](https://togithub.com/masenf) in
[tox-dev/tox#2861

#### New Contributors

- [@&#8203;kerel-fs](https://togithub.com/kerel-fs) made their first
contribution in
[tox-dev/tox#2854

**Full Changelog**: tox-dev/tox@4.2.8...4.3.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xMDEuMCIsInVwZGF0ZWRJblZlciI6IjM0LjEwMS4wIn0=-->

Co-authored-by: descope[bot] <descope[bot]@users.noreply.github.com>
@rwols
Copy link

rwols commented Apr 12, 2024

It seems that this changed behavior for the TOX_ENV_NAME, TOX_WORK_DIR injected environment variables.

Before this PR, you could reference these variables in the commands section with {env:TOX_ENV_NAME}. But after this PR, these placeholders resolve to the empty string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants