Skip to content

Commit b96a3f1

Browse files
authored
Dedicated error code for explicit any (#18398)
1 parent 02c07c8 commit b96a3f1

File tree

6 files changed

+66
-46
lines changed

6 files changed

+66
-46
lines changed

docs/source/error_code_list.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,22 @@ Consider this example:
12411241
`PEP 705 <https://peps.python.org/pep-0705>`_ specifies
12421242
how ``ReadOnly`` special form works for ``TypedDict`` objects.
12431243

1244+
.. _code-narrowed-type-not-subtype:
1245+
1246+
Check that ``TypeIs`` narrows types [narrowed-type-not-subtype]
1247+
---------------------------------------------------------------
1248+
1249+
:pep:`742` requires that when ``TypeIs`` is used, the narrowed
1250+
type must be a subtype of the original type::
1251+
1252+
from typing_extensions import TypeIs
1253+
1254+
def f(x: int) -> TypeIs[str]: # Error, str is not a subtype of int
1255+
...
1256+
1257+
def g(x: object) -> TypeIs[str]: # OK
1258+
...
1259+
12441260
.. _code-misc:
12451261

12461262
Miscellaneous checks [misc]

docs/source/error_code_list2.rst

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -594,18 +594,19 @@ Correct usage:
594594
When this code is enabled, using ``reveal_locals`` is always an error,
595595
because there's no way one can import it.
596596

597-
.. _code-narrowed-type-not-subtype:
598597

599-
Check that ``TypeIs`` narrows types [narrowed-type-not-subtype]
600-
---------------------------------------------------------------
598+
.. _code-explicit-any:
601599

602-
:pep:`742` requires that when ``TypeIs`` is used, the narrowed
603-
type must be a subtype of the original type::
600+
Check that explicit Any type annotations are not allowed [explicit-any]
601+
-----------------------------------------------------------------------
604602

605-
from typing_extensions import TypeIs
603+
If you use :option:`--disallow-any-explicit <mypy --disallow-any-explicit>`, mypy generates an error
604+
if you use an explicit ``Any`` type annotation.
606605

607-
def f(x: int) -> TypeIs[str]: # Error, str is not a subtype of int
608-
...
606+
Example:
609607

610-
def g(x: object) -> TypeIs[str]: # OK
611-
...
608+
.. code-block:: python
609+
610+
# mypy: disallow-any-explicit
611+
from typing import Any
612+
x: Any = 1 # Error: Explicit "Any" type annotation [explicit-any]

mypy/errorcodes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ def __hash__(self) -> int:
304304
"General",
305305
)
306306

307+
EXPLICIT_ANY: Final = ErrorCode(
308+
"explicit-any", "Warn about explicit Any type annotations", "General"
309+
)
310+
307311
DEPRECATED: Final = ErrorCode(
308312
"deprecated",
309313
"Warn when importing or using deprecated (overloaded) functions, methods or classes",

mypy/messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1821,7 +1821,7 @@ def need_annotation_for_var(
18211821
)
18221822

18231823
def explicit_any(self, ctx: Context) -> None:
1824-
self.fail('Explicit "Any" is not allowed', ctx)
1824+
self.fail('Explicit "Any" is not allowed', ctx, code=codes.EXPLICIT_ANY)
18251825

18261826
def unsupported_target_for_star_typeddict(self, typ: Type, ctx: Context) -> None:
18271827
self.fail(

test-data/unit/check-flags.test

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,120 +1829,120 @@ x: A # E:4: Missing type parameters for generic type "A"
18291829
[builtins fixtures/list.pyi]
18301830

18311831
[case testDisallowAnyExplicitDefSignature]
1832-
# flags: --disallow-any-explicit
1832+
# flags: --disallow-any-explicit --show-error-codes
18331833

18341834
from typing import Any, List
18351835

1836-
def f(x: Any) -> None: # E: Explicit "Any" is not allowed
1836+
def f(x: Any) -> None: # E: Explicit "Any" is not allowed [explicit-any]
18371837
pass
18381838

1839-
def g() -> Any: # E: Explicit "Any" is not allowed
1839+
def g() -> Any: # E: Explicit "Any" is not allowed [explicit-any]
18401840
pass
18411841

1842-
def h() -> List[Any]: # E: Explicit "Any" is not allowed
1842+
def h() -> List[Any]: # E: Explicit "Any" is not allowed [explicit-any]
18431843
pass
18441844
[builtins fixtures/list.pyi]
18451845

18461846
[case testDisallowAnyExplicitVarDeclaration]
1847-
# flags: --disallow-any-explicit
1847+
# flags: --disallow-any-explicit --show-error-codes
18481848
from typing import Any
1849-
v: Any = '' # E: Explicit "Any" is not allowed
1850-
w = '' # type: Any # E: Explicit "Any" is not allowed
1849+
v: Any = '' # E: Explicit "Any" is not allowed [explicit-any]
1850+
w = '' # type: Any # E: Explicit "Any" is not allowed [explicit-any]
18511851
class X:
1852-
y = '' # type: Any # E: Explicit "Any" is not allowed
1852+
y = '' # type: Any # E: Explicit "Any" is not allowed [explicit-any]
18531853

18541854
[case testDisallowAnyExplicitGenericVarDeclaration]
1855-
# flags: --disallow-any-explicit
1855+
# flags: --disallow-any-explicit --show-error-codes
18561856
from typing import Any, List
1857-
v: List[Any] = [] # E: Explicit "Any" is not allowed
1857+
v: List[Any] = [] # E: Explicit "Any" is not allowed [explicit-any]
18581858
[builtins fixtures/list.pyi]
18591859

18601860
[case testDisallowAnyExplicitInheritance]
1861-
# flags: --disallow-any-explicit
1861+
# flags: --disallow-any-explicit --show-error-codes
18621862
from typing import Any, List
18631863

1864-
class C(Any): # E: Explicit "Any" is not allowed
1864+
class C(Any): # E: Explicit "Any" is not allowed [explicit-any]
18651865
pass
18661866

1867-
class D(List[Any]): # E: Explicit "Any" is not allowed
1867+
class D(List[Any]): # E: Explicit "Any" is not allowed [explicit-any]
18681868
pass
18691869
[builtins fixtures/list.pyi]
18701870

18711871
[case testDisallowAnyExplicitAlias]
1872-
# flags: --disallow-any-explicit
1872+
# flags: --disallow-any-explicit --show-error-codes
18731873
from typing import Any, List
18741874

1875-
X = Any # E: Explicit "Any" is not allowed
1876-
Y = List[Any] # E: Explicit "Any" is not allowed
1875+
X = Any # E: Explicit "Any" is not allowed [explicit-any]
1876+
Y = List[Any] # E: Explicit "Any" is not allowed [explicit-any]
18771877

18781878
def foo(x: X) -> Y: # no error
18791879
x.nonexistent() # no error
18801880
return x
18811881
[builtins fixtures/list.pyi]
18821882

18831883
[case testDisallowAnyExplicitGenericAlias]
1884-
# flags: --disallow-any-explicit
1884+
# flags: --disallow-any-explicit --show-error-codes
18851885
from typing import Any, TypeVar, Tuple
18861886

18871887
T = TypeVar('T')
18881888

1889-
TupleAny = Tuple[Any, T] # E: Explicit "Any" is not allowed
1889+
TupleAny = Tuple[Any, T] # E: Explicit "Any" is not allowed [explicit-any]
18901890

18911891
def foo(x: TupleAny[str]) -> None: # no error
18921892
pass
18931893

1894-
def goo(x: TupleAny[Any]) -> None: # E: Explicit "Any" is not allowed
1894+
def goo(x: TupleAny[Any]) -> None: # E: Explicit "Any" is not allowed [explicit-any]
18951895
pass
18961896
[builtins fixtures/tuple.pyi]
18971897

18981898
[case testDisallowAnyExplicitCast]
1899-
# flags: --disallow-any-explicit
1899+
# flags: --disallow-any-explicit --show-error-codes
19001900
from typing import Any, List, cast
19011901

19021902
x = 1
1903-
y = cast(Any, x) # E: Explicit "Any" is not allowed
1904-
z = cast(List[Any], x) # E: Explicit "Any" is not allowed
1903+
y = cast(Any, x) # E: Explicit "Any" is not allowed [explicit-any]
1904+
z = cast(List[Any], x) # E: Explicit "Any" is not allowed [explicit-any]
19051905
[builtins fixtures/list.pyi]
19061906

19071907
[case testDisallowAnyExplicitNamedTuple]
1908-
# flags: --disallow-any-explicit
1908+
# flags: --disallow-any-explicit --show-error-codes
19091909
from typing import Any, List, NamedTuple
19101910

1911-
Point = NamedTuple('Point', [('x', List[Any]), ('y', Any)]) # E: Explicit "Any" is not allowed
1911+
Point = NamedTuple('Point', [('x', List[Any]), ('y', Any)]) # E: Explicit "Any" is not allowed [explicit-any]
19121912
[builtins fixtures/list.pyi]
19131913

19141914
[case testDisallowAnyExplicitTypeVarConstraint]
1915-
# flags: --disallow-any-explicit
1915+
# flags: --disallow-any-explicit --show-error-codes
19161916
from typing import Any, List, TypeVar
19171917

1918-
T = TypeVar('T', Any, List[Any]) # E: Explicit "Any" is not allowed
1918+
T = TypeVar('T', Any, List[Any]) # E: Explicit "Any" is not allowed [explicit-any]
19191919
[builtins fixtures/list.pyi]
19201920

19211921
[case testDisallowAnyExplicitNewType]
1922-
# flags: --disallow-any-explicit
1922+
# flags: --disallow-any-explicit --show-error-codes
19231923
from typing import Any, List, NewType
19241924

19251925
# this error does not come from `--disallow-any-explicit` flag
1926-
Baz = NewType('Baz', Any) # E: Argument 2 to NewType(...) must be subclassable (got "Any")
1927-
Bar = NewType('Bar', List[Any]) # E: Explicit "Any" is not allowed
1926+
Baz = NewType('Baz', Any) # E: Argument 2 to NewType(...) must be subclassable (got "Any") [valid-newtype]
1927+
Bar = NewType('Bar', List[Any]) # E: Explicit "Any" is not allowed [explicit-any]
19281928
[builtins fixtures/list.pyi]
19291929

19301930
[case testDisallowAnyExplicitTypedDictSimple]
1931-
# flags: --disallow-any-explicit
1931+
# flags: --disallow-any-explicit --show-error-codes
19321932
from mypy_extensions import TypedDict
19331933
from typing import Any
19341934

1935-
M = TypedDict('M', {'x': str, 'y': Any}) # E: Explicit "Any" is not allowed
1935+
M = TypedDict('M', {'x': str, 'y': Any}) # E: Explicit "Any" is not allowed [explicit-any]
19361936
M(x='x', y=2) # no error
19371937
def f(m: M) -> None: pass # no error
19381938
[builtins fixtures/dict.pyi]
19391939

19401940
[case testDisallowAnyExplicitTypedDictGeneric]
1941-
# flags: --disallow-any-explicit
1941+
# flags: --disallow-any-explicit --show-error-codes
19421942
from mypy_extensions import TypedDict
19431943
from typing import Any, List
19441944

1945-
M = TypedDict('M', {'x': str, 'y': List[Any]}) # E: Explicit "Any" is not allowed
1945+
M = TypedDict('M', {'x': str, 'y': List[Any]}) # E: Explicit "Any" is not allowed [explicit-any]
19461946
N = TypedDict('N', {'x': str, 'y': List}) # no error
19471947
[builtins fixtures/dict.pyi]
19481948

test-data/unit/fixtures/typing-typeddict.pyi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ class Iterator(Iterable[T_co], Protocol):
4747
def __next__(self) -> T_co: pass
4848

4949
class Sequence(Iterable[T_co]):
50-
# misc is for explicit Any.
51-
def __getitem__(self, n: Any) -> T_co: pass # type: ignore[misc]
50+
def __getitem__(self, n: Any) -> T_co: pass # type: ignore[explicit-any]
5251

5352
class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta):
5453
def keys(self) -> Iterable[T]: pass # Approximate return type

0 commit comments

Comments
 (0)