Skip to content

Commit 6b933ef

Browse files
authored
Merge branch 'master' into fix-typeis-for-types-with-type-params-in-unions
2 parents 431d722 + 43a605f commit 6b933ef

File tree

164 files changed

+4806
-820
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+4806
-820
lines changed

docs/source/error_code_list.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,29 @@ annotations in an unchecked function:
11711171
Note that mypy will still exit with return code ``0``, since such behaviour is
11721172
specified by :pep:`484`.
11731173

1174+
.. _code-prop-decorator:
1175+
1176+
Decorator preceding property not supported [prop-decorator]
1177+
-----------------------------------------------------------
1178+
1179+
Mypy does not yet support analysis of decorators that precede the property
1180+
decorator. If the decorator does not preserve the declared type of the property,
1181+
mypy will not infer the correct type for the declaration. If the decorator cannot
1182+
be moved after the ``@property`` decorator, then you must use a type ignore
1183+
comment:
1184+
1185+
.. code-block:: python
1186+
1187+
class MyClass
1188+
@special # type: ignore[prop-decorator]
1189+
@property
1190+
def magic(self) -> str:
1191+
return "xyzzy"
1192+
1193+
.. note::
1194+
1195+
For backward compatibility, this error code is a subcode of the generic ``[misc]`` code.
1196+
11741197
.. _code-syntax:
11751198

11761199
Report syntax errors [syntax]

misc/sync-typeshed.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ def update_typeshed(typeshed_dir: str, commit: str | None) -> str:
5151
# Remove existing stubs.
5252
shutil.rmtree(stdlib_dir)
5353
# Copy new stdlib stubs.
54-
shutil.copytree(os.path.join(typeshed_dir, "stdlib"), stdlib_dir)
54+
shutil.copytree(
55+
os.path.join(typeshed_dir, "stdlib"), stdlib_dir, ignore=shutil.ignore_patterns("@tests")
56+
)
5557
shutil.copy(os.path.join(typeshed_dir, "LICENSE"), os.path.join("mypy", "typeshed"))
5658
return commit
5759

mypy/checker.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
from mypy.state import state
147147
from mypy.subtypes import (
148148
find_member,
149+
infer_class_variances,
149150
is_callable_compatible,
150151
is_equivalent,
151152
is_more_precise,
@@ -1003,7 +1004,7 @@ def _visit_func_def(self, defn: FuncDef) -> None:
10031004
"""Type check a function definition."""
10041005
self.check_func_item(defn, name=defn.name)
10051006
if defn.info:
1006-
if not defn.is_dynamic() and not defn.is_overload and not defn.is_decorated:
1007+
if not defn.is_overload and not defn.is_decorated:
10071008
# If the definition is the implementation for an
10081009
# overload, the legality of the override has already
10091010
# been typechecked, and decorated methods will be
@@ -1912,9 +1913,17 @@ def check_method_override(
19121913
Return a list of base classes which contain an attribute with the method name.
19131914
"""
19141915
# Check against definitions in base classes.
1916+
check_override_compatibility = defn.name not in (
1917+
"__init__",
1918+
"__new__",
1919+
"__init_subclass__",
1920+
"__post_init__",
1921+
) and (self.options.check_untyped_defs or not defn.is_dynamic())
19151922
found_method_base_classes: list[TypeInfo] = []
19161923
for base in defn.info.mro[1:]:
1917-
result = self.check_method_or_accessor_override_for_base(defn, base)
1924+
result = self.check_method_or_accessor_override_for_base(
1925+
defn, base, check_override_compatibility
1926+
)
19181927
if result is None:
19191928
# Node was deferred, we will have another attempt later.
19201929
return None
@@ -1923,7 +1932,10 @@ def check_method_override(
19231932
return found_method_base_classes
19241933

19251934
def check_method_or_accessor_override_for_base(
1926-
self, defn: FuncDef | OverloadedFuncDef | Decorator, base: TypeInfo
1935+
self,
1936+
defn: FuncDef | OverloadedFuncDef | Decorator,
1937+
base: TypeInfo,
1938+
check_override_compatibility: bool,
19271939
) -> bool | None:
19281940
"""Check if method definition is compatible with a base class.
19291941
@@ -1944,10 +1956,8 @@ def check_method_or_accessor_override_for_base(
19441956
if defn.is_final:
19451957
self.check_if_final_var_override_writable(name, base_attr.node, defn)
19461958
found_base_method = True
1947-
1948-
# Check the type of override.
1949-
if name not in ("__init__", "__new__", "__init_subclass__", "__post_init__"):
1950-
# Check method override
1959+
if check_override_compatibility:
1960+
# Check compatibility of the override signature
19511961
# (__init__, __new__, __init_subclass__ are special).
19521962
if self.check_method_override_for_base_with_name(defn, name, base):
19531963
return None
@@ -2374,7 +2384,7 @@ def visit_class_def(self, defn: ClassDef) -> None:
23742384
self.allow_abstract_call = old_allow_abstract_call
23752385
# TODO: Apply the sig to the actual TypeInfo so we can handle decorators
23762386
# that completely swap out the type. (e.g. Callable[[Type[A]], Type[B]])
2377-
if typ.defn.type_vars:
2387+
if typ.defn.type_vars and typ.defn.type_args is None:
23782388
for base_inst in typ.bases:
23792389
for base_tvar, base_decl_tvar in zip(
23802390
base_inst.args, base_inst.type.defn.type_vars
@@ -2396,6 +2406,7 @@ def visit_class_def(self, defn: ClassDef) -> None:
23962406
self.check_protocol_variance(defn)
23972407
if not defn.has_incompatible_baseclass and defn.info.is_enum:
23982408
self.check_enum(defn)
2409+
infer_class_variances(defn.info)
23992410

24002411
def check_final_deletable(self, typ: TypeInfo) -> None:
24012412
# These checks are only for mypyc. Only perform some checks that are easier
@@ -2566,6 +2577,9 @@ def check_protocol_variance(self, defn: ClassDef) -> None:
25662577
if they are actually covariant/contravariant, since this may break
25672578
transitivity of subtyping, see PEP 544.
25682579
"""
2580+
if defn.type_args is not None:
2581+
# Using new-style syntax (PEP 695), so variance will be inferred
2582+
return
25692583
info = defn.info
25702584
object_type = Instance(info.mro[-1], [])
25712585
tvars = info.defn.type_vars
@@ -3412,8 +3426,8 @@ def check_final(self, s: AssignmentStmt | OperatorAssignmentStmt | AssignmentExp
34123426
if (
34133427
lv.node.final_unset_in_class
34143428
and not lv.node.final_set_in_init
3415-
and not self.is_stub
3416-
and # It is OK to skip initializer in stub files.
3429+
and not self.is_stub # It is OK to skip initializer in stub files.
3430+
and
34173431
# Avoid extra error messages, if there is no type in Final[...],
34183432
# then we already reported the error about missing r.h.s.
34193433
isinstance(s, AssignmentStmt)

mypy/checkexpr.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,14 +1229,14 @@ def apply_function_plugin(
12291229
assert callback is not None # Assume that caller ensures this
12301230
return callback(
12311231
FunctionContext(
1232-
formal_arg_types,
1233-
formal_arg_kinds,
1234-
callee.arg_names,
1235-
formal_arg_names,
1236-
callee.ret_type,
1237-
formal_arg_exprs,
1238-
context,
1239-
self.chk,
1232+
arg_types=formal_arg_types,
1233+
arg_kinds=formal_arg_kinds,
1234+
callee_arg_names=callee.arg_names,
1235+
arg_names=formal_arg_names,
1236+
default_return_type=callee.ret_type,
1237+
args=formal_arg_exprs,
1238+
context=context,
1239+
api=self.chk,
12401240
)
12411241
)
12421242
else:
@@ -1246,15 +1246,15 @@ def apply_function_plugin(
12461246
object_type = get_proper_type(object_type)
12471247
return method_callback(
12481248
MethodContext(
1249-
object_type,
1250-
formal_arg_types,
1251-
formal_arg_kinds,
1252-
callee.arg_names,
1253-
formal_arg_names,
1254-
callee.ret_type,
1255-
formal_arg_exprs,
1256-
context,
1257-
self.chk,
1249+
type=object_type,
1250+
arg_types=formal_arg_types,
1251+
arg_kinds=formal_arg_kinds,
1252+
callee_arg_names=callee.arg_names,
1253+
arg_names=formal_arg_names,
1254+
default_return_type=callee.ret_type,
1255+
args=formal_arg_exprs,
1256+
context=context,
1257+
api=self.chk,
12581258
)
12591259
)
12601260

mypy/dmypy_server.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ def cmd_recheck(
383383
removals = set(remove)
384384
sources = [s for s in sources if s.path and s.path not in removals]
385385
if update:
386+
# Sort list of file updates by extension, so *.pyi files are first.
387+
update.sort(key=lambda f: os.path.splitext(f)[1], reverse=True)
388+
386389
known = {s.path for s in sources if s.path}
387390
added = [p for p in update if p not in known]
388391
try:

mypy/errorcodes.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ def __hash__(self) -> int:
262262
default_enabled=False,
263263
)
264264

265-
266265
# Syntax errors are often blocking.
267266
SYNTAX: Final[ErrorCode] = ErrorCode("syntax", "Report syntax errors", "General")
268267

@@ -281,6 +280,13 @@ def __hash__(self) -> int:
281280
sub_code_of=MISC,
282281
)
283282

283+
PROPERTY_DECORATOR = ErrorCode(
284+
"prop-decorator",
285+
"Decorators on top of @property are not supported",
286+
"General",
287+
sub_code_of=MISC,
288+
)
289+
284290
NARROWED_TYPE_NOT_SUBTYPE: Final[ErrorCode] = ErrorCode(
285291
"narrowed-type-not-subtype",
286292
"Warn if a TypeIs function's narrowed type is not a subtype of the original type",

0 commit comments

Comments
 (0)