Skip to content

Commit 28129f3

Browse files
Merge branch 'master' into weak-proxy
2 parents 652de32 + db67fac commit 28129f3

File tree

147 files changed

+1743
-1341
lines changed

Some content is hidden

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

147 files changed

+1743
-1341
lines changed

.github/workflows/test.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,6 @@ jobs:
3737
toxenv: py
3838
tox_extra_args: "-n 4"
3939
test_mypyc: true
40-
- name: Test suite with py39-windows-64
41-
python: '3.9'
42-
os: windows-latest
43-
toxenv: py39
44-
tox_extra_args: "-n 4"
4540
- name: Test suite with py310-ubuntu
4641
python: '3.10'
4742
os: ubuntu-24.04-arm
@@ -64,6 +59,11 @@ jobs:
6459
toxenv: py
6560
tox_extra_args: "-n 4"
6661
test_mypyc: true
62+
- name: Test suite with py313-windows-64
63+
python: '3.13'
64+
os: windows-latest
65+
toxenv: py
66+
tox_extra_args: "-n 4"
6767

6868
- name: Test suite with py314-dev-ubuntu
6969
python: '3.14-dev'

misc/typeshed_patches/0001-Partially-revert-Clean-up-argparse-hacks.patch

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
From 05f351f6a37fe8b73c698c348bf6aa5108363049 Mon Sep 17 00:00:00 2001
1+
From 84a9d586544a0408d4654f57f83a93cb048070fb Mon Sep 17 00:00:00 2001
22
From: Marc Mueller <[email protected]>
33
Date: Sat, 15 Feb 2025 20:11:06 +0100
44
Subject: [PATCH] Partially revert Clean up argparse hacks
@@ -8,15 +8,15 @@ Subject: [PATCH] Partially revert Clean up argparse hacks
88
1 file changed, 5 insertions(+), 3 deletions(-)
99

1010
diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi
11-
index 95ad6c7da..79e6cfde1 100644
11+
index b9fa31139..3c3ba116a 100644
1212
--- a/mypy/typeshed/stdlib/argparse.pyi
1313
+++ b/mypy/typeshed/stdlib/argparse.pyi
1414
@@ -2,7 +2,7 @@ import sys
1515
from _typeshed import SupportsWrite, sentinel
1616
from collections.abc import Callable, Generator, Iterable, Sequence
1717
from re import Pattern
18-
-from typing import IO, Any, ClassVar, Final, Generic, NoReturn, Protocol, TypeVar, overload
19-
+from typing import IO, Any, ClassVar, Final, Generic, NewType, NoReturn, Protocol, TypeVar, overload
18+
-from typing import IO, Any, ClassVar, Final, Generic, NoReturn, Protocol, TypeVar, overload, type_check_only
19+
+from typing import IO, Any, ClassVar, Final, Generic, NewType, NoReturn, Protocol, TypeVar, overload, type_check_only
2020
from typing_extensions import Self, TypeAlias, deprecated
2121

2222
__all__ = [
@@ -41,5 +41,5 @@ index 95ad6c7da..79e6cfde1 100644
4141
default: Any = ...,
4242
type: _ActionType = ...,
4343
--
44-
2.49.0
44+
2.50.1
4545

misc/typeshed_patches/0001-Revert-Remove-redundant-inheritances-from-Iterator.patch

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
From 363d69b366695fea117631d30c348e36b9a5a99d Mon Sep 17 00:00:00 2001
1+
From c217544146d36899d50e828d627652a0d8f63bb7 Mon Sep 17 00:00:00 2001
22
From: Marc Mueller <[email protected]>
33
Date: Sat, 21 Dec 2024 22:36:38 +0100
44
Subject: [PATCH] Revert Remove redundant inheritances from Iterator in
@@ -15,7 +15,7 @@ Subject: [PATCH] Revert Remove redundant inheritances from Iterator in
1515
7 files changed, 34 insertions(+), 34 deletions(-)
1616

1717
diff --git a/mypy/typeshed/stdlib/_asyncio.pyi b/mypy/typeshed/stdlib/_asyncio.pyi
18-
index 4544680cc..19a2d12d8 100644
18+
index ed56f33af..5253e967e 100644
1919
--- a/mypy/typeshed/stdlib/_asyncio.pyi
2020
+++ b/mypy/typeshed/stdlib/_asyncio.pyi
2121
@@ -1,6 +1,6 @@
@@ -36,10 +36,10 @@ index 4544680cc..19a2d12d8 100644
3636
@property
3737
def _exception(self) -> BaseException | None: ...
3838
diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi
39-
index ea77a730f..900c4c93f 100644
39+
index 0575be3c8..d9be595fe 100644
4040
--- a/mypy/typeshed/stdlib/builtins.pyi
4141
+++ b/mypy/typeshed/stdlib/builtins.pyi
42-
@@ -1170,7 +1170,7 @@ class frozenset(AbstractSet[_T_co]):
42+
@@ -1186,7 +1186,7 @@ class frozenset(AbstractSet[_T_co]):
4343
def __hash__(self) -> int: ...
4444
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
4545

@@ -48,7 +48,7 @@ index ea77a730f..900c4c93f 100644
4848
def __new__(cls, iterable: Iterable[_T], start: int = 0) -> Self: ...
4949
def __iter__(self) -> Self: ...
5050
def __next__(self) -> tuple[int, _T]: ...
51-
@@ -1366,7 +1366,7 @@ else:
51+
@@ -1380,7 +1380,7 @@ else:
5252

5353
exit: _sitebuiltins.Quitter
5454

@@ -57,7 +57,7 @@ index ea77a730f..900c4c93f 100644
5757
@overload
5858
def __new__(cls, function: None, iterable: Iterable[_T | None], /) -> Self: ...
5959
@overload
60-
@@ -1431,7 +1431,7 @@ license: _sitebuiltins._Printer
60+
@@ -1444,7 +1444,7 @@ license: _sitebuiltins._Printer
6161

6262
def locals() -> dict[str, Any]: ...
6363

@@ -66,7 +66,7 @@ index ea77a730f..900c4c93f 100644
6666
# 3.14 adds `strict` argument.
6767
if sys.version_info >= (3, 14):
6868
@overload
69-
@@ -1734,7 +1734,7 @@ def pow(base: _SupportsSomeKindOfPow, exp: complex, mod: None = None) -> complex
69+
@@ -1750,7 +1750,7 @@ def pow(base: _SupportsSomeKindOfPow, exp: complex, mod: None = None) -> complex
7070

7171
quit: _sitebuiltins.Quitter
7272

@@ -75,7 +75,7 @@ index ea77a730f..900c4c93f 100644
7575
@overload
7676
def __new__(cls, sequence: Reversible[_T], /) -> Iterator[_T]: ... # type: ignore[misc]
7777
@overload
78-
@@ -1795,7 +1795,7 @@ def vars(object: type, /) -> types.MappingProxyType[str, Any]: ...
78+
@@ -1814,7 +1814,7 @@ def vars(object: type, /) -> types.MappingProxyType[str, Any]: ...
7979
@overload
8080
def vars(object: Any = ..., /) -> dict[str, Any]: ...
8181

@@ -107,7 +107,7 @@ index 2c8e7109c..4ed0ab1d8 100644
107107
restkey: _T | None
108108
restval: str | Any | None
109109
diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi
110-
index 948b39ea1..1d5f9cf00 100644
110+
index 910d63814..eb942bc55 100644
111111
--- a/mypy/typeshed/stdlib/fileinput.pyi
112112
+++ b/mypy/typeshed/stdlib/fileinput.pyi
113113
@@ -1,8 +1,8 @@
@@ -116,12 +116,12 @@ index 948b39ea1..1d5f9cf00 100644
116116
-from collections.abc import Callable, Iterable
117117
+from collections.abc import Callable, Iterable, Iterator
118118
from types import GenericAlias, TracebackType
119-
-from typing import IO, Any, AnyStr, Generic, Literal, Protocol, overload
120-
+from typing import IO, Any, AnyStr, Literal, Protocol, overload
119+
-from typing import IO, Any, AnyStr, Generic, Literal, Protocol, overload, type_check_only
120+
+from typing import IO, Any, AnyStr, Literal, Protocol, overload, type_check_only
121121
from typing_extensions import Self, TypeAlias
122122

123123
__all__ = [
124-
@@ -104,7 +104,7 @@ def fileno() -> int: ...
124+
@@ -105,7 +105,7 @@ def fileno() -> int: ...
125125
def isfirstline() -> bool: ...
126126
def isstdin() -> bool: ...
127127

@@ -307,10 +307,10 @@ index b79f9e773..f276372d0 100644
307307
def __iter__(self) -> Self: ...
308308
def next(self, timeout: float | None = None) -> _T: ...
309309
diff --git a/mypy/typeshed/stdlib/sqlite3/__init__.pyi b/mypy/typeshed/stdlib/sqlite3/__init__.pyi
310-
index 5d3c2330b..ab783dbde 100644
310+
index bcfea3a13..5a659deac 100644
311311
--- a/mypy/typeshed/stdlib/sqlite3/__init__.pyi
312312
+++ b/mypy/typeshed/stdlib/sqlite3/__init__.pyi
313-
@@ -399,7 +399,7 @@ class Connection:
313+
@@ -405,7 +405,7 @@ class Connection:
314314
self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None, /
315315
) -> Literal[False]: ...
316316

@@ -320,5 +320,5 @@ index 5d3c2330b..ab783dbde 100644
320320
@property
321321
def connection(self) -> Connection: ...
322322
--
323-
2.49.0
323+
2.50.1
324324

mypy/checker.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
730730
assert isinstance(item, Decorator)
731731
item_type = self.extract_callable_type(item.var.type, item)
732732
if item_type is not None:
733-
item_type.definition = item
733+
item_type.definition = item.func
734734
item_types.append(item_type)
735735
if item_types:
736736
defn.type = Overloaded(item_types)
@@ -832,8 +832,10 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
832832
# At this point we should have set the impl already, and all remaining
833833
# items are decorators
834834

835-
if self.msg.errors.file in self.msg.errors.ignored_files or (
836-
self.is_typeshed_stub and self.options.test_env
835+
if (
836+
self.options.ignore_errors
837+
or self.msg.errors.file in self.msg.errors.ignored_files
838+
or (self.is_typeshed_stub and self.options.test_env)
837839
):
838840
# This is a little hacky, however, the quadratic check here is really expensive, this
839841
# method has no side effects, so we should skip it if we aren't going to report
@@ -1444,7 +1446,19 @@ def check_func_def(
14441446
# TODO: Find a way of working around this limitation
14451447
if _is_empty_generator_function(item) or len(expanded) >= 2:
14461448
self.binder.suppress_unreachable_warnings()
1447-
self.accept(item.body)
1449+
# When checking a third-party library, we can skip function body,
1450+
# if during semantic analysis we found that there are no attributes
1451+
# defined via self here.
1452+
if (
1453+
not (
1454+
self.options.ignore_errors
1455+
or self.msg.errors.file in self.msg.errors.ignored_files
1456+
)
1457+
or self.options.preserve_asts
1458+
or not isinstance(defn, FuncDef)
1459+
or defn.has_self_attr_def
1460+
):
1461+
self.accept(item.body)
14481462
unreachable = self.binder.is_unreachable()
14491463
if new_frame is not None:
14501464
self.binder.pop_frame(True, 0)
@@ -2127,6 +2141,9 @@ def check_method_override(
21272141
21282142
Return a list of base classes which contain an attribute with the method name.
21292143
"""
2144+
if self.options.ignore_errors or self.msg.errors.file in self.msg.errors.ignored_files:
2145+
# Method override checks may be expensive, so skip them in third-party libraries.
2146+
return None
21302147
# Check against definitions in base classes.
21312148
check_override_compatibility = (
21322149
defn.name not in ("__init__", "__new__", "__init_subclass__", "__post_init__")

mypy/checkexpr.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2934,7 +2934,7 @@ def infer_overload_return_type(
29342934
if not args_contain_any:
29352935
self.chk.store_types(m)
29362936
if isinstance(infer_type, ProperType) and isinstance(infer_type, CallableType):
2937-
self.chk.check_deprecated(infer_type.definition, context)
2937+
self.chk.warn_deprecated(infer_type.definition, context)
29382938
return ret_type, infer_type
29392939
p_infer_type = get_proper_type(infer_type)
29402940
if isinstance(p_infer_type, CallableType):
@@ -2975,7 +2975,7 @@ def infer_overload_return_type(
29752975
if isinstance(inferred_callable, ProperType) and isinstance(
29762976
inferred_callable, CallableType
29772977
):
2978-
self.chk.check_deprecated(inferred_callable.definition, context)
2978+
self.chk.warn_deprecated(inferred_callable.definition, context)
29792979
return return_types[0], inferred_types[0]
29802980

29812981
def overload_erased_call_targets(
@@ -5350,9 +5350,9 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
53505350
# an error, but returns the TypedDict type that matches the literal it found
53515351
# that would cause a second error when that TypedDict type is returned upstream
53525352
# to avoid the second error, we always return TypedDict type that was requested
5353-
typeddict_contexts = self.find_typeddict_context(self.type_context[-1], e)
5353+
typeddict_contexts, exhaustive = self.find_typeddict_context(self.type_context[-1], e)
53545354
if typeddict_contexts:
5355-
if len(typeddict_contexts) == 1:
5355+
if len(typeddict_contexts) == 1 and exhaustive:
53565356
return self.check_typeddict_literal_in_context(e, typeddict_contexts[0])
53575357
# Multiple items union, check if at least one of them matches cleanly.
53585358
for typeddict_context in typeddict_contexts:
@@ -5363,7 +5363,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
53635363
self.chk.store_types(tmap)
53645364
return ret_type
53655365
# No item matched without an error, so we can't unambiguously choose the item.
5366-
self.msg.typeddict_context_ambiguous(typeddict_contexts, e)
5366+
if exhaustive:
5367+
self.msg.typeddict_context_ambiguous(typeddict_contexts, e)
53675368

53685369
# fast path attempt
53695370
dt = self.fast_dict_type(e)
@@ -5425,22 +5426,29 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
54255426

54265427
def find_typeddict_context(
54275428
self, context: Type | None, dict_expr: DictExpr
5428-
) -> list[TypedDictType]:
5429+
) -> tuple[list[TypedDictType], bool]:
5430+
"""Extract `TypedDict` members of the enclosing context.
5431+
5432+
Returns:
5433+
a 2-tuple, (found_candidates, is_exhaustive)
5434+
"""
54295435
context = get_proper_type(context)
54305436
if isinstance(context, TypedDictType):
5431-
return [context]
5437+
return [context], True
54325438
elif isinstance(context, UnionType):
54335439
items = []
5440+
exhaustive = True
54345441
for item in context.items:
5435-
item_contexts = self.find_typeddict_context(item, dict_expr)
5442+
item_contexts, item_exhaustive = self.find_typeddict_context(item, dict_expr)
54365443
for item_context in item_contexts:
54375444
if self.match_typeddict_call_with_dict(
54385445
item_context, dict_expr.items, dict_expr
54395446
):
54405447
items.append(item_context)
5441-
return items
5448+
exhaustive = exhaustive and item_exhaustive
5449+
return items, exhaustive
54425450
# No TypedDict type in context.
5443-
return []
5451+
return [], False
54445452

54455453
def visit_lambda_expr(self, e: LambdaExpr) -> Type:
54465454
"""Type check lambda expression."""

mypy/fastparse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,7 @@ def visit_index_expr(self, e: IndexExpr) -> None:
22342234
pass
22352235

22362236
def visit_member_expr(self, e: MemberExpr) -> None:
2237-
if self.lvalue:
2237+
if self.lvalue and isinstance(e.expr, NameExpr):
22382238
self.found = True
22392239

22402240

mypy/fixup.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
Overloaded,
3030
Parameters,
3131
ParamSpecType,
32+
ProperType,
3233
TupleType,
3334
TypeAliasType,
3435
TypedDictType,
@@ -177,6 +178,11 @@ def visit_overloaded_func_def(self, o: OverloadedFuncDef) -> None:
177178
item.accept(self)
178179
if o.impl:
179180
o.impl.accept(self)
181+
if isinstance(o.type, Overloaded):
182+
# For error messages we link the original definition for each item.
183+
for typ, item in zip(o.type.items, o.items):
184+
if isinstance(item, Decorator):
185+
typ.definition = item.func
180186

181187
def visit_decorator(self, d: Decorator) -> None:
182188
if self.current_info is not None:
@@ -187,6 +193,8 @@ def visit_decorator(self, d: Decorator) -> None:
187193
d.var.accept(self)
188194
for node in d.decorators:
189195
node.accept(self)
196+
if isinstance(d.var.type, ProperType) and isinstance(d.var.type, CallableType):
197+
d.var.type.definition = d.func
190198

191199
def visit_class_def(self, c: ClassDef) -> None:
192200
for v in c.type_vars:

mypy/fscache.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,12 @@ def init_under_package_root(self, path: str) -> bool:
117117
if not stat.S_ISDIR(st.st_mode):
118118
return False
119119
ok = False
120-
drive, path = os.path.splitdrive(path) # Ignore Windows drive name
120+
121+
# skip if on a different drive
122+
current_drive, _ = os.path.splitdrive(os.getcwd())
123+
drive, _ = os.path.splitdrive(path)
124+
if drive != current_drive:
125+
return False
121126
if os.path.isabs(path):
122127
path = os.path.relpath(path)
123128
path = os.path.normpath(path)

mypy/main.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,10 +1086,6 @@ def add_invertible_flag(
10861086
internals_group.add_argument(
10871087
"--old-type-inference", action="store_true", help=argparse.SUPPRESS
10881088
)
1089-
# Deprecated reverse variant of the above.
1090-
internals_group.add_argument(
1091-
"--new-type-inference", action="store_true", help=argparse.SUPPRESS
1092-
)
10931089
internals_group.add_argument(
10941090
"--disable-expression-cache", action="store_true", help=argparse.SUPPRESS
10951091
)
@@ -1507,12 +1503,6 @@ def set_strict_flags() -> None:
15071503
if options.logical_deps:
15081504
options.cache_fine_grained = True
15091505

1510-
if options.new_type_inference:
1511-
print(
1512-
"Warning: --new-type-inference flag is deprecated;"
1513-
" new type inference algorithm is already enabled by default"
1514-
)
1515-
15161506
if options.strict_concatenate and not strict_option_set:
15171507
print("Warning: --strict-concatenate is deprecated; use --extra-checks instead")
15181508

mypy/messages.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ def maybe_note_about_special_args(self, callee: CallableType, context: Context)
10031003
if self.prefer_simple_messages():
10041004
return
10051005
# https://github.com/python/mypy/issues/11309
1006-
first_arg = callee.def_extras.get("first_arg")
1006+
first_arg = get_first_arg(callee)
10071007
if first_arg and first_arg not in {"self", "cls", "mcs"}:
10081008
self.note(
10091009
"Looks like the first special argument in a method "
@@ -3007,7 +3007,7 @@ def [T <: int] f(self, x: int, y: T) -> None
30073007
s = definition_arg_names[0] + s
30083008
s = f"{tp.definition.name}({s})"
30093009
elif tp.name:
3010-
first_arg = tp.def_extras.get("first_arg")
3010+
first_arg = get_first_arg(tp)
30113011
if first_arg:
30123012
if s:
30133013
s = ", " + s
@@ -3050,6 +3050,12 @@ def [T <: int] f(self, x: int, y: T) -> None
30503050
return f"def {s}"
30513051

30523052

3053+
def get_first_arg(tp: CallableType) -> str | None:
3054+
if not isinstance(tp.definition, FuncDef) or not tp.definition.info or tp.definition.is_static:
3055+
return None
3056+
return tp.definition.original_first_arg
3057+
3058+
30533059
def variance_string(variance: int) -> str:
30543060
if variance == COVARIANT:
30553061
return "covariant"

0 commit comments

Comments
 (0)