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

Side by Side Diff: third_party/logilab/logilab/astroid/raw_building.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 months 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
OLDNEW
(Empty)
1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 #
4 # This file is part of astroid.
5 #
6 # astroid is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU Lesser General Public License as published by the
8 # Free Software Foundation, either version 2.1 of the License, or (at your
9 # option) any later version.
10 #
11 # astroid is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 # for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public License along
17 # with astroid. If not, see <http://www.gnu.org/licenses/>.
18 """this module contains a set of functions to create astroid trees from scratch
19 (build_* functions) or from living object (object_build_* functions)
20 """
21
22 __docformat__ = "restructuredtext en"
23
24 import sys
25 from os.path import abspath
26 from inspect import (getargspec, isdatadescriptor, isfunction, ismethod,
27 ismethoddescriptor, isclass, isbuiltin, ismodule)
28 import six
29
30 from astroid.node_classes import CONST_CLS
31 from astroid.nodes import (Module, Class, Const, const_factory, From,
32 Function, EmptyNode, Name, Arguments)
33 from astroid.bases import BUILTINS, Generator
34 from astroid.manager import AstroidManager
35 MANAGER = AstroidManager()
36
37 _CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types
38
39 def _io_discrepancy(member):
40 # _io module names itself `io`: http://bugs.python.org/issue18602
41 member_self = getattr(member, '__self__', None)
42 return (member_self and
43 ismodule(member_self) and
44 member_self.__name__ == '_io' and
45 member.__module__ == 'io')
46
47 def _attach_local_node(parent, node, name):
48 node.name = name # needed by add_local_node
49 parent.add_local_node(node)
50
51 _marker = object()
52
53 def attach_dummy_node(node, name, object=_marker):
54 """create a dummy node and register it in the locals of the given
55 node with the specified name
56 """
57 enode = EmptyNode()
58 enode.object = object
59 _attach_local_node(node, enode, name)
60
61 def _has_underlying_object(self):
62 return hasattr(self, 'object') and self.object is not _marker
63
64 EmptyNode.has_underlying_object = _has_underlying_object
65
66 def attach_const_node(node, name, value):
67 """create a Const node and register it in the locals of the given
68 node with the specified name
69 """
70 if not name in node.special_attributes:
71 _attach_local_node(node, const_factory(value), name)
72
73 def attach_import_node(node, modname, membername):
74 """create a From node and register it in the locals of the given
75 node with the specified name
76 """
77 from_node = From(modname, [(membername, None)])
78 _attach_local_node(node, from_node, membername)
79
80
81 def build_module(name, doc=None):
82 """create and initialize a astroid Module node"""
83 node = Module(name, doc, pure_python=False)
84 node.package = False
85 node.parent = None
86 return node
87
88 def build_class(name, basenames=(), doc=None):
89 """create and initialize a astroid Class node"""
90 node = Class(name, doc)
91 for base in basenames:
92 basenode = Name()
93 basenode.name = base
94 node.bases.append(basenode)
95 basenode.parent = node
96 return node
97
98 def build_function(name, args=None, defaults=None, flag=0, doc=None):
99 """create and initialize a astroid Function node"""
100 args, defaults = args or [], defaults or []
101 # first argument is now a list of decorators
102 func = Function(name, doc)
103 func.args = argsnode = Arguments()
104 argsnode.args = []
105 for arg in args:
106 argsnode.args.append(Name())
107 argsnode.args[-1].name = arg
108 argsnode.args[-1].parent = argsnode
109 argsnode.defaults = []
110 for default in defaults:
111 argsnode.defaults.append(const_factory(default))
112 argsnode.defaults[-1].parent = argsnode
113 argsnode.kwarg = None
114 argsnode.vararg = None
115 argsnode.parent = func
116 if args:
117 register_arguments(func)
118 return func
119
120
121 def build_from_import(fromname, names):
122 """create and initialize an astroid From import statement"""
123 return From(fromname, [(name, None) for name in names])
124
125 def register_arguments(func, args=None):
126 """add given arguments to local
127
128 args is a list that may contains nested lists
129 (i.e. def func(a, (b, c, d)): ...)
130 """
131 if args is None:
132 args = func.args.args
133 if func.args.vararg:
134 func.set_local(func.args.vararg, func.args)
135 if func.args.kwarg:
136 func.set_local(func.args.kwarg, func.args)
137 for arg in args:
138 if isinstance(arg, Name):
139 func.set_local(arg.name, arg)
140 else:
141 register_arguments(func, arg.elts)
142
143 def object_build_class(node, member, localname):
144 """create astroid for a living class object"""
145 basenames = [base.__name__ for base in member.__bases__]
146 return _base_class_object_build(node, member, basenames,
147 localname=localname)
148
149 def object_build_function(node, member, localname):
150 """create astroid for a living function object"""
151 args, varargs, varkw, defaults = getargspec(member)
152 if varargs is not None:
153 args.append(varargs)
154 if varkw is not None:
155 args.append(varkw)
156 func = build_function(getattr(member, '__name__', None) or localname, args,
157 defaults, member.func_code.co_flags, member.__doc__)
158 node.add_local_node(func, localname)
159
160 def object_build_datadescriptor(node, member, name):
161 """create astroid for a living data descriptor object"""
162 return _base_class_object_build(node, member, [], name)
163
164 def object_build_methoddescriptor(node, member, localname):
165 """create astroid for a living method descriptor object"""
166 # FIXME get arguments ?
167 func = build_function(getattr(member, '__name__', None) or localname,
168 doc=member.__doc__)
169 # set node's arguments to None to notice that we have no information, not
170 # and empty argument list
171 func.args.args = None
172 node.add_local_node(func, localname)
173
174 def _base_class_object_build(node, member, basenames, name=None, localname=None) :
175 """create astroid for a living class object, with a given set of base names
176 (e.g. ancestors)
177 """
178 klass = build_class(name or getattr(member, '__name__', None) or localname,
179 basenames, member.__doc__)
180 klass._newstyle = isinstance(member, type)
181 node.add_local_node(klass, localname)
182 try:
183 # limit the instantiation trick since it's too dangerous
184 # (such as infinite test execution...)
185 # this at least resolves common case such as Exception.args,
186 # OSError.errno
187 if issubclass(member, Exception):
188 instdict = member().__dict__
189 else:
190 raise TypeError
191 except:
192 pass
193 else:
194 for name, obj in instdict.items():
195 valnode = EmptyNode()
196 valnode.object = obj
197 valnode.parent = klass
198 valnode.lineno = 1
199 klass.instance_attrs[name] = [valnode]
200 return klass
201
202
203
204
205 class InspectBuilder(object):
206 """class for building nodes from living object
207
208 this is actually a really minimal representation, including only Module,
209 Function and Class nodes and some others as guessed.
210 """
211
212 # astroid from living objects ############################################## #
213
214 def __init__(self):
215 self._done = {}
216 self._module = None
217
218 def inspect_build(self, module, modname=None, path=None):
219 """build astroid from a living module (i.e. using inspect)
220 this is used when there is no python source code available (either
221 because it's a built-in module or because the .py is not available)
222 """
223 self._module = module
224 if modname is None:
225 modname = module.__name__
226 try:
227 node = build_module(modname, module.__doc__)
228 except AttributeError:
229 # in jython, java modules have no __doc__ (see #109562)
230 node = build_module(modname)
231 node.file = node.path = path and abspath(path) or path
232 node.name = modname
233 MANAGER.cache_module(node)
234 node.package = hasattr(module, '__path__')
235 self._done = {}
236 self.object_build(node, module)
237 return node
238
239 def object_build(self, node, obj):
240 """recursive method which create a partial ast from real objects
241 (only function, class, and method are handled)
242 """
243 if obj in self._done:
244 return self._done[obj]
245 self._done[obj] = node
246 for name in dir(obj):
247 try:
248 member = getattr(obj, name)
249 except AttributeError:
250 # damned ExtensionClass.Base, I know you're there !
251 attach_dummy_node(node, name)
252 continue
253 if ismethod(member):
254 member = six.get_method_function(member)
255 if isfunction(member):
256 # verify this is not an imported function
257 filename = getattr(six.get_function_code(member),
258 'co_filename', None)
259 if filename is None:
260 assert isinstance(member, object)
261 object_build_methoddescriptor(node, member, name)
262 elif filename != getattr(self._module, '__file__', None):
263 attach_dummy_node(node, name, member)
264 else:
265 object_build_function(node, member, name)
266 elif isbuiltin(member):
267 if (not _io_discrepancy(member) and
268 self.imported_member(node, member, name)):
269 continue
270 object_build_methoddescriptor(node, member, name)
271 elif isclass(member):
272 if self.imported_member(node, member, name):
273 continue
274 if member in self._done:
275 class_node = self._done[member]
276 if not class_node in node.locals.get(name, ()):
277 node.add_local_node(class_node, name)
278 else:
279 class_node = object_build_class(node, member, name)
280 # recursion
281 self.object_build(class_node, member)
282 if name == '__class__' and class_node.parent is None:
283 class_node.parent = self._done[self._module]
284 elif ismethoddescriptor(member):
285 assert isinstance(member, object)
286 object_build_methoddescriptor(node, member, name)
287 elif isdatadescriptor(member):
288 assert isinstance(member, object)
289 object_build_datadescriptor(node, member, name)
290 elif type(member) in _CONSTANTS:
291 attach_const_node(node, name, member)
292 else:
293 # create an empty node so that the name is actually defined
294 attach_dummy_node(node, name, member)
295
296 def imported_member(self, node, member, name):
297 """verify this is not an imported class or handle it"""
298 # /!\ some classes like ExtensionClass doesn't have a __module__
299 # attribute ! Also, this may trigger an exception on badly built module
300 # (see http://www.logilab.org/ticket/57299 for instance)
301 try:
302 modname = getattr(member, '__module__', None)
303 except:
304 # XXX use logging
305 print('unexpected error while building astroid from living object')
306 import traceback
307 traceback.print_exc()
308 modname = None
309 if modname is None:
310 if name in ('__new__', '__subclasshook__'):
311 # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14)
312 # >>> print object.__new__.__module__
313 # None
314 modname = BUILTINS
315 else:
316 attach_dummy_node(node, name, member)
317 return True
318 if {'gtk': 'gtk._gtk'}.get(modname, modname) != self._module.__name__:
319 # check if it sounds valid and then add an import node, else use a
320 # dummy node
321 try:
322 getattr(sys.modules[modname], name)
323 except (KeyError, AttributeError):
324 attach_dummy_node(node, name, member)
325 else:
326 attach_import_node(node, modname, name)
327 return True
328 return False
329
330
331 ### astroid bootstrapping ######################################################
332 Astroid_BUILDER = InspectBuilder()
333
334 _CONST_PROXY = {}
335 def _astroid_bootstrapping(astroid_builtin=None):
336 """astroid boot strapping the builtins module"""
337 # this boot strapping is necessary since we need the Const nodes to
338 # inspect_build builtins, and then we can proxy Const
339 if astroid_builtin is None:
340 from logilab.common.compat import builtins
341 astroid_builtin = Astroid_BUILDER.inspect_build(builtins)
342
343 for cls, node_cls in CONST_CLS.items():
344 if cls is type(None):
345 proxy = build_class('NoneType')
346 proxy.parent = astroid_builtin
347 else:
348 proxy = astroid_builtin.getattr(cls.__name__)[0]
349 if cls in (dict, list, set, tuple):
350 node_cls._proxied = proxy
351 else:
352 _CONST_PROXY[cls] = proxy
353
354 _astroid_bootstrapping()
355
356 # TODO : find a nicer way to handle this situation;
357 # However __proxied introduced an
358 # infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870)
359 def _set_proxied(const):
360 return _CONST_PROXY[const.value.__class__]
361 Const._proxied = property(_set_proxied)
362
363 from types import GeneratorType
364 Generator._proxied = Class(GeneratorType.__name__, GeneratorType.__doc__)
365 Astroid_BUILDER.object_build(Generator._proxied, GeneratorType)
366
OLDNEW
« no previous file with comments | « third_party/logilab/logilab/astroid/protocols.py ('k') | third_party/logilab/logilab/astroid/rebuilder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698