Pyupgrade: Format specifiers#1594
Pyupgrade: Format specifiers#1594charliermarsh merged 31 commits intoastral-sh:mainfrom colin99d:formatspecifiers
Conversation
|
I will try to have this done by Sunday night. |
|
@charliermarsh I have the following function to detect expressions: It works fine for an expression like this: But the second you make it multi-line like so: The whole thing fails. Is this an error with my coding, or an error with libcst_native? |
|
I'm wondering if you need to dedent the code. You might be passing |
|
It looks like the issue still happens with the de-indented code: 'foo{0}'\n'bar{1}'.format(1, 2). |
…UP_DELETEME.py --no-cache --select UP
|
thread 'main' panicked at 'called Looks like this is a parse error from the
Just let me know which you would like for me to pursue. |
|
Would you be open to filing an issue on the LibCST repo? In the meantime, we could just skip those cases. (Are they needed for detection, or just autofixing?) |
|
Here is the issue: |
| )); | ||
| } | ||
| checker.add_check(check); | ||
| checker.diagnostics.push(diagnostic); |
There was a problem hiding this comment.
Thank you and sorry that this all churned mid-PR for you.
There was a problem hiding this comment.
Im never going to complain about you making this project easier to contribute to.
|
Hey @charliermarsh I got all the positive test cases working (except for the one edge case we talked about), and all the negative cases working except one. I wanted to get your feedback before I implemented it. Since the format specifier is split into two different strings, it is NOT supposed to be formatted. However, both the Expr |
|
I think it's best just to ignore it (i.e., treat it as if there is no space). It strikes me as exceptionally rare, to the point that it's likely either a mistake or that it's not worth adding more complexity to our own implementation to handle it. |
|
We could probably detect it by tokenizing... but it doesn't seem worth it to me. |
100% agree, especially since the python code will still work. |
|
I just need to fix one bug with this edge case, and then I should be able to take this PR out of draft. |
|
@charliermarsh anything else you want to see from this for merge? |
|
@colin99d - Will review this tonight! |
| // FOR REVIEWER: If the new and old are identical, don't create a fix. Pyupgrade | ||
| // doesnt even want me to report this, so we could just have an enum for errors, | ||
| // and if a special one is returned here then we dont even report a fix | ||
| if module_text == final_state.to_string() { |
| } | ||
|
|
||
| /// UP030 | ||
| pub(crate) fn format_literals(checker: &mut Checker, summary: &FormatSummary, expr: &Expr) { |
There was a problem hiding this comment.
@colin99d - It turns out that we already had a utility for extracting the format positions, which uses the RustPython string parser underneath and so is very robust. Sorry that I didn't flag this earlier -- I didn't realize it could even be reused here, but it should make things more efficient too since we can do one string parse and share that "summary" amongst a bunch of checks.
| contents, | ||
| expr.location, | ||
| expr.end_location.unwrap(), | ||
| )); |
There was a problem hiding this comment.
I feel like one strategy that could work here would be...
- Take the entire text.
- Replace the string part via the regex above.
- Replace the arguments via LibCST.
Kinda tough, hacky, etc... but would solve the missing cases.
There was a problem hiding this comment.
Actually, I guess that wouldn't solve the '{' '0}'.format(1) case.
|
Thanks for the review! |
[](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ruff](https://togithub.com/charliermarsh/ruff) | `^0.0.217` -> `^0.0.218` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>charliermarsh/ruff</summary> ### [`v0.0.218`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.218) [Compare Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.217...v0.0.218) #### What's Changed - Implement flake8-simplify SIM112 by [@​messense](https://togithub.com/messense) in [https://github.com/charliermarsh/ruff/pull/1764](https://togithub.com/charliermarsh/ruff/pull/1764) - Do not autofix PT004 and PT005 by [@​harupy](https://togithub.com/harupy) in [https://github.com/charliermarsh/ruff/pull/1763](https://togithub.com/charliermarsh/ruff/pull/1763) - Disable release builds on CI by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1761](https://togithub.com/charliermarsh/ruff/pull/1761) - Move CONTRIBUTING.md to top-level by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1768](https://togithub.com/charliermarsh/ruff/pull/1768) - \[`flake8-bandit`] Add Rule for `S508` (snmp insecure version) & `S509` (snmp weak cryptography) by [@​saadmk11](https://togithub.com/saadmk11) in [https://github.com/charliermarsh/ruff/pull/1771](https://togithub.com/charliermarsh/ruff/pull/1771) - Generate RuleCode::origin() via macro by [@​not-my-profile](https://togithub.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1770](https://togithub.com/charliermarsh/ruff/pull/1770) - Disable doctests by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1772](https://togithub.com/charliermarsh/ruff/pull/1772) - Enable isort-style `required-imports` enforcement by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1762](https://togithub.com/charliermarsh/ruff/pull/1762) - Pyupgrade: Format specifiers by [@​colin99d](https://togithub.com/colin99d) in [https://github.com/charliermarsh/ruff/pull/1594](https://togithub.com/charliermarsh/ruff/pull/1594) - Avoid B023 false-positives for some common builtins by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1776](https://togithub.com/charliermarsh/ruff/pull/1776) **Full Changelog**: astral-sh/ruff@v0.0.217...v0.0.218 </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 --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/ixm-one/pytest-cmake-presets). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC45Ny4xIiwidXBkYXRlZEluVmVyIjoiMzQuOTcuMSJ9--> Signed-off-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

A part of #827. Posting this for visibility. Still has some work to do to be done.
Things that still need done before this is ready:
Tests from pyupgrade can be seen here: https://github.com/asottile/pyupgrade/blob/main/tests/features/format_literals_test.py