From ecf13fac8b098614f362e6e4d4348943e363b9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:58:06 +0200 Subject: [PATCH 01/24] export more flags --- Modules/symtablemodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index 63c4dd4225298d..b39b59bf7b06bf 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -81,6 +81,8 @@ symtable_init_constants(PyObject *m) if (PyModule_AddIntMacro(m, DEF_IMPORT) < 0) return -1; if (PyModule_AddIntMacro(m, DEF_BOUND) < 0) return -1; if (PyModule_AddIntMacro(m, DEF_ANNOT) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_COMP_ITER) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_COMP_CELL) < 0) return -1; if (PyModule_AddIntConstant(m, "TYPE_FUNCTION", FunctionBlock) < 0) return -1; From 6b52473e67a8329b53f179895d1705ee072d4f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:58:31 +0200 Subject: [PATCH 02/24] rename private module constant "SCOPE_OFF" -> "SCOPE_OFFSET" --- Modules/symtablemodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index b39b59bf7b06bf..e198c2373b8c67 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -105,7 +105,7 @@ symtable_init_constants(PyObject *m) if (PyModule_AddIntMacro(m, FREE) < 0) return -1; if (PyModule_AddIntMacro(m, CELL) < 0) return -1; - if (PyModule_AddIntConstant(m, "SCOPE_OFF", SCOPE_OFFSET) < 0) return -1; + if (PyModule_AddIntMacro(m, SCOPE_OFFSET) < 0) return -1; if (PyModule_AddIntMacro(m, SCOPE_MASK) < 0) return -1; return 0; From 4fe8b3447ce84eac89d6680683eb9be2ca38950f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:59:55 +0200 Subject: [PATCH 03/24] add private Python function mirroring '_PyST_GetScope' --- Lib/symtable.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index ba2f0dafcd0063..e9c8e2300a3f79 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -5,7 +5,7 @@ USE, DEF_GLOBAL, DEF_NONLOCAL, DEF_LOCAL, DEF_PARAM, DEF_TYPE_PARAM, DEF_IMPORT, DEF_BOUND, DEF_ANNOT, - SCOPE_OFF, SCOPE_MASK, + SCOPE_OFFSET, SCOPE_MASK, FREE, LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL ) @@ -158,6 +158,10 @@ def get_children(self): for st in self._table.children] +def _get_scope(flags): # like _PyST_GetScope() + return (flags >> SCOPE_OFFSET) & SCOPE_MASK + + class Function(SymbolTable): # Default values for instance variables @@ -183,7 +187,7 @@ def get_locals(self): """ if self.__locals is None: locs = (LOCAL, CELL) - test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs + test = lambda x: _get_scope(x) in locs self.__locals = self.__idents_matching(test) return self.__locals @@ -192,7 +196,7 @@ def get_globals(self): """ if self.__globals is None: glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) - test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob + test = lambda x: _get_scope(x) in glob self.__globals = self.__idents_matching(test) return self.__globals @@ -207,7 +211,7 @@ def get_frees(self): """Return a tuple of free variables in the function. """ if self.__frees is None: - is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE + is_free = lambda x: _get_scope(x) == FREE self.__frees = self.__idents_matching(is_free) return self.__frees @@ -232,7 +236,7 @@ class Symbol: def __init__(self, name, flags, namespaces=None, *, module_scope=False): self.__name = name self.__flags = flags - self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope() + self.__scope = _get_scope(flags) self.__namespaces = namespaces or () self.__module_scope = module_scope From 73f8dc78310b98537a9aac3530d8aa78581f8b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:00:50 +0200 Subject: [PATCH 04/24] fix some reference in a comment --- Include/internal/pycore_symtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index ac6c499c08264e..e95b53e9f1055a 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -150,7 +150,7 @@ extern PyObject* _Py_Mangle(PyObject *p, PyObject *name); #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT) /* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol - table. GLOBAL is returned from PyST_GetScope() for either of them. + table. GLOBAL is returned from _PyST_GetScope() for either of them. It is stored in ste_symbols at bits 13-16. */ #define SCOPE_OFFSET 12 From 477ad7f6589f253c08e490d52d1de4d6a854c5c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:01:36 +0200 Subject: [PATCH 05/24] handle exported flags --- Lib/symtable.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index e9c8e2300a3f79..e5c28ebbfe4ca0 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -4,7 +4,10 @@ from _symtable import ( USE, DEF_GLOBAL, DEF_NONLOCAL, DEF_LOCAL, - DEF_PARAM, DEF_TYPE_PARAM, DEF_IMPORT, DEF_BOUND, DEF_ANNOT, + DEF_PARAM, DEF_TYPE_PARAM, + DEF_FREE, DEF_FREE_CLASS, + DEF_IMPORT, DEF_BOUND, DEF_ANNOT, + DEF_COMP_ITER, DEF_COMP_CELL, SCOPE_OFFSET, SCOPE_MASK, FREE, LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL ) @@ -315,6 +318,16 @@ def is_assigned(self): """Return *True* if a symbol is assigned to.""" return bool(self.__flags & DEF_LOCAL) + def is_comp_iter(self): + """Return *True* if the symbol is a comprehension iteration variable. + """ + return bool(self.__flags & DEF_COMP_ITER) + + def is_comp_cell(self): + """Return *True* if the symbol is a cell in an inlined comprehension. + """ + return bool(self.__flags & DEF_COMP_ITER) + def is_namespace(self): """Returns *True* if name binding introduces new namespace. From d04b01366c602d06962743bd802cc74a88a62ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:01:46 +0200 Subject: [PATCH 06/24] add test --- Lib/test/test_symtable.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index ef2a228b15ed4e..cb9f8891b622fc 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -302,6 +302,14 @@ def test_symbol_repr(self): self.assertEqual(repr(self.GenericMine.lookup("T")), "") + st1 = symtable.symtable("[x for x in [1]]", "?", "exec") + self.assertEqual(repr(st1.lookup("x")), + "") + + st2 = symtable.symtable("[(lambda: x) for x in [1]]", "?", "exec") + self.assertEqual(repr(st2.lookup("x")), + "") + def test_symtable_entry_repr(self): expected = f"" self.assertEqual(repr(self.top._table), expected) From ff02dfa90eda9ff55474c30959f7befff4f766ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:08:13 +0200 Subject: [PATCH 07/24] add doc --- Doc/library/symtable.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index e17a33f7feb1ab..1e25c1af80d7ee 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -155,6 +155,8 @@ Examining Symbol Tables Return ``True`` if the symbol is a type parameter. + .. versionadded:: 3.14 + .. method:: is_global() Return ``True`` if the symbol is global. @@ -186,6 +188,18 @@ Examining Symbol Tables Return ``True`` if the symbol is assigned to in its block. + .. method:: is_comp_iter() + + Return ``True`` if the symbol is a comprehension iteration variable. + + .. versionadded:: 3.14 + + .. method:: is_comp_cell() + + Return ``True`` if the symbol is a cell in an inlined comprehension. + + .. versionadded:: 3.14 + .. method:: is_namespace() Return ``True`` if name binding introduces new namespace. From 5c612de52fbe73dd20b0b1a825e1c669574aadbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:04:49 +0200 Subject: [PATCH 08/24] blurb --- .../Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst diff --git a/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst new file mode 100644 index 00000000000000..04f1a17d85ac4a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst @@ -0,0 +1,4 @@ +Expose :meth:`symtable.Symbol.is_comp_iter` and :meth:`symtable.Symbol.is_comp_cell` +in the :mod:`symtable` module. +Patch by Bénédikt Tran. + From 1e849737ff94eae6ae290b5d801f9e4a25bd2584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:10:09 +0200 Subject: [PATCH 09/24] address review - restore 'symtable.SCOPE_OFF' for compatibility purposes - fix `Symbol.is_comp_cell()` --- Lib/symtable.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index e5c28ebbfe4ca0..0e665e9d5b1e82 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -16,6 +16,9 @@ __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] +SCOPE_OFF = SCOPE_OFFSET # kept for backward compatibility + + def symtable(code, filename, compile_type): """ Return the toplevel *SymbolTable* for the source code. @@ -326,7 +329,7 @@ def is_comp_iter(self): def is_comp_cell(self): """Return *True* if the symbol is a cell in an inlined comprehension. """ - return bool(self.__flags & DEF_COMP_ITER) + return bool(self.__flags & DEF_COMP_CELL) def is_namespace(self): """Returns *True* if name binding introduces new namespace. From 388e40e22114942c11d67e677a24889bb0dbbbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:47:11 +0200 Subject: [PATCH 10/24] revert to using `SCOPE_OFF` --- Lib/symtable.py | 6 ++---- Modules/symtablemodule.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index 0e665e9d5b1e82..23b520a273005f 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -8,7 +8,7 @@ DEF_FREE, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, DEF_ANNOT, DEF_COMP_ITER, DEF_COMP_CELL, - SCOPE_OFFSET, SCOPE_MASK, + SCOPE_OFF, SCOPE_MASK, FREE, LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL ) @@ -16,8 +16,6 @@ __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] -SCOPE_OFF = SCOPE_OFFSET # kept for backward compatibility - def symtable(code, filename, compile_type): """ Return the toplevel *SymbolTable* for the source code. @@ -165,7 +163,7 @@ def get_children(self): def _get_scope(flags): # like _PyST_GetScope() - return (flags >> SCOPE_OFFSET) & SCOPE_MASK + return (flags >> SCOPE_OFF) & SCOPE_MASK class Function(SymbolTable): diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c index e198c2373b8c67..b39b59bf7b06bf 100644 --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -105,7 +105,7 @@ symtable_init_constants(PyObject *m) if (PyModule_AddIntMacro(m, FREE) < 0) return -1; if (PyModule_AddIntMacro(m, CELL) < 0) return -1; - if (PyModule_AddIntMacro(m, SCOPE_OFFSET) < 0) return -1; + if (PyModule_AddIntConstant(m, "SCOPE_OFF", SCOPE_OFFSET) < 0) return -1; if (PyModule_AddIntMacro(m, SCOPE_MASK) < 0) return -1; return 0; From 9a74d6be7b13cbdb5ef6cd0642fb1ea13ffee4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:47:55 +0200 Subject: [PATCH 11/24] fixup new line --- Lib/symtable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index 23b520a273005f..094d9580466177 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -16,7 +16,6 @@ __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] - def symtable(code, filename, compile_type): """ Return the toplevel *SymbolTable* for the source code. From 46f16046990f05deb632d1b8afa3ebd07076f6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:11:07 +0200 Subject: [PATCH 12/24] expose ``is_free_class`` --- Doc/library/symtable.rst | 19 +++++++++++++++++++ Lib/symtable.py | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 1e25c1af80d7ee..501b9ff1d95751 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -184,6 +184,25 @@ Examining Symbol Tables Return ``True`` if the symbol is referenced in its block, but not assigned to. + .. method:: is_free_class() + + Return *True* if a symbol is free from a method perspective. + + Consider the following example:: + + def f(): + x = 1 # function-scoped + class C: + x = 2 # class-scoped + def method(self): + return x + + In this example, the the class-scoped ``x`` symbol is considered + to be free from the perspective of ``C.method``, thereby allowing + the ``method`` to return `1` at runtime and not `2`. + + .. versionadded:: 3.14 + .. method:: is_assigned() Return ``True`` if the symbol is assigned to in its block. diff --git a/Lib/symtable.py b/Lib/symtable.py index 094d9580466177..f578175f179a84 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -308,6 +308,10 @@ def is_free(self): """ return bool(self.__scope == FREE) + def is_free_class(self): + """Return *True* if a symbol is free from a method perspective.""" + return bool(self.__flags & DEF_FREE_CLASS) + def is_imported(self): """Return *True* if the symbol is created from an import statement. From f853905c3de2d86edbca987f0dd71269ae9a6f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:13:12 +0200 Subject: [PATCH 13/24] un-expose `DEF_FREE` --- Lib/symtable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/symtable.py b/Lib/symtable.py index f578175f179a84..a8b535ead20433 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -5,7 +5,7 @@ USE, DEF_GLOBAL, DEF_NONLOCAL, DEF_LOCAL, DEF_PARAM, DEF_TYPE_PARAM, - DEF_FREE, DEF_FREE_CLASS, + DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, DEF_ANNOT, DEF_COMP_ITER, DEF_COMP_CELL, SCOPE_OFF, SCOPE_MASK, From f2ef8999e6851d3760792bd1ec12d7eab5f535bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:14:34 +0200 Subject: [PATCH 14/24] re-blurb --- .../Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst index 04f1a17d85ac4a..36a10d625f263a 100644 --- a/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst +++ b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst @@ -1,4 +1,4 @@ -Expose :meth:`symtable.Symbol.is_comp_iter` and :meth:`symtable.Symbol.is_comp_cell` -in the :mod:`symtable` module. +Expose :meth:`symtable.Symbol.is_free_class`, :meth:`symtable.Symbol.is_comp_iter` +and :meth:`symtable.Symbol.is_comp_cell` in the :mod:`symtable` module. Patch by Bénédikt Tran. From c915f04c67ccb7d8fb80200939e6e6b7bc05e1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:20:41 +0200 Subject: [PATCH 15/24] add test --- Lib/test/test_symtable.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index cb9f8891b622fc..83787e9635e6af 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -310,6 +310,18 @@ def test_symbol_repr(self): self.assertEqual(repr(st2.lookup("x")), "") + st3 = symtable.symtable("def f():\n" + " x = 1\n" + " class A:\n" + " x = 2\n" + " def method():\n" + " return x\n", + "?", "exec") + func_f = st3.get_children()[0] + class_A = func_f.get_children()[0] + self.assertEqual(repr(class_A.lookup('x')), + "") + def test_symtable_entry_repr(self): expected = f"" self.assertEqual(repr(self.top._table), expected) From d101a582bd887abec036c0123c3b4df2d006a9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:21:06 +0200 Subject: [PATCH 16/24] fix lint --- Doc/library/symtable.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 501b9ff1d95751..ce8f133f6196ab 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -199,7 +199,7 @@ Examining Symbol Tables In this example, the the class-scoped ``x`` symbol is considered to be free from the perspective of ``C.method``, thereby allowing - the ``method`` to return `1` at runtime and not `2`. + the ``method`` to return *1* at runtime and not *2*. .. versionadded:: 3.14 From 6c450fa9d70cd331705e6b5d4d9c25f52617476a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:47:35 +0200 Subject: [PATCH 17/24] fix indentation --- Doc/library/symtable.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index ce8f133f6196ab..dc01d82eab7f5e 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -192,10 +192,10 @@ Examining Symbol Tables def f(): x = 1 # function-scoped - class C: - x = 2 # class-scoped - def method(self): - return x + class C: + x = 2 # class-scoped + def method(self): + return x In this example, the the class-scoped ``x`` symbol is considered to be free from the perspective of ``C.method``, thereby allowing From c44622b505f97b2d4820285eea6e9bbde731ce18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:49:25 +0200 Subject: [PATCH 18/24] update NEWS --- .../Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst index 36a10d625f263a..d1b2c592a113ce 100644 --- a/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst +++ b/Misc/NEWS.d/next/Library/2024-06-05-11-03-10.gh-issue-120029.QBsw47.rst @@ -1,4 +1,4 @@ -Expose :meth:`symtable.Symbol.is_free_class`, :meth:`symtable.Symbol.is_comp_iter` -and :meth:`symtable.Symbol.is_comp_cell` in the :mod:`symtable` module. +Expose :class:`symtable.Symbol` methods :meth:`~symtable.Symbol.is_free_class`, +:meth:`~symtable.Symbol.is_comp_iter` and :meth:`~symtable.Symbol.is_comp_cell`. Patch by Bénédikt Tran. From 379c368a8df860ac8ef1e7ac68b6339c0e71d4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:53:56 +0200 Subject: [PATCH 19/24] update CHANGELOG --- Doc/whatsnew/3.14.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index b2dd80b64a691a..71d79d46ce1915 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -92,6 +92,16 @@ ast Added :func:`ast.compare` for comparing two ASTs. (Contributed by Batuhan Taskaya and Jeremy Hylton in :issue:`15987`.) +symtable +-------- + +* Expose the following :class:`symtable.Symbol` methods: + + * :meth:`~symtable.Symbol.is_free_class` + * :meth:`~symtable.Symbol.is_comp_iter` + * :meth:`~symtable.Symbol.is_comp_cell` + + (Contributed by Bénédikt Tran in :issue:`120029`.) Optimizations From 8420820c5ae1e41982eb417e55168c53532dd6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:54:56 +0200 Subject: [PATCH 20/24] fix typo --- Doc/library/symtable.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index dc01d82eab7f5e..5985854dc66e78 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -197,9 +197,9 @@ Examining Symbol Tables def method(self): return x - In this example, the the class-scoped ``x`` symbol is considered - to be free from the perspective of ``C.method``, thereby allowing - the ``method`` to return *1* at runtime and not *2*. + In this example, the class-scoped ``x`` symbol is considered to + be free from the perspective of ``C.method``, thereby allowing + the latter to return *1* at runtime and not *2*. .. versionadded:: 3.14 From ede2a58a981522dde19fcd720eace7eb0563201d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:06:12 +0200 Subject: [PATCH 21/24] fixup --- Doc/whatsnew/3.14.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 71d79d46ce1915..f05b6668d04304 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -101,7 +101,7 @@ symtable * :meth:`~symtable.Symbol.is_comp_iter` * :meth:`~symtable.Symbol.is_comp_cell` - (Contributed by Bénédikt Tran in :issue:`120029`.) + (Contributed by Bénédikt Tran in :gh:`120029`.) Optimizations From 9d8dfb417a657f2b0f790de7a6abe6d865088375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:42:45 +0200 Subject: [PATCH 22/24] address review --- Doc/library/symtable.rst | 3 ++- Lib/symtable.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 5985854dc66e78..7b88df664b004d 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -186,7 +186,8 @@ Examining Symbol Tables .. method:: is_free_class() - Return *True* if a symbol is free from a method perspective. + Return *True* if a class-scoped symbol is free from + the perspective of a method. Consider the following example:: diff --git a/Lib/symtable.py b/Lib/symtable.py index a8b535ead20433..f0b43919d5b01c 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -309,7 +309,8 @@ def is_free(self): return bool(self.__scope == FREE) def is_free_class(self): - """Return *True* if a symbol is free from a method perspective.""" + """Return *True* if a class-scoped symbol is free from + the perspective of a method.""" return bool(self.__flags & DEF_FREE_CLASS) def is_imported(self): From de459bb88313bad255b9979616d3ad0535b107ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:43:28 +0200 Subject: [PATCH 23/24] fixup --- Doc/library/symtable.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 7b88df664b004d..050a941d9d0516 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -198,7 +198,7 @@ Examining Symbol Tables def method(self): return x - In this example, the class-scoped ``x`` symbol is considered to + In this example, the class-scoped symbol ``x`` is considered to be free from the perspective of ``C.method``, thereby allowing the latter to return *1* at runtime and not *2*. From ac51d696f5d6b8893e3111d6d899bc78b3154063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:08:20 +0200 Subject: [PATCH 24/24] fix test --- Lib/test/test_symtable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index dec951f666b2aa..903c6d66f50964 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -319,7 +319,8 @@ def test_symbol_repr(self): " def method():\n" " return x\n", "?", "exec") - func_f = st3.get_children()[0] + # child 0 is for __annotate__ + func_f = st3.get_children()[1] class_A = func_f.get_children()[0] self.assertEqual(repr(class_A.lookup('x')), "")