def replaceHazards(a):
if not isinstance(a, ast.AST):
return
for field in ast.walk(a):
if type(a) == ast.Import:
for i in range(len(a.names)):
if a.names[i].name not in supportedLibraries:
if not (a.names[i].name[0] == "r" and a.names[i].name[1] in "0123456789") and not ("NotAllowed" in a.names[i].name):
a.names[i].name = a.names[i].name + "NotAllowed"
elif type(a) == ast.ImportFrom:
if a.module not in supportedLibraries:
if not (a.module[0] == "r" and a.module[1] in "0123456789") and not ("NotAllowed" in a.module):
a.module = a.module + "NotAllowed"
elif type(a) == ast.Call:
if type(a.func) == ast.Name and a.func.id in ["compile", "eval", "execfile", "file", "open", "__import__", "apply"]:
a.func.id = a.func.id + "NotAllowed"
python类ImportFrom()的实例源码
def getAllImports(a):
"""Gather all imported module names"""
if not isinstance(a, ast.AST):
return []
imports = []
for child in ast.walk(a):
if type(child) == ast.Import:
for alias in child.names:
if alias.name in supportedLibraries:
imports.append(alias.asname if alias.asname != None else alias.name)
else:
log("astTools\tgetAllImports\tUnknown library: " + alias.name, "bug")
elif type(child) == ast.ImportFrom:
if child.module in supportedLibraries:
for alias in child.names: # these are all functions
if alias.name in libraryMap[child.module]:
imports.append(alias.asname if alias.asname != None else alias.name)
else:
log("astTools\tgetAllImports\tUnknown import from name: " + \
child.module + "," + alias.name, "bug")
else:
log("astTools\tgetAllImports\tUnknown library: " + child.module, "bug")
return imports
def match_type(self, typ, node):
if typ == 'class':
return isinstance(node, ast.ClassDef)
if typ == 'def':
return isinstance(node, ast.FunctionDef)
if typ == 'import':
return isinstance(node, (ast.Import, ast.ImportFrom))
if typ == 'assign':
return isinstance(node, ast.Assign)
if typ == 'attr':
return isinstance(node, ast.Attribute)
if typ == 'call':
if isinstance(node, ast.Call):
return True
# Python 2.x compatibility
return hasattr(ast, 'Print') and isinstance(node, ast.Print)
def _imports_unicode_literals(contents_text):
try:
ast_obj = ast_parse(contents_text)
except SyntaxError:
return False
for node in ast_obj.body:
# Docstring
if isinstance(node, ast.Expr) and isinstance(node.value, ast.Str):
continue
elif isinstance(node, ast.ImportFrom):
if (
node.module == '__future__' and
any(name.name == 'unicode_literals' for name in node.names)
):
return True
elif node.module == '__future__':
continue
else:
return False
else:
return False
def _add_aliases(self, node):
"""
We delegate to this method instead of using visit_alias() to have
access to line numbers and to filter imports from __future__.
"""
assert isinstance(node, (ast.Import, ast.ImportFrom))
for name_and_alias in node.names:
# Store only top-level module name ("os.path" -> "os").
# We can't easily detect when "os.path" is used.
name = name_and_alias.name.partition('.')[0]
alias = name_and_alias.asname
self._define(
self.defined_imports, alias or name, node,
confidence=90, ignore=_ignore_import)
if alias is not None:
self.used_names.add(name_and_alias.name)
def add_import(tree, name, asname):
# import fat as __fat__
import_node = ast.Import(names=[ast.alias(name=name, asname=asname)],
lineno=1, col_offset=1)
for index, node in enumerate(tree.body):
if (index == 0 and isinstance(node, ast.Expr)
and isinstance(node.value, ast.Constant)
and isinstance(node.value.value, str)):
# docstring
continue
if (isinstance(node, ast.ImportFrom) and node.module == '__future__'):
# from __future__ import ...
continue
tree.body.insert(index, import_node)
break
else:
# body is empty or only contains __future__ imports
tree.body.append(import_node)
def handleNode(self, node, parent):
if node is None:
return
if self.offset and getattr(node, 'lineno', None) is not None:
node.lineno += self.offset[0]
node.col_offset += self.offset[1]
if self.traceTree:
print(' ' * self.nodeDepth + node.__class__.__name__)
if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
self.isDocstring(node)):
self.futuresAllowed = False
self.nodeDepth += 1
node.depth = self.nodeDepth
node.parent = parent
try:
handler = self.getNodeHandler(node.__class__)
handler(node)
finally:
self.nodeDepth -= 1
if self.traceTree:
print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
def walk(self, prog_ast):
result = list(ast.walk(prog_ast))
import_nodes = [node for node in result if isinstance(node, ast.Import)]
import_from_nodes = [node for node in result if isinstance(node, ast.ImportFrom)]
for node in import_nodes:
for name in node.names:
if ImportHandler.is_builtin(name.name):
new_ast = ImportHandler.get_builtin_ast(name.name)
else:
new_ast = ImportHandler.get_module_ast(name.name, self.base_folder)
result += self.walk(new_ast)
for node in import_from_nodes:
if node.module == "typing":
# FIXME ignore typing for now, not to break type vars
continue
if ImportHandler.is_builtin(node.module):
new_ast = ImportHandler.get_builtin_ast(node.module)
else:
new_ast = ImportHandler.get_module_ast(node.module, self.base_folder)
result += self.walk(new_ast)
return result
def get_all_filters():
"""Return all the available filters"""
return (
# TODO: Add ast.Module to the docstring search.
DocString('d', 'doc', (ast.FunctionDef, ast.ClassDef, ast.Module),
help="Match class and function docstrings."),
NameFilter('c', 'class', (ast.ClassDef, ),
help="Match class names."),
DefFilter('f', 'def', (ast.FunctionDef, ), (ast.AST, ),
help="Match all defs."),
DefFilter('F', 'function', (ast.FunctionDef, ), (ast.Module, ),
help="Match function names at the module level."),
DefFilter('m', 'method', (ast.FunctionDef, ), (ast.ClassDef, ),
help="Match class method names."),
DefFilter('j', 'closure', (ast.FunctionDef, ), (ast.FunctionDef, ),
help="Match closure def names."),
ImportFilter('i', 'import', (ast.Import, ast.ImportFrom, ),
help="Match imported package names."),
CallFilter('C', 'call', (ast.Call, ),
help="Match call statements."),
AttrFilter('a', 'attr', (ast.Attribute, ),
help="Match attributes on objects"),
)
def handleNode(self, node, parent):
if node is None:
return
if self.offset and getattr(node, 'lineno', None) is not None:
node.lineno += self.offset[0]
node.col_offset += self.offset[1]
if self.traceTree:
print(' ' * self.nodeDepth + node.__class__.__name__)
if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
self.isDocstring(node)):
self.futuresAllowed = False
self.nodeDepth += 1
node.depth = self.nodeDepth
node.parent = parent
try:
handler = self.getNodeHandler(node.__class__)
handler(node)
finally:
self.nodeDepth -= 1
if self.traceTree:
print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
def get_coverable_nodes(cls):
return {
ast.Assert,
ast.Assign,
ast.AugAssign,
ast.Break,
ast.Continue,
ast.Delete,
ast.Expr,
ast.Global,
ast.Import,
ast.ImportFrom,
ast.Nonlocal,
ast.Pass,
ast.Raise,
ast.Return,
ast.FunctionDef,
ast.ClassDef,
ast.TryExcept,
ast.TryFinally,
ast.ExceptHandler,
ast.If,
ast.For,
ast.While,
}
def get_coverable_nodes(cls):
return {
ast.Assert,
ast.Assign,
ast.AugAssign,
ast.Break,
ast.Continue,
ast.Delete,
ast.Expr,
ast.Global,
ast.Import,
ast.ImportFrom,
ast.Nonlocal,
ast.Pass,
ast.Raise,
ast.Return,
ast.ClassDef,
ast.FunctionDef,
ast.Try,
ast.ExceptHandler,
ast.If,
ast.For,
ast.While,
}
def handleNode(self, node, parent):
if node is None:
return
if self.offset and getattr(node, 'lineno', None) is not None:
node.lineno += self.offset[0]
node.col_offset += self.offset[1]
if self.traceTree:
print(' ' * self.nodeDepth + node.__class__.__name__)
if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
self.isDocstring(node)):
self.futuresAllowed = False
self.nodeDepth += 1
node.depth = self.nodeDepth
node.parent = parent
try:
handler = self.getNodeHandler(node.__class__)
handler(node)
finally:
self.nodeDepth -= 1
if self.traceTree:
print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
def _find_imports(self, node):
"""Recurses through AST collecting the targets of all import
statements."""
if isinstance(node, ast.Import):
return {self._extract_root_module(alias.name) for alias in node.names}
elif isinstance(node, ast.ImportFrom):
# We ignore all imports with levels other than 0. That's because if
# if level > 0, we know that it's a relative import, and we only
# care about root modules.
if node.level == 0:
return {self._extract_root_module(node.module)}
else:
return set()
elif hasattr(node, 'body') and hasattr(node.body, '__iter__'):
# Not all bodies are lists (for ex. exec)
imps = set()
for child_node in node.body:
imps.update(self._find_imports(child_node))
return imps
else:
return set()
def visit_ImportFrom(self, node: ast.ImportFrom) -> ast.ImportFrom:
const = self.__class__._constants
if node.module in const:
for alias in node.names:
if alias.name in const[node.module] and not alias.asname:
self._add_value(node.module, alias.name, alias.name)
return self.generic_visit(node)
def importedName(id, importList):
for imp in importList:
if type(imp) == ast.Import:
for name in imp.names:
if hasattr(name, "asname") and name.asname != None:
if id == name.asname:
return True
else:
if id == name.name:
return True
elif type(imp) == ast.ImportFrom:
if hasattr(imp, "module"):
if imp.module in supportedLibraries:
libMap = libraryMap[imp.module]
for name in imp.names:
if hasattr(name, "asname") and name.asname != None:
if id == name.asname:
return True
else:
if id == name.name:
return True
else:
log("astTools\timportedName\tUnsupported library: " + printFunction(imp), "bug")
else:
log("astTools\timportedName\tWhy no module? " + printFunction(imp), "bug")
return False
def isStatement(a):
"""Determine whether the given node is a statement (vs an expression)"""
return type(a) in [ ast.Module, ast.Interactive, ast.Expression, ast.Suite,
ast.FunctionDef, ast.ClassDef, ast.Return, ast.Delete,
ast.Assign, ast.AugAssign, ast.For, ast.While,
ast.If, ast.With, ast.Raise, ast.Try,
ast.Assert, ast.Import, ast.ImportFrom, ast.Global,
ast.Expr, ast.Pass, ast.Break, ast.Continue ]
def getAllImportStatements(a):
if not isinstance(a, ast.AST):
return []
imports = []
for child in ast.walk(a):
if type(child) == ast.Import:
imports.append(child)
elif type(child) == ast.ImportFrom:
imports.append(child)
return imports
def rule_I200(self, node):
if isinstance(node, ast.Import):
for alias in node.names:
if '.' not in alias.name:
from_name = None
imported_name = alias.name
else:
from_name, imported_name = alias.name.rsplit('.', 1)
if imported_name == alias.asname:
if from_name:
rewritten = 'from {} import {}'.format(
from_name, imported_name
)
else:
rewritten = 'import {}'.format(imported_name)
yield (
node.lineno,
node.col_offset,
self.message_I200.format(rewritten),
type(self)
)
elif isinstance(node, ast.ImportFrom):
for alias in node.names:
if alias.name == alias.asname:
rewritten = 'from {} import {}'.format(node.module, alias.name)
yield (
node.lineno,
node.col_offset,
self.message_I200.format(rewritten),
type(self)
)
def rule_I201(self, node):
if isinstance(node, ast.Import):
module_names = [alias.name for alias in node.names]
elif isinstance(node, ast.ImportFrom):
node_module = node.module or ''
module_names = [node_module]
for alias in node.names:
module_names.append('{}.{}'.format(node_module, alias.name))
else:
return
# Sort from most to least specific paths.
module_names.sort(key=len, reverse=True)
warned = set()
for module_name in module_names:
if module_name in self.banned_modules:
message = self.message_I201.format(
name=module_name,
msg=self.banned_modules[module_name]
)
if any(mod.startswith(module_name) for mod in warned):
# Do not show an error for this line if we already showed
# a more specific error.
continue
else:
warned.add(module_name)
yield (
node.lineno,
node.col_offset,
message,
type(self)
)
def test_import(self):
matches = list(self.m.match('import', self.filepath('imports.py')))
self.assertEqual(len(matches), 6)
# check instances
self.assertIsInstance(matches[0][0], ast.ImportFrom)
self.assertIsInstance(matches[1][0], ast.ImportFrom)
self.assertIsInstance(matches[2][0], ast.ImportFrom)
self.assertIsInstance(matches[3][0], ast.ImportFrom)
self.assertIsInstance(matches[4][0], ast.Import)
self.assertIsInstance(matches[5][0], ast.Import)
def test_import_from(self):
matches = list(self.m.match('import[from=foo]',
self.filepath('imports.py')))
self.assertEqual(len(matches), 2)
# check instances
self.assertIsInstance(matches[0][0], ast.ImportFrom)
self.assertIsInstance(matches[1][0], ast.ImportFrom)
# check lines
self.assertEqual(matches[0][1], 1)
self.assertEqual(matches[1][1], 2)
def test_import_not_from(self):
matches = list(self.m.match('import:not([from^=foo])',
self.filepath('imports.py')))
self.assertEqual(len(matches), 3)
# check instances
self.assertIsInstance(matches[0][0], ast.ImportFrom)
self.assertIsInstance(matches[1][0], ast.Import)
self.assertIsInstance(matches[2][0], ast.Import)
def test_bad_integer(self):
# issue13436: Bad error message with invalid numeric values
body = [ast.ImportFrom(module='time',
names=[ast.alias(name='sleep')],
level=None,
lineno=None, col_offset=None)]
mod = ast.Module(body)
with self.assertRaises((TypeError, ValueError)) as cm:
compile(mod, 'test', 'exec')
if support.check_impl_detail():
self.assertIn("invalid integer value: None", str(cm.exception))
def analysis(self):
for node in self.module_node.body:
if isinstance(node, ast.Assign):
self.analysis_assign_node(self.variables, node)
elif isinstance(node, ast.Expr):
if isinstance(node.value, ast.Call):
self.get_type(node.value)
elif isinstance(node, ast.ImportFrom):
analyze_cmd(node)
generator = CodeGenerator(self.code, functions=self.functions, variables=self.variables)
return generator
def test_non_interned_future_from_ast(self):
mod = ast.parse("from __future__ import division")
self.assertIsInstance(mod.body[0], ast.ImportFrom)
mod.body[0].module = " __future__ ".strip()
compile(mod, "<test>", "exec")
def test_non_interned_future_from_ast(self):
mod = ast.parse("from __future__ import division")
self.assertIsInstance(mod.body[0], ast.ImportFrom)
mod.body[0].module = " __future__ ".strip()
compile(mod, "<test>", "exec")
def iter_imported_modules(node):
"""
Yield the imported module names from *node* where *node* is either an
ast.Import or ast.ImportFrom instance.
"""
if isinstance(node, ast.Import):
for alias in node.names:
yield alias.name
elif isinstance(node, ast.ImportFrom):
for alias in node.names:
yield node.module + '.' + alias.name
else:
raise ValueError('node must be an instance of either ast.Import or ast.ImportFrom')
def iter_method_classes(parent, call_node, context, child=None):
import_aliases = context._context['import_aliases']
if not isinstance(call_node, ast.Call):
raise ValueError('call_node must be of type ast.Call')
if not isinstance(call_node.func, ast.Attribute):
raise ValueError('call_node must be an attribute')
for init_node in iter_expr_values(parent, call_node.func.value, call_node):
# the init_node is the one in which the class is initialized
# all expr nodes should be either call (Name or Attribute) or Name
if not isinstance(init_node, ast.Call):
continue
if isinstance(init_node.func, ast.Attribute):
klass_name = get_attribute_name(init_node.func)
if klass_name is None:
continue
module_name, klass_name = klass_name.rsplit('.', 1)
for def_node in get_definition_nodes(parent, init_node.func.value, child=init_node):
if isinstance(def_node, (ast.Import, ast.ImportFrom)):
yield import_aliases.get(module_name, module_name) + '.' + klass_name
elif isinstance(init_node.func, ast.Name):
if init_node.func.id in import_aliases:
yield import_aliases[init_node.func.id]
continue
for klass_node in iter_expr_values(parent, init_node.func):
if isinstance(klass_node, ast.Attribute):
yield get_attribute_name(klass_node, import_aliases)
def test_non_interned_future_from_ast(self):
mod = ast.parse("from __future__ import division")
self.assertIsInstance(mod.body[0], ast.ImportFrom)
mod.body[0].module = " __future__ ".strip()
compile(mod, "<test>", "exec")