mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 04:19:43 +00:00
[flake8-pyi
] Ignore 'unused' private type dicts in class scopes (#9952)
## 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 https://github.com/astral-sh/ruff/issues/9948.
This commit is contained in:
parent
90f8e4baf4
commit
e2785f3fb6
5 changed files with 50 additions and 17 deletions
|
@ -17,7 +17,19 @@ class _UsedTypedDict(TypedDict):
|
||||||
class _CustomClass(_UsedTypedDict):
|
class _CustomClass(_UsedTypedDict):
|
||||||
bar: list[int]
|
bar: list[int]
|
||||||
|
|
||||||
|
|
||||||
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
||||||
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
||||||
|
|
||||||
|
|
||||||
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...
|
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()
|
||||||
|
|
|
@ -35,3 +35,13 @@ _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
||||||
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
||||||
|
|
||||||
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...
|
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()
|
||||||
|
|
|
@ -281,6 +281,9 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if checker.source_type.is_stub()
|
||||||
|
|| matches!(scope.kind, ScopeKind::Module | ScopeKind::Function(_))
|
||||||
|
{
|
||||||
if checker.enabled(Rule::UnusedPrivateTypeVar) {
|
if checker.enabled(Rule::UnusedPrivateTypeVar) {
|
||||||
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
|
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
@ -293,6 +296,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
||||||
if checker.enabled(Rule::UnusedPrivateTypedDict) {
|
if checker.enabled(Rule::UnusedPrivateTypedDict) {
|
||||||
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
|
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if checker.enabled(Rule::AsyncioDanglingTask) {
|
if checker.enabled(Rule::AsyncioDanglingTask) {
|
||||||
ruff::rules::asyncio_dangling_binding(scope, &checker.semantic, &mut diagnostics);
|
ruff::rules::asyncio_dangling_binding(scope, &checker.semantic, &mut diagnostics);
|
||||||
|
|
|
@ -15,13 +15,11 @@ PYI049.py:9:7: PYI049 Private TypedDict `_UnusedTypedDict2` is never used
|
||||||
10 | bar: int
|
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]
|
21 | _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
||||||
19 |
|
|
||||||
20 | _UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
|
||||||
| ^^^^^^^^^^^^^^^^^ PYI049
|
| ^^^^^^^^^^^^^^^^^ PYI049
|
||||||
21 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
22 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,4 +24,13 @@ PYI049.pyi:34:1: PYI049 Private TypedDict `_UnusedTypedDict3` is never used
|
||||||
35 | _UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
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
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue