Skip to content

Commit 525a4e4

Browse files
committed
Do not use special names in STRING format
1 parent 6e31c69 commit 525a4e4

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

Lib/annotationlib.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,13 @@ def __convert_to_ast(self, other):
305305
if isinstance(other.__ast_node__, str):
306306
return ast.Name(id=other.__ast_node__), other.__extra_names__
307307
return other.__ast_node__, other.__extra_names__
308-
elif other is None or type(other) in (str, int, float, bool, complex):
308+
elif (
309+
# In STRING format we don't bother with the create_unique_name() dance;
310+
# it's better to emit the repr() of the object instead of an opaque name.
311+
self.__stringifier_dict__.format == Format.STRING
312+
or other is None
313+
or type(other) in (str, int, float, bool, complex)
314+
):
309315
return ast.Constant(value=other), None
310316
elif type(other) is dict:
311317
extra_names = {}
@@ -519,14 +525,15 @@ def unary_op(self):
519525

520526

521527
class _StringifierDict(dict):
522-
def __init__(self, namespace, globals=None, owner=None, is_class=False):
528+
def __init__(self, namespace, *, globals=None, owner=None, is_class=False, format):
523529
super().__init__(namespace)
524530
self.namespace = namespace
525531
self.globals = globals
526532
self.owner = owner
527533
self.is_class = is_class
528534
self.stringifiers = []
529535
self.next_id = 1
536+
self.format = format
530537

531538
def __missing__(self, key):
532539
fwdref = _Stringifier(
@@ -587,7 +594,7 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
587594
# possibly constants if the annotate function uses them directly). We then
588595
# convert each of those into a string to get an approximation of the
589596
# original source.
590-
globals = _StringifierDict({})
597+
globals = _StringifierDict({}, format=format)
591598
if annotate.__closure__:
592599
freevars = annotate.__code__.co_freevars
593600
new_closure = []
@@ -637,9 +644,10 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
637644
is_class = isinstance(owner, type)
638645
globals = _StringifierDict(
639646
namespace,
640-
annotate.__globals__,
641-
owner,
642-
is_class,
647+
globals=annotate.__globals__,
648+
owner=owner,
649+
is_class=is_class,
650+
format=format,
643651
)
644652
if annotate.__closure__:
645653
freevars = annotate.__code__.co_freevars

Lib/test/test_annotationlib.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,17 @@ def f(fstring_format: f"{a:02d}"):
406406
with self.assertRaisesRegex(TypeError, format_msg):
407407
annotationlib.get_annotations(f, format=Format.STRING)
408408

409+
def test_shenanigans(self):
410+
# In cases like this we can't reconstruct the source; test that we do something
411+
# halfway reasonable.
412+
def f(x: x | (1).__class__, y: (1).__class__):
413+
pass
414+
415+
self.assertEqual(
416+
annotationlib.get_annotations(f, format=Format.STRING),
417+
{"x": "x | <class 'int'>", "y": "<class 'int'>"},
418+
)
419+
409420

410421
class TestForwardRefClass(unittest.TestCase):
411422
def test_special_attrs(self):

0 commit comments

Comments
 (0)