[med-svn] [Git][python-team/packages/mypy][upstream] New upstream version 1.17.1
Michael R. Crusoe (@crusoe)
gitlab at salsa.debian.org
Thu Aug 7 13:56:45 BST 2025
Michael R. Crusoe pushed to branch upstream at Debian Python Team / packages / mypy
Commits:
aa534b9e by Michael R. Crusoe at 2025-08-07T13:05:52+02:00
New upstream version 1.17.1
- - - - -
10 changed files:
- PKG-INFO
- mypy.egg-info/PKG-INFO
- mypy/checker.py
- mypy/server/astmerge.py
- mypy/solve.py
- mypy/version.py
- pyproject.toml
- test-data/unit/check-dataclasses.test
- test-data/unit/check-recursive-types.test
- test-data/unit/check-typeddict.test
Changes:
=====================================
PKG-INFO
=====================================
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: mypy
-Version: 1.17.0
+Version: 1.17.1
Summary: Optional static typing for Python
Author-email: Jukka Lehtosalo <jukka.lehtosalo at iki.fi>
License: MIT
=====================================
mypy.egg-info/PKG-INFO
=====================================
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: mypy
-Version: 1.17.0
+Version: 1.17.1
Summary: Optional static typing for Python
Author-email: Jukka Lehtosalo <jukka.lehtosalo at iki.fi>
License: MIT
=====================================
mypy/checker.py
=====================================
@@ -2169,7 +2169,14 @@ class TypeChecker(NodeVisitor[None], TypeCheckerSharedApi):
else:
override_class_or_static = defn.func.is_class or defn.func.is_static
typ, _ = self.node_type_from_base(defn.name, defn.info, defn)
- assert typ is not None
+ if typ is None:
+ # This may only happen if we're checking `x-redefinition` member
+ # and `x` itself is for some reason gone. Normally the node should
+ # be reachable from the containing class by its name.
+ # The redefinition is never removed, use this as a sanity check to verify
+ # the reasoning above.
+ assert f"{defn.name}-redefinition" in defn.info.names
+ return False
original_node = base_attr.node
# `original_type` can be partial if (e.g.) it is originally an
=====================================
mypy/server/astmerge.py
=====================================
@@ -345,13 +345,11 @@ class NodeReplaceVisitor(TraverserVisitor):
def fixup(self, node: SN) -> SN:
if node in self.replacements:
new = self.replacements[node]
- skip_slots: tuple[str, ...] = ()
if isinstance(node, TypeInfo) and isinstance(new, TypeInfo):
# Special case: special_alias is not exposed in symbol tables, but may appear
# in external types (e.g. named tuples), so we need to update it manually.
- skip_slots = ("special_alias",)
replace_object_state(new.special_alias, node.special_alias)
- replace_object_state(new, node, skip_slots=skip_slots)
+ replace_object_state(new, node, skip_slots=_get_ignored_slots(new))
return cast(SN, new)
return node
@@ -556,9 +554,16 @@ def replace_nodes_in_symbol_table(
if node.node in replacements:
new = replacements[node.node]
old = node.node
- # Needed for TypeInfo, see comment in fixup() above.
- replace_object_state(new, old, skip_slots=("special_alias",))
+ replace_object_state(new, old, skip_slots=_get_ignored_slots(new))
node.node = new
if isinstance(node.node, (Var, TypeAlias)):
# Handle them here just in case these aren't exposed through the AST.
node.node.accept(NodeReplaceVisitor(replacements))
+
+
+def _get_ignored_slots(node: SymbolNode) -> tuple[str, ...]:
+ if isinstance(node, OverloadedFuncDef):
+ return ("setter",)
+ if isinstance(node, TypeInfo):
+ return ("special_alias",)
+ return ()
=====================================
mypy/solve.py
=====================================
@@ -270,6 +270,7 @@ def solve_one(lowers: Iterable[Type], uppers: Iterable[Type]) -> Type | None:
uppers = new_uppers
# ...unless this is the only information we have, then we just pass it on.
+ lowers = list(lowers)
if not uppers and not lowers:
candidate = UninhabitedType()
candidate.ambiguous = True
@@ -281,10 +282,11 @@ def solve_one(lowers: Iterable[Type], uppers: Iterable[Type]) -> Type | None:
# Process each bound separately, and calculate the lower and upper
# bounds based on constraints. Note that we assume that the constraint
# targets do not have constraint references.
- if type_state.infer_unions:
+ if type_state.infer_unions and lowers:
# This deviates from the general mypy semantics because
# recursive types are union-heavy in 95% of cases.
- bottom = UnionType.make_union(list(lowers))
+ # Retain `None` when no bottoms were provided to avoid bogus `Never` inference.
+ bottom = UnionType.make_union(lowers)
else:
# The order of lowers is non-deterministic.
# We attempt to sort lowers because joins are non-associative. For instance:
=====================================
mypy/version.py
=====================================
@@ -8,7 +8,7 @@ from mypy import git
# - Release versions have the form "1.2.3".
# - Dev versions have the form "1.2.3+dev" (PLUS sign to conform to PEP 440).
# - Before 1.0 we had the form "0.NNN".
-__version__ = "1.17.0"
+__version__ = "1.17.1"
base_version = __version__
mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
=====================================
pyproject.toml
=====================================
@@ -222,6 +222,14 @@ addopts = "-nauto --strict-markers --strict-config"
# treat xpasses as test failures so they get converted to regular tests as soon as possible
xfail_strict = true
+# Force warnings as errors
+filterwarnings = [
+ "error",
+ # Some testcases may contain code that emits SyntaxWarnings, and they are not yet
+ # handled consistently in 3.14 (PEP 765)
+ "default::SyntaxWarning",
+]
+
[tool.coverage.run]
branch = true
source = ["mypy"]
=====================================
test-data/unit/check-dataclasses.test
=====================================
@@ -2666,3 +2666,19 @@ class PersonBad(TypedDict):
class JobBad:
person: PersonBad = field(default_factory=PersonBad) # E: Argument "default_factory" to "field" has incompatible type "type[PersonBad]"; expected "Callable[[], PersonBad]"
[builtins fixtures/dict.pyi]
+
+[case testDataclassInitVarRedefinitionNoCrash]
+# https://github.com/python/mypy/issues/19443
+from dataclasses import InitVar, dataclass
+
+class ClassA:
+ def value(self) -> int:
+ return 0
+
+ at dataclass
+class ClassB(ClassA):
+ value: InitVar[int]
+
+ def value(self) -> int: # E: Name "value" already defined on line 10
+ return 0
+[builtins fixtures/dict.pyi]
=====================================
test-data/unit/check-recursive-types.test
=====================================
@@ -54,7 +54,7 @@ reveal_type(flatten([1, [2, [3]]])) # N: Revealed type is "builtins.list[builti
class Bad: ...
x: Nested[int] = [1, [2, [3]]]
-x = [1, [Bad()]] # E: List item 1 has incompatible type "list[Bad]"; expected "Union[int, Nested[int]]"
+x = [1, [Bad()]] # E: List item 0 has incompatible type "Bad"; expected "Union[int, Nested[int]]"
[builtins fixtures/isinstancelist.pyi]
[case testRecursiveAliasGenericInferenceNested]
@@ -605,7 +605,7 @@ class NT(NamedTuple, Generic[T]):
class A: ...
class B(A): ...
-nti: NT[int] = NT(key=0, value=NT(key=1, value=A())) # E: Argument "value" to "NT" has incompatible type "NT[A]"; expected "Union[int, NT[int]]"
+nti: NT[int] = NT(key=0, value=NT(key=1, value=A())) # E: Argument "value" to "NT" has incompatible type "A"; expected "Union[int, NT[int]]"
reveal_type(nti) # N: Revealed type is "tuple[builtins.int, Union[builtins.int, ...], fallback=__main__.NT[builtins.int]]"
nta: NT[A]
=====================================
test-data/unit/check-typeddict.test
=====================================
@@ -4271,3 +4271,21 @@ reveal_type(dicts.TF) # N: Revealed type is "def (*, user_id: builtins.int =) -
reveal_type(dicts.TotalFalse) # N: Revealed type is "def (*, user_id: builtins.int =) -> TypedDict('__main__.Dicts.TF', {'user_id'?: builtins.int})"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]
+
+[case testRecursiveNestedTypedDictInference]
+from typing import TypedDict, Sequence
+from typing_extensions import NotRequired
+
+class Component(TypedDict):
+ type: str
+ components: NotRequired[Sequence['Component']]
+
+inputs: Sequence[Component] = [{
+ 'type': 'tuple',
+ 'components': [
+ {'type': 'uint256'},
+ {'type': 'address'},
+ ]
+}]
+[builtins fixtures/dict.pyi]
+[typing fixtures/typing-typeddict.pyi]
View it on GitLab: https://salsa.debian.org/python-team/packages/mypy/-/commit/aa534b9e8fee30be38ed78b6154b613bd4bceb01
--
View it on GitLab: https://salsa.debian.org/python-team/packages/mypy/-/commit/aa534b9e8fee30be38ed78b6154b613bd4bceb01
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20250807/8d302972/attachment-0001.htm>
More information about the debian-med-commit
mailing list