[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