mirror of
https://github.com/python/cpython.git
synced 2024-11-24 00:38:00 +01:00
gh-70764: inspect.getclosurevars now identifies global variables with LOAD_GLOBAL (#120143)
This commit is contained in:
parent
fc233f46d3
commit
83ba8c2bba
@ -1507,11 +1507,15 @@ def getclosurevars(func):
|
|||||||
global_vars = {}
|
global_vars = {}
|
||||||
builtin_vars = {}
|
builtin_vars = {}
|
||||||
unbound_names = set()
|
unbound_names = set()
|
||||||
for name in code.co_names:
|
global_names = set()
|
||||||
if name in ("None", "True", "False"):
|
for instruction in dis.get_instructions(code):
|
||||||
# Because these used to be builtins instead of keywords, they
|
opname = instruction.opname
|
||||||
# may still show up as name references. We ignore them.
|
name = instruction.argval
|
||||||
continue
|
if opname == "LOAD_ATTR":
|
||||||
|
unbound_names.add(name)
|
||||||
|
elif opname == "LOAD_GLOBAL":
|
||||||
|
global_names.add(name)
|
||||||
|
for name in global_names:
|
||||||
try:
|
try:
|
||||||
global_vars[name] = global_ns[name]
|
global_vars[name] = global_ns[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -1960,6 +1960,19 @@ class TestGetClosureVars(unittest.TestCase):
|
|||||||
builtin_vars, unbound_names)
|
builtin_vars, unbound_names)
|
||||||
self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
|
self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
|
||||||
|
|
||||||
|
def test_attribute_same_name_as_global_var(self):
|
||||||
|
class C:
|
||||||
|
_global_ref = object()
|
||||||
|
def f():
|
||||||
|
print(C._global_ref, _global_ref)
|
||||||
|
nonlocal_vars = {"C": C}
|
||||||
|
global_vars = {"_global_ref": _global_ref}
|
||||||
|
builtin_vars = {"print": print}
|
||||||
|
unbound_names = {"_global_ref"}
|
||||||
|
expected = inspect.ClosureVars(nonlocal_vars, global_vars,
|
||||||
|
builtin_vars, unbound_names)
|
||||||
|
self.assertEqual(inspect.getclosurevars(f), expected)
|
||||||
|
|
||||||
def test_nonlocal_vars(self):
|
def test_nonlocal_vars(self):
|
||||||
# More complex tests of nonlocal resolution
|
# More complex tests of nonlocal resolution
|
||||||
def _nonlocal_vars(f):
|
def _nonlocal_vars(f):
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Fixed an issue where :func:`inspect.getclosurevars` would incorrectly classify an attribute name as a global variable when the name exists both as an attribute name and a global variable.
|
Loading…
Reference in New Issue
Block a user