[3.10] bpo-46333: Honor module parameter in ForwardRef (GH-30536) (GH-31379)

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 <andreas.hangauer@siemens.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
(cherry picked from commit 6e7b813195)


Co-authored-by: aha79 <34090357+aha79@users.noreply.github.com>

Automerge-Triggered-By: GH:JelleZijlstra
This commit is contained in:
Miss Islington (bot) 2022-02-16 19:53:03 -08:00 committed by GitHub
parent d4e4ef107a
commit a17d59a6df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 2 deletions

View file

@ -2658,6 +2658,10 @@ class ForwardRefTests(BaseTestCase):
fr = typing.ForwardRef('int') fr = typing.ForwardRef('int')
self.assertEqual(fr, typing.ForwardRef('int')) self.assertEqual(fr, typing.ForwardRef('int'))
self.assertNotEqual(List['int'], List[int]) self.assertNotEqual(List['int'], List[int])
self.assertNotEqual(fr, typing.ForwardRef('int', module=__name__))
frm = typing.ForwardRef('int', module=__name__)
self.assertEqual(frm, typing.ForwardRef('int', module=__name__))
self.assertNotEqual(frm, typing.ForwardRef('int', module='__other_name__'))
def test_forward_equality_gth(self): def test_forward_equality_gth(self):
c1 = typing.ForwardRef('C') c1 = typing.ForwardRef('C')
@ -2694,6 +2698,14 @@ class ForwardRefTests(BaseTestCase):
self.assertEqual(hash(c1_gth), hash(c2_gth)) self.assertEqual(hash(c1_gth), hash(c2_gth))
self.assertEqual(hash(c1), hash(c1_gth)) self.assertEqual(hash(c1), hash(c1_gth))
c3 = typing.ForwardRef('int', module=__name__)
c4 = typing.ForwardRef('int', module='__other_name__')
self.assertNotEqual(hash(c3), hash(c1))
self.assertNotEqual(hash(c3), hash(c1_gth))
self.assertNotEqual(hash(c3), hash(c4))
self.assertEqual(hash(c3), hash(typing.ForwardRef('int', module=__name__)))
def test_forward_equality_namespace(self): def test_forward_equality_namespace(self):
class A: class A:
pass pass

View file

@ -705,10 +705,11 @@ class ForwardRef(_Final, _root=True):
if self.__forward_evaluated__ and other.__forward_evaluated__: if self.__forward_evaluated__ and other.__forward_evaluated__:
return (self.__forward_arg__ == other.__forward_arg__ and return (self.__forward_arg__ == other.__forward_arg__ and
self.__forward_value__ == other.__forward_value__) self.__forward_value__ == other.__forward_value__)
return self.__forward_arg__ == other.__forward_arg__ return (self.__forward_arg__ == other.__forward_arg__ and
self.__forward_module__ == other.__forward_module__)
def __hash__(self): def __hash__(self):
return hash(self.__forward_arg__) return hash((self.__forward_arg__, self.__forward_module__))
def __repr__(self): def __repr__(self):
return f'ForwardRef({self.__forward_arg__!r})' return f'ForwardRef({self.__forward_arg__!r})'

View file

@ -677,6 +677,7 @@ Anders Hammarquist
Mark Hammond Mark Hammond
Harald Hanche-Olsen Harald Hanche-Olsen
Manus Hand Manus Hand
Andreas Hangauer
Milton L. Hankins Milton L. Hankins
Carl Bordum Hansen Carl Bordum Hansen
Stephen Hansen Stephen Hansen

View file

@ -0,0 +1,4 @@
The :meth:`__eq__` and :meth:`__hash__` methods of
:class:`typing.ForwardRef` now honor the ``module`` parameter of
:class:`typing.ForwardRef`. Forward references from different
modules are now differentiated.