Skip to content

Commit ad58d83

Browse files
authored
Merge branch 'master' into bugfix/gh-19186-typevar-default-crash
2 parents 26c79d5 + 70d7881 commit ad58d83

123 files changed

Lines changed: 4570 additions & 2069 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.

.github/workflows/mypy_primer.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
runs-on: ubuntu-latest
2929
strategy:
3030
matrix:
31-
shard-index: [0, 1, 2, 3, 4]
31+
shard-index: [0, 1, 2, 3, 4, 5]
3232
fail-fast: false
3333
timeout-minutes: 60
3434
steps:
@@ -63,7 +63,7 @@ jobs:
6363
mypy_primer \
6464
--repo mypy_to_test \
6565
--new $GITHUB_SHA --old base_commit \
66-
--num-shards 5 --shard-index ${{ matrix.shard-index }} \
66+
--num-shards 6 --shard-index ${{ matrix.shard-index }} \
6767
--debug \
6868
--additional-flags="--debug-serialize" \
6969
--output concise \

CHANGELOG.md

Lines changed: 177 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,70 @@
22

33
## Next Release
44

5-
### Remove Support for targeting Python 3.8
5+
## Mypy 1.17
66

7-
Mypy now requires `--python-version 3.9` or greater. Support for only Python 3.8 is
8-
fully removed now. Given an unsupported version, mypy will default to the oldest
9-
supported one, currently 3.9.
7+
We’ve just uploaded mypy 1.17 to the Python Package Index ([PyPI](https://pypi.org/project/mypy/)).
8+
Mypy is a static type checker for Python. This release includes new features and bug fixes.
9+
You can install it as follows:
10+
11+
python3 -m pip install -U mypy
12+
13+
You can read the full documentation for this release on [Read the Docs](http://mypy.readthedocs.io).
14+
15+
### Optionally Check That Match Is Exhaustive
16+
17+
Mypy can now optionally generate an error if a match statement does not
18+
match exhaustively, without having to use `assert_never(...)`. Enable
19+
this by using `--enable-error-code exhaustive-match`.
20+
21+
Example:
22+
23+
```python
24+
# mypy: enable-error-code=exhaustive-match
25+
26+
import enum
27+
28+
class Color(enum.Enum):
29+
RED = 1
30+
BLUE = 2
31+
32+
def show_color(val: Color) -> None:
33+
# error: Unhandled case for values of type "Literal[Color.BLUE]"
34+
match val:
35+
case Color.RED:
36+
print("red")
37+
```
38+
39+
This feature was contributed by Donal Burns (PR [19144](https://github.com/python/mypy/pull/19144)).
40+
41+
### Further Improvements to Attribute Resolution
42+
43+
This release includes additional improvements to how attribute types
44+
and kinds are resolved. These fix many bugs and overall improve consistency.
45+
46+
* Handle corner case: protocol/class variable/descriptor (Ivan Levkivskyi, PR [19277](https://github.com/python/mypy/pull/19277))
47+
* Fix a few inconsistencies in protocol/type object interactions (Ivan Levkivskyi, PR [19267](https://github.com/python/mypy/pull/19267))
48+
* Refactor/unify access to static attributes (Ivan Levkivskyi, PR [19254](https://github.com/python/mypy/pull/19254))
49+
* Remove inconsistencies in operator handling (Ivan Levkivskyi, PR [19250](https://github.com/python/mypy/pull/19250))
50+
* Make protocol subtyping more consistent (Ivan Levkivskyi, PR [18943](https://github.com/python/mypy/pull/18943))
51+
52+
### Fixes to Nondeterministic Type Checking
53+
54+
Previous mypy versions could infer different types for certain expressions
55+
across different runs (typically depending on which order certain types
56+
were processed, and this order was nondeterministic). This release includes
57+
fixes to several such issues.
58+
59+
* Fix nondeterministic type checking by making join with explicit Protocol and type promotion commute (Shantanu, PR [18402](https://github.com/python/mypy/pull/18402))
60+
* Fix nondeterministic type checking caused by nonassociative of None joins (Shantanu, PR [19158](https://github.com/python/mypy/pull/19158))
61+
* Fix nondeterministic type checking caused by nonassociativity of joins (Shantanu, PR [19147](https://github.com/python/mypy/pull/19147))
62+
* Fix nondeterministic type checking by making join between `type` and TypeVar commute (Shantanu, PR [19149](https://github.com/python/mypy/pull/19149))
63+
64+
### Remove Support for Targeting Python 3.8
65+
66+
Mypy now requires `--python-version 3.9` or greater. Support for targeting Python 3.8 is
67+
fully removed now. Since 3.8 is an unsupported version, mypy will default to the oldest
68+
supported version (currently 3.9) if you still try to target 3.8.
1069

1170
This change is necessary because typeshed stopped supporting Python 3.8 after it
1271
reached its End of Life in October 2024.
@@ -17,18 +76,128 @@ Contributed by Marc Mueller
1776
### Initial Support for Python 3.14
1877

1978
Mypy is now tested on 3.14 and mypyc works with 3.14.0b3 and later.
20-
Mypyc compiled wheels of mypy itself will be available for new versions after 3.14.0rc1 is released.
79+
Binary wheels compiled with mypyc for mypy itself will be available for 3.14
80+
some time after 3.14.0rc1 has been released.
2181

22-
Note that not all new features might be supported just yet.
82+
Note that not all features are supported just yet.
2383

2484
Contributed by Marc Mueller (PR [19164](https://github.com/python/mypy/pull/19164))
2585

26-
### Deprecated Flag: \--force-uppercase-builtins
86+
### Deprecated Flag: `--force-uppercase-builtins`
2787

28-
Mypy only supports Python 3.9+. The \--force-uppercase-builtins flag is now deprecated and a no-op. It will be removed in a future version.
88+
Mypy only supports Python 3.9+. The `--force-uppercase-builtins` flag is now
89+
deprecated as unnecessary, and a no-op. It will be removed in a future version.
2990

3091
Contributed by Marc Mueller (PR [19176](https://github.com/python/mypy/pull/19176))
3192

93+
### Mypyc: Improvements to Generators and Async Functions
94+
95+
This release includes both performance improvements and bug fixes related
96+
to generators and async functions (these share many implementation details).
97+
98+
* Fix exception swallowing in async try/finally blocks with await (Chainfire, PR [19353](https://github.com/python/mypy/pull/19353))
99+
* Fix AttributeError in async try/finally with mixed return paths (Chainfire, PR [19361](https://github.com/python/mypy/pull/19361))
100+
* Make generated generator helper method internal (Jukka Lehtosalo, PR [19268](https://github.com/python/mypy/pull/19268))
101+
* Free coroutine after await encounters StopIteration (Jukka Lehtosalo, PR [19231](https://github.com/python/mypy/pull/19231))
102+
* Use non-tagged integer for generator label (Jukka Lehtosalo, PR [19218](https://github.com/python/mypy/pull/19218))
103+
* Merge generator and environment classes in simple cases (Jukka Lehtosalo, PR [19207](https://github.com/python/mypy/pull/19207))
104+
105+
### Mypyc: Partial, Unsafe Support for Free Threading
106+
107+
Mypyc has minimal, quite memory-unsafe support for the free threaded
108+
builds of 3.14. It is also only lightly tested. Bug reports and experience
109+
reports are welcome!
110+
111+
Here are some of the major limitations:
112+
* Free threading only works when compiling a single module at a time.
113+
* If there is concurrent access to an object while another thread is mutating the same
114+
object, it's possible to encounter segfaults and memory corruption.
115+
* There are no efficient native primitives for thread synthronization, though the
116+
regular `threading` module can be used.
117+
* Some workloads don't scale well to multiple threads for no clear reason.
118+
119+
Related PRs:
120+
121+
* Enable partial, unsafe support for free-threading (Jukka Lehtosalo, PR [19167](https://github.com/python/mypy/pull/19167))
122+
* Fix incref/decref on free-threaded builds (Jukka Lehtosalo, PR [19127](https://github.com/python/mypy/pull/19127))
123+
124+
### Other Mypyc Fixes and Improvements
125+
126+
* Derive .c file name from full module name if using multi_file (Jukka Lehtosalo, PR [19278](https://github.com/python/mypy/pull/19278))
127+
* Support overriding the group name used in output files (Jukka Lehtosalo, PR [19272](https://github.com/python/mypy/pull/19272))
128+
* Add note about using non-native class to subclass built-in types (Jukka Lehtosalo, PR [19236](https://github.com/python/mypy/pull/19236))
129+
* Make some generated classes implicitly final (Jukka Lehtosalo, PR [19235](https://github.com/python/mypy/pull/19235))
130+
* Don't simplify module prefixes if using separate compilation (Jukka Lehtosalo, PR [19206](https://github.com/python/mypy/pull/19206))
131+
132+
### Stubgen Improvements
133+
134+
* Add import for `types` in `__exit__` method signature (Alexey Makridenko, PR [19120](https://github.com/python/mypy/pull/19120))
135+
* Add support for including class and property docstrings (Chad Dombrova, PR [17964](https://github.com/python/mypy/pull/17964))
136+
* Don't generate `Incomplete | None = None` argument annotation (Sebastian Rittau, PR [19097](https://github.com/python/mypy/pull/19097))
137+
* Support several more constructs in stubgen's alias printer (Stanislav Terliakov, PR [18888](https://github.com/python/mypy/pull/18888))
138+
139+
### Miscellaneous Fixes and Improvements
140+
141+
* Combine the revealed types of multiple iteration steps in a more robust manner (Christoph Tyralla, PR [19324](https://github.com/python/mypy/pull/19324))
142+
* Improve the handling of "iteration dependent" errors and notes in finally clauses (Christoph Tyralla, PR [19270](https://github.com/python/mypy/pull/19270))
143+
* Lessen dmypy suggest path limitations for Windows machines (CoolCat467, PR [19337](https://github.com/python/mypy/pull/19337))
144+
* Fix type ignore comments erroneously marked as unused by dmypy (Charlie Denton, PR [15043](https://github.com/python/mypy/pull/15043))
145+
* Fix misspelled `exhaustive-match` error code (johnthagen, PR [19276](https://github.com/python/mypy/pull/19276))
146+
* Fix missing error context for unpacking assignment involving star expression (Brian Schubert, PR [19258](https://github.com/python/mypy/pull/19258))
147+
* Fix and simplify error de-duplication (Ivan Levkivskyi, PR [19247](https://github.com/python/mypy/pull/19247))
148+
* Disallow `ClassVar` in type aliases (Brian Schubert, PR [19263](https://github.com/python/mypy/pull/19263))
149+
* Add script that prints list of compiled files when compiling mypy (Jukka Lehtosalo, PR [19260](https://github.com/python/mypy/pull/19260))
150+
* Fix help message url for "None and Optional handling" section (Guy Wilson, PR [19252](https://github.com/python/mypy/pull/19252))
151+
* Display fully qualified name of imported base classes in errors about incompatible overrides (Mikhail Golubev, PR [19115](https://github.com/python/mypy/pull/19115))
152+
* Avoid false `unreachable`, `redundant-expr`, and `redundant-casts` warnings in loops more robustly and efficiently, and avoid multiple `revealed type` notes for the same line (Christoph Tyralla, PR [19118](https://github.com/python/mypy/pull/19118))
153+
* Fix type extraction from `isinstance` checks (Stanislav Terliakov, PR [19223](https://github.com/python/mypy/pull/19223))
154+
* Erase stray type variables in `functools.partial` (Stanislav Terliakov, PR [18954](https://github.com/python/mypy/pull/18954))
155+
* Make inferring condition value recognize the whole truth table (Stanislav Terliakov, PR [18944](https://github.com/python/mypy/pull/18944))
156+
* Support type aliases, `NamedTuple` and `TypedDict` in constrained TypeVar defaults (Stanislav Terliakov, PR [18884](https://github.com/python/mypy/pull/18884))
157+
* Move dataclass `kw_only` fields to the end of the signature (Stanislav Terliakov, PR [19018](https://github.com/python/mypy/pull/19018))
158+
* Provide a better fallback value for the `python_version` option (Marc Mueller, PR [19162](https://github.com/python/mypy/pull/19162))
159+
* Avoid spurious non-overlapping equality error with metaclass with `__eq__` (Michael J. Sullivan, PR [19220](https://github.com/python/mypy/pull/19220))
160+
* Narrow type variable bounds (Ivan Levkivskyi, PR [19183](https://github.com/python/mypy/pull/19183))
161+
* Add classifier for Python 3.14 (Marc Mueller, PR [19199](https://github.com/python/mypy/pull/19199))
162+
* Capitalize syntax error messages (Charulata, PR [19114](https://github.com/python/mypy/pull/19114))
163+
* Infer constraints eagerly if actual is Any (Ivan Levkivskyi, PR [19190](https://github.com/python/mypy/pull/19190))
164+
* Include walrus assignments in conditional inference (Stanislav Terliakov, PR [19038](https://github.com/python/mypy/pull/19038))
165+
* Use PEP 604 syntax when converting types to strings (Marc Mueller, PR [19179](https://github.com/python/mypy/pull/19179))
166+
* Use more lower-case builtin types in error messages (Marc Mueller, PR [19177](https://github.com/python/mypy/pull/19177))
167+
* Fix example to use correct method of Stack (Łukasz Kwieciński, PR [19123](https://github.com/python/mypy/pull/19123))
168+
* Forbid `.pop` of `Readonly` `NotRequired` TypedDict items (Stanislav Terliakov, PR [19133](https://github.com/python/mypy/pull/19133))
169+
* Emit a friendlier warning on invalid exclude regex, instead of a stacktrace (wyattscarpenter, PR [19102](https://github.com/python/mypy/pull/19102))
170+
* Enable ANSI color codes for dmypy client in Windows (wyattscarpenter, PR [19088](https://github.com/python/mypy/pull/19088))
171+
* Extend special case for context-based type variable inference to unions in return position (Stanislav Terliakov, PR [18976](https://github.com/python/mypy/pull/18976))
172+
173+
### Acknowledgements
174+
175+
Thanks to all mypy contributors who contributed to this release:
176+
177+
* Alexey Makridenko
178+
* Brian Schubert
179+
* Chad Dombrova
180+
* Chainfire
181+
* Charlie Denton
182+
* Charulata
183+
* Christoph Tyralla
184+
* CoolCat467
185+
* Donal Burns
186+
* Guy Wilson
187+
* Ivan Levkivskyi
188+
* johnthagen
189+
* Jukka Lehtosalo
190+
* Łukasz Kwieciński
191+
* Marc Mueller
192+
* Michael J. Sullivan
193+
* Mikhail Golubev
194+
* Sebastian Rittau
195+
* Shantanu
196+
* Stanislav Terliakov
197+
* wyattscarpenter
198+
199+
I’d also like to thank my employer, Dropbox, for supporting mypy development.
200+
32201
## Mypy 1.16
33202

34203
We’ve just uploaded mypy 1.16 to the Python Package Index ([PyPI](https://pypi.org/project/mypy/)).

mypy/checker.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ def accept_loop(
618618
if on_enter_body is not None:
619619
on_enter_body()
620620

621-
with IterationErrorWatcher(self.msg.errors, iter_errors) as watcher:
621+
with IterationErrorWatcher(self.msg.errors, iter_errors):
622622
self.accept(body)
623623

624624
partials_new = sum(len(pts.map) for pts in self.partial_types)
@@ -641,10 +641,7 @@ def accept_loop(
641641
if iter == 20:
642642
raise RuntimeError("Too many iterations when checking a loop")
643643

644-
for error_info in watcher.yield_error_infos():
645-
self.msg.fail(*error_info[:2], code=error_info[2])
646-
for note_info in watcher.yield_note_infos(self.options):
647-
self.note(*note_info)
644+
self.msg.iteration_dependent_errors(iter_errors)
648645

649646
# If exit_condition is set, assume it must be False on exit from the loop:
650647
if exit_condition:
@@ -3041,7 +3038,7 @@ def is_noop_for_reachability(self, s: Statement) -> bool:
30413038
if isinstance(s.expr, EllipsisExpr):
30423039
return True
30433040
elif isinstance(s.expr, CallExpr):
3044-
with self.expr_checker.msg.filter_errors():
3041+
with self.expr_checker.msg.filter_errors(filter_revealed_type=True):
30453042
typ = get_proper_type(
30463043
self.expr_checker.accept(
30473044
s.expr, allow_none_return=True, always_allow_any=True
@@ -3141,7 +3138,7 @@ def check_assignment(
31413138
else:
31423139
self.check_getattr_method(signature, lvalue, name)
31433140

3144-
if name == "__slots__":
3141+
if name == "__slots__" and self.scope.active_class() is not None:
31453142
typ = lvalue_type or self.expr_checker.accept(rvalue)
31463143
self.check_slots_definition(typ, lvalue)
31473144
if name == "__match_args__" and inferred is not None:
@@ -3320,6 +3317,12 @@ def get_variable_type_context(self, inferred: Var, rvalue: Expression) -> Type |
33203317
type_contexts.append(base_type)
33213318
# Use most derived supertype as type context if available.
33223319
if not type_contexts:
3320+
if inferred.name == "__slots__" and self.scope.active_class() is not None:
3321+
str_type = self.named_type("builtins.str")
3322+
return self.named_generic_type("typing.Iterable", [str_type])
3323+
if inferred.name == "__all__" and self.scope.is_top_level():
3324+
str_type = self.named_type("builtins.str")
3325+
return self.named_generic_type("typing.Sequence", [str_type])
33233326
return None
33243327
candidate = type_contexts[0]
33253328
for other in type_contexts:
@@ -4969,7 +4972,7 @@ def visit_try_stmt(self, s: TryStmt) -> None:
49694972
if s.finally_body:
49704973
# First we check finally_body is type safe on all abnormal exit paths
49714974
iter_errors = IterationDependentErrors()
4972-
with IterationErrorWatcher(self.msg.errors, iter_errors) as watcher:
4975+
with IterationErrorWatcher(self.msg.errors, iter_errors):
49734976
self.accept(s.finally_body)
49744977

49754978
if s.finally_body:
@@ -4986,13 +4989,9 @@ def visit_try_stmt(self, s: TryStmt) -> None:
49864989
# that follows the try statement.)
49874990
assert iter_errors is not None
49884991
if not self.binder.is_unreachable():
4989-
with IterationErrorWatcher(self.msg.errors, iter_errors) as watcher:
4992+
with IterationErrorWatcher(self.msg.errors, iter_errors):
49904993
self.accept(s.finally_body)
4991-
4992-
for error_info in watcher.yield_error_infos():
4993-
self.msg.fail(*error_info[:2], code=error_info[2])
4994-
for note_info in watcher.yield_note_infos(self.options):
4995-
self.msg.note(*note_info)
4994+
self.msg.iteration_dependent_errors(iter_errors)
49964995

49974996
def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None:
49984997
"""Type check a try statement, ignoring the finally block.
@@ -7280,7 +7279,7 @@ def named_type(self, name: str) -> Instance:
72807279
if isinstance(node, TypeAlias):
72817280
assert isinstance(node.target, Instance) # type: ignore[misc]
72827281
node = node.target.type
7283-
assert isinstance(node, TypeInfo)
7282+
assert isinstance(node, TypeInfo), node
72847283
any_type = AnyType(TypeOfAny.from_omitted_generics)
72857284
return Instance(node, [any_type] * len(node.defn.type_vars))
72867285

@@ -7299,7 +7298,7 @@ def lookup_typeinfo(self, fullname: str) -> TypeInfo:
72997298
# Assume that the name refers to a class.
73007299
sym = self.lookup_qualified(fullname)
73017300
node = sym.node
7302-
assert isinstance(node, TypeInfo)
7301+
assert isinstance(node, TypeInfo), node
73037302
return node
73047303

73057304
def type_type(self) -> Instance:
@@ -7890,6 +7889,9 @@ def has_valid_attribute(self, typ: Type, name: str) -> bool:
78907889
def get_expression_type(self, node: Expression, type_context: Type | None = None) -> Type:
78917890
return self.expr_checker.accept(node, type_context=type_context)
78927891

7892+
def is_defined_in_stub(self, typ: Instance, /) -> bool:
7893+
return self.modules[typ.type.module_name].is_stub
7894+
78937895
def check_deprecated(self, node: Node | None, context: Context) -> None:
78947896
"""Warn if deprecated and not directly imported with a `from` statement."""
78957897
if isinstance(node, Decorator):

mypy/checker_shared.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ def checking_await_set(self) -> Iterator[None]:
277277
def get_precise_awaitable_type(self, typ: Type, local_errors: ErrorWatcher) -> Type | None:
278278
raise NotImplementedError
279279

280+
@abstractmethod
281+
def is_defined_in_stub(self, typ: Instance, /) -> bool:
282+
raise NotImplementedError
283+
280284

281285
class CheckerScope:
282286
# We keep two stacks combined, to maintain the relative order
@@ -334,6 +338,10 @@ def current_self_type(self) -> Instance | TupleType | None:
334338
return fill_typevars(item)
335339
return None
336340

341+
def is_top_level(self) -> bool:
342+
"""Is current scope top-level (no classes or functions)?"""
343+
return len(self.stack) == 1
344+
337345
@contextmanager
338346
def push_function(self, item: FuncItem) -> Iterator[None]:
339347
self.stack.append(item)

mypy/checkpattern.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,9 @@ def get_var(expr: Expression) -> Var:
796796
Warning: this in only true for expressions captured by a match statement.
797797
Don't call it from anywhere else
798798
"""
799-
assert isinstance(expr, NameExpr)
799+
assert isinstance(expr, NameExpr), expr
800800
node = expr.node
801-
assert isinstance(node, Var)
801+
assert isinstance(node, Var), node
802802
return node
803803

804804

0 commit comments

Comments
 (0)