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

Side by Side Diff: third_party/logilab/astng/manager.py

Issue 739393004: Revert "Revert "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
« no previous file with comments | « third_party/logilab/astng/inspector.py ('k') | third_party/logilab/astng/mixins.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # copyright 2003-2010 Sylvain Thenault, all rights reserved.
4 # contact mailto:thenault@gmail.com
5 #
6 # This file is part of logilab-astng.
7 #
8 # logilab-astng is free software: you can redistribute it and/or modify it
9 # under the terms of the GNU Lesser General Public License as published by the
10 # Free Software Foundation, either version 2.1 of the License, or (at your
11 # option) any later version.
12 #
13 # logilab-astng is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 # for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public License along
19 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
20 """astng manager: avoid multiple astng build of a same module when
21 possible by providing a class responsible to get astng representation
22 from various source and using a cache of built modules)
23 """
24
25 __docformat__ = "restructuredtext en"
26
27 import sys
28 import os
29 from os.path import dirname, basename, abspath, join, isdir, exists
30
31 from logilab.common.modutils import NoSourceFile, is_python_source, \
32 file_from_modpath, load_module_from_name, modpath_from_file, \
33 get_module_files, get_source_file, zipimport
34 from logilab.common.configuration import OptionsProviderMixIn
35
36 from logilab.astng.exceptions import ASTNGBuildingException
37
38 def astng_wrapper(func, modname):
39 """wrapper to give to ASTNGManager.project_from_files"""
40 print 'parsing %s...' % modname
41 try:
42 return func(modname)
43 except ASTNGBuildingException, exc:
44 print exc
45 except Exception, exc:
46 import traceback
47 traceback.print_exc()
48
49 def _silent_no_wrap(func, modname):
50 """silent wrapper that doesn't do anything; can be used for tests"""
51 return func(modname)
52
53 def safe_repr(obj):
54 try:
55 return repr(obj)
56 except:
57 return '???'
58
59
60
61 class ASTNGManager(OptionsProviderMixIn):
62 """the astng manager, responsible to build astng from files
63 or modules.
64
65 Use the Borg pattern.
66 """
67
68 name = 'astng loader'
69 options = (("ignore",
70 {'type' : "csv", 'metavar' : "<file>",
71 'dest' : "black_list", "default" : ('CVS',),
72 'help' : "add <file> (may be a directory) to the black list\
73 . It should be a base name, not a path. You may set this option multiple times\
74 ."}),
75 ("project",
76 {'default': "No Name", 'type' : 'string', 'short': 'p',
77 'metavar' : '<project name>',
78 'help' : 'set the project name.'}),
79 )
80 brain = {}
81 def __init__(self):
82 self.__dict__ = ASTNGManager.brain
83 if not self.__dict__:
84 OptionsProviderMixIn.__init__(self)
85 self.load_defaults()
86 # NOTE: cache entries are added by the [re]builder
87 self.astng_cache = {}
88 self._mod_file_cache = {}
89 self.transformers = []
90
91 def astng_from_file(self, filepath, modname=None, fallback=True, source=Fals e):
92 """given a module name, return the astng object"""
93 try:
94 filepath = get_source_file(filepath, include_no_ext=True)
95 source = True
96 except NoSourceFile:
97 pass
98 if modname is None:
99 try:
100 modname = '.'.join(modpath_from_file(filepath))
101 except ImportError:
102 modname = filepath
103 if modname in self.astng_cache:
104 return self.astng_cache[modname]
105 if source:
106 from logilab.astng.builder import ASTNGBuilder
107 return ASTNGBuilder(self).file_build(filepath, modname)
108 elif fallback and modname:
109 return self.astng_from_module_name(modname)
110 raise ASTNGBuildingException('unable to get astng for file %s' %
111 filepath)
112
113 def astng_from_module_name(self, modname, context_file=None):
114 """given a module name, return the astng object"""
115 if modname in self.astng_cache:
116 return self.astng_cache[modname]
117 if modname == '__main__':
118 from logilab.astng.builder import ASTNGBuilder
119 return ASTNGBuilder(self).string_build('', modname)
120 old_cwd = os.getcwd()
121 if context_file:
122 os.chdir(dirname(context_file))
123 try:
124 filepath = self.file_from_module_name(modname, context_file)
125 if filepath is not None and not is_python_source(filepath):
126 module = self.zip_import_data(filepath)
127 if module is not None:
128 return module
129 if filepath is None or not is_python_source(filepath):
130 try:
131 module = load_module_from_name(modname)
132 except Exception, ex:
133 msg = 'Unable to load module %s (%s)' % (modname, ex)
134 raise ASTNGBuildingException(msg)
135 return self.astng_from_module(module, modname)
136 return self.astng_from_file(filepath, modname, fallback=False)
137 finally:
138 os.chdir(old_cwd)
139
140 def zip_import_data(self, filepath):
141 if zipimport is None:
142 return None
143 from logilab.astng.builder import ASTNGBuilder
144 builder = ASTNGBuilder(self)
145 for ext in ('.zip', '.egg'):
146 try:
147 eggpath, resource = filepath.rsplit(ext + '/', 1)
148 except ValueError:
149 continue
150 try:
151 importer = zipimport.zipimporter(eggpath + ext)
152 zmodname = resource.replace('/', '.')
153 if importer.is_package(resource):
154 zmodname = zmodname + '.__init__'
155 module = builder.string_build(importer.get_source(resource),
156 zmodname, filepath)
157 return module
158 except:
159 continue
160 return None
161
162 def file_from_module_name(self, modname, contextfile):
163 try:
164 value = self._mod_file_cache[(modname, contextfile)]
165 except KeyError:
166 try:
167 value = file_from_modpath(modname.split('.'),
168 context_file=contextfile)
169 except ImportError, ex:
170 msg = 'Unable to load module %s (%s)' % (modname, ex)
171 value = ASTNGBuildingException(msg)
172 self._mod_file_cache[(modname, contextfile)] = value
173 if isinstance(value, ASTNGBuildingException):
174 raise value
175 return value
176
177 def astng_from_module(self, module, modname=None):
178 """given an imported module, return the astng object"""
179 modname = modname or module.__name__
180 if modname in self.astng_cache:
181 return self.astng_cache[modname]
182 try:
183 # some builtin modules don't have __file__ attribute
184 filepath = module.__file__
185 if is_python_source(filepath):
186 return self.astng_from_file(filepath, modname)
187 except AttributeError:
188 pass
189 from logilab.astng.builder import ASTNGBuilder
190 return ASTNGBuilder(self).module_build(module, modname)
191
192 def astng_from_class(self, klass, modname=None):
193 """get astng for the given class"""
194 if modname is None:
195 try:
196 modname = klass.__module__
197 except AttributeError:
198 raise ASTNGBuildingException(
199 'Unable to get module for class %s' % safe_repr(klass))
200 modastng = self.astng_from_module_name(modname)
201 return modastng.getattr(klass.__name__)[0] # XXX
202
203
204 def infer_astng_from_something(self, obj, context=None):
205 """infer astng for the given class"""
206 if hasattr(obj, '__class__') and not isinstance(obj, type):
207 klass = obj.__class__
208 else:
209 klass = obj
210 try:
211 modname = klass.__module__
212 except AttributeError:
213 raise ASTNGBuildingException(
214 'Unable to get module for %s' % safe_repr(klass))
215 except Exception, ex:
216 raise ASTNGBuildingException(
217 'Unexpected error while retrieving module for %s: %s'
218 % (safe_repr(klass), ex))
219 try:
220 name = klass.__name__
221 except AttributeError:
222 raise ASTNGBuildingException(
223 'Unable to get name for %s' % safe_repr(klass))
224 except Exception, ex:
225 raise ASTNGBuildingException(
226 'Unexpected error while retrieving name for %s: %s'
227 % (safe_repr(klass), ex))
228 # take care, on living object __module__ is regularly wrong :(
229 modastng = self.astng_from_module_name(modname)
230 if klass is obj:
231 for infered in modastng.igetattr(name, context):
232 yield infered
233 else:
234 for infered in modastng.igetattr(name, context):
235 yield infered.instanciate_class()
236
237 def project_from_files(self, files, func_wrapper=astng_wrapper,
238 project_name=None, black_list=None):
239 """return a Project from a list of files or modules"""
240 # build the project representation
241 project_name = project_name or self.config.project
242 black_list = black_list or self.config.black_list
243 project = Project(project_name)
244 for something in files:
245 if not exists(something):
246 fpath = file_from_modpath(something.split('.'))
247 elif isdir(something):
248 fpath = join(something, '__init__.py')
249 else:
250 fpath = something
251 astng = func_wrapper(self.astng_from_file, fpath)
252 if astng is None:
253 continue
254 # XXX why is first file defining the project.path ?
255 project.path = project.path or astng.file
256 project.add_module(astng)
257 base_name = astng.name
258 # recurse in package except if __init__ was explicitly given
259 if astng.package and something.find('__init__') == -1:
260 # recurse on others packages / modules if this is a package
261 for fpath in get_module_files(dirname(astng.file),
262 black_list):
263 astng = func_wrapper(self.astng_from_file, fpath)
264 if astng is None or astng.name == base_name:
265 continue
266 project.add_module(astng)
267 return project
268
269 def register_transformer(self, transformer):
270 self.transformers.append(transformer)
271
272 class Project:
273 """a project handle a set of modules / packages"""
274 def __init__(self, name=''):
275 self.name = name
276 self.path = None
277 self.modules = []
278 self.locals = {}
279 self.__getitem__ = self.locals.__getitem__
280 self.__iter__ = self.locals.__iter__
281 self.values = self.locals.values
282 self.keys = self.locals.keys
283 self.items = self.locals.items
284
285 def add_module(self, node):
286 self.locals[node.name] = node
287 self.modules.append(node)
288
289 def get_module(self, name):
290 return self.locals[name]
291
292 def get_children(self):
293 return self.modules
294
295 def __repr__(self):
296 return '<Project %r at %s (%s modules)>' % (self.name, id(self),
297 len(self.modules))
298
299
OLDNEW
« no previous file with comments | « third_party/logilab/astng/inspector.py ('k') | third_party/logilab/astng/mixins.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698