chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2016, Serge Guelton
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# Neither the name of HPCProject, Serge Guelton nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# NOTE(paddle-dev): We introduce third-party library Gast as unified AST
|
||||
# representation. See https://github.com/serge-sans-paille/gast for details.
|
||||
|
||||
from .gast import *
|
||||
from ast import NodeVisitor, NodeTransformer, iter_fields
|
||||
@@ -0,0 +1,602 @@
|
||||
# Copyright (c) 2016, Serge Guelton
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# Neither the name of HPCProject, Serge Guelton nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# NOTE(paddle-dev): We introduce third-party library Gast as unified AST
|
||||
# representation. See https://github.com/serge-sans-paille/gast for details.
|
||||
|
||||
from .astn import AstToGAst, GAstToAst
|
||||
from . import gast
|
||||
import ast
|
||||
import sys
|
||||
|
||||
|
||||
class Ast3ToGAst(AstToGAst):
|
||||
if sys.version_info.minor == 12:
|
||||
|
||||
def visit_TypeVar(self, node):
|
||||
new_node = gast.TypeVar(
|
||||
self._visit(node.name),
|
||||
self._visit(node.bound),
|
||||
None
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_TypeVarTuple(self, node):
|
||||
new_node = gast.TypeVarTuple(
|
||||
self._visit(node.name),
|
||||
None
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_ParamSpec(self, node):
|
||||
new_node = gast.ParamSpec(
|
||||
self._visit(node.name),
|
||||
None
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
if sys.version_info.minor < 10:
|
||||
|
||||
def visit_alias(self, node):
|
||||
new_node = gast.alias(
|
||||
self._visit(node.name),
|
||||
self._visit(node.asname),
|
||||
)
|
||||
new_node.lineno = new_node.col_offset = None
|
||||
new_node.end_lineno = new_node.end_col_offset = None
|
||||
return new_node
|
||||
|
||||
if sys.version_info.minor < 9:
|
||||
|
||||
def visit_ExtSlice(self, node):
|
||||
new_node = gast.Tuple(self._visit(node.dims), gast.Load())
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_Index(self, node):
|
||||
return self._visit(node.value)
|
||||
|
||||
def visit_Assign(self, node):
|
||||
new_node = gast.Assign(
|
||||
self._visit(node.targets),
|
||||
self._visit(node.value),
|
||||
None, # type_comment
|
||||
)
|
||||
|
||||
gast.copy_location(new_node, node)
|
||||
new_node.end_lineno = new_node.end_col_offset = None
|
||||
return new_node
|
||||
|
||||
if sys.version_info.minor < 8:
|
||||
def visit_Module(self, node):
|
||||
new_node = gast.Module(
|
||||
self._visit(node.body),
|
||||
[] # type_ignores
|
||||
)
|
||||
return new_node
|
||||
|
||||
def visit_Num(self, node):
|
||||
new_node = gast.Constant(
|
||||
node.n,
|
||||
None,
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_Ellipsis(self, node):
|
||||
new_node = gast.Constant(
|
||||
Ellipsis,
|
||||
None,
|
||||
)
|
||||
gast.copy_location(new_node, node)
|
||||
new_node.end_lineno = new_node.end_col_offset = None
|
||||
return new_node
|
||||
|
||||
def visit_Str(self, node):
|
||||
new_node = gast.Constant(
|
||||
node.s,
|
||||
None,
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_Bytes(self, node):
|
||||
new_node = gast.Constant(
|
||||
node.s,
|
||||
None,
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_FunctionDef(self, node):
|
||||
new_node = gast.FunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
None, # type_comment
|
||||
[], # type_params
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFunctionDef(self, node):
|
||||
new_node = gast.AsyncFunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
None, # type_comment
|
||||
[], # type_params
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_For(self, node):
|
||||
new_node = gast.For(
|
||||
self._visit(node.target),
|
||||
self._visit(node.iter),
|
||||
self._visit(node.body),
|
||||
self._visit(node.orelse),
|
||||
None, # type_comment
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFor(self, node):
|
||||
new_node = gast.AsyncFor(
|
||||
self._visit(node.target),
|
||||
self._visit(node.iter),
|
||||
self._visit(node.body),
|
||||
self._visit(node.orelse),
|
||||
None, # type_comment
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_With(self, node):
|
||||
new_node = gast.With(
|
||||
self._visit(node.items),
|
||||
self._visit(node.body),
|
||||
None, # type_comment
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncWith(self, node):
|
||||
new_node = gast.AsyncWith(
|
||||
self._visit(node.items),
|
||||
self._visit(node.body),
|
||||
None, # type_comment
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_Call(self, node):
|
||||
if sys.version_info.minor < 5:
|
||||
if node.starargs:
|
||||
star = gast.Starred(self._visit(node.starargs),
|
||||
gast.Load())
|
||||
gast.copy_location(star, node)
|
||||
starred = [star]
|
||||
else:
|
||||
starred = []
|
||||
|
||||
if node.kwargs:
|
||||
kw = gast.keyword(None, self._visit(node.kwargs))
|
||||
gast.copy_location(kw, node.kwargs)
|
||||
kwargs = [kw]
|
||||
else:
|
||||
kwargs = []
|
||||
else:
|
||||
starred = kwargs = []
|
||||
|
||||
new_node = gast.Call(
|
||||
self._visit(node.func),
|
||||
self._visit(node.args) + starred,
|
||||
self._visit(node.keywords) + kwargs,
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_NameConstant(self, node):
|
||||
if node.value is None:
|
||||
new_node = gast.Constant(None, None)
|
||||
elif node.value is True:
|
||||
new_node = gast.Constant(True, None)
|
||||
elif node.value is False:
|
||||
new_node = gast.Constant(False, None)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_arguments(self, node):
|
||||
new_node = gast.arguments(
|
||||
self._visit(node.args),
|
||||
[], # posonlyargs
|
||||
self._visit(node.vararg),
|
||||
self._visit(node.kwonlyargs),
|
||||
self._visit(node.kw_defaults),
|
||||
self._visit(node.kwarg),
|
||||
self._visit(node.defaults),
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_Name(self, node):
|
||||
new_node = gast.Name(
|
||||
node.id, # micro-optimization here, don't call self._visit
|
||||
self._visit(node.ctx),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_arg(self, node):
|
||||
if sys.version_info.minor < 8:
|
||||
extra_arg = None
|
||||
else:
|
||||
extra_arg = self._visit(node.type_comment)
|
||||
|
||||
new_node = gast.Name(
|
||||
node.arg, # micro-optimization here, don't call self._visit
|
||||
gast.Param(),
|
||||
self._visit(node.annotation),
|
||||
extra_arg # type_comment
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_ExceptHandler(self, node):
|
||||
if node.name:
|
||||
new_node = gast.ExceptHandler(
|
||||
self._visit(node.type),
|
||||
gast.Name(node.name, gast.Store(), None, None),
|
||||
self._visit(node.body))
|
||||
return ast.copy_location(new_node, node)
|
||||
else:
|
||||
return self.generic_visit(node)
|
||||
|
||||
if sys.version_info.minor < 6:
|
||||
|
||||
def visit_comprehension(self, node):
|
||||
new_node = gast.comprehension(
|
||||
target=self._visit(node.target),
|
||||
iter=self._visit(node.iter),
|
||||
ifs=self._visit(node.ifs),
|
||||
is_async=0,
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
if 8 <= sys.version_info.minor < 12:
|
||||
def visit_FunctionDef(self, node):
|
||||
new_node = gast.FunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
self._visit(node.type_comment),
|
||||
[], # type_params
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFunctionDef(self, node):
|
||||
new_node = gast.AsyncFunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
self._visit(node.type_comment),
|
||||
[], # type_params
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
if sys.version_info.minor < 12:
|
||||
|
||||
def visit_ClassDef(self, node):
|
||||
new_node = gast.ClassDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.bases),
|
||||
self._visit(node.keywords),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
[], # type_params
|
||||
)
|
||||
return gast.copy_location(new_node, node)
|
||||
|
||||
|
||||
class GAstToAst3(GAstToAst):
|
||||
if sys.version_info.minor == 12:
|
||||
def visit_TypeVar(self, node):
|
||||
new_node = ast.TypeVar(
|
||||
self._visit(node.name),
|
||||
self._visit(node.bound)
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_TypeVarTuple(self, node):
|
||||
new_node = ast.TypeVarTuple(
|
||||
self._visit(node.name),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_ParamSpec(self, node):
|
||||
new_node = ast.ParamSpec(
|
||||
self._visit(node.name),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
if sys.version_info.minor < 10:
|
||||
def visit_alias(self, node):
|
||||
new_node = ast.alias(
|
||||
self._visit(node.name),
|
||||
self._visit(node.asname)
|
||||
)
|
||||
return new_node
|
||||
|
||||
if sys.version_info.minor < 9:
|
||||
def visit_Subscript(self, node):
|
||||
def adjust_slice(s):
|
||||
if isinstance(s, ast.Slice):
|
||||
return s
|
||||
else:
|
||||
return ast.Index(s)
|
||||
if isinstance(node.slice, gast.Tuple):
|
||||
if any(isinstance(elt, gast.slice) for elt in node.slice.elts):
|
||||
new_slice = ast.ExtSlice(
|
||||
[adjust_slice(x) for x in
|
||||
self._visit(node.slice.elts)])
|
||||
else:
|
||||
value = ast.Tuple(self._visit(node.slice.elts), ast.Load())
|
||||
ast.copy_location(value, node.slice)
|
||||
new_slice = ast.Index(value)
|
||||
else:
|
||||
new_slice = adjust_slice(self._visit(node.slice))
|
||||
ast.copy_location(new_slice, node.slice)
|
||||
|
||||
new_node = ast.Subscript(
|
||||
self._visit(node.value),
|
||||
new_slice,
|
||||
self._visit(node.ctx),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_Assign(self, node):
|
||||
new_node = ast.Assign(
|
||||
self._visit(node.targets),
|
||||
self._visit(node.value),
|
||||
)
|
||||
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
if sys.version_info.minor < 8:
|
||||
|
||||
def visit_Module(self, node):
|
||||
new_node = ast.Module(self._visit(node.body))
|
||||
return new_node
|
||||
|
||||
def visit_Constant(self, node):
|
||||
if node.value is None:
|
||||
new_node = ast.NameConstant(node.value)
|
||||
elif node.value is Ellipsis:
|
||||
new_node = ast.Ellipsis()
|
||||
elif isinstance(node.value, bool):
|
||||
new_node = ast.NameConstant(node.value)
|
||||
elif isinstance(node.value, (int, float, complex)):
|
||||
new_node = ast.Num(node.value)
|
||||
elif isinstance(node.value, str):
|
||||
new_node = ast.Str(node.value)
|
||||
else:
|
||||
new_node = ast.Bytes(node.value)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def _make_arg(self, node):
|
||||
if node is None:
|
||||
return None
|
||||
|
||||
if sys.version_info.minor < 8:
|
||||
extra_args = tuple()
|
||||
else:
|
||||
extra_args = self._visit(node.type_comment),
|
||||
|
||||
new_node = ast.arg(
|
||||
self._visit(node.id),
|
||||
self._visit(node.annotation),
|
||||
*extra_args
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_Name(self, node):
|
||||
new_node = ast.Name(
|
||||
self._visit(node.id),
|
||||
self._visit(node.ctx),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_ExceptHandler(self, node):
|
||||
if node.name:
|
||||
new_node = ast.ExceptHandler(
|
||||
self._visit(node.type),
|
||||
node.name.id,
|
||||
self._visit(node.body))
|
||||
return ast.copy_location(new_node, node)
|
||||
else:
|
||||
return self.generic_visit(node)
|
||||
|
||||
if sys.version_info.minor < 5:
|
||||
|
||||
def visit_Call(self, node):
|
||||
if node.args and isinstance(node.args[-1], gast.Starred):
|
||||
args = node.args[:-1]
|
||||
starargs = node.args[-1].value
|
||||
else:
|
||||
args = node.args
|
||||
starargs = None
|
||||
|
||||
if node.keywords and node.keywords[-1].arg is None:
|
||||
keywords = node.keywords[:-1]
|
||||
kwargs = node.keywords[-1].value
|
||||
else:
|
||||
keywords = node.keywords
|
||||
kwargs = None
|
||||
|
||||
new_node = ast.Call(
|
||||
self._visit(node.func),
|
||||
self._visit(args),
|
||||
self._visit(keywords),
|
||||
self._visit(starargs),
|
||||
self._visit(kwargs),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_ClassDef(self, node):
|
||||
self.generic_visit(node)
|
||||
new_node = ast.ClassDef(
|
||||
name=self._visit(node.name),
|
||||
bases=self._visit(node.bases),
|
||||
keywords=self._visit(node.keywords),
|
||||
body=self._visit(node.body),
|
||||
decorator_list=self._visit(node.decorator_list),
|
||||
starargs=None,
|
||||
kwargs=None,
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
elif sys.version_info.minor < 8:
|
||||
|
||||
def visit_FunctionDef(self, node):
|
||||
new_node = ast.FunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFunctionDef(self, node):
|
||||
new_node = ast.AsyncFunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_For(self, node):
|
||||
new_node = ast.For(
|
||||
self._visit(node.target),
|
||||
self._visit(node.iter),
|
||||
self._visit(node.body),
|
||||
self._visit(node.orelse),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFor(self, node):
|
||||
new_node = ast.AsyncFor(
|
||||
self._visit(node.target),
|
||||
self._visit(node.iter),
|
||||
self._visit(node.body),
|
||||
self._visit(node.orelse),
|
||||
None, # type_comment
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_With(self, node):
|
||||
new_node = ast.With(
|
||||
self._visit(node.items),
|
||||
self._visit(node.body),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncWith(self, node):
|
||||
new_node = ast.AsyncWith(
|
||||
self._visit(node.items),
|
||||
self._visit(node.body),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_Call(self, node):
|
||||
new_node = ast.Call(
|
||||
self._visit(node.func),
|
||||
self._visit(node.args),
|
||||
self._visit(node.keywords),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
if 5 <= sys.version_info.minor < 12:
|
||||
def visit_ClassDef(self, node):
|
||||
new_node = ast.ClassDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.bases),
|
||||
self._visit(node.keywords),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
if 8 <= sys.version_info.minor < 12:
|
||||
def visit_FunctionDef(self, node):
|
||||
new_node = ast.FunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
self._visit(node.type_comment),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
def visit_AsyncFunctionDef(self, node):
|
||||
new_node = ast.AsyncFunctionDef(
|
||||
self._visit(node.name),
|
||||
self._visit(node.args),
|
||||
self._visit(node.body),
|
||||
self._visit(node.decorator_list),
|
||||
self._visit(node.returns),
|
||||
self._visit(node.type_comment),
|
||||
)
|
||||
return ast.copy_location(new_node, node)
|
||||
|
||||
|
||||
|
||||
def visit_arguments(self, node):
|
||||
extra_args = [self._make_arg(node.vararg),
|
||||
[self._make_arg(n) for n in node.kwonlyargs],
|
||||
self._visit(node.kw_defaults),
|
||||
self._make_arg(node.kwarg),
|
||||
self._visit(node.defaults), ]
|
||||
if sys.version_info.minor >= 8:
|
||||
new_node = ast.arguments(
|
||||
[self._make_arg(arg) for arg in node.posonlyargs],
|
||||
[self._make_arg(n) for n in node.args],
|
||||
*extra_args
|
||||
)
|
||||
else:
|
||||
new_node = ast.arguments(
|
||||
[self._make_arg(n) for n in node.args],
|
||||
*extra_args
|
||||
)
|
||||
return new_node
|
||||
|
||||
|
||||
def ast_to_gast(node):
|
||||
return Ast3ToGAst().visit(node)
|
||||
|
||||
|
||||
def gast_to_ast(node):
|
||||
return GAstToAst3().visit(node)
|
||||
@@ -0,0 +1,74 @@
|
||||
# Copyright (c) 2016, Serge Guelton
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# Neither the name of HPCProject, Serge Guelton nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# NOTE(paddle-dev): We introduce third-party library Gast as unified AST
|
||||
# representation. See https://github.com/serge-sans-paille/gast for details.
|
||||
|
||||
import ast
|
||||
from . import gast
|
||||
|
||||
|
||||
def _generate_translators(to):
|
||||
|
||||
class Translator(ast.NodeTransformer):
|
||||
|
||||
def _visit(self, node):
|
||||
if isinstance(node, ast.AST):
|
||||
return self.visit(node)
|
||||
elif isinstance(node, list):
|
||||
return [self._visit(n) for n in node]
|
||||
else:
|
||||
return node
|
||||
|
||||
def generic_visit(self, node):
|
||||
class_name = type(node).__name__
|
||||
if not hasattr(to, class_name):
|
||||
# handle nodes that are not part of the AST
|
||||
return
|
||||
cls = getattr(to, class_name)
|
||||
new_node = cls(
|
||||
**{
|
||||
field: self._visit(getattr(node, field))
|
||||
for field in node._fields
|
||||
if hasattr(node, field)
|
||||
}
|
||||
)
|
||||
|
||||
for attr in node._attributes:
|
||||
try:
|
||||
setattr(new_node, attr, getattr(node, attr))
|
||||
except AttributeError:
|
||||
pass
|
||||
return new_node
|
||||
|
||||
return Translator
|
||||
|
||||
|
||||
AstToGAst = _generate_translators(gast)
|
||||
|
||||
GAstToAst = _generate_translators(ast)
|
||||
@@ -0,0 +1,718 @@
|
||||
# Copyright (c) 2016, Serge Guelton
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# Neither the name of HPCProject, Serge Guelton nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# NOTE(paddle-dev): We introduce third-party library Gast as unified AST
|
||||
# representation. See https://github.com/serge-sans-paille/gast for details.
|
||||
|
||||
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
|
||||
from ast import iter_child_nodes, walk
|
||||
|
||||
try:
|
||||
from ast import TypeIgnore
|
||||
except ImportError:
|
||||
class TypeIgnore(AST):
|
||||
pass
|
||||
|
||||
try:
|
||||
from ast import pattern
|
||||
except ImportError:
|
||||
class pattern(AST):
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
from ast import type_param
|
||||
except ImportError:
|
||||
class type_param(AST):
|
||||
pass
|
||||
|
||||
|
||||
def _make_node(Name, Fields, Attributes, Bases):
|
||||
|
||||
# This constructor is used a lot during conversion from ast to gast,
|
||||
# then as the primary way to build ast nodes. So we tried to optimized it
|
||||
# for speed and not for readability.
|
||||
def create_node(self, *args, **kwargs):
|
||||
if len(args) > len(Fields):
|
||||
raise TypeError(
|
||||
"{} constructor takes at most {} positional arguments".
|
||||
format(Name, len(Fields)))
|
||||
|
||||
# it's faster to iterate rather than zipping or enumerate
|
||||
for i in range(len(args)):
|
||||
setattr(self, Fields[i], args[i])
|
||||
if kwargs: # cold branch
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
setattr(_sys.modules[__name__],
|
||||
Name,
|
||||
type(Name,
|
||||
Bases,
|
||||
{'__init__': create_node,
|
||||
'_fields': Fields,
|
||||
'_field_types': {},
|
||||
'_attributes': Attributes}))
|
||||
|
||||
def _fill_field_types(Name, FieldTypes):
|
||||
node = getattr(_sys.modules[__name__], Name)
|
||||
assert len(node._fields) == len(FieldTypes), Name
|
||||
node._field_types.update(zip(node._fields, FieldTypes))
|
||||
|
||||
_nodes = (
|
||||
# mod
|
||||
('Module', (('body', 'type_ignores'), (), (mod,))),
|
||||
('Interactive', (('body',), (), (mod,))),
|
||||
('Expression', (('body',), (), (mod,))),
|
||||
('FunctionType', (('argtypes', 'returns'), (), (mod,))),
|
||||
('Suite', (('body',), (), (mod,))),
|
||||
|
||||
# stmt
|
||||
('FunctionDef', (('name', 'args', 'body', 'decorator_list', 'returns',
|
||||
'type_comment', 'type_params'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('AsyncFunctionDef', (('name', 'args', 'body', 'decorator_list', 'returns',
|
||||
'type_comment', 'type_params',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('ClassDef', (('name', 'bases', 'keywords', 'body', 'decorator_list',
|
||||
'type_params',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Return', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Delete', (('targets',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Assign', (('targets', 'value', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('TypeAlias', (('name', 'type_params', 'value'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('AugAssign', (('target', 'op', 'value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('AnnAssign', (('target', 'annotation', 'value', 'simple',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Print', (('dest', 'values', 'nl',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('For', (('target', 'iter', 'body', 'orelse', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('AsyncFor', (('target', 'iter', 'body', 'orelse', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('While', (('test', 'body', 'orelse',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('If', (('test', 'body', 'orelse',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('With', (('items', 'body', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('AsyncWith', (('items', 'body', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Match', (('subject', 'cases'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Raise', (('exc', 'cause',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Try', (('body', 'handlers', 'orelse', 'finalbody',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('TryStar', (('body', 'handlers', 'orelse', 'finalbody',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Assert', (('test', 'msg',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Import', (('names',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('ImportFrom', (('module', 'names', 'level',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Exec', (('body', 'globals', 'locals',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Global', (('names',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Nonlocal', (('names',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Expr', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Pass', ((), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Break', ((), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
('Continue', ((),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(stmt,))),
|
||||
|
||||
# expr
|
||||
|
||||
('BoolOp', (('op', 'values',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('NamedExpr', (('target', 'value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('BinOp', (('left', 'op', 'right',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('UnaryOp', (('op', 'operand',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Lambda', (('args', 'body',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('IfExp', (('test', 'body', 'orelse',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Dict', (('keys', 'values',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Set', (('elts',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('ListComp', (('elt', 'generators',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('SetComp', (('elt', 'generators',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('DictComp', (('key', 'value', 'generators',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('GeneratorExp', (('elt', 'generators',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Await', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Yield', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('YieldFrom', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Compare', (('left', 'ops', 'comparators',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Call', (('func', 'args', 'keywords',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Repr', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('FormattedValue', (('value', 'conversion', 'format_spec',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Interpolation', (('value', 'str', 'conversion', 'format_spec',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('JoinedStr', (('values',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('TemplateStr', (('values',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Constant', (('value', 'kind'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Attribute', (('value', 'attr', 'ctx',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Subscript', (('value', 'slice', 'ctx',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Starred', (('value', 'ctx',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Name', (('id', 'ctx', 'annotation', 'type_comment'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('List', (('elts', 'ctx',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(expr,))),
|
||||
('Tuple', (('elts', 'ctx',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_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'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
|
||||
(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',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(excepthandler,))),
|
||||
|
||||
# arguments
|
||||
('arguments', (('args', 'posonlyargs', 'vararg', 'kwonlyargs',
|
||||
'kw_defaults', 'kwarg', 'defaults'), (), (AST,))),
|
||||
|
||||
# keyword
|
||||
('keyword', (('arg', 'value'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset'),
|
||||
(AST,))),
|
||||
|
||||
# alias
|
||||
('alias', (('name', 'asname'),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset'),
|
||||
(AST,))),
|
||||
|
||||
# withitem
|
||||
('withitem', (('context_expr', 'optional_vars'), (), (AST,))),
|
||||
|
||||
# match_case
|
||||
('match_case', (('pattern', 'guard', 'body'), (), (AST,))),
|
||||
|
||||
# pattern
|
||||
('MatchValue', (('value',),
|
||||
('lineno', 'col_offset', 'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchSingleton', (('value',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchSequence', (('patterns',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchMapping', (('keys', 'patterns', 'rest'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchClass', (('cls', 'patterns', 'kwd_attrs', 'kwd_patterns'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchStar', (('name',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchAs', (('pattern', 'name'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
('MatchOr', (('patterns',),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(pattern,))),
|
||||
|
||||
# type_ignore
|
||||
('type_ignore', ((), ('lineno', 'tag'), (TypeIgnore,))),
|
||||
|
||||
# type_param
|
||||
('TypeVar', (('name', 'bound', 'default_value'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(type_param,))),
|
||||
('ParamSpec', (('name', 'default_value'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(type_param,))),
|
||||
('TypeVarTuple', (('name', 'default_value'),
|
||||
('lineno', 'col_offset',
|
||||
'end_lineno', 'end_col_offset'),
|
||||
(type_param,))),
|
||||
)
|
||||
|
||||
for _name, _descr in _nodes:
|
||||
_make_node(_name, *_descr)
|
||||
|
||||
# As an exception to gast rule that states that all nodes are identical for all
|
||||
# python version, we don't fill the field type for python with a version lower
|
||||
# than 3.10. Those version lack type support to be compatible with the more
|
||||
# modern representation anyway. The _field_types still exists though, but it's
|
||||
# always empty.
|
||||
if _sys.version_info >= (3, 10):
|
||||
|
||||
_node_types = (
|
||||
# mod
|
||||
('Module', (list[stmt], list[type_ignore])),
|
||||
('Interactive', (list[stmt],)),
|
||||
('Expression', (expr,)),
|
||||
('FunctionType', ('argtypes', 'returns'),),
|
||||
('Suite', (list[stmt],),),
|
||||
|
||||
# stmt
|
||||
('FunctionDef', (str, arguments, list[stmt], list[expr], expr | None, str | None, list[type_param]),),
|
||||
('AsyncFunctionDef', (str, arguments, list[stmt], list[expr], expr | None, str | None, list[type_param]),),
|
||||
('ClassDef', (str, list[expr], list[keyword], list[stmt], list[expr], list[type_param])),
|
||||
('Return', (expr | None,)),
|
||||
('Delete', (list[expr],)),
|
||||
('Assign', (list[expr], expr, str | None),),
|
||||
('TypeAlias', (expr, list[type_param], expr),),
|
||||
('AugAssign', (expr, operator, expr), ),
|
||||
('AnnAssign', (expr, expr, expr | None, int), ),
|
||||
('Print', (expr | None, list[expr], bool), ),
|
||||
('For', (expr, expr, list[stmt], list[stmt], str | None), ),
|
||||
('AsyncFor', (expr, expr, list[stmt], list[stmt], str | None), ),
|
||||
('While', (expr, list[stmt], list[stmt]), ),
|
||||
('If', (expr, list[stmt], list[stmt]), ),
|
||||
('With', (list[withitem], list[stmt], str | None), ),
|
||||
('AsyncWith', (list[withitem], list[stmt], str | None), ),
|
||||
('Match', (expr, match_case), ),
|
||||
('Raise', (expr | None, expr | None), ),
|
||||
('Try', (list[stmt], list[excepthandler], list[stmt], list[stmt]), ),
|
||||
('TryStar', (list[stmt], list[excepthandler], list[stmt], list[stmt]), ),
|
||||
('Assert', (expr, expr | None), ),
|
||||
('Import', (list[alias],), ),
|
||||
('ImportFrom', (str|None, list[alias], int | None), ),
|
||||
('Exec', (expr, expr | None, expr | None), ),
|
||||
('Global', (list[str],), ),
|
||||
('Nonlocal', (list[str],), ),
|
||||
('Expr', (expr,), ),
|
||||
|
||||
# expr
|
||||
|
||||
('BoolOp', (boolop, list[expr]), ),
|
||||
('NamedExpr', (expr, expr), ),
|
||||
('BinOp', (expr, operator, expr), ),
|
||||
('UnaryOp', (unaryop, expr), ),
|
||||
('Lambda', (arguments, expr), ),
|
||||
('IfExp', (expr, expr, expr), ),
|
||||
('Dict', (list[expr], list[expr]), ),
|
||||
('Set', (list[expr],), ),
|
||||
('ListComp', (expr, list[comprehension]), ),
|
||||
('SetComp', (expr, list[comprehension]), ),
|
||||
('DictComp', (expr, expr, list[comprehension]), ),
|
||||
('GeneratorExp', (expr, list[comprehension]), ),
|
||||
('Await', (expr,), ),
|
||||
('Yield', (expr | None,), ),
|
||||
('YieldFrom', (expr,), ),
|
||||
('Compare', (expr, list[cmpop], list[expr]), ),
|
||||
('Call', (expr, list[expr], list[keyword]), ),
|
||||
('Repr', (expr,), ),
|
||||
('FormattedValue', (expr, int, expr | None), ),
|
||||
('Interpolation', (expr, str, int, expr | None), ),
|
||||
('JoinedStr', (list[expr],), ),
|
||||
('TemplateStr', (list[expr],), ),
|
||||
('Constant', (object, str | None), ),
|
||||
('Attribute', (expr, str, expr_context), ),
|
||||
('Subscript', (expr, expr, expr_context), ),
|
||||
('Starred', (expr, expr_context), ),
|
||||
('Name', (str, expr_context, expr, str | None), ),
|
||||
('List', (list[expr], expr_context), ),
|
||||
('Tuple', (list[expr], expr_context), ),
|
||||
('Slice', (expr | None, expr | None, expr | None), ),
|
||||
|
||||
# comprehension
|
||||
('comprehension', (expr, expr, list[expr], int), ),
|
||||
|
||||
# excepthandler
|
||||
('ExceptHandler', (expr | None, str | None, list[stmt]), ),
|
||||
|
||||
# arguments
|
||||
('arguments', (list[expr], list[expr], expr | None, list[expr], list[expr], expr | None, list[expr]), ),
|
||||
|
||||
# keyword
|
||||
('keyword', (str | None, expr), ),
|
||||
|
||||
# alias
|
||||
('alias', (str, str | None), ),
|
||||
|
||||
# withitem
|
||||
('withitem', (expr, expr | None), ),
|
||||
|
||||
# match_case
|
||||
('match_case', (pattern, expr, list[stmt]), ),
|
||||
|
||||
# pattern
|
||||
('MatchValue', (expr,), ),
|
||||
('MatchSingleton', (object,), ),
|
||||
('MatchSequence', (list[pattern],), ),
|
||||
('MatchMapping', (list[expr], list[pattern], str | None), ),
|
||||
('MatchClass', (expr, list[pattern], list[str], list[pattern]), ),
|
||||
('MatchStar', (str | None,), ),
|
||||
('MatchAs', (pattern | None, str | None), ),
|
||||
('MatchOr', (list[pattern],), ),
|
||||
|
||||
# type_param
|
||||
('TypeVar', (str, expr | None, expr | None), ),
|
||||
('ParamSpec', (str, expr | None), ),
|
||||
('TypeVarTuple', (str, expr | None), ),
|
||||
)
|
||||
|
||||
for _name, _types in _node_types:
|
||||
_fill_field_types(_name, _types)
|
||||
|
||||
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, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
|
||||
raise TypeError("%r can't have docstrings" % node.__class__.__name__)
|
||||
if not(node.body and isinstance(node.body[0], Expr)):
|
||||
return None
|
||||
node = node.body[0].value
|
||||
if isinstance(node, Constant) and isinstance(node.value, str):
|
||||
text = node.value
|
||||
else:
|
||||
return None
|
||||
if clean:
|
||||
import inspect
|
||||
text = inspect.cleandoc(text)
|
||||
return text
|
||||
|
||||
|
||||
# the following are directly imported from python3.8's Lib/ast.py #
|
||||
|
||||
def copy_location(new_node, old_node):
|
||||
"""
|
||||
Copy source location (`lineno`, `col_offset`, `end_lineno`, and
|
||||
`end_col_offset` attributes) from *old_node* to *new_node* if possible,
|
||||
and return *new_node*.
|
||||
"""
|
||||
for attr in 'lineno', 'col_offset', 'end_lineno', 'end_col_offset':
|
||||
if attr in old_node._attributes and attr in new_node._attributes \
|
||||
and hasattr(old_node, attr):
|
||||
setattr(new_node, attr, getattr(old_node, attr))
|
||||
return new_node
|
||||
|
||||
|
||||
def fix_missing_locations(node):
|
||||
"""
|
||||
When you compile a node tree with compile(), the compiler expects lineno
|
||||
and col_offset attributes for every node that supports them. This is
|
||||
rather tedious to fill in for generated nodes, so this helper adds these
|
||||
attributes recursively where not already set, by setting them to the values
|
||||
of the parent node. It works recursively starting at *node*.
|
||||
"""
|
||||
def _fix(node, lineno, col_offset, end_lineno, end_col_offset):
|
||||
if 'lineno' in node._attributes:
|
||||
if not hasattr(node, 'lineno'):
|
||||
node.lineno = lineno
|
||||
else:
|
||||
lineno = node.lineno
|
||||
if 'end_lineno' in node._attributes:
|
||||
if not hasattr(node, 'end_lineno'):
|
||||
node.end_lineno = end_lineno
|
||||
else:
|
||||
end_lineno = node.end_lineno
|
||||
if 'col_offset' in node._attributes:
|
||||
if not hasattr(node, 'col_offset'):
|
||||
node.col_offset = col_offset
|
||||
else:
|
||||
col_offset = node.col_offset
|
||||
if 'end_col_offset' in node._attributes:
|
||||
if not hasattr(node, 'end_col_offset'):
|
||||
node.end_col_offset = end_col_offset
|
||||
else:
|
||||
end_col_offset = node.end_col_offset
|
||||
for child in iter_child_nodes(node):
|
||||
_fix(child, lineno, col_offset, end_lineno, end_col_offset)
|
||||
_fix(node, 1, 0, 1, 0)
|
||||
return node
|
||||
|
||||
|
||||
if _sys.version_info.major == 3 and _sys.version_info.minor >= 8:
|
||||
get_source_segment = _ast.get_source_segment
|
||||
else:
|
||||
# No end_lineno no end_col_offset info set for those version, so always
|
||||
# return None
|
||||
def get_source_segment(source, node, padded=False):
|
||||
return None
|
||||
|
||||
|
||||
def increment_lineno(node, n=1):
|
||||
"""
|
||||
Increment the line number and end line number of each node in the tree
|
||||
starting at *node* by *n*. This is useful to "move code" to a different
|
||||
location in a file.
|
||||
"""
|
||||
for child in walk(node):
|
||||
if 'lineno' in child._attributes:
|
||||
child.lineno = (getattr(child, 'lineno', 0) or 0) + n
|
||||
if 'end_lineno' in child._attributes:
|
||||
child.end_lineno = (getattr(child, 'end_lineno', 0) or 0) + n
|
||||
return node
|
||||
|
||||
# Code import from Lib/ast.py
|
||||
#
|
||||
# minor changes: getattr(x, y, ...) is None => getattr(x, y, 42) is None
|
||||
#
|
||||
def dump(
|
||||
node, annotate_fields=True, include_attributes=False,
|
||||
# *, # removed for compatibility with python2 :-/
|
||||
indent=None, show_empty=False,
|
||||
):
|
||||
"""
|
||||
Return a formatted dump of the tree in node. This is mainly useful for
|
||||
debugging purposes. If annotate_fields is true (by default),
|
||||
the returned string will show the names and the values for fields.
|
||||
If annotate_fields is false, the result string will be more compact by
|
||||
omitting unambiguous field names. Attributes such as line
|
||||
numbers and column offsets are not dumped by default. If this is wanted,
|
||||
include_attributes can be set to true. If indent is a non-negative
|
||||
integer or string, then the tree will be pretty-printed with that indent
|
||||
level. None (the default) selects the single line representation.
|
||||
If show_empty is False, then empty lists and fields that are None
|
||||
will be omitted from the output for better readability.
|
||||
"""
|
||||
def _format(node, level=0):
|
||||
if indent is not None:
|
||||
level += 1
|
||||
prefix = '\n' + indent * level
|
||||
sep = ',\n' + indent * level
|
||||
else:
|
||||
prefix = ''
|
||||
sep = ', '
|
||||
if isinstance(node, AST):
|
||||
cls = type(node)
|
||||
args = []
|
||||
args_buffer = []
|
||||
allsimple = True
|
||||
keywords = annotate_fields
|
||||
for name in node._fields:
|
||||
try:
|
||||
value = getattr(node, name)
|
||||
except AttributeError:
|
||||
keywords = True
|
||||
continue
|
||||
if value is None and getattr(cls, name, 42) is None:
|
||||
keywords = True
|
||||
continue
|
||||
if not show_empty:
|
||||
if value == []:
|
||||
if not keywords:
|
||||
args_buffer.append(repr(value))
|
||||
continue
|
||||
if not keywords:
|
||||
args.extend(args_buffer)
|
||||
args_buffer = []
|
||||
value, simple = _format(value, level)
|
||||
allsimple = allsimple and simple
|
||||
if keywords:
|
||||
args.append('%s=%s' % (name, value))
|
||||
else:
|
||||
args.append(value)
|
||||
if include_attributes and node._attributes:
|
||||
for name in node._attributes:
|
||||
try:
|
||||
value = getattr(node, name)
|
||||
except AttributeError:
|
||||
continue
|
||||
if value is None and getattr(cls, name, 42) is None:
|
||||
continue
|
||||
value, simple = _format(value, level)
|
||||
allsimple = allsimple and simple
|
||||
args.append('%s=%s' % (name, value))
|
||||
if allsimple and len(args) <= 3:
|
||||
return '%s(%s)' % (node.__class__.__name__, ', '.join(args)), not args
|
||||
return '%s(%s%s)' % (node.__class__.__name__, prefix, sep.join(args)), False
|
||||
elif isinstance(node, list):
|
||||
if not node:
|
||||
return '[]', True
|
||||
return '[%s%s]' % (prefix, sep.join(_format(x, level)[0] for x in node)), False
|
||||
return repr(node), True
|
||||
|
||||
if not isinstance(node, AST):
|
||||
raise TypeError('expected AST, got %r' % node.__class__.__name__)
|
||||
if indent is not None and not isinstance(indent, str):
|
||||
indent = ' ' * indent
|
||||
return _format(node)[0]
|
||||
Reference in New Issue
Block a user