ruff/crates/ruff_linter/resources/test/fixtures/ruff
Mikko Leppänen e2a1d1a8eb
[`ruff`] Catch more dummy variable uses (`RUF052`) (#19799)
## Summary

Extends the `used-dummy-variable` rule
([RUF052](https://docs.astral.sh/ruff/rules/used-dummy-variable/)) to
detect dummy variables that are used within list comprehensions, dict
comprehensions, set comprehensions, and generator expressions, not just
regular for loops and function assignments.

### Problem

Previously, RUF052 only flagged dummy variables (variables with leading
underscores) that were used in function scopes via assignments or
regular for loops. It missed cases where dummy variables were used
within comprehensions:

```python
def example():
    my_list = [{"foo": 1}, {"foo": 2}]
    
    # These were not detected before:
    [_item["foo"] for _item in my_list]  # Should warn: _item is used
    {_item["key"]: _item["val"] for _item in my_list}  # Should warn: _item is used
    (_item["foo"] for _item in my_list)  # Should warn: _item is used
```

### Solution

- Extended scope checking to include all generator scopes () with any
(list/dict/set comprehensions and generator expressions)
`ScopeKind::Generator``GeneratorKind`
- Added support for bindings, which cover loop variables in both regular
for loops and comprehensions `BindingKind::LoopVar`
- Refactored the scope validation logic for better readability with a
descriptive variable `is_allowed_scope`



[ISSUE](https://github.com/astral-sh/ruff/issues/19732)

## Test Plan

```bash
cargo test
```

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-11-21 12:57:02 -05:00
..
pyproject_toml Update pyproject-toml to support PEP 639 (#13902) 2024-11-20 13:11:51 +01:00
.editorconfig [`pyupgrade`] Preserve parenthesis when fixing native literals containing newlines (`UP018`) (#17220) 2025-04-24 08:48:02 +02:00
RUF005.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
RUF005_slices.py [`ruff`] Support slices in `RUF005` (#17078) 2025-03-31 09:09:39 -04:00
RUF006.py Add test cases for `RUF006` with lambdas (#13628) 2024-10-04 14:09:43 -05:00
RUF007.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
RUF008.py [`ruff`] Analyze deferred annotations before enforcing `mutable-(data)class-default` and `function-call-in-dataclass-default-argument` (`RUF008`,`RUF009`,`RUF012`) (#15921) 2025-02-05 06:44:19 -06:00
RUF008_attrs.py [`ruff`] Also report problems for `attrs` dataclasses in preview mode (`RUF008`, `RUF009`) (#14327) 2024-11-14 15:13:49 +00:00
RUF008_deferred.py [`ruff`] Analyze deferred annotations before enforcing `mutable-(data)class-default` and `function-call-in-dataclass-default-argument` (`RUF008`,`RUF009`,`RUF012`) (#15921) 2025-02-05 06:44:19 -06:00
RUF009.py [`ruff`] Allow dataclass attribute value instantiation from nested frozen dataclass (`RUF009`) (#20352) 2025-09-12 16:46:49 -04:00
RUF009_attrs.py [`ruff`] Allow more `field` calls from `attrs` (`RUF009`) (#19021) 2025-07-03 10:29:55 -04:00
RUF009_attrs_auto_attribs.py Use truthiness check in `auto_attribs` detection (#14562) 2024-11-23 22:06:10 -05:00
RUF009_deferred.py [`ruff`] Analyze deferred annotations before enforcing `mutable-(data)class-default` and `function-call-in-dataclass-default-argument` (`RUF008`,`RUF009`,`RUF012`) (#15921) 2025-02-05 06:44:19 -06:00
RUF010.py [`ruff`] Suppress diagnostic for f-string interpolations with debug text (`RUF010`) (#20525) 2025-10-07 16:57:59 -04:00
RUF012.py [`ruff`] Avoid false positive on `ClassVar` reassignment (`RUF012`) (#21478) 2025-11-17 15:52:24 -05:00
RUF012_deferred.py [`ruff`] Analyze deferred annotations before enforcing `mutable-(data)class-default` and `function-call-in-dataclass-default-argument` (`RUF008`,`RUF009`,`RUF012`) (#15921) 2025-02-05 06:44:19 -06:00
RUF013_0.py Avoid failures due to non-deterministic binding ordering (#10478) 2024-03-19 18:01:33 +00:00
RUF013_1.py Avoid failures due to non-deterministic binding ordering (#10478) 2024-03-19 18:01:33 +00:00
RUF013_2.py Treat all `typing_extensions` members as typing aliases (#9335) 2023-12-31 14:23:33 -04:00
RUF013_3.py Avoid failures due to non-deterministic binding ordering (#10478) 2024-03-19 18:01:33 +00:00
RUF013_4.py [`ruff`] Do not report when `Optional` has no type arguments (`RUF013`) (#14181) 2024-11-09 08:48:56 -05:00
RUF015.py [`ruff`] Expand rule for `list(iterable).pop(0)` idiom (`RUF015`) (#10148) 2024-02-28 00:24:28 +00:00
RUF016.py [`ruff`] Recognize t-strings, generators, and lambdas in `invalid-index-type` (`RUF016`) (#20213) 2025-09-12 13:37:02 -05:00
RUF017_0.py Perform insertions before replacements (#7739) 2023-10-01 14:53:54 +00:00
RUF017_1.py Perform insertions before replacements (#7739) 2023-10-01 14:53:54 +00:00
RUF018.py [`ruff`] Avoid emitting `assignment-in-assert` when all references to the assigned variable are themselves inside `assert`s (`RUF018`) (#14661) 2024-11-29 13:36:59 +00:00
RUF019.py Treat `not` operations as boolean tests (#12301) 2024-07-12 08:53:37 -04:00
RUF020.py [`ruff`] Improve autofix safety for `never-union` (RUF020) (#14589) 2024-11-25 18:35:07 +01:00
RUF021.py Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
RUF022.py Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
RUF023.py [`ruff`] Mark `RUF023` fix as unsafe if `__slots__` is not a set and the binding is used elsewhere (#12692) 2024-08-07 10:41:03 +01:00
RUF024.py Improve handling of builtin symbols in linter rules (#10919) 2024-04-16 11:37:31 +01:00
RUF026.py [`ruff`] Fix false positive for t-strings in `default-factory-kwarg` (`RUF026`) (#20032) 2025-08-22 09:29:42 -05:00
RUF027_0.py Fix `unreachable` panic in parser (#19183) 2025-07-20 22:04:14 +00:00
RUF027_1.py [`ruff`] Avoid false positives for RUF027 for typing context bindings. (#15037) 2024-12-18 08:50:49 +01:00
RUF027_2.py Fix panic on RUF027 (#9990) 2024-02-16 20:04:39 +00:00
RUF028.py [`ruff`] - fix false positive for decorators (`RUF028`) (#14061) 2024-11-03 11:49:03 +00:00
RUF029.py Use TypeChecker for detecting fastapi routes (#15093) 2024-12-21 15:45:28 +01:00
RUF030.py [`ruff`] Add `assert-with-print-expression` rule (#11974) (#11981) 2024-06-23 16:54:55 +00:00
RUF031.py [`ruff`] Skip singleton starred expressions for `incorrectly-parenthesized-tuple-in-subscript` (`RUF031`) (#16083) 2025-02-10 11:30:07 -06:00
RUF031_prefer_parens.py [`ruff`] Skip singleton starred expressions for `incorrectly-parenthesized-tuple-in-subscript` (`RUF031`) (#16083) 2025-02-10 11:30:07 -06:00
RUF032.py [`ruff`] Handle unary operators in `decimal-from-float-literal (RUF032)` (#13275) 2024-09-07 13:25:49 +00:00
RUF033.py [`ruff`] Preserve relative whitespace in multi-line expressions (`RUF033`) (#19647) 2025-08-27 19:15:44 +00:00
RUF034.py [ruff] implement useless if-else (RUF034) (#13218) 2024-09-04 08:22:17 +02:00
RUF036.py [`ruff`] Implement `none-not-at-end-of-union` (`RUF036`) (#14314) 2024-11-14 19:37:13 +01:00
RUF036.pyi [`ruff`] Implement `none-not-at-end-of-union` (`RUF036`) (#14314) 2024-11-14 19:37:13 +01:00
RUF037.py Less confidently mark f-strings as empty when inferring truthiness (#20152) 2025-08-29 22:12:54 +00:00
RUF038.py [`ruff`] Implement `redundant-bool-literal` (`RUF038`) (#14319) 2024-11-16 21:52:51 +00:00
RUF038.pyi [`ruff`] Implement `redundant-bool-literal` (`RUF038`) (#14319) 2024-11-16 21:52:51 +00:00
RUF039.py [`ruff`] Offer fixes for `RUF039` in more cases (#19065) 2025-07-24 11:45:45 -04:00
RUF039_concat.py [`ruff`] Offer fixes for `RUF039` in more cases (#19065) 2025-07-24 11:45:45 -04:00
RUF039_py_version_sensitive.py [`ruff`] Offer fixes for `RUF039` in more cases (#19065) 2025-07-24 11:45:45 -04:00
RUF040.py [`ruff`] Implement `invalid-assert-message-literal-argument` (`RUF040`) (#14488) 2024-11-25 17:41:07 -06:00
RUF041.py Fix typos found by codespell (#14863) 2024-12-09 09:32:12 +00:00
RUF041.pyi Fix typos found by codespell (#14863) 2024-12-09 09:32:12 +00:00
RUF043.py [`ruff`] Treat `)` as a regex metacharacter (`RUF043`, `RUF055`) (#15318) 2025-01-07 12:11:05 -05:00
RUF045.py [`ruff`] Implicit class variable in dataclass (`RUF045`) (#14349) 2025-02-15 09:08:13 -06:00
RUF046.py [`ruff`] Parenthesize arguments to `int` when removing `int` would change semantics in `unnecessary-cast-to-int` (`RUF046`) (#15277) 2025-01-07 21:43:50 +00:00
RUF046_CR.py [`pyupgrade`] Preserve parenthesis when fixing native literals containing newlines (`UP018`) (#17220) 2025-04-24 08:48:02 +02:00
RUF046_LF.py [`pyupgrade`] Preserve parenthesis when fixing native literals containing newlines (`UP018`) (#17220) 2025-04-24 08:48:02 +02:00
RUF047_for.py [`ruff`] Needless `else` clause (`RUF047`) (#15051) 2025-01-21 08:21:19 +00:00
RUF047_if.py [`ruff`] Needless `else` clause (`RUF047`) (#15051) 2025-01-21 08:21:19 +00:00
RUF047_try.py [`ruff`] Needless `else` clause (`RUF047`) (#15051) 2025-01-21 08:21:19 +00:00
RUF047_while.py [`ruff`] Needless `else` clause (`RUF047`) (#15051) 2025-01-21 08:21:19 +00:00
RUF048.py [`ruff`] Add rule forbidding `map(int, package.__version__.split('.'))` (`RUF048`) (#14373) 2024-11-18 13:43:24 +00:00
RUF048_1.py [`ruff`] Add rule forbidding `map(int, package.__version__.split('.'))` (`RUF048`) (#14373) 2024-11-18 13:43:24 +00:00
RUF049.py [`ruff`] Dataclass enums (`RUF049`) (#15299) 2025-01-06 14:44:20 +01:00
RUF051.py [`RUF051`] Ignore if `else`/`elif` block is present (#20705) 2025-10-06 08:02:27 -05:00
RUF052_0.py [`ruff`] Catch more dummy variable uses (`RUF052`) (#19799) 2025-11-21 12:57:02 -05:00
RUF052_1.py [`ruff`] Catch more dummy variable uses (`RUF052`) (#19799) 2025-11-21 12:57:02 -05:00
RUF053.py [`ruff`] Classes with mixed type variable style (`RUF053`) (#15841) 2025-02-06 18:35:51 +00:00
RUF054.py [`ruff`] Indented form feeds (`RUF054`) (#16049) 2025-02-09 19:23:48 -05:00
RUF055_0.py [`ruff`] Add support for more `re` patterns (`RUF055`) (#15764) 2025-01-29 10:14:44 -05:00
RUF055_1.py [`ruff`] Extend unnecessary-regular-expression to non-literal strings (`RUF055`) (#14679) 2024-12-03 15:17:20 +00:00
RUF055_2.py [`ruff`] Add support for more `re` patterns (`RUF055`) (#15764) 2025-01-29 10:14:44 -05:00
RUF055_3.py [`ruff`] Support byte strings (`RUF055`) (#18926) 2025-07-20 17:58:40 -04:00
RUF056.py Handle parenthesized arguments in `remove_argument` (#18805) 2025-06-20 21:24:41 +00:00
RUF057.py [`ruff`] Fix false positives on starred arguments (`RUF057`) (#21256) 2025-11-05 12:07:33 -05:00
RUF058_0.py [`ruff`] Check for shadowed `map` before suggesting fix (`RUF058`) (#15790) 2025-01-28 14:15:37 -05:00
RUF058_1.py [`ruff`] Check for shadowed `map` before suggesting fix (`RUF058`) (#15790) 2025-01-28 14:15:37 -05:00
RUF058_2.py [`ruff`] Allow `strict` kwarg when checking for `starmap-zip` (`RUF058`) in Python 3.14+ (#19333) 2025-07-15 07:04:23 -05:00
RUF059_0.py [`ruff`] skip fix for `RUF059` if dummy name is already bound (unused-unpacked-variable) (#18509) 2025-06-11 07:58:05 +02:00
RUF059_1.py Add new rule RUF059: Unused unpacked assignment (#16449) 2025-03-03 10:51:36 +01:00
RUF059_2.py Add new rule RUF059: Unused unpacked assignment (#16449) 2025-03-03 10:51:36 +01:00
RUF059_3.py Add new rule RUF059: Unused unpacked assignment (#16449) 2025-03-03 10:51:36 +01:00
RUF060.py [`ruff`] Use helper function for empty f-string detection in `in-empty-collection` (`RUF060`) (#20249) 2025-09-04 20:20:59 +00:00
RUF061_deprecated_call.py [`ruff`] Check for non-context-manager use of `pytest.raises`, `pytest.warns`, and `pytest.deprecated_call` (`RUF061`) (#17368) 2025-06-16 13:03:54 -04:00
RUF061_raises.py [`ruff`] Check for non-context-manager use of `pytest.raises`, `pytest.warns`, and `pytest.deprecated_call` (`RUF061`) (#17368) 2025-06-16 13:03:54 -04:00
RUF061_warns.py [`ruff`] Check for non-context-manager use of `pytest.raises`, `pytest.warns`, and `pytest.deprecated_call` (`RUF061`) (#17368) 2025-06-16 13:03:54 -04:00
RUF063.py [`ruff`] Added `cls.__dict__.get('__annotations__')` check (`RUF063`) (#18233) 2025-06-20 09:32:40 -04:00
RUF064.py RUF064: offer a safe fix for multi-digit zeros (#19847) 2025-08-10 20:35:27 +00:00
RUF065_0.py [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330) 2025-11-10 18:04:41 -05:00
RUF065_1.py [`ruff`] Fix false positive for complex conversion specifiers in `logging-eager-conversion` (`RUF065`) (#21464) 2025-11-19 09:38:33 +01:00
RUF100_0.py Fix a few typos found by codespell (#11404) 2024-05-13 13:22:35 +00:00
RUF100_1.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
RUF100_2.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
RUF100_3.py Avoid parsing joint rule codes as distinct codes in `# noqa` (#12809) 2024-11-02 20:24:59 +00:00
RUF100_4.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
RUF100_5.py [`ruff`] - extend comment deletions for unused-noqa (`RUF100`) (#13105) 2024-08-29 10:50:16 +05:30
RUF100_6.py Fix RUF100 to detect unused file-level noqa directives with specific codes (#17042) (#17061) 2025-04-07 09:21:52 -05:00
RUF100_7.py Fix RUF100 to detect unused file-level noqa directives with specific codes (#17042) (#17061) 2025-04-07 09:21:52 -05:00
RUF101_0.py [`ruff`] Detect redirected-noqa in file-level comments (`RUF101`) (#14635) 2024-11-27 18:25:47 +01:00
RUF101_1.py [`ruff`] Detect redirected-noqa in file-level comments (`RUF101`) (#14635) 2024-11-27 18:25:47 +01:00
RUF102.py [`RUF102`] Respect rule redirects in invalid rule code detection (#20245) 2025-09-10 14:27:07 -07:00
confusables.py [`ruff`] Skip RUF001 diagnostics when visiting string type definitions (#16122) 2025-02-12 16:27:38 +00:00
flake8_noqa.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
noqa.py Make noqa parsing consistent and more robust (#16483) 2025-03-13 15:37:37 +01:00
redirects.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
ruff_noqa_all.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
ruff_noqa_codes.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
ruff_noqa_invalid.py Rename `ruff` crate to `ruff_linter` (#7529) 2023-09-20 08:38:27 +02:00
ruff_per_file_ignores.py Respect `per-file-ignores` for `RUF100` on blanket `# noqa` (#10908) 2024-04-12 13:45:29 +00:00