Skip to content

Commit da699ed

Browse files
gh-121914: Change the names of the symbol tables for lambda and genexpr (GH-135288)
Change the names of the symbol tables for lambda expressions and generator expressions to "<lambda>" and "<genexpr>" respectively to avoid conflicts with user-defined names.
1 parent 85ec3b3 commit da699ed

File tree

8 files changed

+60
-52
lines changed

8 files changed

+60
-52
lines changed

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@ struct _Py_global_strings {
395395
STRUCT_FOR_ID(deterministic)
396396
STRUCT_FOR_ID(device)
397397
STRUCT_FOR_ID(dict)
398-
STRUCT_FOR_ID(dictcomp)
399398
STRUCT_FOR_ID(difference_update)
400399
STRUCT_FOR_ID(digest)
401400
STRUCT_FOR_ID(digest_size)
@@ -470,7 +469,6 @@ struct _Py_global_strings {
470469
STRUCT_FOR_ID(func)
471470
STRUCT_FOR_ID(future)
472471
STRUCT_FOR_ID(generation)
473-
STRUCT_FOR_ID(genexpr)
474472
STRUCT_FOR_ID(get)
475473
STRUCT_FOR_ID(get_debug)
476474
STRUCT_FOR_ID(get_event_loop)
@@ -546,7 +544,6 @@ struct _Py_global_strings {
546544
STRUCT_FOR_ID(kw2)
547545
STRUCT_FOR_ID(kwdefaults)
548546
STRUCT_FOR_ID(label)
549-
STRUCT_FOR_ID(lambda)
550547
STRUCT_FOR_ID(last)
551548
STRUCT_FOR_ID(last_exc)
552549
STRUCT_FOR_ID(last_node)
@@ -562,7 +559,6 @@ struct _Py_global_strings {
562559
STRUCT_FOR_ID(line)
563560
STRUCT_FOR_ID(line_buffering)
564561
STRUCT_FOR_ID(lineno)
565-
STRUCT_FOR_ID(listcomp)
566562
STRUCT_FOR_ID(little)
567563
STRUCT_FOR_ID(lo)
568564
STRUCT_FOR_ID(locale)
@@ -709,7 +705,6 @@ struct _Py_global_strings {
709705
STRUCT_FOR_ID(server_hostname)
710706
STRUCT_FOR_ID(server_side)
711707
STRUCT_FOR_ID(session)
712-
STRUCT_FOR_ID(setcomp)
713708
STRUCT_FOR_ID(setpgroup)
714709
STRUCT_FOR_ID(setsid)
715710
STRUCT_FOR_ID(setsigdef)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 0 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/symtable.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -255,25 +255,13 @@ def is_local_symbol(ident):
255255
if is_local_symbol(st.name):
256256
match st.type:
257257
case _symtable.TYPE_FUNCTION:
258-
# generators are of type TYPE_FUNCTION with a ".0"
259-
# parameter as a first parameter (which makes them
260-
# distinguishable from a function named 'genexpr')
261-
if st.name == 'genexpr' and '.0' in st.varnames:
262-
continue
263258
d[st.name] = 1
264259
case _symtable.TYPE_TYPE_PARAMETERS:
265260
# Get the function-def block in the annotation
266261
# scope 'st' with the same identifier, if any.
267262
scope_name = st.name
268263
for c in st.children:
269264
if c.name == scope_name and c.type == _symtable.TYPE_FUNCTION:
270-
# A generic generator of type TYPE_FUNCTION
271-
# cannot be a direct child of 'st' (but it
272-
# can be a descendant), e.g.:
273-
#
274-
# class A:
275-
# type genexpr[genexpr] = (x for x in [])
276-
assert scope_name != 'genexpr' or '.0' not in c.varnames
277265
d[scope_name] = 1
278266
break
279267
self.__methods = tuple(d)

Lib/test/test_symtable.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,58 @@ def test_symtable_entry_repr(self):
527527
expected = f"<symtable entry top({self.top.get_id()}), line {self.top.get_lineno()}>"
528528
self.assertEqual(repr(self.top._table), expected)
529529

530+
def test_lambda(self):
531+
st = symtable.symtable("lambda x: x", "?", "exec")
532+
self.assertEqual(len(st.get_children()), 1)
533+
st = st.get_children()[0]
534+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
535+
self.assertEqual(st.get_name(), "<lambda>")
536+
self.assertFalse(st.is_nested())
537+
self.assertEqual(sorted(st.get_identifiers()), ["x"])
538+
self.assertEqual(st.get_children(), [])
539+
540+
def test_nested_lambda(self):
541+
st = symtable.symtable("lambda x: lambda y=x: y", "?", "exec")
542+
self.assertEqual(len(st.get_children()), 1)
543+
st = st.get_children()[0]
544+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
545+
self.assertEqual(st.get_name(), "<lambda>")
546+
self.assertFalse(st.is_nested())
547+
self.assertEqual(sorted(st.get_identifiers()), ["x"])
548+
self.assertEqual(len(st.get_children()), 1)
549+
st = st.get_children()[0]
550+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
551+
self.assertEqual(st.get_name(), "<lambda>")
552+
self.assertTrue(st.is_nested())
553+
self.assertEqual(sorted(st.get_identifiers()), ["y"])
554+
self.assertEqual(st.get_children(), [])
555+
556+
def test_genexpr(self):
557+
st = symtable.symtable("(x for x in a)", "?", "exec")
558+
self.assertEqual(len(st.get_children()), 1)
559+
st = st.get_children()[0]
560+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
561+
self.assertEqual(st.get_name(), "<genexpr>")
562+
self.assertFalse(st.is_nested())
563+
self.assertEqual(sorted(st.get_identifiers()), [".0", "x"])
564+
self.assertEqual(st.get_children(), [])
565+
566+
def test_nested_genexpr(self):
567+
st = symtable.symtable("((y for y in x) for x in a)", "?", "exec")
568+
self.assertEqual(len(st.get_children()), 1)
569+
st = st.get_children()[0]
570+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
571+
self.assertEqual(st.get_name(), "<genexpr>")
572+
self.assertFalse(st.is_nested())
573+
self.assertEqual(sorted(st.get_identifiers()), [".0", "x"])
574+
self.assertEqual(len(st.get_children()), 1)
575+
st = st.get_children()[0]
576+
self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION)
577+
self.assertEqual(st.get_name(), "<genexpr>")
578+
self.assertTrue(st.is_nested())
579+
self.assertEqual(sorted(st.get_identifiers()), [".0", "y"])
580+
self.assertEqual(st.get_children(), [])
581+
530582

531583
class ComprehensionTests(unittest.TestCase):
532584
def get_identifiers_recursive(self, st, res):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Changed the names of the symbol tables for lambda expressions and generator
2+
expressions to "<lambda>" and "<genexpr>" respectively to avoid conflicts
3+
with user-defined names.

Python/symtable.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,7 +2413,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
24132413
VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);
24142414
if (e->v.Lambda.args->kw_defaults)
24152415
VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults);
2416-
if (!symtable_enter_block(st, &_Py_ID(lambda),
2416+
if (!symtable_enter_block(st, &_Py_STR(anon_lambda),
24172417
FunctionBlock, (void *)e, LOCATION(e))) {
24182418
return 0;
24192419
}
@@ -3055,31 +3055,31 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e,
30553055
static int
30563056
symtable_visit_genexp(struct symtable *st, expr_ty e)
30573057
{
3058-
return symtable_handle_comprehension(st, e, &_Py_ID(genexpr),
3058+
return symtable_handle_comprehension(st, e, &_Py_STR(anon_genexpr),
30593059
e->v.GeneratorExp.generators,
30603060
e->v.GeneratorExp.elt, NULL);
30613061
}
30623062

30633063
static int
30643064
symtable_visit_listcomp(struct symtable *st, expr_ty e)
30653065
{
3066-
return symtable_handle_comprehension(st, e, &_Py_ID(listcomp),
3066+
return symtable_handle_comprehension(st, e, &_Py_STR(anon_listcomp),
30673067
e->v.ListComp.generators,
30683068
e->v.ListComp.elt, NULL);
30693069
}
30703070

30713071
static int
30723072
symtable_visit_setcomp(struct symtable *st, expr_ty e)
30733073
{
3074-
return symtable_handle_comprehension(st, e, &_Py_ID(setcomp),
3074+
return symtable_handle_comprehension(st, e, &_Py_STR(anon_setcomp),
30753075
e->v.SetComp.generators,
30763076
e->v.SetComp.elt, NULL);
30773077
}
30783078

30793079
static int
30803080
symtable_visit_dictcomp(struct symtable *st, expr_ty e)
30813081
{
3082-
return symtable_handle_comprehension(st, e, &_Py_ID(dictcomp),
3082+
return symtable_handle_comprehension(st, e, &_Py_STR(anon_dictcomp),
30833083
e->v.DictComp.generators,
30843084
e->v.DictComp.key,
30853085
e->v.DictComp.value);

0 commit comments

Comments
 (0)