Get the mapping of free variables to their current values. Returns a named tuple of dicts mapping the current nonlocal, global and builtin references as seen by the body of the function. A final set of unbound names that could not be resolved is also provided.
(func)
| 1484 | ClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound') |
| 1485 | |
| 1486 | def getclosurevars(func): |
| 1487 | """ |
| 1488 | Get the mapping of free variables to their current values. |
| 1489 | |
| 1490 | Returns a named tuple of dicts mapping the current nonlocal, global |
| 1491 | and builtin references as seen by the body of the function. A final |
| 1492 | set of unbound names that could not be resolved is also provided. |
| 1493 | """ |
| 1494 | |
| 1495 | if ismethod(func): |
| 1496 | func = func.__func__ |
| 1497 | |
| 1498 | if not isfunction(func): |
| 1499 | raise TypeError("{!r} is not a Python function".format(func)) |
| 1500 | |
| 1501 | code = func.__code__ |
| 1502 | # Nonlocal references are named in co_freevars and resolved |
| 1503 | # by looking them up in __closure__ by positional index |
| 1504 | if func.__closure__ is None: |
| 1505 | nonlocal_vars = {} |
| 1506 | else: |
| 1507 | nonlocal_vars = { |
| 1508 | var : cell.cell_contents |
| 1509 | for var, cell in zip(code.co_freevars, func.__closure__) |
| 1510 | } |
| 1511 | |
| 1512 | # Global and builtin references are named in co_names and resolved |
| 1513 | # by looking them up in __globals__ or __builtins__ |
| 1514 | global_ns = func.__globals__ |
| 1515 | builtin_ns = global_ns.get("__builtins__", builtins.__dict__) |
| 1516 | if ismodule(builtin_ns): |
| 1517 | builtin_ns = builtin_ns.__dict__ |
| 1518 | global_vars = {} |
| 1519 | builtin_vars = {} |
| 1520 | unbound_names = set() |
| 1521 | global_names = set() |
| 1522 | for instruction in dis.get_instructions(code): |
| 1523 | opname = instruction.opname |
| 1524 | name = instruction.argval |
| 1525 | if opname == "LOAD_ATTR": |
| 1526 | unbound_names.add(name) |
| 1527 | elif opname == "LOAD_GLOBAL": |
| 1528 | global_names.add(name) |
| 1529 | for name in global_names: |
| 1530 | try: |
| 1531 | global_vars[name] = global_ns[name] |
| 1532 | except KeyError: |
| 1533 | try: |
| 1534 | builtin_vars[name] = builtin_ns[name] |
| 1535 | except KeyError: |
| 1536 | unbound_names.add(name) |
| 1537 | |
| 1538 | return ClosureVars(nonlocal_vars, global_vars, |
| 1539 | builtin_vars, unbound_names) |
| 1540 | |
| 1541 | # -------------------------------------------------- stack frame extraction |
| 1542 |
nothing calls this directly
no test coverage detected