Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-143831: Compare cells by identity in forward references#143848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
14 commits
Select commitHold shift + click to select a range
55e07ae
Hash and compare cells by identity
johnslavikJan 14, 2026
9194bbf
Merge branch 'main' into fix-forwardrefs-dont-hash-cells
johnslavikJan 15, 2026
ff81d6a
Use appropriate semantics in `__eq__`
johnslavikJan 16, 2026
6c36442
Add base test
johnslavikJan 16, 2026
d8f5bc8
Test two paths
johnslavikJan 16, 2026
348127f
Simplify first self-test
johnslavikJan 16, 2026
bc86ed2
Fix first self-test (typo)
johnslavikJan 16, 2026
d434a40
Fix second self-test (typo)
johnslavikJan 16, 2026
1f36f76
Add news entry
johnslavikJan 16, 2026
32a3bef
Re-run CI
johnslavikJan 16, 2026
866aef1
Move self-tests to class level
johnslavikJan 16, 2026
094f0f8
Fix typo in a test forwardref
johnslavikJan 16, 2026
416c501
Use dict comprehensions instead of dict+zip
johnslavikJan 18, 2026
4707033
Merge branch 'main' into fix-forwardrefs-dont-hash-cells
JelleZijlstraJan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletionsLib/annotationlib.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -279,7 +279,13 @@ def __eq__(self, other):
# because dictionaries are not hashable.
and self.__globals__ is other.__globals__
and self.__forward_is_class__ == other.__forward_is_class__
and self.__cell__ == other.__cell__
# Two separate cells are always considered unequal in forward refs.
and (
{name: id(cell) for name, cell in self.__cell__.items()}
== {name: id(cell) for name, cell in other.__cell__.items()}
if isinstance(self.__cell__, dict) and isinstance(other.__cell__, dict)
else self.__cell__ is other.__cell__
)
and self.__owner__ == other.__owner__
and (
(tuple(sorted(self.__extra_names__.items())) if self.__extra_names__ else None) ==
Expand All@@ -293,7 +299,10 @@ def __hash__(self):
self.__forward_module__,
id(self.__globals__), # dictionaries are not hashable, so hash by identity
self.__forward_is_class__,
tuple(sorted(self.__cell__.items())) if isinstance(self.__cell__, dict) else self.__cell__,
( # cells are not hashable as well
tuple(sorted([(name, id(cell)) for name, cell in self.__cell__.items()]))
if isinstance(self.__cell__, dict) else id(self.__cell__),
),
self.__owner__,
tuple(sorted(self.__extra_names__.items())) if self.__extra_names__ else None,
))
Expand Down
34 changes: 34 additions & 0 deletionsLib/test/test_annotationlib.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@
import itertools
import pickle
from string.templatelib import Template, Interpolation
import types
import typing
import sys
import unittest
Expand DownExpand Up@@ -1862,6 +1863,39 @@ def foo(a: c1_gth, b: c2_gth):
self.assertNotEqual(hash(c3), hash(c4))
self.assertEqual(hash(c3), hash(ForwardRef("int", module=__name__)))

def test_forward_equality_and_hash_with_cells(self):
"""Regression test for GH-143831."""
class A:
def one(_) -> C1:
"""One cell."""

one_f = ForwardRef("C1", owner=one)
one_f_ga1 = get_annotations(one, format=Format.FORWARDREF)["return"]
one_f_ga2 = get_annotations(one, format=Format.FORWARDREF)["return"]
self.assertIsInstance(one_f_ga1.__cell__, types.CellType)
self.assertIs(one_f_ga1.__cell__, one_f_ga2.__cell__)

def two(_) -> C1 | C2:
"""Two cells."""

two_f_ga1 = get_annotations(two, format=Format.FORWARDREF)["return"]
two_f_ga2 = get_annotations(two, format=Format.FORWARDREF)["return"]
self.assertIsNot(two_f_ga1.__cell__, two_f_ga2.__cell__)
self.assertIsInstance(two_f_ga1.__cell__, dict)
self.assertIsInstance(two_f_ga2.__cell__, dict)

type C1 = None
type C2 = None

self.assertNotEqual(A.one_f, A.one_f_ga1)
self.assertNotEqual(hash(A.one_f), hash(A.one_f_ga1))

self.assertEqual(A.one_f_ga1, A.one_f_ga2)
self.assertEqual(hash(A.one_f_ga1), hash(A.one_f_ga2))

self.assertEqual(A.two_f_ga1, A.two_f_ga2)
self.assertEqual(hash(A.two_f_ga1), hash(A.two_f_ga2))

def test_forward_equality_namespace(self):
def namespace1():
a = ForwardRef("A")
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
:class:`annotationlib.ForwardRef` objects are now hashable when created from
annotation scopes with closures. Previously, hashing such objects would
throw an exception. Patch by Bartosz Sławecki.
Loading

[8]ページ先頭

©2009-2026 Movatter.jp