Skip to content

Commit

Permalink
[3.12] gh-70764: inspect.getclosurevars now identifies global variabl…
Browse files Browse the repository at this point in the history
…es with LOAD_GLOBAL (GH-120143) (#126460)

gh-70764: inspect.getclosurevars now identifies global variables with LOAD_GLOBAL (GH-120143)
(cherry picked from commit 83ba8c2)

Co-authored-by: blhsing <[email protected]>
  • Loading branch information
miss-islington and blhsing authored Nov 6, 2024
1 parent b00887d commit fc01844
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
14 changes: 9 additions & 5 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1638,11 +1638,15 @@ def getclosurevars(func):
global_vars = {}
builtin_vars = {}
unbound_names = set()
for name in code.co_names:
if name in ("None", "True", "False"):
# Because these used to be builtins instead of keywords, they
# may still show up as name references. We ignore them.
continue
global_names = set()
for instruction in dis.get_instructions(code):
opname = instruction.opname
name = instruction.argval
if opname == "LOAD_ATTR":
unbound_names.add(name)
elif opname == "LOAD_GLOBAL":
global_names.add(name)
for name in global_names:
try:
global_vars[name] = global_ns[name]
except KeyError:
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,19 @@ def g(local_ref):
builtin_vars, unbound_names)
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):
# More complex tests of nonlocal resolution
def _nonlocal_vars(f):
Expand Down
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit fc01844

Please sign in to comment.