Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@gforcada @karamanolev @dopplershift @dirk-thomas
252 lines (210 sloc) 8.41 KB
# -*- coding: utf-8 -*-
import ast
import inspect
import sys
try:
from flake8.engine import pep8 as stdin_utils
except ImportError:
from flake8 import utils as stdin_utils
WHITE_LIST = [
'__name__',
'__doc__',
'credits',
'_',
]
if sys.version_info >= (3, 0):
import builtins
BUILTINS = [
a[0]
for a in inspect.getmembers(builtins)
if a[0] not in WHITE_LIST
]
PY3 = True
else:
import __builtin__
BUILTINS = [
a[0]
for a in inspect.getmembers(__builtin__)
if a[0] not in WHITE_LIST
]
PY3 = False
class BuiltinsChecker(object):
name = 'flake8_builtins'
version = '1.4.1'
assign_msg = 'A001 "{0}" is a python builtin and is being shadowed, ' \
'consider renaming the variable'
argument_msg = 'A002 "{0}" is used as an argument and thus shadows a ' \
'python builtin, consider renaming the argument'
class_attribute_msg = 'A003 "{0}" is a python builtin, consider ' \
'renaming the class attribute'
def __init__(self, tree, filename):
self.tree = tree
self.filename = filename
def run(self):
tree = self.tree
if self.filename == 'stdin':
lines = stdin_utils.stdin_get_value()
tree = ast.parse(lines)
for statement in ast.walk(tree):
for child in ast.iter_child_nodes(statement):
child.__flake8_builtins_parent = statement
function_nodes = [ast.FunctionDef]
if getattr(ast, 'AsyncFunctionDef', None):
function_nodes.append(ast.AsyncFunctionDef)
function_nodes = tuple(function_nodes)
for_nodes = [ast.For]
if getattr(ast, 'AsyncFor', None):
for_nodes.append(ast.AsyncFor)
for_nodes = tuple(for_nodes)
with_nodes = [ast.With]
if getattr(ast, 'AsyncWith', None):
with_nodes.append(ast.AsyncWith)
with_nodes = tuple(with_nodes)
for statement in ast.walk(tree):
value = None
if isinstance(statement, ast.Assign):
value = self.check_assignment(statement)
elif isinstance(statement, function_nodes):
value = self.check_function_definition(statement)
elif isinstance(statement, for_nodes):
value = self.check_for_loop(statement)
elif isinstance(statement, with_nodes):
value = self.check_with(statement)
elif isinstance(statement, ast.excepthandler):
value = self.check_exception(statement)
elif isinstance(statement, ast.ListComp):
value = self.check_list_comprehension(statement)
elif isinstance(statement, (ast.Import, ast.ImportFrom)):
value = self.check_import(statement)
elif isinstance(statement, ast.ClassDef):
value = self.check_class(statement)
if value:
for line, offset, msg, rtype in value:
yield line, offset, msg, rtype
def check_assignment(self, statement):
msg = self.assign_msg
if type(statement.__flake8_builtins_parent) is ast.ClassDef:
msg = self.class_attribute_msg
stack = list(statement.targets)
while stack:
item = stack.pop()
if isinstance(item, (ast.Tuple, ast.List)):
stack.extend(list(item.elts))
elif isinstance(item, ast.Name) and \
item.id in BUILTINS:
yield self.error(item, message=msg, variable=item.id)
elif PY3 and \
isinstance(item, ast.Starred) and \
item.value.id in BUILTINS:
yield self.error(
statement,
message=msg,
variable=item.value.id,
)
def check_function_definition(self, statement):
if statement.name in BUILTINS:
msg = self.assign_msg
if type(statement.__flake8_builtins_parent) is ast.ClassDef:
msg = self.class_attribute_msg
yield self.error(statement, message=msg, variable=statement.name)
if PY3:
for arg in statement.args.args:
if isinstance(arg, ast.arg) and \
arg.arg in BUILTINS:
yield self.error(
arg,
message=self.argument_msg,
variable=arg.arg,
)
else:
for arg in statement.args.args:
if isinstance(arg, ast.Name) and \
arg.id in BUILTINS:
yield self.error(arg, message=self.argument_msg)
def check_for_loop(self, statement):
stack = [statement.target]
while stack:
item = stack.pop()
if isinstance(item, (ast.Tuple, ast.List)):
stack.extend(list(item.elts))
elif isinstance(item, ast.Name) and \
item.id in BUILTINS:
yield self.error(statement, variable=item.id)
elif PY3 and \
isinstance(item, ast.Starred) and \
item.value.id in BUILTINS:
yield self.error(statement, variable=item.value.id)
def check_with(self, statement):
if not PY3:
var = statement.optional_vars
if isinstance(var, (ast.Tuple, ast.List)):
for element in var.elts:
if isinstance(element, ast.Name) and \
element.id in BUILTINS:
yield self.error(statement, variable=element.id)
elif isinstance(var, ast.Name) and var.id in BUILTINS:
yield self.error(statement, variable=var.id)
else:
for item in statement.items:
var = item.optional_vars
if isinstance(var, (ast.Tuple, ast.List)):
for element in var.elts:
if isinstance(element, ast.Name) and \
element.id in BUILTINS:
yield self.error(statement, variable=element.id)
elif isinstance(element, ast.Starred) and \
element.value.id in BUILTINS:
yield self.error(
element,
variable=element.value.id,
)
elif isinstance(var, ast.Name) and var.id in BUILTINS:
yield self.error(statement, variable=var.id)
def check_exception(self, statement):
exception_name = statement.name
value = ''
if isinstance(exception_name, ast.Name):
value = exception_name.id
elif isinstance(exception_name, str): # Python +3.x
value = exception_name
if value in BUILTINS:
yield self.error(statement, variable=value)
def check_list_comprehension(self, statement):
for generator in statement.generators:
if isinstance(generator.target, ast.Name) \
and generator.target.id in BUILTINS:
yield self.error(statement, variable=generator.target.id)
elif isinstance(generator.target, (ast.Tuple, ast.List)):
for tuple_element in generator.target.elts:
if isinstance(tuple_element, ast.Name) and \
tuple_element.id in BUILTINS:
yield self.error(statement, variable=tuple_element.id)
def check_import(self, statement):
for name in statement.names:
if name.asname in BUILTINS:
yield self.error(statement, variable=name.asname)
def check_class(self, statement):
if statement.name in BUILTINS:
yield self.error(statement, variable=statement.name)
def error(
self,
statement,
message=None,
variable=None,
line=None,
column=None,
):
if not message:
message = self.assign_msg
if not variable:
variable = statement.id
if not line:
line = statement.lineno
if not column:
column = statement.col_offset
return (
line,
column,
message.format(variable),
type(self),
)
You can’t perform that action at this time.