From b840e4ea1cec50c5e20908b1ff4a20651ed421f8 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 8 Jan 2026 13:28:18 +0530 Subject: [PATCH 1/7] symtable commit --- Lib/symtable.py | 13 +++++++++++++ Lib/test/test_symtable.py | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Lib/symtable.py b/Lib/symtable.py index 4c832e68f94cbd..0ca17ae1581726 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -184,6 +184,7 @@ class Function(SymbolTable): __frees = None __globals = None __nonlocals = None + __cells = None def __idents_matching(self, test_func): return tuple(ident for ident in self.get_identifiers() @@ -229,6 +230,14 @@ def get_frees(self): self.__frees = self.__idents_matching(is_free) return self.__frees + def get_cells(self): + """Return a tuple of cells in the function.""" + if self.__cells is None: + is_cell = lambda x: _get_scope(x) == CELL + self.__cells = self.__idents_matching(is_cell) + return self.__cells + + class Class(SymbolTable): @@ -342,6 +351,10 @@ def is_free(self): """ return bool(self.__scope == FREE) + def is_cell(self): + """Return *True* if the symbol is a cell variable.""" + return bool(self.__scope == CELL) + def is_free_class(self): """Return *True* if a class-scoped symbol is free from the perspective of a method.""" diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 094ab8f573e7ba..1a972f8d50e173 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -611,6 +611,22 @@ def test_filter_syntax_warnings_by_module(self): self.assertEqual(wm.filename, filename) self.assertIs(wm.category, SyntaxWarning) + def test_cells(self): + #test for addition of is_cell() and get_cells() + #see https://github.com/python/cpython/issues/143504 + code="""def outer(): + x=1 + def inner(): + return x""" + + top=symtable.symtable(code,"?","exec") + outer=top.get_children()[0] + + self.assertIn("x",outer.get_cells()) + + self.assertTrue(outer.lookup("x").is_cell()) + self.assertFalse(outer.lookup("inner").is_cell()) + class ComprehensionTests(unittest.TestCase): def get_identifiers_recursive(self, st, res): From 0b676e42d9c3306a0986a03cfb48def6b364777a Mon Sep 17 00:00:00 2001 From: Yashraj Date: Thu, 8 Jan 2026 16:17:19 +0530 Subject: [PATCH 2/7] symtable fix 1 Co-authored-by: AN Long --- Lib/symtable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index 0ca17ae1581726..b22149f4f7794e 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -238,7 +238,6 @@ def get_cells(self): return self.__cells - class Class(SymbolTable): __methods = None From 2175829e698f01a7f555dcb3ee09a30879de09c0 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 8 Jan 2026 16:28:33 +0530 Subject: [PATCH 3/7] symtable fix 2- news --- .../2026-01-08-16-28-03.gh-issue-143504.PlC_Yv.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-16-28-03.gh-issue-143504.PlC_Yv.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-16-28-03.gh-issue-143504.PlC_Yv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-16-28-03.gh-issue-143504.PlC_Yv.rst new file mode 100644 index 00000000000000..a4692f9c36777a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-08-16-28-03.gh-issue-143504.PlC_Yv.rst @@ -0,0 +1 @@ +Add symtable.is_cell() and get_cells() methods for cell variable analysis. From 17072bdae2f20519bc7ac148dedf98c253809279 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 21 Jan 2026 15:51:46 +0530 Subject: [PATCH 4/7] symtable fix 3 --- Lib/symtable.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index b22149f4f7794e..a4caaa6c0c392c 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -171,6 +171,11 @@ def get_children(self): return [_newSymbolTable(st, self._filename) for st in self._table.children] + def get_cells(self): + """Return a list of cell variable names in the table.""" + return [s.get_name() for s in self.get_symbols() if s.is_cell()] + + def _get_scope(flags): # like _PyST_GetScope() return (flags >> SCOPE_OFF) & SCOPE_MASK @@ -230,13 +235,6 @@ def get_frees(self): self.__frees = self.__idents_matching(is_free) return self.__frees - def get_cells(self): - """Return a tuple of cells in the function.""" - if self.__cells is None: - is_cell = lambda x: _get_scope(x) == CELL - self.__cells = self.__idents_matching(is_cell) - return self.__cells - class Class(SymbolTable): From f09648869f1eee1487b3fcde09bfdea7768dd4d2 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 21 Jan 2026 16:58:48 +0530 Subject: [PATCH 5/7] symtable fix 4 --- Lib/test/test_symtable.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 1a972f8d50e173..9a47ef9973574e 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -620,10 +620,8 @@ def inner(): return x""" top=symtable.symtable(code,"?","exec") - outer=top.get_children()[0] - + outer = find_block(top, "outer") self.assertIn("x",outer.get_cells()) - self.assertTrue(outer.lookup("x").is_cell()) self.assertFalse(outer.lookup("inner").is_cell()) From 57b36be4f7818758aa4f71b00124da74abcc4b02 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 21 Jan 2026 23:27:40 +0530 Subject: [PATCH 6/7] symtable fix 5 --- Lib/symtable.py | 9 ++++----- Lib/test/test_symtable.py | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index a4caaa6c0c392c..29fb74680f4543 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -171,10 +171,6 @@ def get_children(self): return [_newSymbolTable(st, self._filename) for st in self._table.children] - def get_cells(self): - """Return a list of cell variable names in the table.""" - return [s.get_name() for s in self.get_symbols() if s.is_cell()] - def _get_scope(flags): # like _PyST_GetScope() @@ -189,7 +185,6 @@ class Function(SymbolTable): __frees = None __globals = None __nonlocals = None - __cells = None def __idents_matching(self, test_func): return tuple(ident for ident in self.get_identifiers() @@ -235,6 +230,10 @@ def get_frees(self): self.__frees = self.__idents_matching(is_free) return self.__frees + def get_cells(self): + """Return a list of cell variable names in the table.""" + return [s.get_name() for s in self.get_symbols() if s.is_cell()] + class Class(SymbolTable): diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 9a47ef9973574e..164e1068a6b1db 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -284,6 +284,20 @@ def test_local(self): def test_free(self): self.assertTrue(self.internal.lookup("x").is_free()) + def test_cells(self): + #test for addition of is_cell() and get_cells() + #see https://github.com/python/cpython/issues/143504 + code="""def outer(): + x=1 + def inner(): + return x""" + + top=symtable.symtable(code,"?","exec") + outer = find_block(top, "outer") + self.assertIn("x",outer.get_cells()) + self.assertTrue(outer.lookup("x").is_cell()) + self.assertFalse(outer.lookup("inner").is_cell()) + def test_referenced(self): self.assertTrue(self.internal.lookup("x").is_referenced()) self.assertTrue(self.spam.lookup("internal").is_referenced()) @@ -611,20 +625,6 @@ def test_filter_syntax_warnings_by_module(self): self.assertEqual(wm.filename, filename) self.assertIs(wm.category, SyntaxWarning) - def test_cells(self): - #test for addition of is_cell() and get_cells() - #see https://github.com/python/cpython/issues/143504 - code="""def outer(): - x=1 - def inner(): - return x""" - - top=symtable.symtable(code,"?","exec") - outer = find_block(top, "outer") - self.assertIn("x",outer.get_cells()) - self.assertTrue(outer.lookup("x").is_cell()) - self.assertFalse(outer.lookup("inner").is_cell()) - class ComprehensionTests(unittest.TestCase): def get_identifiers_recursive(self, st, res): From 5c558f448f4baa5491951228d0df1136584b3a77 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 21 Jan 2026 23:28:44 +0530 Subject: [PATCH 7/7] symtable fix 5 --- Lib/symtable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index 29fb74680f4543..544211c98a6f62 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -172,7 +172,6 @@ def get_children(self): for st in self._table.children] - def _get_scope(flags): # like _PyST_GetScope() return (flags >> SCOPE_OFF) & SCOPE_MASK