-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add RUF005 "unpack instead of concatenating" check #1957
Conversation
Thank you for this contribution! It looks great. I'll look to add comments soon. The main thing I'm trying to decide is whether this should be in In the future (not certain when), we'll likely recategorize the rules under more meaningful categories (like My gut is to keep this in What do you think? Would love to hear your reactions. |
4ecc274
to
3d8cbea
Compare
Hi @charliermarsh, thanks for the kind words! I'm absolutely more than fine moving this to Beyond the categorization effort in #1774, maybe it might be worth it to be able to mark checks (like this) separately as As an aside, I fixed the |
Some prior art, if only for the amusement value: |
One way we could model this is that we could omit this from the |
From @andersk's link I saw that rustc/clippy assigns "applicability" to suggestions: https://doc.rust-lang.org/stable/nightly-rustc/rustc_errors/enum.Applicability.html |
@akx - Let's go ahead and move this under @bluetech - Applicability looks nice and is something we should support (defined at the Rule level, configurable at the command-line and in \cc @not-my-profile who's probably interested in that too. |
f0be282
to
1a8d9ec
Compare
@charliermarsh Moved to RUF005. I also added a commented-out "failing test" in the fixture – chained concatenations aren't handled gracefully at all at present, but I suppose that could be improved later :) |
I agree about rule applicability being something we should have ... I had already noticed it when looking at the clippy lint documentation ... I just opened #1997 for tracking that :) |
Great, I'll look to get this merged today! |
src/rules/ruff/rules/unpack_instead_of_concatenating_to_collection_literal.rs
Outdated
Show resolved
Hide resolved
1a8d9ec
to
42df14d
Compare
@charliermarsh Thanks for the review! I think this looks pretty good now: class Fun:
words = ("how", "fun!")
def yay(self):
return self.words
yay = Fun().yay
foo = [4, 5, 6]
-bar = [1, 2, 3] + foo
+bar = [1, 2, 3, *foo]
zoob = tuple(bar)
-quux = (7, 8, 9) + zoob
-spam = quux + (10, 11, 12)
+quux = (7, 8, 9, *zoob)
+spam = (*quux, 10, 11, 12)
spom = list(spam)
-eggs = spom + [13, 14, 15]
-elatement = ("we all say", ) + yay()
-excitement = ("we all think", ) + Fun().yay()
-astonishment = ("we all feel", ) + Fun.words
+eggs = [*spom, 13, 14, 15]
+elatement = ("we all say", *yay())
+excitement = ("we all think", *Fun().yay())
+astonishment = ("we all feel", *Fun.words)
-chain = ['a', 'b', 'c'] + eggs + list(('yes', 'no', 'pants') + zoob)
+chain = ["a", "b", "c", *eggs, *list(("yes", "no", "pants", *zoob))] |
42df14d
to
3ead67c
Compare
An interesting edge case to test would be empty tuples. Does it handle the following correctly? baz = () + zoob Unpacking as |
@rhkleijn I'm a bit surprised myself, but it does the right thing! -baz = () + zoob
+baz = (*zoob,) |
* Guard against complex splattees * Wrap tuples in parens
3ead67c
to
d9dcf92
Compare
@akx - How would you feel if I subsequently turned off autofix (by default) on this rule for now, instead requiring it to be opt-in (via the |
(Merging regardless but may follow-up to tweak the default fix list -- LMK what you think!) |
@charliermarsh Sounds good to me! Thanks for the merge :) |
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ruff](https://github.com/charliermarsh/ruff) | `^0.0.226` -> `^0.0.227` | [![age](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/compatibility-slim/0.0.226)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/ruff/0.0.227/confidence-slim/0.0.226)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>charliermarsh/ruff</summary> ### [`v0.0.227`](https://github.com/charliermarsh/ruff/releases/tag/v0.0.227) [Compare Source](https://github.com/charliermarsh/ruff/compare/v0.0.226...v0.0.227) #### What's Changed - Drop `RuleCode` in favor of `Rule` enum with human-friendly names by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1941](https://github.com/charliermarsh/ruff/pull/1941) - Make define_rule_mapping! set rule code as doc comment of variants by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1991](https://github.com/charliermarsh/ruff/pull/1991) - Added pylint formatter by [@​damienallen](https://github.com/damienallen) in [https://github.com/charliermarsh/ruff/pull/1995](https://github.com/charliermarsh/ruff/pull/1995) - Preserve unmatched comparators in `SIM109` by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/1998](https://github.com/charliermarsh/ruff/pull/1998) - Drop `Violation::placeholder` by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/1996](https://github.com/charliermarsh/ruff/pull/1996) - Apply #\[derive(Default)] fixes suggested by Clippy by [@​akx](https://github.com/akx) in [https://github.com/charliermarsh/ruff/pull/2000](https://github.com/charliermarsh/ruff/pull/2000) - Avoid `SIM201` and `SIM202` errors in `__ne__` et al by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2001](https://github.com/charliermarsh/ruff/pull/2001) - Fix that --explain panics by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2002](https://github.com/charliermarsh/ruff/pull/2002) - Split up pydocstyle rules by [@​akx](https://github.com/akx) in [https://github.com/charliermarsh/ruff/pull/2003](https://github.com/charliermarsh/ruff/pull/2003) - Add RUF005 "unpack instead of concatenating" check by [@​akx](https://github.com/akx) in [https://github.com/charliermarsh/ruff/pull/1957](https://github.com/charliermarsh/ruff/pull/1957) - Enable autofix for `FitsOnOneLine` (`D200`) by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2006](https://github.com/charliermarsh/ruff/pull/2006) - Change AsRef<str> impl for Rule to kebab-case by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2009](https://github.com/charliermarsh/ruff/pull/2009) - Upgrade RustPython by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2011](https://github.com/charliermarsh/ruff/pull/2011) - Avoid SIM401 in `elif` blocks by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2012](https://github.com/charliermarsh/ruff/pull/2012) - Improve --explain output by [@​not-my-profile](https://github.com/not-my-profile) in [https://github.com/charliermarsh/ruff/pull/2010](https://github.com/charliermarsh/ruff/pull/2010) - Avoid checking row types for single-name [@​parametrize](https://github.com/parametrize) decorators by [@​charliermarsh](https://github.com/charliermarsh) in [https://github.com/charliermarsh/ruff/pull/2013](https://github.com/charliermarsh/ruff/pull/2013) #### New Contributors - [@​damienallen](https://github.com/damienallen) made their first contribution in [https://github.com/charliermarsh/ruff/pull/1995](https://github.com/charliermarsh/ruff/pull/1995) **Full Changelog**: astral-sh/ruff@v0.0.226...v0.0.227 </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:eyJjcmVhdGVkSW5WZXIiOiIzNC4xMDUuNCIsInVwZGF0ZWRJblZlciI6IjM0LjEwNS40In0=--> Signed-off-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR adds a new check that turns expressions such as
[1, 2, 3] + foo
into[1, 2, 3, *foo]
, since the latter is easier to read and faster:However there's a couple of gotchas:
simplify
rule, so I borrowed an unusedSIM
code even if the upstreamflake8-simplify
doesn't do this transform. If it should be assigned some other code, let me know 😄+
operation has overridden__add__
to do something else. What's theruff
policy around potentially unsafe operations? (I think some of the suggestions other ported rules give could be semantically different from the original code, but I'm not sure.)match
statement?)Thanks for
ruff
, by the way! :)