@@ -47,6 +47,7 @@ class Format(enum.IntEnum):
4747 "__cell__" ,
4848 "__owner__" ,
4949 "__stringifier_dict__" ,
50+ "__resolved_str_cache__" ,
5051)
5152
5253
@@ -94,6 +95,7 @@ def __init__(
9495 # value later.
9596 self .__code__ = None
9697 self .__ast_node__ = None
98+ self .__resolved_str_cache__ = None
9799
98100 def __init_subclass__ (cls , / , * args , ** kwds ):
99101 raise TypeError ("Cannot subclass ForwardRef" )
@@ -113,7 +115,7 @@ def evaluate(
113115 """
114116 match format :
115117 case Format .STRING :
116- return self .__resolved_forward_str__
118+ return self .__resolved_str__
117119 case Format .VALUE :
118120 is_forwardref_format = False
119121 case Format .FORWARDREF :
@@ -259,24 +261,27 @@ def __forward_arg__(self):
259261 )
260262
261263 @property
262- def __resolved_forward_str__ (self ):
264+ def __resolved_str__ (self ):
263265 # __forward_arg__ with any names from __extra_names__ replaced
264266 # with the type_repr of the value they represent
265- resolved_str = self .__forward_arg__
266- names = self .__extra_names__
267-
268- if names :
269- # identifiers can be replaced directly
270- if resolved_str .isidentifier ():
271- if (name_obj := names .get (resolved_str ), _sentinel ) is not _sentinel :
272- resolved_str = type_repr (name_obj )
273- else :
274- visitor = _ExtraNameFixer (names )
275- ast_expr = ast .parse (resolved_str , mode = "eval" ).body
276- node = visitor .visit (ast_expr )
277- resolved_str = ast .unparse (node )
267+ if self .__resolved_str_cache__ is None :
268+ resolved_str = self .__forward_arg__
269+ names = self .__extra_names__
270+
271+ if names :
272+ # identifiers can be replaced directly
273+ if resolved_str .isidentifier ():
274+ if (name_obj := names .get (resolved_str ), _sentinel ) is not _sentinel :
275+ resolved_str = type_repr (name_obj )
276+ else :
277+ visitor = _ExtraNameFixer (names )
278+ ast_expr = ast .parse (resolved_str , mode = "eval" ).body
279+ node = visitor .visit (ast_expr )
280+ resolved_str = ast .unparse (node )
281+
282+ self .__resolved_str_cache__ = resolved_str
278283
279- return resolved_str
284+ return self . __resolved_str_cache__
280285
281286 @property
282287 def __forward_code__ (self ):
@@ -341,7 +346,7 @@ def __repr__(self):
341346 extra .append (", is_class=True" )
342347 if self .__owner__ is not None :
343348 extra .append (f", owner={ self .__owner__ !r} " )
344- return f"ForwardRef({ self .__resolved_forward_str__ !r} { '' .join (extra )} )"
349+ return f"ForwardRef({ self .__resolved_str__ !r} { '' .join (extra )} )"
345350
346351
347352_Template = type (t "" )
@@ -377,6 +382,7 @@ def __init__(
377382 self .__cell__ = cell
378383 self .__owner__ = owner
379384 self .__stringifier_dict__ = stringifier_dict
385+ self .__resolved_str_cache__ = None # Needed for ForwardRef
380386
381387 def __convert_to_ast (self , other ):
382388 if isinstance (other , _Stringifier ):
0 commit comments