Skip to content

Commit 2298829

Browse files
authored
attrs: remove fields type check (#15983)
Since python-attrs/attrs#890 (≥ 22.1.0) `attrs.fields` is typed to accept a protocol. Since python-attrs/attrs#997 (≥ 22.2.0) `attrs.has` is a type-guard. Support both by removing the explicit error reporting and letting it fall through to the type stub. Fixes #15980.
1 parent 379b52f commit 2298829

File tree

3 files changed

+20
-14
lines changed

3 files changed

+20
-14
lines changed

mypy/plugins/attrs.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,9 +1111,4 @@ def fields_function_sig_callback(ctx: mypy.plugin.FunctionSigContext) -> Callabl
11111111
assert ret_type is not None
11121112
return ctx.default_signature.copy_modified(arg_types=arg_types, ret_type=ret_type)
11131113

1114-
ctx.api.fail(
1115-
f'Argument 1 to "fields" has incompatible type "{format_type_bare(proper_type, ctx.api.options)}"; expected an attrs class',
1116-
ctx.context,
1117-
)
1118-
11191114
return ctx.default_signature

test-data/unit/check-plugin-attrs.test

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,16 +1596,18 @@ def f(t: TA) -> None:
15961596
[builtins fixtures/plugin_attrs.pyi]
15971597

15981598
[case testNonattrsFields]
1599-
# flags: --no-strict-optional
16001599
from typing import Any, cast, Type
1601-
from attrs import fields
1600+
from attrs import fields, has
16021601

16031602
class A:
16041603
b: int
16051604
c: str
16061605

1607-
fields(A) # E: Argument 1 to "fields" has incompatible type "Type[A]"; expected an attrs class
1608-
fields(None) # E: Argument 1 to "fields" has incompatible type "None"; expected an attrs class
1606+
if has(A):
1607+
fields(A)
1608+
else:
1609+
fields(A) # E: Argument 1 to "fields" has incompatible type "Type[A]"; expected "Type[AttrsInstance]"
1610+
fields(None) # E: Argument 1 to "fields" has incompatible type "None"; expected "Type[AttrsInstance]"
16091611
fields(cast(Any, 42))
16101612
fields(cast(Type[Any], 43))
16111613

@@ -2167,7 +2169,8 @@ TA = TypeVar('TA', bound=A)
21672169
TB = TypeVar('TB', bound=B)
21682170

21692171
def f(b_or_t: TA | TB | int) -> None:
2170-
a2 = attrs.evolve(b_or_t) # E: Argument 1 to "evolve" has type "Union[TA, TB, int]" whose item "TB" is not bound to an attrs class # E: Argument 1 to "evolve" has incompatible type "Union[TA, TB, int]" whose item "int" is not an attrs class
2172+
a2 = attrs.evolve(b_or_t) # E: Argument 1 to "evolve" has type "Union[TA, TB, int]" whose item "TB" is not bound to an attrs class \
2173+
# E: Argument 1 to "evolve" has incompatible type "Union[TA, TB, int]" whose item "int" is not an attrs class
21712174

21722175

21732176
[builtins fixtures/plugin_attrs.pyi]
@@ -2216,7 +2219,8 @@ def h(t: TNone) -> None:
22162219
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has a variable type "TNone" not bound to an attrs class
22172220

22182221
def x(t: TUnion) -> None:
2219-
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "str" is not an attrs class # E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "int" is not an attrs class
2222+
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "str" is not an attrs class \
2223+
# E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "int" is not an attrs class
22202224

22212225
[builtins fixtures/plugin_attrs.pyi]
22222226

test-data/unit/lib-stub/attrs/__init__.pyi

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
from typing import TypeVar, overload, Callable, Any, Optional, Union, Sequence, Mapping, Generic
1+
from typing import TypeVar, overload, Callable, Any, Optional, Union, Sequence, Mapping, \
2+
Protocol, ClassVar, Type
3+
from typing_extensions import TypeGuard
24

35
from attr import Attribute as Attribute
46

7+
8+
class AttrsInstance(Protocol):
9+
__attrs_attrs__: ClassVar[Any]
10+
11+
512
_T = TypeVar('_T')
613
_C = TypeVar('_C', bound=type)
714

@@ -131,5 +138,5 @@ def field(
131138

132139
def evolve(inst: _T, **changes: Any) -> _T: ...
133140
def assoc(inst: _T, **changes: Any) -> _T: ...
134-
135-
def fields(cls: type) -> Any: ...
141+
def has(cls: type) -> TypeGuard[Type[AttrsInstance]]: ...
142+
def fields(cls: Type[AttrsInstance]) -> Any: ...

0 commit comments

Comments
 (0)