Skip to content

Commit 83ba8c2

Browse files
authored
gh-70764: inspect.getclosurevars now identifies global variables with LOAD_GLOBAL (#120143)
1 parent fc233f4 commit 83ba8c2

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

Lib/inspect.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,11 +1507,15 @@ def getclosurevars(func):
15071507
global_vars = {}
15081508
builtin_vars = {}
15091509
unbound_names = set()
1510-
for name in code.co_names:
1511-
if name in ("None", "True", "False"):
1512-
# Because these used to be builtins instead of keywords, they
1513-
# may still show up as name references. We ignore them.
1514-
continue
1510+
global_names = set()
1511+
for instruction in dis.get_instructions(code):
1512+
opname = instruction.opname
1513+
name = instruction.argval
1514+
if opname == "LOAD_ATTR":
1515+
unbound_names.add(name)
1516+
elif opname == "LOAD_GLOBAL":
1517+
global_names.add(name)
1518+
for name in global_names:
15151519
try:
15161520
global_vars[name] = global_ns[name]
15171521
except KeyError:

Lib/test/test_inspect/test_inspect.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,6 +1960,19 @@ def g(local_ref):
19601960
builtin_vars, unbound_names)
19611961
self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
19621962

1963+
def test_attribute_same_name_as_global_var(self):
1964+
class C:
1965+
_global_ref = object()
1966+
def f():
1967+
print(C._global_ref, _global_ref)
1968+
nonlocal_vars = {"C": C}
1969+
global_vars = {"_global_ref": _global_ref}
1970+
builtin_vars = {"print": print}
1971+
unbound_names = {"_global_ref"}
1972+
expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1973+
builtin_vars, unbound_names)
1974+
self.assertEqual(inspect.getclosurevars(f), expected)
1975+
19631976
def test_nonlocal_vars(self):
19641977
# More complex tests of nonlocal resolution
19651978
def _nonlocal_vars(f):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

0 commit comments

Comments
 (0)