if self._table.name == "global": return "<{0}SymbolTable for module {1}>".format(kind, self._filename) else: return "<{0}SymbolTable for {1} in {2}>".format(kind, self._table.name, self._filename)
def get_type(self): if self._table.type == _symtable.TYPE_MODULE: return "module" if self._table.type == _symtable.TYPE_FUNCTION: return "function" if self._table.type == _symtable.TYPE_CLASS: return "class" assert self._table.type in (1, 2, 3), \ "unexpected type: {0}".format(self._table.type)
def get_methods(self): if self.__methods is None: d = {} for st in self._table.children: d[st.name] = 1 self.__methods = tuple(d) return self.__methods
class Symbol(object):
def __init__(self, name, flags, namespaces=None): self.__name = name self.__flags = flags self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope() self.__namespaces = namespaces or ()
def is_namespace(self): """Returns true if name binding introduces new namespace.
If the name is used as the target of a function or class statement, this will be true.
Note that a single name can be bound to multiple objects. If is_namespace() is true, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace. """ return bool(self.__namespaces)
def get_namespaces(self): """Return a list of namespaces bound to this name""" return self.__namespaces
def get_namespace(self): """Returns the single namespace bound to this name.
Raises ValueError if the name is bound to multiple namespaces. """ if len(self.__namespaces) != 1: raise ValueError("name is bound to multiple namespaces") return self.__namespaces[0]
if __name__ == "__main__": import os, sys with open(sys.argv[0]) as f: src = f.read() mod = symtable(src, os.path.split(sys.argv[0])[1], "exec") for ident in mod.get_identifiers(): info = mod.lookup(ident) print(info, info.is_local(), info.is_namespace())