@@ -32,18 +32,16 @@ class Format(enum.IntEnum):
32
32
# preserved for compatibility with the old typing.ForwardRef class. The remaining
33
33
# names are private.
34
34
_SLOTS = (
35
- "__forward_evaluated__" ,
36
- "__forward_value__" ,
37
35
"__forward_is_argument__" ,
38
36
"__forward_is_class__" ,
39
37
"__forward_module__" ,
40
38
"__weakref__" ,
41
39
"__arg__" ,
42
- "__ast_node__" ,
43
- "__code__" ,
44
40
"__globals__" ,
45
- "__owner__" ,
41
+ "__code__" ,
42
+ "__ast_node__" ,
46
43
"__cell__" ,
44
+ "__owner__" ,
47
45
"__stringifier_dict__" ,
48
46
)
49
47
@@ -76,14 +74,12 @@ def __init__(
76
74
raise TypeError (f"Forward reference must be a string -- got { arg !r} " )
77
75
78
76
self .__arg__ = arg
79
- self .__forward_evaluated__ = False
80
- self .__forward_value__ = None
81
77
self .__forward_is_argument__ = is_argument
82
78
self .__forward_is_class__ = is_class
83
79
self .__forward_module__ = module
80
+ self .__globals__ = None
84
81
self .__code__ = None
85
82
self .__ast_node__ = None
86
- self .__globals__ = None
87
83
self .__cell__ = None
88
84
self .__owner__ = owner
89
85
@@ -95,17 +91,11 @@ def evaluate(self, *, globals=None, locals=None, type_params=None, owner=None):
95
91
96
92
If the forward reference cannot be evaluated, raise an exception.
97
93
"""
98
- if self .__forward_evaluated__ :
99
- return self .__forward_value__
100
94
if self .__cell__ is not None :
101
95
try :
102
- value = self .__cell__ .cell_contents
96
+ return self .__cell__ .cell_contents
103
97
except ValueError :
104
98
pass
105
- else :
106
- self .__forward_evaluated__ = True
107
- self .__forward_value__ = value
108
- return value
109
99
if owner is None :
110
100
owner = self .__owner__
111
101
@@ -171,8 +161,6 @@ def evaluate(self, *, globals=None, locals=None, type_params=None, owner=None):
171
161
else :
172
162
code = self .__forward_code__
173
163
value = eval (code , globals = globals , locals = locals )
174
- self .__forward_evaluated__ = True
175
- self .__forward_value__ = value
176
164
return value
177
165
178
166
def _evaluate (self , globalns , localns , type_params = _sentinel , * , recursive_guard ):
@@ -230,18 +218,30 @@ def __forward_code__(self):
230
218
def __eq__ (self , other ):
231
219
if not isinstance (other , ForwardRef ):
232
220
return NotImplemented
233
- if self .__forward_evaluated__ and other .__forward_evaluated__ :
234
- return (
235
- self .__forward_arg__ == other .__forward_arg__
236
- and self .__forward_value__ == other .__forward_value__
237
- )
238
221
return (
239
222
self .__forward_arg__ == other .__forward_arg__
240
223
and self .__forward_module__ == other .__forward_module__
224
+ # Use "is" here because we use id() for this in __hash__
225
+ # because dictionaries are not hashable.
226
+ and self .__globals__ is other .__globals__
227
+ and self .__forward_is_class__ == other .__forward_is_class__
228
+ and self .__code__ == other .__code__
229
+ and self .__ast_node__ == other .__ast_node__
230
+ and self .__cell__ == other .__cell__
231
+ and self .__owner__ == other .__owner__
241
232
)
242
233
243
234
def __hash__ (self ):
244
- return hash ((self .__forward_arg__ , self .__forward_module__ ))
235
+ return hash ((
236
+ self .__forward_arg__ ,
237
+ self .__forward_module__ ,
238
+ id (self .__globals__ ), # dictionaries are not hashable, so hash by identity
239
+ self .__forward_is_class__ ,
240
+ self .__code__ ,
241
+ self .__ast_node__ ,
242
+ self .__cell__ ,
243
+ self .__owner__ ,
244
+ ))
245
245
246
246
def __or__ (self , other ):
247
247
return types .UnionType [self , other ]
@@ -250,11 +250,14 @@ def __ror__(self, other):
250
250
return types .UnionType [other , self ]
251
251
252
252
def __repr__ (self ):
253
- if self .__forward_module__ is None :
254
- module_repr = ""
255
- else :
256
- module_repr = f", module={ self .__forward_module__ !r} "
257
- return f"ForwardRef({ self .__forward_arg__ !r} { module_repr } )"
253
+ extra = []
254
+ if self .__forward_module__ is not None :
255
+ extra .append (f", module={ self .__forward_module__ !r} " )
256
+ if self .__forward_is_class__ :
257
+ extra .append (", is_class=True" )
258
+ if self .__owner__ is not None :
259
+ extra .append (f", owner={ self .__owner__ !r} " )
260
+ return f"ForwardRef({ self .__forward_arg__ !r} { '' .join (extra )} )"
258
261
259
262
260
263
class _Stringifier :
@@ -276,8 +279,6 @@ def __init__(
276
279
# represent a single name).
277
280
assert isinstance (node , (ast .AST , str ))
278
281
self .__arg__ = None
279
- self .__forward_evaluated__ = False
280
- self .__forward_value__ = None
281
282
self .__forward_is_argument__ = False
282
283
self .__forward_is_class__ = is_class
283
284
self .__forward_module__ = None
0 commit comments