Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: third_party/pylint/pyreverse/diagrams.py

Issue 707353002: pylint: upgrade to 1.3.1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2004-2010 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2004-2013 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # This program is free software; you can redistribute it and/or modify it under 4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software 5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; either version 2 of the License, or (at your option) any later 6 # Foundation; either version 2 of the License, or (at your option) any later
7 # version. 7 # version.
8 # 8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT 9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License along with 13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 14 # this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 """diagram objects 16 """diagram objects
17 """ 17 """
18 18
19 from logilab import astng 19 import astroid
20 from pylint.pyreverse.utils import is_interface, FilterMixIn 20 from pylint.pyreverse.utils import is_interface, FilterMixIn
21 21
22 def set_counter(value): 22 class Figure(object):
23 """Figure counter (re)set"""
24 Figure._UID_COUNT = value
25
26 class Figure:
27 """base class for counter handling""" 23 """base class for counter handling"""
28 _UID_COUNT = 0 24
29 def __init__(self):
30 Figure._UID_COUNT += 1
31 self.fig_id = Figure._UID_COUNT
32
33 class Relationship(Figure): 25 class Relationship(Figure):
34 """a relation ship from an object in the diagram to another 26 """a relation ship from an object in the diagram to another
35 """ 27 """
36 def __init__(self, from_object, to_object, relation_type, name=None): 28 def __init__(self, from_object, to_object, relation_type, name=None):
37 Figure.__init__(self) 29 Figure.__init__(self)
38 self.from_object = from_object 30 self.from_object = from_object
39 self.to_object = to_object 31 self.to_object = to_object
40 self.type = relation_type 32 self.type = relation_type
41 self.name = name 33 self.name = name
42 34
43 35
44 class DiagramEntity(Figure): 36 class DiagramEntity(Figure):
45 """a diagram object, i.e. a label associated to an astng node 37 """a diagram object, i.e. a label associated to an astroid node
46 """ 38 """
47 def __init__(self, title='No name', node=None): 39 def __init__(self, title='No name', node=None):
48 Figure.__init__(self) 40 Figure.__init__(self)
49 self.title = title 41 self.title = title
50 self.node = node 42 self.node = node
51 43
52 class ClassDiagram(Figure, FilterMixIn): 44 class ClassDiagram(Figure, FilterMixIn):
53 """main class diagram handling 45 """main class diagram handling
54 """ 46 """
55 TYPE = 'class' 47 TYPE = 'class'
56 def __init__(self, title, mode): 48 def __init__(self, title, mode):
57 FilterMixIn.__init__(self, mode) 49 FilterMixIn.__init__(self, mode)
58 Figure.__init__(self) 50 Figure.__init__(self)
59 self.title = title 51 self.title = title
60 self.objects = [] 52 self.objects = []
61 self.relationships = {} 53 self.relationships = {}
62 self._nodes = {} 54 self._nodes = {}
63 self.depends = [] 55 self.depends = []
64 56
65 def add_relationship(self, from_object, to_object, 57 def get_relationships(self, role):
58 # sorted to get predictable (hence testable) results
59 return sorted(self.relationships.get(role, ()),
60 key=lambda x: (x.from_object.fig_id, x.to_object.fig_id))
61
62 def add_relationship(self, from_object, to_object,
66 relation_type, name=None): 63 relation_type, name=None):
67 """create a relation ship 64 """create a relation ship
68 """ 65 """
69 rel = Relationship(from_object, to_object, relation_type, name) 66 rel = Relationship(from_object, to_object, relation_type, name)
70 self.relationships.setdefault(relation_type, []).append(rel) 67 self.relationships.setdefault(relation_type, []).append(rel)
71 68
72 def get_relationship(self, from_object, relation_type): 69 def get_relationship(self, from_object, relation_type):
73 """return a relation ship or None 70 """return a relation ship or None
74 """ 71 """
75 for rel in self.relationships.get(relation_type, ()): 72 for rel in self.relationships.get(relation_type, ()):
76 if rel.from_object is from_object: 73 if rel.from_object is from_object:
77 return rel 74 return rel
78 raise KeyError(relation_type) 75 raise KeyError(relation_type)
79 76
80 def get_attrs(self, node): 77 def get_attrs(self, node):
81 """return visible attributes, possibly with class name""" 78 """return visible attributes, possibly with class name"""
82 attrs = [] 79 attrs = []
83 for node_name, ass_nodes in node.instance_attrs_type.items() + \ 80 for node_name, ass_nodes in node.instance_attrs_type.items() + \
84 node.locals_type.items(): 81 node.locals_type.items():
85 if not self.show_attr(node_name): 82 if not self.show_attr(node_name):
86 continue 83 continue
87 names = self.class_names(ass_nodes) 84 names = self.class_names(ass_nodes)
88 if names: 85 if names:
89 node_name = "%s : %s" % (node_name, ", ".join(names)) 86 node_name = "%s : %s" % (node_name, ", ".join(names))
90 attrs.append(node_name) 87 attrs.append(node_name)
91 return attrs 88 return sorted(attrs)
92 89
93 def get_methods(self, node): 90 def get_methods(self, node):
94 """return visible methods""" 91 """return visible methods"""
95 return [m for m in node.values() 92 methods = [
96 if isinstance(m, astng.Function) and self.show_attr(m.name)] 93 m for m in node.values()
94 if isinstance(m, astroid.Function) and self.show_attr(m.name)
95 ]
96 return sorted(methods, key=lambda n: n.name)
97 97
98 def add_object(self, title, node): 98 def add_object(self, title, node):
99 """create a diagram object 99 """create a diagram object
100 """ 100 """
101 assert node not in self._nodes 101 assert node not in self._nodes
102 ent = DiagramEntity(title, node) 102 ent = DiagramEntity(title, node)
103 self._nodes[node] = ent 103 self._nodes[node] = ent
104 self.objects.append(ent) 104 self.objects.append(ent)
105 105
106 def class_names(self, nodes): 106 def class_names(self, nodes):
107 """return class names if needed in diagram""" 107 """return class names if needed in diagram"""
108 names = [] 108 names = []
109 for ass_node in nodes: 109 for ass_node in nodes:
110 if isinstance(ass_node, astng.Instance): 110 if isinstance(ass_node, astroid.Instance):
111 ass_node = ass_node._proxied 111 ass_node = ass_node._proxied
112 if isinstance(ass_node, astng.Class) \ 112 if isinstance(ass_node, astroid.Class) \
113 and hasattr(ass_node, "name") and not self.has_node(ass_node): 113 and hasattr(ass_node, "name") and not self.has_node(ass_node):
114 if ass_node.name not in names: 114 if ass_node.name not in names:
115 ass_name = ass_node.name 115 ass_name = ass_node.name
116 names.append(ass_name) 116 names.append(ass_name)
117 return names 117 return names
118 118
119 def nodes(self): 119 def nodes(self):
120 """return the list of underlying nodes 120 """return the list of underlying nodes
121 """ 121 """
122 return self._nodes.keys() 122 return self._nodes.keys()
123 123
124 def has_node(self, node): 124 def has_node(self, node):
125 """return true if the given node is included in the diagram 125 """return true if the given node is included in the diagram
126 """ 126 """
127 return node in self._nodes 127 return node in self._nodes
128 128
129 def object_from_node(self, node): 129 def object_from_node(self, node):
130 """return the diagram object mapped to node 130 """return the diagram object mapped to node
131 """ 131 """
132 return self._nodes[node] 132 return self._nodes[node]
133 133
134 def classes(self): 134 def classes(self):
135 """return all class nodes in the diagram""" 135 """return all class nodes in the diagram"""
136 return [o for o in self.objects if isinstance(o.node, astng.Class)] 136 return [o for o in self.objects if isinstance(o.node, astroid.Class)]
137 137
138 def classe(self, name): 138 def classe(self, name):
139 """return a class by its name, raise KeyError if not found 139 """return a class by its name, raise KeyError if not found
140 """ 140 """
141 for klass in self.classes(): 141 for klass in self.classes():
142 if klass.node.name == name: 142 if klass.node.name == name:
143 return klass 143 return klass
144 raise KeyError(name) 144 raise KeyError(name)
145 145
146 def extract_relationships(self): 146 def extract_relationships(self):
147 """extract relation ships between nodes in the diagram 147 """extract relation ships between nodes in the diagram
148 """ 148 """
149 for obj in self.classes(): 149 for obj in self.classes():
150 node = obj.node 150 node = obj.node
151 obj.attrs = self.get_attrs(node) 151 obj.attrs = self.get_attrs(node)
152 obj.methods = self.get_methods(node) 152 obj.methods = self.get_methods(node)
153 # shape 153 # shape
154 if is_interface(node): 154 if is_interface(node):
155 obj.shape = 'interface' 155 obj.shape = 'interface'
(...skipping 10 matching lines...) Expand all
166 for impl_node in node.implements: 166 for impl_node in node.implements:
167 try: 167 try:
168 impl_obj = self.object_from_node(impl_node) 168 impl_obj = self.object_from_node(impl_node)
169 self.add_relationship(obj, impl_obj, 'implements') 169 self.add_relationship(obj, impl_obj, 'implements')
170 except KeyError: 170 except KeyError:
171 continue 171 continue
172 # associations link 172 # associations link
173 for name, values in node.instance_attrs_type.items() + \ 173 for name, values in node.instance_attrs_type.items() + \
174 node.locals_type.items(): 174 node.locals_type.items():
175 for value in values: 175 for value in values:
176 if value is astng.YES: 176 if value is astroid.YES:
177 continue 177 continue
178 if isinstance( value, astng.Instance): 178 if isinstance(value, astroid.Instance):
179 value = value._proxied 179 value = value._proxied
180 try: 180 try:
181 ass_obj = self.object_from_node(value) 181 ass_obj = self.object_from_node(value)
182 self.add_relationship(ass_obj, obj, 'association', name) 182 self.add_relationship(ass_obj, obj, 'association', name)
183 except KeyError: 183 except KeyError:
184 continue 184 continue
185 185
186 186
187 class PackageDiagram(ClassDiagram): 187 class PackageDiagram(ClassDiagram):
188 """package diagram handling 188 """package diagram handling
189 """ 189 """
190 TYPE = 'package' 190 TYPE = 'package'
191 191
192 def modules(self): 192 def modules(self):
193 """return all module nodes in the diagram""" 193 """return all module nodes in the diagram"""
194 return [o for o in self.objects if isinstance(o.node, astng.Module)] 194 return [o for o in self.objects if isinstance(o.node, astroid.Module)]
195 195
196 def module(self, name): 196 def module(self, name):
197 """return a module by its name, raise KeyError if not found 197 """return a module by its name, raise KeyError if not found
198 """ 198 """
199 for mod in self.modules(): 199 for mod in self.modules():
200 if mod.node.name == name: 200 if mod.node.name == name:
201 return mod 201 return mod
202 raise KeyError(name) 202 raise KeyError(name)
203 203
204 def get_module(self, name, node): 204 def get_module(self, name, node):
205 """return a module by its name, looking also for relative imports; 205 """return a module by its name, looking also for relative imports;
206 raise KeyError if not found 206 raise KeyError if not found
207 """ 207 """
208 for mod in self.modules(): 208 for mod in self.modules():
209 mod_name = mod.node.name 209 mod_name = mod.node.name
210 if mod_name == name: 210 if mod_name == name:
211 return mod 211 return mod
212 #search for fullname of relative import modules 212 #search for fullname of relative import modules
213 package = node.root().name 213 package = node.root().name
214 if mod_name == "%s.%s" % (package, name): 214 if mod_name == "%s.%s" % (package, name):
215 return mod 215 return mod
216 if mod_name == "%s.%s" % (package.rsplit('.', 1)[0], name): 216 if mod_name == "%s.%s" % (package.rsplit('.', 1)[0], name):
217 return mod 217 return mod
218 raise KeyError(name) 218 raise KeyError(name)
219 219
220 def add_from_depend(self, node, from_module): 220 def add_from_depend(self, node, from_module):
221 """add dependencies created by from-imports 221 """add dependencies created by from-imports
222 """ 222 """
223 mod_name = node.root().name 223 mod_name = node.root().name
224 obj = self.module( mod_name ) 224 obj = self.module(mod_name)
225 if from_module not in obj.node.depends: 225 if from_module not in obj.node.depends:
226 obj.node.depends.append(from_module) 226 obj.node.depends.append(from_module)
227 227
228 def extract_relationships(self): 228 def extract_relationships(self):
229 """extract relation ships between nodes in the diagram 229 """extract relation ships between nodes in the diagram
230 """ 230 """
231 ClassDiagram.extract_relationships(self) 231 ClassDiagram.extract_relationships(self)
232 for obj in self.classes(): 232 for obj in self.classes():
233 # ownership 233 # ownership
234 try: 234 try:
235 mod = self.object_from_node(obj.node.root()) 235 mod = self.object_from_node(obj.node.root())
236 self.add_relationship(obj, mod, 'ownership') 236 self.add_relationship(obj, mod, 'ownership')
237 except KeyError: 237 except KeyError:
238 continue 238 continue
239 for obj in self.modules(): 239 for obj in self.modules():
240 obj.shape = 'package' 240 obj.shape = 'package'
241 # dependencies 241 # dependencies
242 for dep_name in obj.node.depends: 242 for dep_name in obj.node.depends:
243 try: 243 try:
244 dep = self.get_module(dep_name, obj.node) 244 dep = self.get_module(dep_name, obj.node)
245 except KeyError: 245 except KeyError:
246 continue 246 continue
247 self.add_relationship(obj, dep, 'depends') 247 self.add_relationship(obj, dep, 'depends')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698