OLD | NEW |
1 # Copyright (c) 2000-2013 LOGILAB S.A. (Paris, FRANCE). | 1 # Copyright (c) 2000-2010 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 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
16 """handle diagram generation options for class diagram or default diagrams | 16 """handle diagram generation options for class diagram or default diagrams |
17 """ | 17 """ |
18 | 18 |
19 from logilab.common.compat import builtins | 19 from logilab.common.compat import builtins |
20 | 20 BUILTINS_NAME = builtins.__name__ |
21 import astroid | 21 from logilab import astng |
22 from astroid.utils import LocalsVisitor | 22 from logilab.astng.utils import LocalsVisitor |
23 | 23 |
24 from pylint.pyreverse.diagrams import PackageDiagram, ClassDiagram | 24 from pylint.pyreverse.diagrams import PackageDiagram, ClassDiagram |
25 | 25 |
26 BUILTINS_NAME = builtins.__name__ | |
27 | |
28 # diagram generators ########################################################## | 26 # diagram generators ########################################################## |
29 | 27 |
30 class DiaDefGenerator(object): | 28 class DiaDefGenerator: |
31 """handle diagram generation options""" | 29 """handle diagram generation options |
32 | 30 """ |
33 def __init__(self, linker, handler): | 31 def __init__(self, linker, handler): |
34 """common Diagram Handler initialization""" | 32 """common Diagram Handler initialization""" |
35 self.config = handler.config | 33 self.config = handler.config |
36 self._set_default_options() | 34 self._set_default_options() |
37 self.linker = linker | 35 self.linker = linker |
38 self.classdiagram = None # defined by subclasses | 36 self.classdiagram = None # defined by subclasses |
39 | 37 |
40 def get_title(self, node): | 38 def get_title(self, node): |
41 """get title for objects""" | 39 """get title for objects""" |
42 title = node.name | 40 title = node.name |
43 if self.module_names: | 41 if self.module_names: |
44 title = '%s.%s' % (node.root().name, title) | 42 title = '%s.%s' % (node.root().name, title) |
45 return title | 43 return title |
46 | 44 |
47 def _set_option(self, option): | 45 def _set_option(self, option): |
48 """activate some options if not explicitly deactivated""" | 46 """activate some options if not explicitly deactivated""" |
49 # if we have a class diagram, we want more information by default; | 47 # if we have a class diagram, we want more information by default; |
50 # so if the option is None, we return True | 48 # so if the option is None, we return True |
51 if option is None: | 49 if option is None: |
52 if self.config.classes: | 50 if self.config.classes: |
53 return True | 51 return True |
54 else: | 52 else: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 continue | 93 continue |
96 yield ancestor | 94 yield ancestor |
97 | 95 |
98 def get_associated(self, klass_node, level): | 96 def get_associated(self, klass_node, level): |
99 """return associated nodes of a class node""" | 97 """return associated nodes of a class node""" |
100 if level == 0: | 98 if level == 0: |
101 return | 99 return |
102 for ass_nodes in klass_node.instance_attrs_type.values() + \ | 100 for ass_nodes in klass_node.instance_attrs_type.values() + \ |
103 klass_node.locals_type.values(): | 101 klass_node.locals_type.values(): |
104 for ass_node in ass_nodes: | 102 for ass_node in ass_nodes: |
105 if isinstance(ass_node, astroid.Instance): | 103 if isinstance(ass_node, astng.Instance): |
106 ass_node = ass_node._proxied | 104 ass_node = ass_node._proxied |
107 if not (isinstance(ass_node, astroid.Class) | 105 if not (isinstance(ass_node, astng.Class) |
108 and self.show_node(ass_node)): | 106 and self.show_node(ass_node)): |
109 continue | 107 continue |
110 yield ass_node | 108 yield ass_node |
111 | 109 |
112 def extract_classes(self, klass_node, anc_level, ass_level): | 110 def extract_classes(self, klass_node, anc_level, ass_level): |
113 """extract recursively classes related to klass_node""" | 111 """extract recursively classes related to klass_node""" |
114 if self.classdiagram.has_node(klass_node) or not self.show_node(klass_no
de): | 112 if self.classdiagram.has_node(klass_node) or not self.show_node(klass_no
de): |
115 return | 113 return |
116 self.add_class(klass_node) | 114 self.add_class(klass_node) |
117 | 115 |
118 for ancestor in self.get_ancestors(klass_node, anc_level): | 116 for ancestor in self.get_ancestors(klass_node, anc_level): |
119 self.extract_classes(ancestor, anc_level-1, ass_level) | 117 self.extract_classes(ancestor, anc_level-1, ass_level) |
120 | 118 |
121 for ass_node in self.get_associated(klass_node, ass_level): | 119 for ass_node in self.get_associated(klass_node, ass_level): |
122 self.extract_classes(ass_node, anc_level, ass_level-1) | 120 self.extract_classes(ass_node, anc_level, ass_level-1) |
123 | 121 |
124 | 122 |
125 class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator): | 123 class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator): |
126 """generate minimum diagram definition for the project : | 124 """generate minimum diagram definition for the project : |
127 | 125 |
128 * a package diagram including project's modules | 126 * a package diagram including project's modules |
129 * a class diagram including project's classes | 127 * a class diagram including project's classes |
130 """ | 128 """ |
131 | 129 |
132 def __init__(self, linker, handler): | 130 def __init__(self, linker, handler): |
133 DiaDefGenerator.__init__(self, linker, handler) | 131 DiaDefGenerator.__init__(self, linker, handler) |
134 LocalsVisitor.__init__(self) | 132 LocalsVisitor.__init__(self) |
135 | 133 |
136 def visit_project(self, node): | 134 def visit_project(self, node): |
137 """visit an astroid.Project node | 135 """visit an astng.Project node |
138 | 136 |
139 create a diagram definition for packages | 137 create a diagram definition for packages |
140 """ | 138 """ |
141 mode = self.config.mode | 139 mode = self.config.mode |
142 if len(node.modules) > 1: | 140 if len(node.modules) > 1: |
143 self.pkgdiagram = PackageDiagram('packages %s' % node.name, mode) | 141 self.pkgdiagram = PackageDiagram('packages %s' % node.name, mode) |
144 else: | 142 else: |
145 self.pkgdiagram = None | 143 self.pkgdiagram = None |
146 self.classdiagram = ClassDiagram('classes %s' % node.name, mode) | 144 self.classdiagram = ClassDiagram('classes %s' % node.name, mode) |
147 | 145 |
148 def leave_project(self, node): | 146 def leave_project(self, node): |
149 """leave the astroid.Project node | 147 """leave the astng.Project node |
150 | 148 |
151 return the generated diagram definition | 149 return the generated diagram definition |
152 """ | 150 """ |
153 if self.pkgdiagram: | 151 if self.pkgdiagram: |
154 return self.pkgdiagram, self.classdiagram | 152 return self.pkgdiagram, self.classdiagram |
155 return self.classdiagram, | 153 return self.classdiagram, |
156 | 154 |
157 def visit_module(self, node): | 155 def visit_module(self, node): |
158 """visit an astroid.Module node | 156 """visit an astng.Module node |
159 | 157 |
160 add this class to the package diagram definition | 158 add this class to the package diagram definition |
161 """ | 159 """ |
162 if self.pkgdiagram: | 160 if self.pkgdiagram: |
163 self.linker.visit(node) | 161 self.linker.visit(node) |
164 self.pkgdiagram.add_object(node.name, node) | 162 self.pkgdiagram.add_object(node.name, node) |
165 | 163 |
166 def visit_class(self, node): | 164 def visit_class(self, node): |
167 """visit an astroid.Class node | 165 """visit an astng.Class node |
168 | 166 |
169 add this class to the class diagram definition | 167 add this class to the class diagram definition |
170 """ | 168 """ |
171 anc_level, ass_level = self._get_levels() | 169 anc_level, ass_level = self._get_levels() |
172 self.extract_classes(node, anc_level, ass_level) | 170 self.extract_classes(node, anc_level, ass_level) |
173 | 171 |
174 def visit_from(self, node): | 172 def visit_from(self, node): |
175 """visit astroid.From and catch modules for package diagram | 173 """visit astng.From and catch modules for package diagram |
176 """ | 174 """ |
177 if self.pkgdiagram: | 175 if self.pkgdiagram: |
178 self.pkgdiagram.add_from_depend(node, node.modname) | 176 self.pkgdiagram.add_from_depend(node, node.modname) |
179 | 177 |
180 | 178 |
181 class ClassDiadefGenerator(DiaDefGenerator): | 179 class ClassDiadefGenerator(DiaDefGenerator): |
182 """generate a class diagram definition including all classes related to a | 180 """generate a class diagram definition including all classes related to a |
183 given class | 181 given class |
184 """ | 182 """ |
185 | 183 |
(...skipping 13 matching lines...) Expand all Loading... |
199 module = project.modules[0] | 197 module = project.modules[0] |
200 klass = klass.split('.')[-1] | 198 klass = klass.split('.')[-1] |
201 klass = module.ilookup(klass).next() | 199 klass = module.ilookup(klass).next() |
202 | 200 |
203 anc_level, ass_level = self._get_levels() | 201 anc_level, ass_level = self._get_levels() |
204 self.extract_classes(klass, anc_level, ass_level) | 202 self.extract_classes(klass, anc_level, ass_level) |
205 return self.classdiagram | 203 return self.classdiagram |
206 | 204 |
207 # diagram handler ############################################################# | 205 # diagram handler ############################################################# |
208 | 206 |
209 class DiadefsHandler(object): | 207 class DiadefsHandler: |
210 """handle diagram definitions : | 208 """handle diagram definitions : |
211 | 209 |
212 get it from user (i.e. xml files) or generate them | 210 get it from user (i.e. xml files) or generate them |
213 """ | 211 """ |
214 | 212 |
215 def __init__(self, config): | 213 def __init__(self, config): |
216 self.config = config | 214 self.config = config |
217 | 215 |
218 def get_diadefs(self, project, linker): | 216 def get_diadefs(self, project, linker): |
219 """get the diagrams configuration data | 217 """get the diagrams configuration data |
220 :param linker: astroid.inspector.Linker(IdGeneratorMixIn, LocalsVisitor) | 218 :param linker: astng.inspector.Linker(IdGeneratorMixIn, LocalsVisitor) |
221 :param project: astroid.manager.Project | 219 :param project: astng.manager.Project |
222 """ | 220 """ |
223 | 221 |
224 # read and interpret diagram definitions (Diadefs) | 222 # read and interpret diagram definitions (Diadefs) |
225 diagrams = [] | 223 diagrams = [] |
226 generator = ClassDiadefGenerator(linker, self) | 224 generator = ClassDiadefGenerator(linker, self) |
227 for klass in self.config.classes: | 225 for klass in self.config.classes: |
228 diagrams.append(generator.class_diagram(project, klass)) | 226 diagrams.append(generator.class_diagram(project, klass)) |
229 if not diagrams: | 227 if not diagrams: |
230 diagrams = DefaultDiadefGenerator(linker, self).visit(project) | 228 diagrams = DefaultDiadefGenerator(linker, self).visit(project) |
231 for diagram in diagrams: | 229 for diagram in diagrams: |
232 diagram.extract_relationships() | 230 diagram.extract_relationships() |
233 return diagrams | 231 return diagrams |
OLD | NEW |