254 lines
9.1 KiB
Python
254 lines
9.1 KiB
Python
import sys as _sys
|
|
import ast as _ast
|
|
from ast import boolop, cmpop, excepthandler, expr, expr_context, operator
|
|
from ast import slice, stmt, unaryop, mod, AST
|
|
|
|
|
|
def _make_node(Name, Fields, Attributes, Bases):
|
|
def create_node(self, *args, **kwargs):
|
|
nbparam = len(args) + len(kwargs)
|
|
assert nbparam in (0, len(Fields)), \
|
|
"Bad argument number for {}: {}, expecting {}".\
|
|
format(Name, nbparam, len(Fields))
|
|
self._fields = Fields
|
|
self._attributes = Attributes
|
|
for argname, argval in zip(self._fields, args):
|
|
setattr(self, argname, argval)
|
|
for argname, argval in kwargs.items():
|
|
assert argname in Fields, \
|
|
"Invalid Keyword argument for {}: {}".format(Name, argname)
|
|
setattr(self, argname, argval)
|
|
|
|
setattr(_sys.modules[__name__],
|
|
Name,
|
|
type(Name,
|
|
Bases,
|
|
{'__init__': create_node}))
|
|
|
|
_nodes = {
|
|
# mod
|
|
'Module': (('body',), (), (mod,)),
|
|
'Interactive': (('body',), (), (mod,)),
|
|
'Expression': (('body',), (), (mod,)),
|
|
'Suite': (('body',), (), (mod,)),
|
|
|
|
# stmt
|
|
'FunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns',),
|
|
('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'AsyncFunctionDef': (('name', 'args', 'body',
|
|
'decorator_list', 'returns',),
|
|
('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'ClassDef': (('name', 'bases', 'keywords', 'body', 'decorator_list',),
|
|
('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Return': (('value',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Delete': (('targets',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Assign': (('targets', 'value',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'AugAssign': (('target', 'op', 'value',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Print': (('dest', 'values', 'nl',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'For': (('target', 'iter', 'body', 'orelse',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'AsyncFor': (('target', 'iter', 'body', 'orelse',),
|
|
('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'While': (('test', 'body', 'orelse',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'If': (('test', 'body', 'orelse',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'With': (('items', 'body',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'AsyncWith': (('items', 'body',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Raise': (('exc', 'cause',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Try': (('body', 'handlers', 'orelse', 'finalbody',),
|
|
('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Assert': (('test', 'msg',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Import': (('names',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'ImportFrom': (('module', 'names', 'level',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Exec': (('body', 'globals', 'locals',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Global': (('names',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Nonlocal': (('names',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Expr': (('value',), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Pass': ((), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Break': ((), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
'Continue': ((), ('lineno', 'col_offset',),
|
|
(stmt,)),
|
|
|
|
# expr
|
|
|
|
'BoolOp': (('op', 'values',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'BinOp': (('left', 'op', 'right',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'UnaryOp': (('op', 'operand',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Lambda': (('args', 'body',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'IfExp': (('test', 'body', 'orelse',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Dict': (('keys', 'values',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Set': (('elts',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'ListComp': (('elt', 'generators',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'SetComp': (('elt', 'generators',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'DictComp': (('key', 'value', 'generators',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'GeneratorExp': (('elt', 'generators',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Await': (('value',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Yield': (('value',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'YieldFrom': (('value',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Compare': (('left', 'ops', 'comparators',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Call': (('func', 'args', 'keywords',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Repr': (('value',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Num': (('n',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Str': (('s',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'FormattedValue': (('value', 'conversion', 'format_spec',),
|
|
('lineno', 'col_offset',), (expr,)),
|
|
'JoinedStr': (('values',), ('lineno', 'col_offset',), (expr,)),
|
|
'Bytes': (('s',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'NameConstant': (('value',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Ellipsis': ((), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Attribute': (('value', 'attr', 'ctx',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Subscript': (('value', 'slice', 'ctx',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Starred': (('value', 'ctx',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Name': (('id', 'ctx', 'annotation'), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'List': (('elts', 'ctx',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
'Tuple': (('elts', 'ctx',), ('lineno', 'col_offset',),
|
|
(expr,)),
|
|
|
|
# expr_context
|
|
'Load': ((), (), (expr_context,)),
|
|
'Store': ((), (), (expr_context,)),
|
|
'Del': ((), (), (expr_context,)),
|
|
'AugLoad': ((), (), (expr_context,)),
|
|
'AugStore': ((), (), (expr_context,)),
|
|
'Param': ((), (), (expr_context,)),
|
|
|
|
# slice
|
|
'Slice': (('lower', 'upper', 'step'), (), (slice,)),
|
|
'ExtSlice': (('dims',), (), (slice,)),
|
|
'Index': (('value',), (), (slice,)),
|
|
|
|
# boolop
|
|
'And': ((), (), (boolop,)),
|
|
'Or': ((), (), (boolop,)),
|
|
|
|
# operator
|
|
'Add': ((), (), (operator,)),
|
|
'Sub': ((), (), (operator,)),
|
|
'Mult': ((), (), (operator,)),
|
|
'MatMult': ((), (), (operator,)),
|
|
'Div': ((), (), (operator,)),
|
|
'Mod': ((), (), (operator,)),
|
|
'Pow': ((), (), (operator,)),
|
|
'LShift': ((), (), (operator,)),
|
|
'RShift': ((), (), (operator,)),
|
|
'BitOr': ((), (), (operator,)),
|
|
'BitXor': ((), (), (operator,)),
|
|
'BitAnd': ((), (), (operator,)),
|
|
'FloorDiv': ((), (), (operator,)),
|
|
|
|
# unaryop
|
|
'Invert': ((), (), (unaryop, AST,)),
|
|
'Not': ((), (), (unaryop, AST,)),
|
|
'UAdd': ((), (), (unaryop, AST,)),
|
|
'USub': ((), (), (unaryop, AST,)),
|
|
|
|
# cmpop
|
|
'Eq': ((), (), (cmpop,)),
|
|
'NotEq': ((), (), (cmpop,)),
|
|
'Lt': ((), (), (cmpop,)),
|
|
'LtE': ((), (), (cmpop,)),
|
|
'Gt': ((), (), (cmpop,)),
|
|
'GtE': ((), (), (cmpop,)),
|
|
'Is': ((), (), (cmpop,)),
|
|
'IsNot': ((), (), (cmpop,)),
|
|
'In': ((), (), (cmpop,)),
|
|
'NotIn': ((), (), (cmpop,)),
|
|
|
|
# comprehension
|
|
'comprehension': (('target', 'iter', 'ifs', 'is_async'), (), (AST,)),
|
|
|
|
# excepthandler
|
|
'ExceptHandler': (('type', 'name', 'body'), ('lineno', 'col_offset'),
|
|
(excepthandler,)),
|
|
|
|
# arguments
|
|
'arguments': (('args', 'vararg', 'kwonlyargs', 'kw_defaults',
|
|
'kwarg', 'defaults'), (), (AST,)),
|
|
# keyword
|
|
'keyword': (('arg', 'value'), (), (AST,)),
|
|
|
|
# alias
|
|
'alias': (('name', 'asname'), (), (AST,)),
|
|
|
|
# withitem
|
|
'withitem': (('context_expr', 'optional_vars'), (), (AST,)),
|
|
}
|
|
|
|
for name, descr in _nodes.items():
|
|
_make_node(name, *descr)
|
|
|
|
if _sys.version_info.major == 2:
|
|
from .ast2 import ast_to_gast, gast_to_ast
|
|
if _sys.version_info.major == 3:
|
|
from .ast3 import ast_to_gast, gast_to_ast
|
|
|
|
|
|
def parse(*args, **kwargs):
|
|
return ast_to_gast(_ast.parse(*args, **kwargs))
|
|
|
|
|
|
def literal_eval(node_or_string):
|
|
if isinstance(node_or_string, AST):
|
|
node_or_string = gast_to_ast(node_or_string)
|
|
return _ast.literal_eval(node_or_string)
|
|
|
|
|
|
def get_docstring(node, clean=True):
|
|
if not isinstance(node, (FunctionDef, ClassDef, Module)):
|
|
raise TypeError("%r can't have docstrings" % node.__class__.__name__)
|
|
if node.body and isinstance(node.body[0], Expr) and \
|
|
isinstance(node.body[0].value, Str):
|
|
if clean:
|
|
import inspect
|
|
return inspect.cleandoc(node.body[0].value.s)
|
|
return node.body[0].value.s
|