Skip to content

Commit

Permalink
[flake8-pyi] Ignore 'unused' private type dicts in class scopes (#9952
Browse files Browse the repository at this point in the history
)

## Summary

If these are defined within class scopes, they're actually attributes of
the class, and can be accessed through the class itself.

(We preserve our existing behavior for `.pyi` files.)

Closes #9948.
  • Loading branch information
charliermarsh authored Feb 12, 2024
1 parent 90f8e4b commit e2785f3
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
14 changes: 13 additions & 1 deletion crates/ruff_linter/resources/test/fixtures/flake8_pyi/PYI049.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,25 @@ class _UnusedTypedDict2(typing.TypedDict):


class _UsedTypedDict(TypedDict):
foo: bytes
foo: bytes


class _CustomClass(_UsedTypedDict):
bar: list[int]


_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})


def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...


# In `.py` files, we don't flag unused definitions in class scopes (unlike in `.pyi`
# files).
class _CustomClass3:
class _UnusedTypeDict4(TypedDict):
pass

def method(self) -> None:
_CustomClass3._UnusedTypeDict4()
10 changes: 10 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/flake8_pyi/PYI049.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})

def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...


# In `.pyi` files, we flag unused definitions in class scopes as well as in the global
# scope (unlike in `.py` files).
class _CustomClass3:
class _UnusedTypeDict4(TypedDict):
pass

def method(self) -> None:
_CustomClass3._UnusedTypeDict4()
26 changes: 15 additions & 11 deletions crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,17 +281,21 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
}
}

if checker.enabled(Rule::UnusedPrivateTypeVar) {
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateProtocol) {
flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateTypeAlias) {
flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateTypedDict) {
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
if checker.source_type.is_stub()
|| matches!(scope.kind, ScopeKind::Module | ScopeKind::Function(_))
{
if checker.enabled(Rule::UnusedPrivateTypeVar) {
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateProtocol) {
flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateTypeAlias) {
flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics);
}
if checker.enabled(Rule::UnusedPrivateTypedDict) {
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
}
}

if checker.enabled(Rule::AsyncioDanglingTask) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ PYI049.py:9:7: PYI049 Private TypedDict `_UnusedTypedDict2` is never used
10 | bar: int
|

PYI049.py:20:1: PYI049 Private TypedDict `_UnusedTypedDict3` is never used
PYI049.py:21:1: PYI049 Private TypedDict `_UnusedTypedDict3` is never used
|
18 | bar: list[int]
19 |
20 | _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
21 | _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
| ^^^^^^^^^^^^^^^^^ PYI049
21 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
22 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|


Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,13 @@ PYI049.pyi:34:1: PYI049 Private TypedDict `_UnusedTypedDict3` is never used
35 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|

PYI049.pyi:43:11: PYI049 Private TypedDict `_UnusedTypeDict4` is never used
|
41 | # scope (unlike in `.py` files).
42 | class _CustomClass3:
43 | class _UnusedTypeDict4(TypedDict):
| ^^^^^^^^^^^^^^^^ PYI049
44 | pass
|


0 comments on commit e2785f3

Please sign in to comment.