Convert single-argument %-style format calls#3600
Conversation
PR Check ResultsEcosystemℹ️ ecosystem check detected changes. (+5, -0, 0 error(s)) airflow (+1, -0)
+ airflow/providers/google/cloud/hooks/bigtable.py:252:32: UP031 [*] Use format specifiers instead of percent formatbokeh (+3, -0)
+ src/bokeh/plotting/_figure.py:738:41: UP031 [*] Use format specifiers instead of percent format
+ tests/unit/bokeh/models/test_plots.py:486:38: UP031 [*] Use format specifiers instead of percent format
+ tests/unit/bokeh/models/test_plots.py:492:38: UP031 [*] Use format specifiers instead of percent formatscikit-build (+1, -0)
+ skbuild/platform_specifics/cygwin.py:33:27: UP031 [*] Use format specifiers instead of percent formatBenchmarkLinuxWindows |
|
Case 3 does not hold. x = (1,)
print("%s" % x)
print("{}".format(x)) |
|
Ah that's a shame, I'd guess that's a small minority of cases. |
|
I can't think of any way to avoid that, so I guess we have to continue omitting those cases. |
c8cd2e9 to
c4d53d1
Compare
|
(Removed, and amended the PR summary.) |
MichaReiser
left a comment
There was a problem hiding this comment.
LGTM. I can't say much about the inference rules.
| // Otherwise, if we have a single field, we can't make any assumptions about the | ||
| // right-hand side. It _could_ be a tuple, but it could also be a single value, | ||
| // and we can't differentiate between them. | ||
| // For example: | ||
| // ```python | ||
| // x = (1,) | ||
| // print("%s" % x) | ||
| // print("{}".format(x)) | ||
| // ``` |
| // Parse each string segment. | ||
| let mut format_strings = vec![]; | ||
| let mut num_positional = 0; | ||
| let mut num_keyword = 0; |
There was a problem hiding this comment.
Nit: A boolean for keywords seems sufficient
| let mut num_keyword = 0; | |
| let mut has_keyword_arguments = false; |
There was a problem hiding this comment.
Ah, we need to know if there's more than one positional argument. If we have exactly one positional argument, we can't fix it unfortunately 😭
|
I think the proper way to ensure the cases are correctly covered would be reading the cpython source code, but i couldn't find the percent formatting source code, only the tests: https://github.com/python/cpython/blob/5e6661bce968173fa45b74fa2111098645ff609c/Lib/test/test_format.py |
c4d53d1 to
caec651
Compare
[](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ruff](https://togithub.com/charliermarsh/ruff) | `^0.0.257` -> `^0.0.258` | [](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.258`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.258) [Compare Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.257...v0.0.258) <!-- Release notes generated using configuration in .github/release.yml at main --> #### What's Changed ##### Rules - \[`flake8-comprehensions`] Update `C416` with dict comprehension (autofixable) by [@​dhruvmanila](https://togithub.com/dhruvmanila) in [https://github.com/charliermarsh/ruff/pull/3605](https://togithub.com/charliermarsh/ruff/pull/3605) - \[`pylint`]: Implement `assert-on-string-literal` (`W0129`) by [@​latonis](https://togithub.com/latonis) in [https://github.com/charliermarsh/ruff/pull/3610](https://togithub.com/charliermarsh/ruff/pull/3610) - \[`pyupgrade`] Convert single-argument %-style format calls by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3600](https://togithub.com/charliermarsh/ruff/pull/3600) - \[`pyupgrade`] Flag PEP 585 and PEP 604 violations in quoted annotations by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3593](https://togithub.com/charliermarsh/ruff/pull/3593) - \[`pyupgrade`] Enable autofix for annotations within 'simple' string literals by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3657](https://togithub.com/charliermarsh/ruff/pull/3657) - \[`pyflakes`] Add autofix functionality for `F523` ([#​3613](https://togithub.com/charliermarsh/ruff/issues/3613)) by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3613](https://togithub.com/charliermarsh/ruff/pull/3613) - \[`flake8-bandit`]: Implement deny-list rules for suspicious member calls by [@​colin99d](https://togithub.com/colin99d) in [https://github.com/charliermarsh/ruff/pull/3239](https://togithub.com/charliermarsh/ruff/pull/3239) - \[`flake8-annotations`] Add autofix for `ANN204` with magic methods by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3633](https://togithub.com/charliermarsh/ruff/pull/3633) - \[`pylint`] Implement `binary-op-exception` (`PLW0711`) by [@​latonis](https://togithub.com/latonis) in [https://github.com/charliermarsh/ruff/pull/3639](https://togithub.com/charliermarsh/ruff/pull/3639) - \[`flake8-django`]: Implement rule DJ012 by [@​dhruvmanila](https://togithub.com/dhruvmanila) in [https://github.com/charliermarsh/ruff/pull/3659](https://togithub.com/charliermarsh/ruff/pull/3659) ##### Bug Fixes - Check exclusions prior to resolving `pyproject.toml` files by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3588](https://togithub.com/charliermarsh/ruff/pull/3588) - Fix D417 false positive by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3596](https://togithub.com/charliermarsh/ruff/pull/3596) - Avoid removing comment hash for noqa's with trailing content by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3589](https://togithub.com/charliermarsh/ruff/pull/3589) - Avoid panics for implicitly-concatenated docstrings by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3584](https://togithub.com/charliermarsh/ruff/pull/3584) - Fix infinite loop due to rules `D207` & `W605` by [@​vlindhol](https://togithub.com/vlindhol) in [https://github.com/charliermarsh/ruff/pull/3609](https://togithub.com/charliermarsh/ruff/pull/3609) - Avoid trimming escaped whitespace in D210 by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3635](https://togithub.com/charliermarsh/ruff/pull/3635) - Handle `UP032` autofix with adjacent keywords by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3636](https://togithub.com/charliermarsh/ruff/pull/3636) - Consider same-site fixes to be overlapping by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3638](https://togithub.com/charliermarsh/ruff/pull/3638) - Avoid `RUF007` fixes for more than two arguments by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3654](https://togithub.com/charliermarsh/ruff/pull/3654) - Allow `pairwise` diagnostics for `zip(..., strict=True)` by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3669](https://togithub.com/charliermarsh/ruff/pull/3669) - isort: fix bad interaction between `force-sort-within-sections` and `force-to-top` by [@​bluetech](https://togithub.com/bluetech) in [https://github.com/charliermarsh/ruff/pull/3645](https://togithub.com/charliermarsh/ruff/pull/3645) - Gracefully handle lint panics by [@​MichaReiser](https://togithub.com/MichaReiser) in [https://github.com/charliermarsh/ruff/pull/3509](https://togithub.com/charliermarsh/ruff/pull/3509) - Fix TRY300 false positive by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3634](https://togithub.com/charliermarsh/ruff/pull/3634) - Avoid raising PEP 604 errors with forward-referenced members by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3640](https://togithub.com/charliermarsh/ruff/pull/3640) - Avoid attempting infinite `open` fix with re-bound builtin by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3650](https://togithub.com/charliermarsh/ruff/pull/3650) - Check indentation level when executing E231 by [@​kyoto7250](https://togithub.com/kyoto7250) in [https://github.com/charliermarsh/ruff/pull/3668](https://togithub.com/charliermarsh/ruff/pull/3668) - Flag, but don't fix, unused imports (`F401`) in `ModuleNotFoundError` blocks by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3658](https://togithub.com/charliermarsh/ruff/pull/3658) #### New Contributors - [@​Rogdham](https://togithub.com/Rogdham) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3607](https://togithub.com/charliermarsh/ruff/pull/3607) - [@​vlindhol](https://togithub.com/vlindhol) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3609](https://togithub.com/charliermarsh/ruff/pull/3609) - [@​dhruvmanila](https://togithub.com/dhruvmanila) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3605](https://togithub.com/charliermarsh/ruff/pull/3605) - [@​luke396](https://togithub.com/luke396) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3604](https://togithub.com/charliermarsh/ruff/pull/3604) - [@​fuziontech](https://togithub.com/fuziontech) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3641](https://togithub.com/charliermarsh/ruff/pull/3641) **Full Changelog**: astral-sh/ruff@v0.0.257...v0.0.258 </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:eyJjcmVhdGVkSW5WZXIiOiIzNS4xNy4xIiwidXBkYXRlZEluVmVyIjoiMzUuMTcuMSJ9--> Signed-off-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
[](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ruff](https://togithub.com/charliermarsh/ruff) | `==0.0.257` -> `==0.0.259` | [](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.259`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.259) [Compare Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.258...v0.0.259) <!-- Release notes generated using configuration in .github/release.yml at main --> #### Summary Follow-up release to `v0.0.258` to fix an issue related to rule resolution via `select` and `ignore`. #### What's Changed ##### Bug Fixes - Fix RuleSet.remove by [@​MichaReiser](https://togithub.com/MichaReiser) in [https://github.com/charliermarsh/ruff/pull/3685](https://togithub.com/charliermarsh/ruff/pull/3685) - Respect all rule-exemption sources when suppressing parser errors by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3665](https://togithub.com/charliermarsh/ruff/pull/3665) - Avoid nested loops in `missing_whitespace` by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3688](https://togithub.com/charliermarsh/ruff/pull/3688) **Full Changelog**: astral-sh/ruff@v0.0.258...v0.0.259 ### [`v0.0.258`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.258) [Compare Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.257...v0.0.258) <!-- Release notes generated using configuration in .github/release.yml at main --> #### What's Changed ##### Rules - \[`flake8-comprehensions`] Update `C416` with dict comprehension (autofixable) by [@​dhruvmanila](https://togithub.com/dhruvmanila) in [https://github.com/charliermarsh/ruff/pull/3605](https://togithub.com/charliermarsh/ruff/pull/3605) - \[`pylint`]: Implement `assert-on-string-literal` (`W0129`) by [@​latonis](https://togithub.com/latonis) in [https://github.com/charliermarsh/ruff/pull/3610](https://togithub.com/charliermarsh/ruff/pull/3610) - \[`pyupgrade`] Convert single-argument %-style format calls by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3600](https://togithub.com/charliermarsh/ruff/pull/3600) - \[`pyupgrade`] Flag PEP 585 and PEP 604 violations in quoted annotations by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3593](https://togithub.com/charliermarsh/ruff/pull/3593) - \[`pyupgrade`] Enable autofix for annotations within 'simple' string literals by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3657](https://togithub.com/charliermarsh/ruff/pull/3657) - \[`pyflakes`] Add autofix functionality for `F523` ([#​3613](https://togithub.com/charliermarsh/ruff/issues/3613)) by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3613](https://togithub.com/charliermarsh/ruff/pull/3613) - \[`flake8-bandit`]: Implement deny-list rules for suspicious member calls by [@​colin99d](https://togithub.com/colin99d) in [https://github.com/charliermarsh/ruff/pull/3239](https://togithub.com/charliermarsh/ruff/pull/3239) - \[`flake8-annotations`] Add autofix for `ANN204` with magic methods by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3633](https://togithub.com/charliermarsh/ruff/pull/3633) - \[`pylint`] Implement `binary-op-exception` (`PLW0711`) by [@​latonis](https://togithub.com/latonis) in [https://github.com/charliermarsh/ruff/pull/3639](https://togithub.com/charliermarsh/ruff/pull/3639) - \[`flake8-django`]: Implement rule DJ012 by [@​dhruvmanila](https://togithub.com/dhruvmanila) in [https://github.com/charliermarsh/ruff/pull/3659](https://togithub.com/charliermarsh/ruff/pull/3659) ##### Bug Fixes - Check exclusions prior to resolving `pyproject.toml` files by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3588](https://togithub.com/charliermarsh/ruff/pull/3588) - Fix D417 false positive by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3596](https://togithub.com/charliermarsh/ruff/pull/3596) - Avoid removing comment hash for noqa's with trailing content by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3589](https://togithub.com/charliermarsh/ruff/pull/3589) - Avoid panics for implicitly-concatenated docstrings by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3584](https://togithub.com/charliermarsh/ruff/pull/3584) - Fix infinite loop due to rules `D207` & `W605` by [@​vlindhol](https://togithub.com/vlindhol) in [https://github.com/charliermarsh/ruff/pull/3609](https://togithub.com/charliermarsh/ruff/pull/3609) - Avoid trimming escaped whitespace in D210 by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3635](https://togithub.com/charliermarsh/ruff/pull/3635) - Handle `UP032` autofix with adjacent keywords by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3636](https://togithub.com/charliermarsh/ruff/pull/3636) - Consider same-site fixes to be overlapping by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3638](https://togithub.com/charliermarsh/ruff/pull/3638) - Avoid `RUF007` fixes for more than two arguments by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3654](https://togithub.com/charliermarsh/ruff/pull/3654) - Allow `pairwise` diagnostics for `zip(..., strict=True)` by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3669](https://togithub.com/charliermarsh/ruff/pull/3669) - isort: fix bad interaction between `force-sort-within-sections` and `force-to-top` by [@​bluetech](https://togithub.com/bluetech) in [https://github.com/charliermarsh/ruff/pull/3645](https://togithub.com/charliermarsh/ruff/pull/3645) - Gracefully handle lint panics by [@​MichaReiser](https://togithub.com/MichaReiser) in [https://github.com/charliermarsh/ruff/pull/3509](https://togithub.com/charliermarsh/ruff/pull/3509) - Fix TRY300 false positive by [@​JonathanPlasse](https://togithub.com/JonathanPlasse) in [https://github.com/charliermarsh/ruff/pull/3634](https://togithub.com/charliermarsh/ruff/pull/3634) - Avoid raising PEP 604 errors with forward-referenced members by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3640](https://togithub.com/charliermarsh/ruff/pull/3640) - Avoid attempting infinite `open` fix with re-bound builtin by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3650](https://togithub.com/charliermarsh/ruff/pull/3650) - Check indentation level when executing E231 by [@​kyoto7250](https://togithub.com/kyoto7250) in [https://github.com/charliermarsh/ruff/pull/3668](https://togithub.com/charliermarsh/ruff/pull/3668) - Flag, but don't fix, unused imports (`F401`) in `ModuleNotFoundError` blocks by [@​charliermarsh](https://togithub.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/3658](https://togithub.com/charliermarsh/ruff/pull/3658) #### New Contributors - [@​Rogdham](https://togithub.com/Rogdham) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3607](https://togithub.com/charliermarsh/ruff/pull/3607) - [@​vlindhol](https://togithub.com/vlindhol) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3609](https://togithub.com/charliermarsh/ruff/pull/3609) - [@​dhruvmanila](https://togithub.com/dhruvmanila) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3605](https://togithub.com/charliermarsh/ruff/pull/3605) - [@​luke396](https://togithub.com/luke396) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3604](https://togithub.com/charliermarsh/ruff/pull/3604) - [@​fuziontech](https://togithub.com/fuziontech) made their first contribution in [https://github.com/charliermarsh/ruff/pull/3641](https://togithub.com/charliermarsh/ruff/pull/3641) **Full Changelog**: astral-sh/ruff@v0.0.257...v0.0.258 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, 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/allenporter/flux-local). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4xNC4yIiwidXBkYXRlZEluVmVyIjoiMzUuMTQuMiJ9--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Summary
Today, we only convert %-style format calls if the right-hand side is a dictionary or tuple literal. However, I think we can support a larger set of expressions on the right-hand side.
There are three cases to consider...
"%(foo)s" % x). In that case, the right-hand side has to resolve to a map, so we treat it as kwargs (e.g.,"{foo}".format(**x))."%s %s" % x). In that case, the right-hand side has to resolve to a tuple, so we treat it as kwargs (e.g.,"{} {}".format(*x))."%s" % x). In that case, we can't be certain whether the right-hand side is a single expression, or a tuple containing a single expression -- so unfortunately, we have to continue ignoring those.There's one case that's not formally covered above, which is a template string that mixes named and positional values, like
"%(foo)s %s". But I'm unable to come up with a right-hand side that's valid given mixed named and positional values. Does such a case exist? I believe it's impossible.Closes #3549.