-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchecker.py
62 lines (44 loc) · 1.77 KB
/
checker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import ast
import functools
def get_code(file_name):
with open(file_name) as fp:
return fp.read()
def get_tree(code):
return ast.parse(code)
def get_decorator_name(decorator):
if hasattr(decorator, "id"):
return decorator.id
if hasattr(decorator, "attr"):
return decorator.attr
if hasattr(decorator, "func"):
return get_decorator_name(decorator.func)
def has_decorator(decorator_name, function):
for decorator in function.decorator_list:
if get_decorator_name(decorator) == decorator_name:
return True
return False
def get_incompliant_functions(decorator_name, tree, file_name):
functions = filter(lambda x: type(x) == ast.FunctionDef, tree.body)
decorator_checker = functools.partial(has_decorator, decorator_name)
gateway_exposed_functions = filter(decorator_checker, functions)
return filter(
lambda x: get_decorator_name(x.decorator_list[0]) != decorator_name,
gateway_exposed_functions
)
def get_message(decorator_name, function_name):
return "`@{decorator_name}` is not the outermost decorator on the function `{name}`.".format(
decorator_name=decorator_name,
name=function_name
)
def generate_error_commands(decorator_name, incompliant_functions, file_name):
return map(lambda x: {
"lineno": x.lineno,
"message": get_message(decorator_name, x.name),
"file_name": file_name,
}, incompliant_functions)
def check_outermost_decorator(decorator_name, file_name):
code = get_code(file_name)
tree = get_tree(code)
incompliant_functions = get_incompliant_functions(decorator_name, tree, file_name)
errors = generate_error_commands(decorator_name, incompliant_functions, file_name)
return list(errors)