author | Denis Laxalde <denis.laxalde@logilab.fr> |
Fri, 24 Mar 2017 09:37:51 +0100 | |
branch | 3.25 |
changeset 12101 | 3fd9c12a4426 |
parent 11220 | ffef75b7a26e |
permissions | -rw-r--r-- |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
1 |
"""Pylint plugin to analyse cubicweb cubes |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
2 |
|
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
3 |
Done: |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
4 |
* turn functions decorated by @objectify_predicate into classes |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
5 |
* add yams base types to yams.buildobjs module |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
6 |
* add data() function to uiprops module's namespace |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
7 |
* avoid 'abstract method not implemented' for `cell_call`, `entity_call`, `render_body` |
11220
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
8 |
* avoid invalid-name on schema relation class names |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
9 |
|
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
10 |
TODO: |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
11 |
* avoid invalid class name for predicates and predicates |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
12 |
* W:188, 0: Method '__lt__' is abstract in class 'Entity' but is not overridden (abstract-method) |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
13 |
* generate entity attributes from the schema? |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
14 |
""" |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
15 |
|
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
16 |
from astroid import MANAGER, InferenceError, nodes, ClassDef, FunctionDef |
9311
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
17 |
from astroid.builder import AstroidBuilder |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
18 |
|
11218
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
19 |
from pylint.checkers.utils import unimplemented_abstract_methods, class_is_abstract |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
20 |
|
11217
1f686f55ef3d
[pylint] upgrade pylintext plugin
Laura Médioni <laura.medioni@logilab.fr>
parents:
11057
diff
changeset
|
21 |
|
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
22 |
def turn_function_to_class(node): |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
23 |
"""turn a Function node into a Class node (in-place)""" |
11217
1f686f55ef3d
[pylint] upgrade pylintext plugin
Laura Médioni <laura.medioni@logilab.fr>
parents:
11057
diff
changeset
|
24 |
node.__class__ = ClassDef |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
25 |
node.bases = () |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
26 |
# mark class as a new style class |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
27 |
node._newstyle = True |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
28 |
# remove return nodes so that we don't get warned about 'return outside |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
29 |
# function' by pylint |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
30 |
for rnode in node.nodes_of_class(nodes.Return): |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
31 |
rnode.parent.body.remove(rnode) |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
32 |
# add __init__ method to avoid no-init |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
33 |
|
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
34 |
# that seems to be enough :) |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
35 |
|
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
36 |
|
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
37 |
def cubicweb_transform(module): |
8190
2a3c1b787688
[vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8061
diff
changeset
|
38 |
# handle objectify_predicate decorator (and its former name until bw compat |
2a3c1b787688
[vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8061
diff
changeset
|
39 |
# is kept). Only look at module level functions, should be enough. |
10663
54b8a1f249fb
[py3k] dict.itervalues → dict.values
Rémi Cardona <remi.cardona@logilab.fr>
parents:
9311
diff
changeset
|
40 |
for assnodes in module.locals.values(): |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
41 |
for node in assnodes: |
11217
1f686f55ef3d
[pylint] upgrade pylintext plugin
Laura Médioni <laura.medioni@logilab.fr>
parents:
11057
diff
changeset
|
42 |
if isinstance(node, FunctionDef) and node.decorators: |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
43 |
for decorator in node.decorators.nodes: |
9311
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
44 |
try: |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
45 |
for infered in decorator.infer(): |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
46 |
if infered.name in ('objectify_predicate', 'objectify_selector'): |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
47 |
turn_function_to_class(node) |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
48 |
break |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
49 |
else: |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
50 |
continue |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
51 |
break |
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
52 |
except InferenceError: |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
53 |
continue |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
54 |
# add yams base types into 'yams.buildobjs', astng doesn't grasp globals() |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
55 |
# magic in there |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
56 |
if module.name == 'yams.buildobjs': |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
57 |
from yams import BASE_TYPES |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
58 |
for etype in BASE_TYPES: |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
59 |
module.locals[etype] = [ClassDef(etype, None)] |
8061
88ca47ceb9f2
[pylint] enhance plugin: define 'data' function in uiprops module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7941
diff
changeset
|
60 |
# add data() to uiprops module |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
61 |
elif module.name.split('.')[-1] == 'uiprops': |
9311
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
62 |
fake = AstroidBuilder(MANAGER).string_build(''' |
8061
88ca47ceb9f2
[pylint] enhance plugin: define 'data' function in uiprops module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7941
diff
changeset
|
63 |
def data(string): |
88ca47ceb9f2
[pylint] enhance plugin: define 'data' function in uiprops module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7941
diff
changeset
|
64 |
return u'' |
88ca47ceb9f2
[pylint] enhance plugin: define 'data' function in uiprops module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7941
diff
changeset
|
65 |
''') |
88ca47ceb9f2
[pylint] enhance plugin: define 'data' function in uiprops module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7941
diff
changeset
|
66 |
module.locals['data'] = fake.locals['data'] |
11220
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
67 |
# handle lower case with underscores for relation names in schema.py |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
68 |
if not module.qname().endswith('.schema'): |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
69 |
return |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
70 |
schema_locals = module.locals |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
71 |
for assnodes in schema_locals.values(): |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
72 |
for node in assnodes: |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
73 |
if not isinstance(node, ClassDef): |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
74 |
continue |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
75 |
# XXX can we infer ancestor classes? it would be better to know for sure that |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
76 |
# one of the mother classes is yams.buildobjs.RelationDefinition for instance |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
77 |
for base in node.basenames: |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
78 |
if base in ('RelationDefinition', 'ComputedRelation', 'RelationType'): |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
79 |
new_name = node.name.replace('_', '').capitalize() |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
80 |
schema_locals[new_name] = schema_locals[node.name] |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
81 |
del schema_locals[node.name] |
ffef75b7a26e
[pylint] Avoid invalid-name on schema relation class names
Laura Médioni <laura.medioni@logilab.fr>
parents:
11219
diff
changeset
|
82 |
node.name = new_name |
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
83 |
|
11217
1f686f55ef3d
[pylint] upgrade pylintext plugin
Laura Médioni <laura.medioni@logilab.fr>
parents:
11057
diff
changeset
|
84 |
|
11218
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
85 |
def cubicweb_abstractmethods_transform(classdef): |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
86 |
if class_is_abstract(classdef): |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
87 |
return |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
88 |
|
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
89 |
def is_abstract(method): |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
90 |
return method.is_abstract(pass_is_abstract=False) |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
91 |
|
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
92 |
methods = sorted( |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
93 |
unimplemented_abstract_methods(classdef, is_abstract).items(), |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
94 |
key=lambda item: item[0], |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
95 |
) |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
96 |
|
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
97 |
dummy_method = AstroidBuilder(MANAGER).string_build(''' |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
98 |
def dummy_method(self): |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
99 |
"""""" |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
100 |
''') |
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
101 |
|
11218
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
102 |
for name, method in methods: |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
103 |
owner = method.parent.frame() |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
104 |
if owner is classdef: |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
105 |
continue |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
106 |
if name not in classdef.locals: |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
107 |
if name in ('cell_call', 'entity_call', 'render_body'): |
11218
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
108 |
classdef.set_local(name, dummy_method) |
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
109 |
|
3fea2f3b25c1
[pylint] remove abstract-method warning
Laura Médioni <laura.medioni@logilab.fr>
parents:
11217
diff
changeset
|
110 |
|
7941
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
111 |
def register(linter): |
018b5deca73e
pylint extension
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff
changeset
|
112 |
"""called when loaded by pylint --load-plugins, nothing to do here""" |
9311
8833ead6f3e4
update pylint extension to astroid API
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8696
diff
changeset
|
113 |
MANAGER.register_transform(nodes.Module, cubicweb_transform) |
11219
0796b6191cea
[pylint] more work on the pylint support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
11218
diff
changeset
|
114 |
MANAGER.register_transform(ClassDef, cubicweb_abstractmethods_transform) |