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)
| 1578 | ClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound') |
| 1579 | |
| 1580 | def getclosurevars(func): |
| 1581 | """ |
| 1582 | Get the mapping of free variables to their current values. |
| 1583 | |
| 1584 | Returns a named tuple of dicts mapping the current nonlocal, global |
| 1585 | and builtin references as seen by the body of the function. A final |
| 1586 | set of unbound names that could not be resolved is also provided. |
| 1587 | """ |
| 1588 | |
| 1589 | if ismethod(func): |
| 1590 | func = func.__func__ |
| 1591 | |
| 1592 | if not isfunction(func): |
| 1593 | raise TypeError("{!r} is not a Python function".format(func)) |
| 1594 | |
| 1595 | code = func.__code__ |
| 1596 | # Nonlocal references are named in co_freevars and resolved |
| 1597 | # by looking them up in __closure__ by positional index |
| 1598 | if func.__closure__ is None: |
| 1599 | nonlocal_vars = {} |
| 1600 | else: |
| 1601 | nonlocal_vars = { |
| 1602 | var : cell.cell_contents |
| 1603 | for var, cell in zip(code.co_freevars, func.__closure__) |
| 1604 | } |
| 1605 | |
| 1606 | # Global and builtin references are named in co_names and resolved |
| 1607 | # by looking them up in __globals__ or __builtins__ |
| 1608 | global_ns = func.__globals__ |
| 1609 | builtin_ns = global_ns.get("__builtins__", builtins.__dict__) |
| 1610 | if ismodule(builtin_ns): |
| 1611 | builtin_ns = builtin_ns.__dict__ |
| 1612 | global_vars = {} |
| 1613 | builtin_vars = {} |
| 1614 | unbound_names = set() |
| 1615 | for name in code.co_names: |
| 1616 | if name in ("None", "True", "False"): |
| 1617 | # Because these used to be builtins instead of keywords, they |
| 1618 | # may still show up as name references. We ignore them. |
| 1619 | continue |
| 1620 | try: |
| 1621 | global_vars[name] = global_ns[name] |
| 1622 | except KeyError: |
| 1623 | try: |
| 1624 | builtin_vars[name] = builtin_ns[name] |
| 1625 | except KeyError: |
| 1626 | unbound_names.add(name) |
| 1627 | |
| 1628 | return ClosureVars(nonlocal_vars, global_vars, |
| 1629 | builtin_vars, unbound_names) |
| 1630 | |
| 1631 | # -------------------------------------------------- stack frame extraction |
| 1632 |