Skip to content

Commit a6d0e59

Browse files
committed
Move the complete creation process of warning notes from checker.py to semanal.py.
1 parent 6a93d6a commit a6d0e59

File tree

2 files changed

+58
-65
lines changed

2 files changed

+58
-65
lines changed

mypy/checker.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@
184184
)
185185
from mypy.types import (
186186
ANY_STRATEGY,
187-
DEPRECATED_TYPE_NAMES,
188187
MYPYC_NATIVE_INT_NAMES,
189188
OVERLOAD_NAMES,
190189
AnyType,
@@ -637,10 +636,6 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
637636
if len(defn.items) == 1:
638637
self.fail(message_registry.MULTIPLE_OVERLOADS_REQUIRED, defn)
639638

640-
for item in defn.items:
641-
if isinstance(item, Decorator) and isinstance(ct := item.func.type, CallableType):
642-
self.create_deprecation_warning(ct, item.decorators)
643-
644639
if defn.is_property:
645640
# HACK: Infer the type of the property.
646641
assert isinstance(defn.items[0], Decorator)
@@ -659,17 +654,6 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
659654
self.fail(message_registry.INCONSISTENT_ABSTRACT_OVERLOAD, defn)
660655
if defn.impl:
661656
defn.impl.accept(self)
662-
if (
663-
isinstance(defn.impl, Decorator)
664-
and isinstance(defn.impl.func.type, CallableType)
665-
and ((deprecated := defn.impl.func.type.deprecated) is not None)
666-
):
667-
if isinstance(defn.type, (CallableType, Overloaded)):
668-
defn.type.deprecated = deprecated
669-
for subdef in defn.items:
670-
type_ = get_proper_type(subdef.type)
671-
if isinstance(type_, (CallableType, Overloaded)):
672-
type_.deprecated = deprecated
673657
if not defn.is_property:
674658
self.check_overlapping_overloads(defn)
675659
if defn.type is None:
@@ -2422,7 +2406,6 @@ def check__exit__return_type(self, defn: FuncItem) -> None:
24222406
def visit_class_def(self, defn: ClassDef) -> None:
24232407
"""Type check a class definition."""
24242408
typ = defn.info
2425-
self.create_deprecation_warning(typ, defn.decorators)
24262409
for base in typ.mro[1:]:
24272410
if base.is_final:
24282411
self.fail(message_registry.CANNOT_INHERIT_FROM_FINAL.format(base.name), defn)
@@ -5027,8 +5010,6 @@ def visit_del_stmt(self, s: DelStmt) -> None:
50275010
)
50285011

50295012
def visit_decorator(self, e: Decorator) -> None:
5030-
if isinstance(ct := e.func.type, CallableType):
5031-
self.create_deprecation_warning(ct, e.decorators)
50325013
for d in e.decorators:
50335014
if isinstance(d, RefExpr):
50345015
if d.fullname == "typing.no_type_check":
@@ -7556,52 +7537,6 @@ def has_valid_attribute(self, typ: Type, name: str) -> bool:
75567537
def get_expression_type(self, node: Expression, type_context: Type | None = None) -> Type:
75577538
return self.expr_checker.accept(node, type_context=type_context)
75587539

7559-
def create_deprecation_warning(
7560-
self, typ: CallableType | Overloaded | TypeInfo, decorators: Iterable[Expression]
7561-
) -> None:
7562-
"""Create a warning when visiting a deprecated (decorated) callable, overload or
7563-
class that may be used later if the deprecated feature is used."""
7564-
7565-
if isinstance(typ, CallableType):
7566-
if (defn := typ.definition) is None:
7567-
name = f"function {typ.name}"
7568-
else:
7569-
name = f"function {defn.fullname}"
7570-
elif isinstance(typ, Overloaded):
7571-
if isinstance(func := typ.items[0].definition, FuncDef):
7572-
name = f"function {func.fullname}"
7573-
else:
7574-
name = f"function {typ.name}"
7575-
else:
7576-
name = f"class {typ.fullname}"
7577-
7578-
overload = False
7579-
deprecation: str | None = None
7580-
for decorator in decorators:
7581-
if (
7582-
isinstance(typ, CallableType)
7583-
and isinstance(decorator, NameExpr)
7584-
and (decorator.fullname in OVERLOAD_NAMES)
7585-
):
7586-
overload = True
7587-
if deprecation is not None:
7588-
self.msg.note("@overload should be placed before @deprecated", decorator)
7589-
elif (
7590-
isinstance(decorator, CallExpr)
7591-
and isinstance(callee := decorator.callee, NameExpr)
7592-
and (callee.fullname in DEPRECATED_TYPE_NAMES)
7593-
and (len(args := decorator.args) >= 1)
7594-
and isinstance(arg := args[0], StrExpr)
7595-
and ((value := arg.value) is not None)
7596-
):
7597-
deprecation = value
7598-
7599-
if deprecation is not None:
7600-
if overload:
7601-
typ.deprecated = f"overload {typ} of {name} is deprecated: {deprecation}"
7602-
else:
7603-
typ.deprecated = f"{name} is deprecated: {deprecation}"
7604-
76057540
def check_deprecated(
76067541
self, typ: CallableType | Overloaded | TypeInfo, context: Context
76077542
) -> None:

mypy/semanal.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@
249249
from mypy.types import (
250250
ASSERT_TYPE_NAMES,
251251
DATACLASS_TRANSFORM_NAMES,
252+
DEPRECATED_TYPE_NAMES,
252253
FINAL_DECORATOR_NAMES,
253254
FINAL_TYPE_NAMES,
254255
IMPORTED_REVEAL_TYPE_NAMES,
@@ -1255,10 +1256,51 @@ def analyze_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
12551256
return
12561257

12571258
# We know this is an overload def. Infer properties and perform some checks.
1259+
self.process_deprecated_overload(defn)
12581260
self.process_final_in_overload(defn)
12591261
self.process_static_or_class_method_in_overload(defn)
12601262
self.process_overload_impl(defn)
12611263

1264+
def process_deprecated_overload(self, defn: OverloadedFuncDef) -> None:
1265+
if defn.is_property:
1266+
return
1267+
1268+
if isinstance(impl := defn.impl, Decorator) and isinstance(
1269+
type_ := impl.func.type, CallableType
1270+
) and (
1271+
(deprecated := type_.deprecated) is not None
1272+
):
1273+
if isinstance(defn.type, Overloaded):
1274+
defn.type.deprecated = deprecated
1275+
for item in defn.items:
1276+
if isinstance(item, Decorator) and isinstance(item.func.type, Overloaded):
1277+
item.func.type.deprecated = deprecated
1278+
1279+
for item in defn.items:
1280+
deprecation = False
1281+
if isinstance(item, Decorator):
1282+
for d in item.decorators:
1283+
if deprecation and refers_to_fullname(d, OVERLOAD_NAMES):
1284+
self.msg.note("@overload should be placed before @deprecated", d)
1285+
elif (deprecated := self.get_deprecated(d)) is not None:
1286+
deprecation = True
1287+
if isinstance(type_ := item.func.type, CallableType):
1288+
type_.deprecated = (
1289+
f"overload {type_} of function {defn.fullname} is deprecated: "
1290+
f"{deprecated}"
1291+
)
1292+
1293+
@staticmethod
1294+
def get_deprecated(expression: Expression) -> str | None:
1295+
if (
1296+
isinstance(expression, CallExpr)
1297+
and refers_to_fullname(expression.callee, DEPRECATED_TYPE_NAMES)
1298+
and (len(args := expression.args) >= 1)
1299+
and isinstance(deprecated := args[0], StrExpr)
1300+
):
1301+
return deprecated.value
1302+
return None
1303+
12621304
def process_overload_impl(self, defn: OverloadedFuncDef) -> None:
12631305
"""Set flags for an overload implementation.
12641306
@@ -1457,6 +1499,15 @@ def analyze_property_with_multi_part_definition(self, defn: OverloadedFuncDef) -
14571499
for i in reversed(deleted_items):
14581500
del items[i]
14591501

1502+
for item in items[1:]:
1503+
if isinstance(item, Decorator):
1504+
for d in item.decorators:
1505+
if (deprecated := self.get_deprecated(d)) is not None:
1506+
if isinstance(type_ := item.func.type, CallableType):
1507+
type_.deprecated = (
1508+
f"function {item.fullname} is deprecated: {deprecated}"
1509+
)
1510+
14601511
def add_function_to_symbol_table(self, func: FuncDef | OverloadedFuncDef) -> None:
14611512
if self.is_class_scope():
14621513
assert self.type is not None
@@ -1660,6 +1711,11 @@ def visit_decorator(self, dec: Decorator) -> None:
16601711
d.callee, DATACLASS_TRANSFORM_NAMES
16611712
):
16621713
dec.func.dataclass_transform_spec = self.parse_dataclass_transform_spec(d)
1714+
elif (deprecated := self.get_deprecated(d)) is not None:
1715+
if isinstance(type_ := dec.func.type, CallableType):
1716+
type_.deprecated = (
1717+
f"function {dec.fullname} is deprecated: {deprecated}"
1718+
)
16631719
elif not dec.var.is_property:
16641720
# We have seen a "non-trivial" decorator before seeing @property, if
16651721
# we will see a @property later, give an error, as we don't support this.
@@ -2081,6 +2137,8 @@ def analyze_class_decorator_common(
20812137
info.is_final = True
20822138
elif refers_to_fullname(decorator, TYPE_CHECK_ONLY_NAMES):
20832139
info.is_type_check_only = True
2140+
elif (deprecated := self.get_deprecated(decorator)) is not None:
2141+
info.deprecated = f"class {defn.fullname} is deprecated: {deprecated}"
20842142

20852143
def clean_up_bases_and_infer_type_variables(
20862144
self, defn: ClassDef, base_type_exprs: list[Expression], context: Context

0 commit comments

Comments
 (0)