Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 38f311a

Browse files
Merge branch 'master' into untyped-def-end-line
2 parents 5a7c0ec + b207550 commit 38f311a

188 files changed

Lines changed: 5365 additions & 895 deletions

File tree

Some content is hidden

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

docs/source/command_line.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,17 @@ in error messages.
747747

748748
main.py:12:9: error: Unsupported operand types for / ("int" and "str")
749749

750+
.. option:: --show-error-code-links
751+
752+
This flag will also display a link to error code documentation, anchored to the error code reported by mypy.
753+
The corresponding error code will be highlighted within the documentation page.
754+
If we enable this flag, the error message now looks like this::
755+
756+
main.py:3: error: Unsupported operand types for - ("int" and "str") [operator]
757+
main.py:3: note: See 'https://mypy.rtfd.io/en/stable/_refs.html#code-operator' for more info
758+
759+
760+
750761
.. option:: --show-error-end
751762

752763
This flag will make mypy show not just that start position where

docs/source/config_file.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,13 @@ These options may only be set in the global section (``[mypy]``).
787787

788788
Shows column numbers in error messages.
789789

790+
.. confval:: show_error_code_links
791+
792+
:type: boolean
793+
:default: False
794+
795+
Shows documentation link to corresponding error code.
796+
790797
.. confval:: hide_error_codes
791798

792799
:type: boolean

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-requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# NOTE: this needs to be kept in sync with the "requires" list in pyproject.toml
2-
typing_extensions>=4.1.0
2+
# and the pins in setup.py
3+
typing_extensions>=4.6.0
34
mypy_extensions>=1.0.0
45
tomli>=1.1.0; python_version<'3.11'

mypy/build.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
import mypy.semanal_main
4646
from mypy.checker import TypeChecker
47+
from mypy.error_formatter import OUTPUT_CHOICES, ErrorFormatter
4748
from mypy.errors import CompileError, ErrorInfo, Errors, report_internal_error
4849
from mypy.graph_utils import prepare_sccs, strongly_connected_components, topsort
4950
from mypy.indirection import TypeIndirectionVisitor
@@ -253,6 +254,7 @@ def _build(
253254
plugin=plugin,
254255
plugins_snapshot=snapshot,
255256
errors=errors,
257+
error_formatter=None if options.output is None else OUTPUT_CHOICES.get(options.output),
256258
flush_errors=flush_errors,
257259
fscache=fscache,
258260
stdout=stdout,
@@ -607,6 +609,7 @@ def __init__(
607609
fscache: FileSystemCache,
608610
stdout: TextIO,
609611
stderr: TextIO,
612+
error_formatter: ErrorFormatter | None = None,
610613
) -> None:
611614
self.stats: dict[str, Any] = {} # Values are ints or floats
612615
self.stdout = stdout
@@ -615,6 +618,7 @@ def __init__(
615618
self.data_dir = data_dir
616619
self.errors = errors
617620
self.errors.set_ignore_prefix(ignore_prefix)
621+
self.error_formatter = error_formatter
618622
self.search_paths = search_paths
619623
self.source_set = source_set
620624
self.reports = reports
@@ -3463,11 +3467,8 @@ def process_stale_scc(graph: Graph, scc: list[str], manager: BuildManager) -> No
34633467
for id in stale:
34643468
graph[id].transitive_error = True
34653469
for id in stale:
3466-
manager.flush_errors(
3467-
manager.errors.simplify_path(graph[id].xpath),
3468-
manager.errors.file_messages(graph[id].xpath),
3469-
False,
3470-
)
3470+
errors = manager.errors.file_messages(graph[id].xpath, formatter=manager.error_formatter)
3471+
manager.flush_errors(manager.errors.simplify_path(graph[id].xpath), errors, False)
34713472
graph[id].write_cache()
34723473
graph[id].mark_as_rechecked()
34733474

mypy/checker.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from typing_extensions import TypeAlias as _TypeAlias
2727

2828
import mypy.checkexpr
29-
from mypy import errorcodes as codes, message_registry, nodes, operators
29+
from mypy import errorcodes as codes, join, message_registry, nodes, operators
3030
from mypy.binder import ConditionalTypeBinder, Frame, get_declaration
3131
from mypy.checkmember import (
3232
MemberContext,
@@ -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,
@@ -680,6 +681,11 @@ def extract_callable_type(self, inner_type: Type | None, ctx: Context) -> Callab
680681
inner_type = get_proper_type(inner_type)
681682
outer_type: CallableType | None = None
682683
if inner_type is not None and not isinstance(inner_type, AnyType):
684+
if isinstance(inner_type, TypeType):
685+
if isinstance(inner_type.item, Instance):
686+
inner_type = expand_type_by_instance(
687+
type_object_type(inner_type.item.type, self.named_type), inner_type.item
688+
)
683689
if isinstance(inner_type, CallableType):
684690
outer_type = inner_type
685691
elif isinstance(inner_type, Instance):
@@ -698,6 +704,21 @@ def extract_callable_type(self, inner_type: Type | None, ctx: Context) -> Callab
698704
)
699705
if isinstance(inner_call, CallableType):
700706
outer_type = inner_call
707+
elif isinstance(inner_type, UnionType):
708+
union_type = make_simplified_union(inner_type.items)
709+
if isinstance(union_type, UnionType):
710+
items = []
711+
for item in union_type.items:
712+
callable_item = self.extract_callable_type(item, ctx)
713+
if callable_item is None:
714+
break
715+
items.append(callable_item)
716+
else:
717+
joined_type = get_proper_type(join.join_type_list(items))
718+
if isinstance(joined_type, CallableType):
719+
outer_type = joined_type
720+
else:
721+
return self.extract_callable_type(union_type, ctx)
701722
if outer_type is None:
702723
self.msg.not_callable(inner_type, ctx)
703724
return outer_type
@@ -1003,7 +1024,7 @@ def _visit_func_def(self, defn: FuncDef) -> None:
10031024
"""Type check a function definition."""
10041025
self.check_func_item(defn, name=defn.name)
10051026
if defn.info:
1006-
if not defn.is_dynamic() and not defn.is_overload and not defn.is_decorated:
1027+
if not defn.is_overload and not defn.is_decorated:
10071028
# If the definition is the implementation for an
10081029
# overload, the legality of the override has already
10091030
# been typechecked, and decorated methods will be
@@ -1912,9 +1933,17 @@ def check_method_override(
19121933
Return a list of base classes which contain an attribute with the method name.
19131934
"""
19141935
# Check against definitions in base classes.
1936+
check_override_compatibility = defn.name not in (
1937+
"__init__",
1938+
"__new__",
1939+
"__init_subclass__",
1940+
"__post_init__",
1941+
) and (self.options.check_untyped_defs or not defn.is_dynamic())
19151942
found_method_base_classes: list[TypeInfo] = []
19161943
for base in defn.info.mro[1:]:
1917-
result = self.check_method_or_accessor_override_for_base(defn, base)
1944+
result = self.check_method_or_accessor_override_for_base(
1945+
defn, base, check_override_compatibility
1946+
)
19181947
if result is None:
19191948
# Node was deferred, we will have another attempt later.
19201949
return None
@@ -1923,7 +1952,10 @@ def check_method_override(
19231952
return found_method_base_classes
19241953

19251954
def check_method_or_accessor_override_for_base(
1926-
self, defn: FuncDef | OverloadedFuncDef | Decorator, base: TypeInfo
1955+
self,
1956+
defn: FuncDef | OverloadedFuncDef | Decorator,
1957+
base: TypeInfo,
1958+
check_override_compatibility: bool,
19271959
) -> bool | None:
19281960
"""Check if method definition is compatible with a base class.
19291961
@@ -1944,10 +1976,8 @@ def check_method_or_accessor_override_for_base(
19441976
if defn.is_final:
19451977
self.check_if_final_var_override_writable(name, base_attr.node, defn)
19461978
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
1979+
if check_override_compatibility:
1980+
# Check compatibility of the override signature
19511981
# (__init__, __new__, __init_subclass__ are special).
19521982
if self.check_method_override_for_base_with_name(defn, name, base):
19531983
return None
@@ -2374,7 +2404,7 @@ def visit_class_def(self, defn: ClassDef) -> None:
23742404
self.allow_abstract_call = old_allow_abstract_call
23752405
# TODO: Apply the sig to the actual TypeInfo so we can handle decorators
23762406
# that completely swap out the type. (e.g. Callable[[Type[A]], Type[B]])
2377-
if typ.defn.type_vars:
2407+
if typ.defn.type_vars and typ.defn.type_args is None:
23782408
for base_inst in typ.bases:
23792409
for base_tvar, base_decl_tvar in zip(
23802410
base_inst.args, base_inst.type.defn.type_vars
@@ -2396,6 +2426,7 @@ def visit_class_def(self, defn: ClassDef) -> None:
23962426
self.check_protocol_variance(defn)
23972427
if not defn.has_incompatible_baseclass and defn.info.is_enum:
23982428
self.check_enum(defn)
2429+
infer_class_variances(defn.info)
23992430

24002431
def check_final_deletable(self, typ: TypeInfo) -> None:
24012432
# These checks are only for mypyc. Only perform some checks that are easier
@@ -2566,6 +2597,9 @@ def check_protocol_variance(self, defn: ClassDef) -> None:
25662597
if they are actually covariant/contravariant, since this may break
25672598
transitivity of subtyping, see PEP 544.
25682599
"""
2600+
if defn.type_args is not None:
2601+
# Using new-style syntax (PEP 695), so variance will be inferred
2602+
return
25692603
info = defn.info
25702604
object_type = Instance(info.mro[-1], [])
25712605
tvars = info.defn.type_vars
@@ -3412,8 +3446,8 @@ def check_final(self, s: AssignmentStmt | OperatorAssignmentStmt | AssignmentExp
34123446
if (
34133447
lv.node.final_unset_in_class
34143448
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.
3449+
and not self.is_stub # It is OK to skip initializer in stub files.
3450+
and
34173451
# Avoid extra error messages, if there is no type in Final[...],
34183452
# then we already reported the error about missing r.h.s.
34193453
isinstance(s, AssignmentStmt)
@@ -4460,7 +4494,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
44604494
is_lambda = isinstance(self.scope.top_function(), LambdaExpr)
44614495
if isinstance(return_type, UninhabitedType):
44624496
# Avoid extra error messages for failed inference in lambdas
4463-
if not is_lambda or not return_type.ambiguous:
4497+
if not is_lambda and not return_type.ambiguous:
44644498
self.fail(message_registry.NO_RETURN_EXPECTED, s)
44654499
return
44664500

mypy/checkexpr.py

Lines changed: 23 additions & 21 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

@@ -5223,15 +5223,16 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type:
52235223
self.chk.return_types.append(AnyType(TypeOfAny.special_form))
52245224
# Type check everything in the body except for the final return
52255225
# statement (it can contain tuple unpacking before return).
5226-
with self.chk.scope.push_function(e):
5226+
with self.chk.binder.frame_context(
5227+
can_skip=True, fall_through=0
5228+
), self.chk.scope.push_function(e):
52275229
# Lambdas can have more than one element in body,
52285230
# when we add "fictional" AssigmentStatement nodes, like in:
52295231
# `lambda (a, b): a`
52305232
for stmt in e.body.body[:-1]:
52315233
stmt.accept(self.chk)
52325234
# Only type check the return expression, not the return statement.
5233-
# This is important as otherwise the following statements would be
5234-
# considered unreachable. There's no useful type context.
5235+
# There's no useful type context.
52355236
ret_type = self.accept(e.expr(), allow_none_return=True)
52365237
fallback = self.named_type("builtins.function")
52375238
self.chk.return_types.pop()
@@ -5243,7 +5244,8 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type:
52435244
self.chk.check_func_item(e, type_override=type_override)
52445245
if not self.chk.has_type(e.expr()):
52455246
# TODO: return expression must be accepted before exiting function scope.
5246-
self.accept(e.expr(), allow_none_return=True)
5247+
with self.chk.binder.frame_context(can_skip=True, fall_through=0):
5248+
self.accept(e.expr(), allow_none_return=True)
52475249
ret_type = self.chk.lookup_type(e.expr())
52485250
self.chk.return_types.pop()
52495251
return replace_callable_return_type(inferred_type, ret_type)

mypy/checkmember.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:
654654
analyze_descriptor_access(
655655
descriptor_type, mx.copy_modified(original_type=original_type)
656656
)
657-
for original_type in instance_type.items
657+
for original_type in instance_type.relevant_items()
658658
]
659659
)
660660
elif not isinstance(descriptor_type, Instance):

mypy/copytype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def visit_none_type(self, t: NoneType) -> ProperType:
5353
return self.copy_common(t, NoneType())
5454

5555
def visit_uninhabited_type(self, t: UninhabitedType) -> ProperType:
56-
dup = UninhabitedType(t.is_noreturn)
56+
dup = UninhabitedType()
5757
dup.ambiguous = t.ambiguous
5858
return self.copy_common(t, dup)
5959

0 commit comments

Comments
 (0)