Skip to content

Add a note on variable annotation within unchecked function #13851

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2643,6 +2643,9 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
):
self.fail(message_registry.DEPENDENT_FINAL_IN_CLASS_BODY, s)

if s.unanalyzed_type and not self.in_checked_function():
self.msg.annotation_in_unchecked_function(context=s)

def check_type_alias_rvalue(self, s: AssignmentStmt) -> None:
if not (self.is_stub and isinstance(s.rvalue, OpExpr) and s.rvalue.op == "|"):
# We do this mostly for compatibility with old semantic analyzer.
Expand Down
3 changes: 3 additions & 0 deletions mypy/errorcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ def __str__(self) -> str:
UNREACHABLE: Final = ErrorCode(
"unreachable", "Warn about unreachable statements or expressions", "General"
)
ANNOTATION_UNCHECKED = ErrorCode(
"annotation-unchecked", "Notify about type annotations in unchecked functions", "General"
)
PARTIALLY_DEFINED: Final[ErrorCode] = ErrorCode(
"partially-defined",
"Warn about variables that are defined only in some execution paths",
Expand Down
8 changes: 8 additions & 0 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,14 @@ def add_fixture_note(self, fullname: str, ctx: Context) -> None:
ctx,
)

def annotation_in_unchecked_function(self, context: Context) -> None:
self.note(
"By default the bodies of untyped functions are not checked,"
" consider using --check-untyped-defs",
context,
code=codes.ANNOTATION_UNCHECKED,
)


def quote_type_string(type_string: str) -> str:
"""Quotes a type representation for use in messages."""
Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ reveal_type(Foo().Meta.name) # N: Revealed type is "builtins.str"

class A:
def __init__(self):
self.x = None # type: int
self.x = None # type: int # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs
a = None # type: A
a.x = 1
a.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
Expand All @@ -1201,7 +1201,7 @@ a.x = 1
a.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
class A:
def __init__(self):
self.x = None # type: int
self.x = None # type: int # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs


-- Special cases
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -1641,7 +1641,7 @@ A(a=func).a = func # E: Property "a" defined in "A" is read-only
# flags: --python-version 3.7
from dataclasses import dataclass

def foo():
def foo() -> None:
@dataclass
class Foo:
foo: int
Expand Down
5 changes: 5 additions & 0 deletions test-data/unit/check-errorcodes.test
Original file line number Diff line number Diff line change
Expand Up @@ -964,3 +964,8 @@ class C(abc.ABC):
T = TypeVar("T")
def test(tp: Type[T]) -> T: ...
test(C) # E: Only concrete class can be given where "Type[C]" is expected [type-abstract]

[case testUncheckedAnnotationSuppressed]
# flags: --disable-error-code=annotation-unchecked
def f():
x: int = "no" # No warning here
5 changes: 3 additions & 2 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -3544,11 +3544,11 @@ class Bar(Baz): pass

[file c.py]
class Baz:
def __init__(self):
def __init__(self) -> None:
self.x = 12 # type: int
[file c.py.2]
class Baz:
def __init__(self):
def __init__(self) -> None:
self.x = 'lol' # type: str
[out]
[out2]
Expand Down Expand Up @@ -5730,6 +5730,7 @@ class C:
tmp/a.py:2: error: "object" has no attribute "xyz"

[case testIncrementalInvalidNamedTupleInUnannotatedFunction]
# flags: --disable-error-code=annotation-unchecked
import a

[file a.py]
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-inference-context.test
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ if int():
from typing import List
class A:
def __init__(self):
self.x = [] # type: List[int]
self.x = [] # type: List[int] # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs
a = A()
a.x = []
a.x = [1]
Expand Down
3 changes: 2 additions & 1 deletion test-data/unit/check-newsemanal.test
Original file line number Diff line number Diff line change
Expand Up @@ -2963,6 +2963,7 @@ def g() -> None:
reveal_type(y) # N: Revealed type is "__main__.G[Any]"

[case testNewAnalyzerRedefinedNonlocal]
# flags: --disable-error-code=annotation-unchecked
import typing

def f():
Expand All @@ -2977,7 +2978,7 @@ def g() -> None:

def foo() -> None:
nonlocal bar
bar = [] # type: typing.List[int] # E: Name "bar" already defined on line 11
bar = [] # type: typing.List[int] # E: Name "bar" already defined on line 12
[builtins fixtures/list.pyi]

[case testNewAnalyzerMoreInvalidTypeVarArgumentsDeferred]
Expand Down
8 changes: 7 additions & 1 deletion test-data/unit/check-statements.test
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ N = TypedDict('N', {'x': int})
[out]

[case testGlobalWithoutInitialization]

# flags: --disable-error-code=annotation-unchecked
from typing import List

def foo() -> None:
Expand All @@ -2200,3 +2200,9 @@ def foo2():
bar2 = [] # type: List[str]
bar2
[builtins fixtures/list.pyi]

[case testNoteUncheckedAnnotation]
def foo():
x: int = "no" # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs
y = "no" # type: int # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs
z: int # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs