This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author andreash
Recipients andreash, gvanrossum, kj
Date 2022-01-10.15:20:28
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1641828029.13.0.319383260427.issue46333@roundup.psfhosted.org>
In-reply-to
Content
The __eq__ method of ForwardRef does not take into account the module parameter. 

However, ForwardRefs with dissimilar module parameters are referring to different types even if they have different name. Thus also the ForwardRef's with same name but different module, should not be considered equal.


Consider the following code


from typing import *

ZZ = Optional['YY'] 
YY = int

YY = Tuple[Optional[ForwardRef("YY", module=__name__)], int]
print( YY.__args__[0].__args__[0].__forward_module__ )
# this prints None, but should print __main__ (or whatever __name__ contains)


When the first ForwardRef is not created, the program behaves correctly

#ZZ = Optional['YY'] 
YY = int

YY = Tuple[Optional[ForwardRef("YY", module=__name__)], int]
print( YY.__args__[0].__args__[0].__forward_module__ )
# this prints __main__ (or whatever __name__ contains)



The issue is that the line `ZZ = Optional['YY']` creates a cache entry, which is re-used instead of the second definition `Optional[ForwardRef("YY", module=__name__)]` and thus shadows the different argument of ForwardRef.


This problem could be fixed if the __eq__ method of FowardRef also checks for module equality.

i.e. in ForwardRef.__eq__ in typing.py replace 

   return self.__forward_arg__ == other.__forward_arg__

with 

   return self.__forward_arg__ == other.__forward_arg__  and  self.__forward__module__ == other.__forward__module__ 


Ideally, (and for consistency reasons) the `__repr__` method of `ForwardRef` would also include the module arg if it present:

Change:

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

to 

    def __repr__(self):
        if self.__forward_module__ is None:
            return f'ForwardRef({self.__forward_arg__!r})'
        else:
            return f'ForwardRef({self.__forward_arg__!r}, module={self.__forward__module!r})'
History
Date User Action Args
2022-01-10 15:20:29andreashsetrecipients: + andreash, gvanrossum, kj
2022-01-10 15:20:29andreashsetmessageid: <1641828029.13.0.319383260427.issue46333@roundup.psfhosted.org>
2022-01-10 15:20:29andreashlinkissue46333 messages
2022-01-10 15:20:28andreashcreate