Skip to content

Commit 29ae7d3

Browse files
bpo-46333: Honor module parameter in ForwardRef (GH-30536)
The `module` parameter carries semantic information about the forward ref. Forward refs are different if they refer to different module even if they have the same name. This affects the `__eq__`, `__repr__` and `__hash__` methods. Co-authored-by: Andreas Hangauer <[email protected]> Co-authored-by: Alex Waygood <[email protected]> Co-authored-by: Ken Jin <[email protected]> (cherry picked from commit 6e7b813) Co-authored-by: aha79 <[email protected]>
1 parent a657bff commit 29ae7d3

File tree

4 files changed

+20
-2
lines changed

4 files changed

+20
-2
lines changed

Lib/test/test_typing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,10 @@ def test_forward_equality(self):
24632463
fr = typing.ForwardRef('int')
24642464
self.assertEqual(fr, typing.ForwardRef('int'))
24652465
self.assertNotEqual(List['int'], List[int])
2466+
self.assertNotEqual(fr, typing.ForwardRef('int', module=__name__))
2467+
frm = typing.ForwardRef('int', module=__name__)
2468+
self.assertEqual(frm, typing.ForwardRef('int', module=__name__))
2469+
self.assertNotEqual(frm, typing.ForwardRef('int', module='__other_name__'))
24662470

24672471
def test_forward_equality_gth(self):
24682472
c1 = typing.ForwardRef('C')
@@ -2499,6 +2503,14 @@ def foo(a: c1_gth, b: c2_gth):
24992503
self.assertEqual(hash(c1_gth), hash(c2_gth))
25002504
self.assertEqual(hash(c1), hash(c1_gth))
25012505

2506+
c3 = typing.ForwardRef('int', module=__name__)
2507+
c4 = typing.ForwardRef('int', module='__other_name__')
2508+
2509+
self.assertNotEqual(hash(c3), hash(c1))
2510+
self.assertNotEqual(hash(c3), hash(c1_gth))
2511+
self.assertNotEqual(hash(c3), hash(c4))
2512+
self.assertEqual(hash(c3), hash(typing.ForwardRef('int', module=__name__)))
2513+
25022514
def test_forward_equality_namespace(self):
25032515
class A:
25042516
pass

Lib/typing.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,11 @@ def __eq__(self, other):
568568
if self.__forward_evaluated__ and other.__forward_evaluated__:
569569
return (self.__forward_arg__ == other.__forward_arg__ and
570570
self.__forward_value__ == other.__forward_value__)
571-
return self.__forward_arg__ == other.__forward_arg__
571+
return (self.__forward_arg__ == other.__forward_arg__ and
572+
self.__forward_module__ == other.__forward_module__)
572573

573574
def __hash__(self):
574-
return hash(self.__forward_arg__)
575+
return hash((self.__forward_arg__, self.__forward_module__))
575576

576577
def __repr__(self):
577578
return f'ForwardRef({self.__forward_arg__!r})'

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ Anders Hammarquist
665665
Mark Hammond
666666
Harald Hanche-Olsen
667667
Manus Hand
668+
Andreas Hangauer
668669
Milton L. Hankins
669670
Carl Bordum Hansen
670671
Stephen Hansen
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The :meth:`__eq__` and :meth:`__hash__` methods of
2+
:class:`typing.ForwardRef` now honor the ``module`` parameter of
3+
:class:`typing.ForwardRef`. Forward references from different
4+
modules are now differentiated.

0 commit comments

Comments
 (0)