bpo-41224: Document is_annotated() in symtable module and update doc strings (GH-21369)

* Document is_annotate() and update doc strings

* Move quotes to the next line.

Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>

Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
This commit is contained in:
Joannah Nanjekye 2020-07-07 20:09:56 -03:00 committed by GitHub
parent 8f42748ded
commit a95ac779e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 2 deletions

View File

@ -156,6 +156,10 @@ Examining Symbol Tables
Return ``True`` if the symbol is local to its block. Return ``True`` if the symbol is local to its block.
.. method:: is_annotated()
Return ``True`` if the symbol is annotated.
.. method:: is_free() .. method:: is_free()
Return ``True`` if the symbol is referenced in its block, but not assigned Return ``True`` if the symbol is referenced in its block, but not assigned

View File

@ -10,6 +10,11 @@ import weakref
__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
def symtable(code, filename, compile_type): def symtable(code, filename, compile_type):
""" Return the toplevel *SymbolTable* for the source code.
*filename* is the name of the file with the code
and *compile_type* is the *compile()* mode argument.
"""
top = _symtable.symtable(code, filename, compile_type) top = _symtable.symtable(code, filename, compile_type)
return _newSymbolTable(top, filename) return _newSymbolTable(top, filename)
@ -55,6 +60,11 @@ class SymbolTable(object):
self._filename) self._filename)
def get_type(self): def get_type(self):
"""Return the type of the symbol table.
The values retuned are 'class', 'module' and
'function'.
"""
if self._table.type == _symtable.TYPE_MODULE: if self._table.type == _symtable.TYPE_MODULE:
return "module" return "module"
if self._table.type == _symtable.TYPE_FUNCTION: if self._table.type == _symtable.TYPE_FUNCTION:
@ -65,27 +75,51 @@ class SymbolTable(object):
"unexpected type: {0}".format(self._table.type) "unexpected type: {0}".format(self._table.type)
def get_id(self): def get_id(self):
"""Return an identifier for the table.
"""
return self._table.id return self._table.id
def get_name(self): def get_name(self):
"""Return the table's name.
This corresponds to the name of the class, function
or 'top' if the table is for a class, function or
global respectively.
"""
return self._table.name return self._table.name
def get_lineno(self): def get_lineno(self):
"""Return the number of the first line in the
block for the table.
"""
return self._table.lineno return self._table.lineno
def is_optimized(self): def is_optimized(self):
"""Return *True* if the locals in the table
are optimizable.
"""
return bool(self._table.type == _symtable.TYPE_FUNCTION) return bool(self._table.type == _symtable.TYPE_FUNCTION)
def is_nested(self): def is_nested(self):
"""Return *True* if the block is a nested class
or function."""
return bool(self._table.nested) return bool(self._table.nested)
def has_children(self): def has_children(self):
"""Return *True* if the block has nested namespaces.
"""
return bool(self._table.children) return bool(self._table.children)
def get_identifiers(self): def get_identifiers(self):
"""Return a list of names of symbols in the table.
"""
return self._table.symbols.keys() return self._table.symbols.keys()
def lookup(self, name): def lookup(self, name):
"""Lookup a *name* in the table.
Returns a *Symbol* instance.
"""
sym = self._symbols.get(name) sym = self._symbols.get(name)
if sym is None: if sym is None:
flags = self._table.symbols[name] flags = self._table.symbols[name]
@ -94,6 +128,9 @@ class SymbolTable(object):
return sym return sym
def get_symbols(self): def get_symbols(self):
"""Return a list of *Symbol* instances for
names in the table.
"""
return [self.lookup(ident) for ident in self.get_identifiers()] return [self.lookup(ident) for ident in self.get_identifiers()]
def __check_children(self, name): def __check_children(self, name):
@ -102,6 +139,8 @@ class SymbolTable(object):
if st.name == name] if st.name == name]
def get_children(self): def get_children(self):
"""Return a list of the nested symbol tables.
"""
return [_newSymbolTable(st, self._filename) return [_newSymbolTable(st, self._filename)
for st in self._table.children] for st in self._table.children]
@ -120,11 +159,15 @@ class Function(SymbolTable):
if test_func(self._table.symbols[ident])) if test_func(self._table.symbols[ident]))
def get_parameters(self): def get_parameters(self):
"""Return a tuple of parameters to the function.
"""
if self.__params is None: if self.__params is None:
self.__params = self.__idents_matching(lambda x:x & DEF_PARAM) self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
return self.__params return self.__params
def get_locals(self): def get_locals(self):
"""Return a tuple of locals in the function.
"""
if self.__locals is None: if self.__locals is None:
locs = (LOCAL, CELL) locs = (LOCAL, CELL)
test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs
@ -132,6 +175,8 @@ class Function(SymbolTable):
return self.__locals return self.__locals
def get_globals(self): def get_globals(self):
"""Return a tuple of globals in the function.
"""
if self.__globals is None: if self.__globals is None:
glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
@ -139,11 +184,15 @@ class Function(SymbolTable):
return self.__globals return self.__globals
def get_nonlocals(self): def get_nonlocals(self):
"""Return a tuple of nonlocals in the function.
"""
if self.__nonlocals is None: if self.__nonlocals is None:
self.__nonlocals = self.__idents_matching(lambda x:x & DEF_NONLOCAL) self.__nonlocals = self.__idents_matching(lambda x:x & DEF_NONLOCAL)
return self.__nonlocals return self.__nonlocals
def get_frees(self): def get_frees(self):
"""Return a tuple of free variables in the function.
"""
if self.__frees is None: if self.__frees is None:
is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
self.__frees = self.__idents_matching(is_free) self.__frees = self.__idents_matching(is_free)
@ -155,6 +204,8 @@ class Class(SymbolTable):
__methods = None __methods = None
def get_methods(self): def get_methods(self):
"""Return a tuple of methods declared in the class.
"""
if self.__methods is None: if self.__methods is None:
d = {} d = {}
for st in self._table.children: for st in self._table.children:
@ -175,40 +226,63 @@ class Symbol(object):
return "<symbol {0!r}>".format(self.__name) return "<symbol {0!r}>".format(self.__name)
def get_name(self): def get_name(self):
"""Return a name of a symbol.
"""
return self.__name return self.__name
def is_referenced(self): def is_referenced(self):
"""Return *True* if the symbol is used in
its block.
"""
return bool(self.__flags & _symtable.USE) return bool(self.__flags & _symtable.USE)
def is_parameter(self): def is_parameter(self):
"""Return *True* if the symbol is a parameter.
"""
return bool(self.__flags & DEF_PARAM) return bool(self.__flags & DEF_PARAM)
def is_global(self): def is_global(self):
"""Return *True* if the sysmbol is global.
"""
return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
def is_nonlocal(self): def is_nonlocal(self):
"""Return *True* if the symbol is nonlocal."""
return bool(self.__flags & DEF_NONLOCAL) return bool(self.__flags & DEF_NONLOCAL)
def is_declared_global(self): def is_declared_global(self):
"""Return *True* if the symbol is declared global
with a global statement."""
return bool(self.__scope == GLOBAL_EXPLICIT) return bool(self.__scope == GLOBAL_EXPLICIT)
def is_local(self): def is_local(self):
"""Return *True* if the symbol is local.
"""
return bool(self.__scope in (LOCAL, CELL)) return bool(self.__scope in (LOCAL, CELL))
def is_annotated(self): def is_annotated(self):
"""Return *True* if the symbol is annotated.
"""
return bool(self.__flags & DEF_ANNOT) return bool(self.__flags & DEF_ANNOT)
def is_free(self): def is_free(self):
"""Return *True* if a referenced symbol is
not assigned to.
"""
return bool(self.__scope == FREE) return bool(self.__scope == FREE)
def is_imported(self): def is_imported(self):
"""Return *True* if the symbol is created from
an import statement.
"""
return bool(self.__flags & DEF_IMPORT) return bool(self.__flags & DEF_IMPORT)
def is_assigned(self): def is_assigned(self):
"""Return *True* if a symbol is assigned to."""
return bool(self.__flags & DEF_LOCAL) return bool(self.__flags & DEF_LOCAL)
def is_namespace(self): def is_namespace(self):
"""Returns true if name binding introduces new namespace. """Returns *True* if name binding introduces new namespace.
If the name is used as the target of a function or class If the name is used as the target of a function or class
statement, this will be true. statement, this will be true.
@ -225,7 +299,7 @@ class Symbol(object):
return self.__namespaces return self.__namespaces
def get_namespace(self): def get_namespace(self):
"""Returns the single namespace bound to this name. """Return the single namespace bound to this name.
Raises ValueError if the name is bound to multiple namespaces. Raises ValueError if the name is bound to multiple namespaces.
""" """