Skip to content

Commit 0952ddd

Browse files
authored
Merge branch 'master' into master
2 parents f7f09c5 + 4fb187f commit 0952ddd

File tree

101 files changed

+5172
-1027
lines changed

Some content is hidden

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

101 files changed

+5172
-1027
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ jobs:
167167
echo debug build; python -c 'import sysconfig; print(bool(sysconfig.get_config_var("Py_DEBUG")))'
168168
echo os.cpu_count; python -c 'import os; print(os.cpu_count())'
169169
echo os.sched_getaffinity; python -c 'import os; print(len(getattr(os, "sched_getaffinity", lambda *args: [])(0)))'
170-
pip install setuptools==75.1.0 tox==4.21.2
170+
pip install tox==4.21.2
171171
172172
- name: Compiled with mypyc
173173
if: ${{ matrix.test_mypyc }}
@@ -230,7 +230,7 @@ jobs:
230230
default: 3.11.1
231231
command: python -c "import platform; print(f'{platform.architecture()=} {platform.machine()=}');"
232232
- name: Install tox
233-
run: pip install setuptools==75.1.0 tox==4.21.2
233+
run: pip install tox==4.21.2
234234
- name: Setup tox environment
235235
run: tox run -e py --notest
236236
- name: Test

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repos:
1111
- id: black
1212
exclude: '^(test-data/)'
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.8.6
14+
rev: v0.9.10
1515
hooks:
1616
- id: ruff
1717
args: [--exit-non-zero-on-fix]

docs/source/config_file.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ Platform configuration
432432

433433
Specifies the Python version used to parse and check the target
434434
program. The string should be in the format ``MAJOR.MINOR`` --
435-
for example ``2.7``. The default is the version of the Python
435+
for example ``3.9``. The default is the version of the Python
436436
interpreter used to run mypy.
437437

438438
This option may only be set in the global section (``[mypy]``).
@@ -1196,7 +1196,7 @@ of your repo (or append it to the end of an existing ``pyproject.toml`` file) an
11961196
# mypy global options:
11971197
11981198
[tool.mypy]
1199-
python_version = "2.7"
1199+
python_version = "3.9"
12001200
warn_return_any = true
12011201
warn_unused_configs = true
12021202
exclude = [

mypy/argmap.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,8 @@ def expand_actual_type(
249249
formal_name = (set(actual_type.items.keys()) - self.kwargs_used).pop()
250250
self.kwargs_used.add(formal_name)
251251
return actual_type.items[formal_name]
252-
elif (
253-
isinstance(actual_type, Instance)
254-
and len(actual_type.args) > 1
255-
and is_subtype(actual_type, self.context.mapping_type)
252+
elif isinstance(actual_type, Instance) and is_subtype(
253+
actual_type, self.context.mapping_type
256254
):
257255
# Only `Mapping` type can be unpacked with `**`.
258256
# Other types will produce an error somewhere else.

mypy/binder.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
from typing_extensions import TypeAlias as _TypeAlias
88

99
from mypy.erasetype import remove_instance_last_known_values
10-
from mypy.literals import Key, literal, literal_hash, subkeys
10+
from mypy.literals import Key, extract_var_from_literal_hash, literal, literal_hash, subkeys
1111
from mypy.nodes import Expression, IndexExpr, MemberExpr, NameExpr, RefExpr, TypeInfo, Var
12+
from mypy.options import Options
1213
from mypy.subtypes import is_same_type, is_subtype
1314
from mypy.typeops import make_simplified_union
1415
from mypy.types import (
@@ -39,6 +40,7 @@ class CurrentType(NamedTuple):
3940

4041
class Frame:
4142
"""A Frame represents a specific point in the execution of a program.
43+
4244
It carries information about the current types of expressions at
4345
that point, arising either from assignments to those expressions
4446
or the result of isinstance checks and other type narrowing
@@ -97,7 +99,7 @@ class A:
9799
# This maps an expression to a list of bound types for every item in the union type.
98100
type_assignments: Assigns | None = None
99101

100-
def __init__(self) -> None:
102+
def __init__(self, options: Options) -> None:
101103
# Each frame gets an increasing, distinct id.
102104
self.next_id = 1
103105

@@ -131,6 +133,11 @@ def __init__(self) -> None:
131133
self.break_frames: list[int] = []
132134
self.continue_frames: list[int] = []
133135

136+
# If True, initial assignment to a simple variable (e.g. "x", but not "x.y")
137+
# is added to the binder. This allows more precise narrowing and more
138+
# flexible inference of variable types (--allow-redefinition-new).
139+
self.bind_all = options.allow_redefinition_new
140+
134141
def _get_id(self) -> int:
135142
self.next_id += 1
136143
return self.next_id
@@ -226,12 +233,20 @@ def update_from_options(self, frames: list[Frame]) -> bool:
226233
for key in keys:
227234
current_value = self._get(key)
228235
resulting_values = [f.types.get(key, current_value) for f in frames]
229-
if any(x is None for x in resulting_values):
236+
# Keys can be narrowed using two different semantics. The new semantics
237+
# is enabled for plain variables when bind_all is true, and it allows
238+
# variable types to be widened using subsequent assignments. This is
239+
# tricky to support for instance attributes (primarily due to deferrals),
240+
# so we don't use it for them.
241+
old_semantics = not self.bind_all or extract_var_from_literal_hash(key) is None
242+
if old_semantics and any(x is None for x in resulting_values):
230243
# We didn't know anything about key before
231244
# (current_value must be None), and we still don't
232245
# know anything about key in at least one possible frame.
233246
continue
234247

248+
resulting_values = [x for x in resulting_values if x is not None]
249+
235250
if all_reachable and all(
236251
x is not None and not x.from_assignment for x in resulting_values
237252
):
@@ -278,7 +293,11 @@ def update_from_options(self, frames: list[Frame]) -> bool:
278293
# still equivalent to such type).
279294
if isinstance(type, UnionType):
280295
type = collapse_variadic_union(type)
281-
if isinstance(type, ProperType) and isinstance(type, UnionType):
296+
if (
297+
old_semantics
298+
and isinstance(type, ProperType)
299+
and isinstance(type, UnionType)
300+
):
282301
# Simplify away any extra Any's that were added to the declared
283302
# type when popping a frame.
284303
simplified = UnionType.make_union(

mypy/build.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,8 +2240,10 @@ def semantic_analysis_pass1(self) -> None:
22402240
# TODO: Do this while constructing the AST?
22412241
self.tree.names = SymbolTable()
22422242
if not self.tree.is_stub:
2243-
# Always perform some low-key variable renaming
2244-
self.tree.accept(LimitedVariableRenameVisitor())
2243+
if not self.options.allow_redefinition_new:
2244+
# Perform some low-key variable renaming when assignments can't
2245+
# widen inferred types
2246+
self.tree.accept(LimitedVariableRenameVisitor())
22452247
if options.allow_redefinition:
22462248
# Perform more renaming across the AST to allow variable redefinitions
22472249
self.tree.accept(VariableRenameVisitor())

0 commit comments

Comments
 (0)