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
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
@@ -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.
3 changes: 3 additions & 0 deletions mypy/errorcodes.py
Original file line number Diff line number Diff line change
@@ -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",
8 changes: 8 additions & 0 deletions mypy/messages.py
Original file line number Diff line number Diff line change
@@ -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."""
4 changes: 2 additions & 2 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
@@ -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")
@@ -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
2 changes: 1 addition & 1 deletion test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions test-data/unit/check-errorcodes.test
Original file line number Diff line number Diff line change
@@ -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
@@ -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]
@@ -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]
2 changes: 1 addition & 1 deletion test-data/unit/check-inference-context.test
Original file line number Diff line number Diff line change
@@ -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]
3 changes: 2 additions & 1 deletion test-data/unit/check-newsemanal.test
Original file line number Diff line number Diff line change
@@ -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():
@@ -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]
8 changes: 7 additions & 1 deletion test-data/unit/check-statements.test
Original file line number Diff line number Diff line change
@@ -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:
@@ -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