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

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

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
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
« no previous file with comments | « third_party/logilab/astng/rebuilder.py ('k') | third_party/logilab/astng/utils.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 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
3 # 5 #
4 # This file is part of astroid. 6 # This file is part of logilab-astng.
5 # 7 #
6 # astroid is free software: you can redistribute it and/or modify it 8 # logilab-astng 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 9 # 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 10 # Free Software Foundation, either version 2.1 of the License, or (at your
9 # option) any later version. 11 # option) any later version.
10 # 12 #
11 # astroid is distributed in the hope that it will be useful, but 13 # logilab-astng is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 # for more details. 16 # for more details.
15 # 17 #
16 # You should have received a copy of the GNU Lesser General Public License along 18 # 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/>. 19 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
18 """This module contains the classes for "scoped" node, i.e. which are opening a 20 """This module contains the classes for "scoped" node, i.e. which are opening a
19 new local scope in the language definition : Module, Class, Function (and 21 new local scope in the language definition : Module, Class, Function (and
20 Lambda, GenExpr, DictComp and SetComp to some extent). 22 Lambda, GenExpr, DictComp and SetComp to some extent).
21 """ 23 """
22 from __future__ import with_statement 24 from __future__ import with_statement
23 25
24 __doctype__ = "restructuredtext en" 26 __doctype__ = "restructuredtext en"
25 27
26 import sys 28 import sys
27 from itertools import chain 29 from itertools import chain
28 try:
29 from io import BytesIO
30 except ImportError:
31 from cStringIO import StringIO as BytesIO
32 30
33 from logilab.common.compat import builtins 31 from logilab.common.compat import builtins
34 from logilab.common.decorators import cached, cachedproperty 32 from logilab.common.decorators import cached
35 33
36 from astroid.exceptions import NotFoundError, \ 34 from logilab.astng import BUILTINS_MODULE
37 AstroidBuildingException, InferenceError 35 from logilab.astng.exceptions import NotFoundError, NoDefault, \
38 from astroid.node_classes import Const, DelName, DelAttr, \ 36 ASTNGBuildingException, InferenceError
39 Dict, From, List, Pass, Raise, Return, Tuple, Yield, YieldFrom, \ 37 from logilab.astng.node_classes import Const, DelName, DelAttr, \
40 LookupMixIn, const_factory as cf, unpack_infer, Name, CallFunc 38 Dict, From, List, Name, Pass, Raise, Return, Tuple, Yield, \
41 from astroid.bases import NodeNG, InferenceContext, Instance,\ 39 are_exclusive, LookupMixIn, const_factory as cf, unpack_infer
40 from logilab.astng.bases import NodeNG, InferenceContext, Instance,\
42 YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \ 41 YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \
43 BUILTINS 42 BUILTINS_NAME
44 from astroid.mixins import FilterStmtsMixin 43 from logilab.astng.mixins import FilterStmtsMixin
45 from astroid.bases import Statement 44 from logilab.astng.bases import Statement
46 from astroid.manager import AstroidManager 45 from logilab.astng.manager import ASTNGManager
47
48 ITER_METHODS = ('__iter__', '__getitem__')
49 PY3K = sys.version_info >= (3, 0)
50 46
51 47
52 def remove_nodes(func, cls): 48 def remove_nodes(func, cls):
53 def wrapper(*args, **kwargs): 49 def wrapper(*args, **kwargs):
54 nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)] 50 nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)]
55 if not nodes: 51 if not nodes:
56 raise NotFoundError() 52 raise NotFoundError()
57 return nodes 53 return nodes
58 return wrapper 54 return wrapper
59 55
(...skipping 12 matching lines...) Expand all
72 else: 68 else:
73 locals = {} 69 locals = {}
74 if name == '__name__': 70 if name == '__name__':
75 return [cf(self.name)] + locals.get(name, []) 71 return [cf(self.name)] + locals.get(name, [])
76 if name == '__doc__': 72 if name == '__doc__':
77 return [cf(self.doc)] + locals.get(name, []) 73 return [cf(self.doc)] + locals.get(name, [])
78 if name == '__dict__': 74 if name == '__dict__':
79 return [Dict()] + locals.get(name, []) 75 return [Dict()] + locals.get(name, [])
80 raise NotFoundError(name) 76 raise NotFoundError(name)
81 77
82 MANAGER = AstroidManager() 78 MANAGER = ASTNGManager()
83 def builtin_lookup(name): 79 def builtin_lookup(name):
84 """lookup a name into the builtin module 80 """lookup a name into the builtin module
85 return the list of matching statements and the astroid for the builtin 81 return the list of matching statements and the astng for the builtin
86 module 82 module
87 """ 83 """
88 builtin_astroid = MANAGER.ast_from_module(builtins) 84 builtin_astng = MANAGER.astng_from_module(builtins)
89 if name == '__dict__': 85 if name == '__dict__':
90 return builtin_astroid, () 86 return builtin_astng, ()
91 try: 87 try:
92 stmts = builtin_astroid.locals[name] 88 stmts = builtin_astng.locals[name]
93 except KeyError: 89 except KeyError:
94 stmts = () 90 stmts = ()
95 return builtin_astroid, stmts 91 return builtin_astng, stmts
96 92
97 93
98 # TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup 94 # TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup
99 class LocalsDictNodeNG(LookupMixIn, NodeNG): 95 class LocalsDictNodeNG(LookupMixIn, NodeNG):
100 """ this class provides locals handling common to Module, Function 96 """ this class provides locals handling common to Module, Function
101 and Class nodes, including a dict like interface for direct access 97 and Class nodes, including a dict like interface for direct access
102 to locals information 98 to locals information
103 """ 99 """
104 100
105 # attributes below are set by the builder module or by raw factories 101 # attributes below are set by the builder module or by raw factories
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 return zip(self.keys(), self.values()) 203 return zip(self.keys(), self.values())
208 204
209 205
210 def __contains__(self, name): 206 def __contains__(self, name):
211 return name in self.locals 207 return name in self.locals
212 has_key = __contains__ 208 has_key = __contains__
213 209
214 # Module ##################################################################### 210 # Module #####################################################################
215 211
216 class Module(LocalsDictNodeNG): 212 class Module(LocalsDictNodeNG):
217 _astroid_fields = ('body',) 213 _astng_fields = ('body',)
218 214
219 fromlineno = 0 215 fromlineno = 0
220 lineno = 0 216 lineno = 0
221 217
222 # attributes below are set by the builder module or by raw factories 218 # attributes below are set by the builder module or by raw factories
223 219
224 # the file from which as been extracted the astroid representation. It may 220 # the file from which as been extracted the astng representation. It may
225 # be None if the representation has been built from a built-in module 221 # be None if the representation has been built from a built-in module
226 file = None 222 file = None
227 # Alternatively, if built from a string/bytes, this can be set
228 file_bytes = None
229 # encoding of python source file, so we can get unicode out of it (python2
230 # only)
231 file_encoding = None
232 # the module name 223 # the module name
233 name = None 224 name = None
234 # boolean for astroid built from source (i.e. ast) 225 # boolean for astng built from source (i.e. ast)
235 pure_python = None 226 pure_python = None
236 # boolean for package module 227 # boolean for package module
237 package = None 228 package = None
238 # dictionary of globals with name as key and node defining the global 229 # dictionary of globals with name as key and node defining the global
239 # as value 230 # as value
240 globals = None 231 globals = None
241 232
242 # Future imports
243 future_imports = None
244
245 # names of python special attributes (handled by getattr impl.) 233 # names of python special attributes (handled by getattr impl.)
246 special_attributes = set(('__name__', '__doc__', '__file__', '__path__', 234 special_attributes = set(('__name__', '__doc__', '__file__', '__path__',
247 '__dict__')) 235 '__dict__'))
248 # names of module attributes available through the global scope 236 # names of module attributes available through the global scope
249 scope_attrs = set(('__name__', '__doc__', '__file__', '__path__')) 237 scope_attrs = set(('__name__', '__doc__', '__file__', '__path__'))
250 238
251 def __init__(self, name, doc, pure_python=True): 239 def __init__(self, name, doc, pure_python=True):
252 self.name = name 240 self.name = name
253 self.doc = doc 241 self.doc = doc
254 self.pure_python = pure_python 242 self.pure_python = pure_python
255 self.locals = self.globals = {} 243 self.locals = self.globals = {}
256 self.body = [] 244 self.body = []
257 self.future_imports = set()
258 245
259 @property 246 @property
260 def file_stream(self): 247 def file_stream(self):
261 if self.file_bytes is not None:
262 return BytesIO(self.file_bytes)
263 if self.file is not None: 248 if self.file is not None:
264 return open(self.file, 'rb') 249 return file(self.file)
265 return None 250 return None
266 251
267 def block_range(self, lineno): 252 def block_range(self, lineno):
268 """return block line numbers. 253 """return block line numbers.
269 254
270 start from the beginning whatever the given lineno 255 start from the beginning whatever the given lineno
271 """ 256 """
272 return self.fromlineno, self.tolineno 257 return self.fromlineno, self.tolineno
273 258
274 def scope_lookup(self, node, name, offset=0): 259 def scope_lookup(self, node, name, offset=0):
275 if name in self.scope_attrs and not name in self.locals: 260 if name in self.scope_attrs and not name in self.locals:
276 try: 261 try:
277 return self, self.getattr(name) 262 return self, self.getattr(name)
278 except NotFoundError: 263 except NotFoundError:
279 return self, () 264 return self, ()
280 return self._scope_lookup(node, name, offset) 265 return self._scope_lookup(node, name, offset)
281 266
282 def pytype(self): 267 def pytype(self):
283 return '%s.module' % BUILTINS 268 return '%s.module' % BUILTINS_MODULE
284 269
285 def display_type(self): 270 def display_type(self):
286 return 'Module' 271 return 'Module'
287 272
288 def getattr(self, name, context=None, ignore_locals=False): 273 def getattr(self, name, context=None, ignore_locals=False):
289 if name in self.special_attributes: 274 if name in self.special_attributes:
290 if name == '__file__': 275 if name == '__file__':
291 return [cf(self.file)] + self.locals.get(name, []) 276 return [cf(self.file)] + self.locals.get(name, [])
292 if name == '__path__' and self.package: 277 if name == '__path__' and self.package:
293 return [List()] + self.locals.get(name, []) 278 return [List()] + self.locals.get(name, [])
294 return std_special_attributes(self, name) 279 return std_special_attributes(self, name)
295 if not ignore_locals and name in self.locals: 280 if not ignore_locals and name in self.locals:
296 return self.locals[name] 281 return self.locals[name]
297 if self.package: 282 if self.package:
298 try: 283 try:
299 return [self.import_module(name, relative_only=True)] 284 return [self.import_module(name, relative_only=True)]
300 except AstroidBuildingException: 285 except ASTNGBuildingException:
301 raise NotFoundError(name)
302 except SyntaxError:
303 raise NotFoundError(name) 286 raise NotFoundError(name)
304 except Exception:# XXX pylint tests never pass here; do we need it? 287 except Exception:# XXX pylint tests never pass here; do we need it?
305 import traceback 288 import traceback
306 traceback.print_exc() 289 traceback.print_exc()
307 raise NotFoundError(name) 290 raise NotFoundError(name)
308 getattr = remove_nodes(getattr, DelName) 291 getattr = remove_nodes(getattr, DelName)
309 292
310 def igetattr(self, name, context=None): 293 def igetattr(self, name, context=None):
311 """inferred getattr""" 294 """inferred getattr"""
312 # set lookup name since this is necessary to infer on import nodes for 295 # set lookup name since this is necessary to infer on import nodes for
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 return False 329 return False
347 else: 330 else:
348 absolute_import_activated = lambda self: True 331 absolute_import_activated = lambda self: True
349 332
350 def import_module(self, modname, relative_only=False, level=None): 333 def import_module(self, modname, relative_only=False, level=None):
351 """import the given module considering self as context""" 334 """import the given module considering self as context"""
352 if relative_only and level is None: 335 if relative_only and level is None:
353 level = 0 336 level = 0
354 absmodname = self.relative_to_absolute_name(modname, level) 337 absmodname = self.relative_to_absolute_name(modname, level)
355 try: 338 try:
356 return MANAGER.ast_from_module_name(absmodname) 339 return MANAGER.astng_from_module_name(absmodname)
357 except AstroidBuildingException: 340 except ASTNGBuildingException:
358 # we only want to import a sub module or package of this module, 341 # we only want to import a sub module or package of this module,
359 # skip here 342 # skip here
360 if relative_only: 343 if relative_only:
361 raise 344 raise
362 return MANAGER.ast_from_module_name(modname) 345 return MANAGER.astng_from_module_name(modname)
363 346
364 def relative_to_absolute_name(self, modname, level): 347 def relative_to_absolute_name(self, modname, level):
365 """return the absolute module name for a relative import. 348 """return the absolute module name for a relative import.
366 349
367 The relative import can be implicit or explicit. 350 The relative import can be implicit or explicit.
368 """ 351 """
369 # XXX this returns non sens when called on an absolute import 352 # XXX this returns non sens when called on an absolute import
370 # like 'pylint.checkers.astroid.utils' 353 # like 'pylint.checkers.logilab.astng.utils'
371 # XXX doesn't return absolute name if self.name isn't absolute name 354 # XXX doesn't return absolute name if self.name isn't absolute name
372 if self.absolute_import_activated() and level is None: 355 if self.absolute_import_activated() and level is None:
373 return modname 356 return modname
374 if level: 357 if level:
375 if self.package: 358 if self.package:
376 level = level - 1 359 level = level - 1
377 package_name = self.name.rsplit('.', level)[0] 360 package_name = self.name.rsplit('.', level)[0]
378 elif self.package: 361 elif self.package:
379 package_name = self.name 362 package_name = self.name
380 else: 363 else:
(...skipping 16 matching lines...) Expand all
397 try: 380 try:
398 living = sys.modules[self.name] 381 living = sys.modules[self.name]
399 except KeyError: 382 except KeyError:
400 pass 383 pass
401 else: 384 else:
402 try: 385 try:
403 return living.__all__ 386 return living.__all__
404 except AttributeError: 387 except AttributeError:
405 return [name for name in living.__dict__.keys() 388 return [name for name in living.__dict__.keys()
406 if not name.startswith('_')] 389 if not name.startswith('_')]
407 # else lookup the astroid 390 # else lookup the astng
408 # 391 #
409 # We separate the different steps of lookup in try/excepts 392 # We separate the different steps of lookup in try/excepts
410 # to avoid catching too many Exceptions 393 # to avoid catching too many Exceptions
411 # However, we can not analyse dynamically constructed __all__ 394 # However, we can not analyse dynamically constructed __all__
412 try: 395 try:
413 all = self['__all__'] 396 all = self['__all__']
414 except KeyError: 397 except KeyError:
415 return [name for name in self.keys() if not name.startswith('_')] 398 return [name for name in self.keys() if not name.startswith('_')]
416 try: 399 try:
417 explicit = all.assigned_stmts().next() 400 explicit = all.assigned_stmts().next()
(...skipping 11 matching lines...) Expand all
429 412
430 413
431 class ComprehensionScope(LocalsDictNodeNG): 414 class ComprehensionScope(LocalsDictNodeNG):
432 def frame(self): 415 def frame(self):
433 return self.parent.frame() 416 return self.parent.frame()
434 417
435 scope_lookup = LocalsDictNodeNG._scope_lookup 418 scope_lookup = LocalsDictNodeNG._scope_lookup
436 419
437 420
438 class GenExpr(ComprehensionScope): 421 class GenExpr(ComprehensionScope):
439 _astroid_fields = ('elt', 'generators') 422 _astng_fields = ('elt', 'generators')
440 423
441 def __init__(self): 424 def __init__(self):
442 self.locals = {} 425 self.locals = {}
443 self.elt = None 426 self.elt = None
444 self.generators = [] 427 self.generators = []
445 428
446 429
447 class DictComp(ComprehensionScope): 430 class DictComp(ComprehensionScope):
448 _astroid_fields = ('key', 'value', 'generators') 431 _astng_fields = ('key', 'value', 'generators')
449 432
450 def __init__(self): 433 def __init__(self):
451 self.locals = {} 434 self.locals = {}
452 self.key = None 435 self.key = None
453 self.value = None 436 self.value = None
454 self.generators = [] 437 self.generators = []
455 438
456 439
457 class SetComp(ComprehensionScope): 440 class SetComp(ComprehensionScope):
458 _astroid_fields = ('elt', 'generators') 441 _astng_fields = ('elt', 'generators')
459 442
460 def __init__(self): 443 def __init__(self):
461 self.locals = {} 444 self.locals = {}
462 self.elt = None 445 self.elt = None
463 self.generators = [] 446 self.generators = []
464 447
465 448
466 class _ListComp(NodeNG): 449 class _ListComp(NodeNG):
467 """class representing a ListComp node""" 450 """class representing a ListComp node"""
468 _astroid_fields = ('elt', 'generators') 451 _astng_fields = ('elt', 'generators')
469 elt = None 452 elt = None
470 generators = None 453 generators = None
471 454
472 if sys.version_info >= (3, 0): 455 if sys.version_info >= (3, 0):
473 class ListComp(_ListComp, ComprehensionScope): 456 class ListComp(_ListComp, ComprehensionScope):
474 """class representing a ListComp node""" 457 """class representing a ListComp node"""
475 def __init__(self): 458 def __init__(self):
476 self.locals = {} 459 self.locals = {}
477 else: 460 else:
478 class ListComp(_ListComp): 461 class ListComp(_ListComp):
479 """class representing a ListComp node""" 462 """class representing a ListComp node"""
480 463
481 # Function ################################################################### 464 # Function ###################################################################
482 465
483 def _infer_decorator_callchain(node):
484 """ Detect decorator call chaining and see if the
485 end result is a static or a classmethod.
486 """
487 current = node
488 while True:
489 if isinstance(current, CallFunc):
490 try:
491 current = current.func.infer().next()
492 except InferenceError:
493 return
494 elif isinstance(current, Function):
495 if not current.parent:
496 return
497 try:
498 # TODO: We don't handle multiple inference results right now,
499 # because there's no flow to reason when the return
500 # is what we are looking for, a static or a class method.
501 result = current.infer_call_result(current.parent).next()
502 except (StopIteration, InferenceError):
503 return
504 if isinstance(result, (Function, CallFunc)):
505 current = result
506 else:
507 if isinstance(result, Instance):
508 result = result._proxied
509 if isinstance(result, Class):
510 if (result.name == 'classmethod' and
511 result.root().name == BUILTINS):
512 return 'classmethod'
513 elif (result.name == 'staticmethod' and
514 result.root().name == BUILTINS):
515 return 'staticmethod'
516 else:
517 return
518 else:
519 # We aren't interested in anything else returned,
520 # so go back to the function type inference.
521 return
522 else:
523 return
524
525 def _function_type(self):
526 """
527 Function type, possible values are:
528 method, function, staticmethod, classmethod.
529 """
530 # Can't infer that this node is decorated
531 # with a subclass of `classmethod` where `type` is first set,
532 # so do it here.
533 if self.decorators:
534 for node in self.decorators.nodes:
535 if isinstance(node, CallFunc):
536 _type = _infer_decorator_callchain(node)
537 if _type is None:
538 continue
539 else:
540 return _type
541 if not isinstance(node, Name):
542 continue
543 try:
544 for infered in node.infer():
545 if not isinstance(infered, Class):
546 continue
547 for ancestor in infered.ancestors():
548 if isinstance(ancestor, Class):
549 if (ancestor.name == 'classmethod' and
550 ancestor.root().name == BUILTINS):
551 return 'classmethod'
552 elif (ancestor.name == 'staticmethod' and
553 ancestor.root().name == BUILTINS):
554 return 'staticmethod'
555 except InferenceError:
556 pass
557 return self._type
558
559 466
560 class Lambda(LocalsDictNodeNG, FilterStmtsMixin): 467 class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
561 _astroid_fields = ('args', 'body',) 468 _astng_fields = ('args', 'body',)
562 name = '<lambda>' 469 name = '<lambda>'
563 470
564 # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' 471 # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod'
565 type = 'function' 472 type = 'function'
566 473
567 def __init__(self): 474 def __init__(self):
568 self.locals = {} 475 self.locals = {}
569 self.args = [] 476 self.args = []
570 self.body = [] 477 self.body = []
571 478
572 def pytype(self): 479 def pytype(self):
573 if 'method' in self.type: 480 if 'method' in self.type:
574 return '%s.instancemethod' % BUILTINS 481 return '%s.instancemethod' % BUILTINS_MODULE
575 return '%s.function' % BUILTINS 482 return '%s.function' % BUILTINS_MODULE
576 483
577 def display_type(self): 484 def display_type(self):
578 if 'method' in self.type: 485 if 'method' in self.type:
579 return 'Method' 486 return 'Method'
580 return 'Function' 487 return 'Function'
581 488
582 def callable(self): 489 def callable(self):
583 return True 490 return True
584 491
585 def argnames(self): 492 def argnames(self):
586 """return a list of argument names""" 493 """return a list of argument names"""
587 if self.args.args: # maybe None with builtin functions 494 if self.args.args: # maybe None with builtin functions
588 names = _rec_get_names(self.args.args) 495 names = _rec_get_names(self.args.args)
589 else: 496 else:
590 names = [] 497 names = []
591 if self.args.vararg: 498 if self.args.vararg:
592 names.append(self.args.vararg) 499 names.append(self.args.vararg)
593 if self.args.kwarg: 500 if self.args.kwarg:
594 names.append(self.args.kwarg) 501 names.append(self.args.kwarg)
595 return names 502 return names
596 503
597 def infer_call_result(self, caller, context=None): 504 def infer_call_result(self, caller, context=None):
598 """infer what a function is returning when called""" 505 """infer what a function is returning when called"""
599 return self.body.infer(context) 506 return self.body.infer(context)
600 507
601 def scope_lookup(self, node, name, offset=0): 508 def scope_lookup(self, node, name, offset=0):
602 if node in self.args.defaults or node in self.args.kw_defaults: 509 if node in self.args.defaults:
603 frame = self.parent.frame() 510 frame = self.parent.frame()
604 # line offset to avoid that def func(f=func) resolve the default 511 # line offset to avoid that def func(f=func) resolve the default
605 # value to the defined function 512 # value to the defined function
606 offset = -1 513 offset = -1
607 else: 514 else:
608 # check this is not used in function decorators 515 # check this is not used in function decorators
609 frame = self 516 frame = self
610 return frame._scope_lookup(node, name, offset) 517 return frame._scope_lookup(node, name, offset)
611 518
612 519
613 class Function(Statement, Lambda): 520 class Function(Statement, Lambda):
614 if PY3K: 521 _astng_fields = ('decorators', 'args', 'body')
615 _astroid_fields = ('decorators', 'args', 'body', 'returns')
616 returns = None
617 else:
618 _astroid_fields = ('decorators', 'args', 'body')
619 522
620 special_attributes = set(('__name__', '__doc__', '__dict__')) 523 special_attributes = set(('__name__', '__doc__', '__dict__'))
621 is_function = True 524 is_function = True
622 # attributes below are set by the builder module or by raw factories 525 # attributes below are set by the builder module or by raw factories
623 blockstart_tolineno = None 526 blockstart_tolineno = None
624 decorators = None 527 decorators = None
625 _type = "function"
626 type = cachedproperty(_function_type)
627 528
628 def __init__(self, name, doc): 529 def __init__(self, name, doc):
629 self.locals = {} 530 self.locals = {}
630 self.args = [] 531 self.args = []
631 self.body = [] 532 self.body = []
632 self.decorators = None 533 self.decorators = None
633 self.name = name 534 self.name = name
634 self.doc = doc 535 self.doc = doc
635 self.extra_decorators = [] 536 self.extra_decorators = []
636 self.instance_attrs = {} 537 self.instance_attrs = {}
637 538
638 def set_line_info(self, lastchild): 539 def set_line_info(self, lastchild):
639 self.fromlineno = self.lineno 540 self.fromlineno = self.lineno
640 # lineno is the line number of the first decorator, we want the def stat ement lineno 541 # lineno is the line number of the first decorator, we want the def stat ement lineno
641 if self.decorators is not None: 542 if self.decorators is not None:
642 self.fromlineno += sum(node.tolineno - node.lineno + 1 543 self.fromlineno += len(self.decorators.nodes)
643 for node in self.decorators.nodes)
644 if self.args.fromlineno < self.fromlineno:
645 self.args.fromlineno = self.fromlineno
646 self.tolineno = lastchild.tolineno 544 self.tolineno = lastchild.tolineno
647 self.blockstart_tolineno = self.args.tolineno 545 self.blockstart_tolineno = self.args.tolineno
648 546
649 def block_range(self, lineno): 547 def block_range(self, lineno):
650 """return block line numbers. 548 """return block line numbers.
651 549
652 start from the "def" position whatever the given lineno 550 start from the "def" position whatever the given lineno
653 """ 551 """
654 return self.fromlineno, self.tolineno 552 return self.fromlineno, self.tolineno
655 553
(...skipping 24 matching lines...) Expand all
680 for infnode in decnode.infer(): 578 for infnode in decnode.infer():
681 result.add(infnode.qname()) 579 result.add(infnode.qname())
682 return result 580 return result
683 decoratornames = cached(decoratornames) 581 decoratornames = cached(decoratornames)
684 582
685 def is_bound(self): 583 def is_bound(self):
686 """return true if the function is bound to an Instance or a class""" 584 """return true if the function is bound to an Instance or a class"""
687 return self.type == 'classmethod' 585 return self.type == 'classmethod'
688 586
689 def is_abstract(self, pass_is_abstract=True): 587 def is_abstract(self, pass_is_abstract=True):
690 """Returns True if the method is abstract. 588 """return true if the method is abstract
691 589 It's considered as abstract if the only statement is a raise of
692 A method is considered abstract if 590 NotImplementError, or, if pass_is_abstract, a pass statement
693 - the only statement is 'raise NotImplementedError', or
694 - the only statement is 'pass' and pass_is_abstract is True, or
695 - the method is annotated with abc.astractproperty/abc.abstractmethod
696 """ 591 """
697 if self.decorators:
698 for node in self.decorators.nodes:
699 try:
700 infered = node.infer().next()
701 except InferenceError:
702 continue
703 if infered and infered.qname() in ('abc.abstractproperty',
704 'abc.abstractmethod'):
705 return True
706
707 for child_node in self.body: 592 for child_node in self.body:
708 if isinstance(child_node, Raise): 593 if isinstance(child_node, Raise):
709 if child_node.raises_not_implemented(): 594 if child_node.raises_not_implemented():
710 return True 595 return True
711 if pass_is_abstract and isinstance(child_node, Pass): 596 if pass_is_abstract and isinstance(child_node, Pass):
712 return True 597 return True
713 return False 598 return False
714 # empty function is the same as function with a single "pass" statement 599 # empty function is the same as function with a single "pass" statement
715 if pass_is_abstract: 600 if pass_is_abstract:
716 return True 601 return True
717 602
718 def is_generator(self): 603 def is_generator(self):
719 """return true if this is a generator function""" 604 """return true if this is a generator function"""
720 # XXX should be flagged, not computed 605 # XXX should be flagged, not computed
721 try: 606 try:
722 return self.nodes_of_class((Yield, YieldFrom), 607 return self.nodes_of_class(Yield, skip_klass=Function).next()
723 skip_klass=(Function, Lambda)).next()
724 except StopIteration: 608 except StopIteration:
725 return False 609 return False
726 610
727 def infer_call_result(self, caller, context=None): 611 def infer_call_result(self, caller, context=None):
728 """infer what a function is returning when called""" 612 """infer what a function is returning when called"""
729 if self.is_generator(): 613 if self.is_generator():
730 yield Generator() 614 yield Generator(self)
731 return 615 return
732 returns = self.nodes_of_class(Return, skip_klass=Function) 616 returns = self.nodes_of_class(Return, skip_klass=Function)
733 for returnnode in returns: 617 for returnnode in returns:
734 if returnnode.value is None: 618 if returnnode.value is None:
735 yield Const(None) 619 yield Const(None)
736 else: 620 else:
737 try: 621 try:
738 for infered in returnnode.value.infer(context): 622 for infered in returnnode.value.infer(context):
739 yield infered 623 yield infered
740 except InferenceError: 624 except InferenceError:
741 yield YES 625 yield YES
742 626
743 627
744 def _rec_get_names(args, names=None): 628 def _rec_get_names(args, names=None):
745 """return a list of all argument names""" 629 """return a list of all argument names"""
746 if names is None: 630 if names is None:
747 names = [] 631 names = []
748 for arg in args: 632 for arg in args:
749 if isinstance(arg, Tuple): 633 if isinstance(arg, Tuple):
750 _rec_get_names(arg.elts, names) 634 _rec_get_names(arg.elts, names)
751 else: 635 else:
752 names.append(arg.name) 636 names.append(arg.name)
753 return names 637 return names
754 638
755 639
756 # Class ###################################################################### 640 # Class ######################################################################
757 641
758
759 def _is_metaclass(klass, seen=None):
760 """ Return if the given class can be
761 used as a metaclass.
762 """
763 if klass.name == 'type':
764 return True
765 if seen is None:
766 seen = set()
767 for base in klass.bases:
768 try:
769 for baseobj in base.infer():
770 if baseobj in seen:
771 continue
772 else:
773 seen.add(baseobj)
774 if isinstance(baseobj, Instance):
775 # not abstract
776 return False
777 if baseobj is YES:
778 continue
779 if baseobj is klass:
780 continue
781 if not isinstance(baseobj, Class):
782 continue
783 if baseobj._type == 'metaclass':
784 return True
785 if _is_metaclass(baseobj, seen):
786 return True
787 except InferenceError:
788 continue
789 return False
790
791
792 def _class_type(klass, ancestors=None): 642 def _class_type(klass, ancestors=None):
793 """return a Class node type to differ metaclass, interface and exception 643 """return a Class node type to differ metaclass, interface and exception
794 from 'regular' classes 644 from 'regular' classes
795 """ 645 """
796 # XXX we have to store ancestors in case we have a ancestor loop 646 # XXX we have to store ancestors in case we have a ancestor loop
797 if klass._type is not None: 647 if klass._type is not None:
798 return klass._type 648 return klass._type
799 if _is_metaclass(klass): 649 if klass.name == 'type':
800 klass._type = 'metaclass' 650 klass._type = 'metaclass'
801 elif klass.name.endswith('Interface'): 651 elif klass.name.endswith('Interface'):
802 klass._type = 'interface' 652 klass._type = 'interface'
803 elif klass.name.endswith('Exception'): 653 elif klass.name.endswith('Exception'):
804 klass._type = 'exception' 654 klass._type = 'exception'
805 else: 655 else:
806 if ancestors is None: 656 if ancestors is None:
807 ancestors = set() 657 ancestors = set()
808 if klass in ancestors: 658 if klass in ancestors:
809 # XXX we are in loop ancestors, and have found no type 659 # XXX we are in loop ancestors, and have found no type
810 klass._type = 'class' 660 klass._type = 'class'
811 return 'class' 661 return 'class'
812 ancestors.add(klass) 662 ancestors.add(klass)
813 # print >> sys.stderr, '_class_type', repr(klass) 663 # print >> sys.stderr, '_class_type', repr(klass)
814 for base in klass.ancestors(recurs=False): 664 for base in klass.ancestors(recurs=False):
815 name = _class_type(base, ancestors) 665 if _class_type(base, ancestors) != 'class':
816 if name != 'class':
817 if name == 'metaclass' and not _is_metaclass(klass):
818 # don't propagate it if the current class
819 # can't be a metaclass
820 continue
821 klass._type = base.type 666 klass._type = base.type
822 break 667 break
823 if klass._type is None: 668 if klass._type is None:
824 klass._type = 'class' 669 klass._type = 'class'
825 return klass._type 670 return klass._type
826 671
827 def _iface_hdlr(iface_node): 672 def _iface_hdlr(iface_node):
828 """a handler function used by interfaces to handle suspicious 673 """a handler function used by interfaces to handle suspicious
829 interface nodes 674 interface nodes
830 """ 675 """
831 return True 676 return True
832 677
833 678
834 class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin): 679 class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
835 680
836 # some of the attributes below are set by the builder module or 681 # some of the attributes below are set by the builder module or
837 # by a raw factories 682 # by a raw factories
838 683
839 # a dictionary of class instances attributes 684 # a dictionary of class instances attributes
840 _astroid_fields = ('decorators', 'bases', 'body') # name 685 _astng_fields = ('decorators', 'bases', 'body') # name
841 686
842 decorators = None 687 decorators = None
843 special_attributes = set(('__name__', '__doc__', '__dict__', '__module__', 688 special_attributes = set(('__name__', '__doc__', '__dict__', '__module__',
844 '__bases__', '__mro__', '__subclasses__')) 689 '__bases__', '__mro__', '__subclasses__'))
845 blockstart_tolineno = None 690 blockstart_tolineno = None
846 691
847 _type = None 692 _type = None
848 type = property(_class_type, 693 type = property(_class_type,
849 doc="class'type, possible values are 'class' | " 694 doc="class'type, possible values are 'class' | "
850 "'metaclass' | 'interface' | 'exception'") 695 "'metaclass' | 'interface' | 'exception'")
851 696
852 def __init__(self, name, doc): 697 def __init__(self, name, doc):
853 self.instance_attrs = {} 698 self.instance_attrs = {}
854 self.locals = {} 699 self.locals = {}
855 self.bases = [] 700 self.bases = []
856 self.body = [] 701 self.body = []
857 self.name = name 702 self.name = name
858 self.doc = doc 703 self.doc = doc
859 704
860 def _newstyle_impl(self, context=None): 705 def _newstyle_impl(self, context=None):
861 if context is None: 706 if context is None:
862 context = InferenceContext() 707 context = InferenceContext()
863 if self._newstyle is not None: 708 if self._newstyle is not None:
864 return self._newstyle 709 return self._newstyle
865 for base in self.ancestors(recurs=False, context=context): 710 for base in self.ancestors(recurs=False, context=context):
866 if base._newstyle_impl(context): 711 if base._newstyle_impl(context):
867 self._newstyle = True 712 self._newstyle = True
868 break 713 break
869 klass = self._explicit_metaclass()
870 # could be any callable, we'd need to infer the result of klass(name,
871 # bases, dict). punt if it's not a class node.
872 if klass is not None and isinstance(klass, Class):
873 self._newstyle = klass._newstyle_impl(context)
874 if self._newstyle is None: 714 if self._newstyle is None:
875 self._newstyle = False 715 self._newstyle = False
876 return self._newstyle 716 return self._newstyle
877 717
878 _newstyle = None 718 _newstyle = None
879 newstyle = property(_newstyle_impl, 719 newstyle = property(_newstyle_impl,
880 doc="boolean indicating if it's a new style class" 720 doc="boolean indicating if it's a new style class"
881 "or not") 721 "or not")
882 722
883 def set_line_info(self, lastchild): 723 def set_line_info(self, lastchild):
884 self.fromlineno = self.lineno 724 self.fromlineno = self.lineno
885 self.blockstart_tolineno = self.bases and self.bases[-1].tolineno or sel f.fromlineno 725 self.blockstart_tolineno = self.bases and self.bases[-1].tolineno or sel f.fromlineno
886 if lastchild is not None: 726 if lastchild is not None:
887 self.tolineno = lastchild.tolineno 727 self.tolineno = lastchild.tolineno
888 # else this is a class with only a docstring, then tolineno is (should b e) already ok 728 # else this is a class with only a docstring, then tolineno is (should b e) already ok
889 729
890 def block_range(self, lineno): 730 def block_range(self, lineno):
891 """return block line numbers. 731 """return block line numbers.
892 732
893 start from the "class" position whatever the given lineno 733 start from the "class" position whatever the given lineno
894 """ 734 """
895 return self.fromlineno, self.tolineno 735 return self.fromlineno, self.tolineno
896 736
897 def pytype(self): 737 def pytype(self):
898 if self.newstyle: 738 if self.newstyle:
899 return '%s.type' % BUILTINS 739 return '%s.type' % BUILTINS_MODULE
900 return '%s.classobj' % BUILTINS 740 return '%s.classobj' % BUILTINS_MODULE
901 741
902 def display_type(self): 742 def display_type(self):
903 return 'Class' 743 return 'Class'
904 744
905 def callable(self): 745 def callable(self):
906 return True 746 return True
907 747
908 def _is_subtype_of(self, type_name):
909 if self.qname() == type_name:
910 return True
911 for anc in self.ancestors():
912 if anc.qname() == type_name:
913 return True
914
915 def infer_call_result(self, caller, context=None): 748 def infer_call_result(self, caller, context=None):
916 """infer what a class is returning when called""" 749 """infer what a class is returning when called"""
917 if self._is_subtype_of('%s.type' % (BUILTINS,)) and len(caller.args) == 3: 750 yield Instance(self)
918 name_node = caller.args[0].infer().next()
919 if isinstance(name_node, Const) and isinstance(name_node.value, base string):
920 name = name_node.value
921 else:
922 yield YES
923 return
924 result = Class(name, None)
925 bases = caller.args[1].infer().next()
926 if isinstance(bases, (Tuple, List)):
927 result.bases = bases.itered()
928 else:
929 # There is currently no AST node that can represent an 'unknown'
930 # node (YES is not an AST node), therefore we simply return YES here
931 # although we know at least the name of the class.
932 yield YES
933 return
934 result.parent = caller.parent
935 yield result
936 else:
937 yield Instance(self)
938 751
939 def scope_lookup(self, node, name, offset=0): 752 def scope_lookup(self, node, name, offset=0):
940 if node in self.bases: 753 if node in self.bases:
941 frame = self.parent.frame() 754 frame = self.parent.frame()
942 # line offset to avoid that class A(A) resolve the ancestor to 755 # line offset to avoid that class A(A) resolve the ancestor to
943 # the defined class 756 # the defined class
944 offset = -1 757 offset = -1
945 else: 758 else:
946 frame = self 759 frame = self
947 return frame._scope_lookup(node, name, offset) 760 return frame._scope_lookup(node, name, offset)
(...skipping 16 matching lines...) Expand all
964 # XXX inference make infinite loops possible here (see BaseTransformer 777 # XXX inference make infinite loops possible here (see BaseTransformer
965 # manipulation in the builder module for instance) 778 # manipulation in the builder module for instance)
966 yielded = set([self]) 779 yielded = set([self])
967 if context is None: 780 if context is None:
968 context = InferenceContext() 781 context = InferenceContext()
969 for stmt in self.bases: 782 for stmt in self.bases:
970 with context.restore_path(): 783 with context.restore_path():
971 try: 784 try:
972 for baseobj in stmt.infer(context): 785 for baseobj in stmt.infer(context):
973 if not isinstance(baseobj, Class): 786 if not isinstance(baseobj, Class):
974 if isinstance(baseobj, Instance): 787 # duh ?
975 baseobj = baseobj._proxied 788 continue
976 else:
977 # duh ?
978 continue
979 if baseobj in yielded: 789 if baseobj in yielded:
980 continue # cf xxx above 790 continue # cf xxx above
981 yielded.add(baseobj) 791 yielded.add(baseobj)
982 yield baseobj 792 yield baseobj
983 if recurs: 793 if recurs:
984 for grandpa in baseobj.ancestors(True, context): 794 for grandpa in baseobj.ancestors(True, context):
985 if grandpa in yielded: 795 if grandpa in yielded:
986 continue # cf xxx above 796 continue # cf xxx above
987 yielded.add(grandpa) 797 yielded.add(grandpa)
988 yield grandpa 798 yield grandpa
989 except InferenceError: 799 except InferenceError:
990 # XXX log error ? 800 # XXX log error ?
991 continue 801 continue
992 802
993 def local_attr_ancestors(self, name, context=None): 803 def local_attr_ancestors(self, name, context=None):
994 """return an iterator on astroid representation of parent classes 804 """return an iterator on astng representation of parent classes
995 which have <name> defined in their locals 805 which have <name> defined in their locals
996 """ 806 """
997 for astroid in self.ancestors(context=context): 807 for astng in self.ancestors(context=context):
998 if name in astroid: 808 if name in astng:
999 yield astroid 809 yield astng
1000 810
1001 def instance_attr_ancestors(self, name, context=None): 811 def instance_attr_ancestors(self, name, context=None):
1002 """return an iterator on astroid representation of parent classes 812 """return an iterator on astng representation of parent classes
1003 which have <name> defined in their instance attribute dictionary 813 which have <name> defined in their instance attribute dictionary
1004 """ 814 """
1005 for astroid in self.ancestors(context=context): 815 for astng in self.ancestors(context=context):
1006 if name in astroid.instance_attrs: 816 if name in astng.instance_attrs:
1007 yield astroid 817 yield astng
1008 818
1009 def has_base(self, node): 819 def has_base(self, node):
1010 return node in self.bases 820 return node in self.bases
1011 821
1012 def local_attr(self, name, context=None): 822 def local_attr(self, name, context=None):
1013 """return the list of assign node associated to name in this class 823 """return the list of assign node associated to name in this class
1014 locals or in its parents 824 locals or in its parents
1015 825
1016 :raises `NotFoundError`: 826 :raises `NotFoundError`:
1017 if no attribute with this name has been find in this class or 827 if no attribute with this name has been find in this class or
1018 its parent classes 828 its parent classes
1019 """ 829 """
1020 try: 830 try:
1021 return self.locals[name] 831 return self.locals[name]
1022 except KeyError: 832 except KeyError:
1023 # get if from the first parent implementing it if any 833 # get if from the first parent implementing it if any
1024 for class_node in self.local_attr_ancestors(name, context): 834 for class_node in self.local_attr_ancestors(name, context):
1025 return class_node.locals[name] 835 return class_node.locals[name]
1026 raise NotFoundError(name) 836 raise NotFoundError(name)
1027 local_attr = remove_nodes(local_attr, DelAttr) 837 local_attr = remove_nodes(local_attr, DelAttr)
1028 838
1029 def instance_attr(self, name, context=None): 839 def instance_attr(self, name, context=None):
1030 """return the astroid nodes associated to name in this class instance 840 """return the astng nodes associated to name in this class instance
1031 attributes dictionary and in its parents 841 attributes dictionary and in its parents
1032 842
1033 :raises `NotFoundError`: 843 :raises `NotFoundError`:
1034 if no attribute with this name has been find in this class or 844 if no attribute with this name has been find in this class or
1035 its parent classes 845 its parent classes
1036 """ 846 """
1037 # Return a copy, so we don't modify self.instance_attrs, 847 values = self.instance_attrs.get(name, [])
1038 # which could lead to infinite loop.
1039 values = list(self.instance_attrs.get(name, []))
1040 # get all values from parents 848 # get all values from parents
1041 for class_node in self.instance_attr_ancestors(name, context): 849 for class_node in self.instance_attr_ancestors(name, context):
1042 values += class_node.instance_attrs[name] 850 values += class_node.instance_attrs[name]
1043 if not values: 851 if not values:
1044 raise NotFoundError(name) 852 raise NotFoundError(name)
1045 return values 853 return values
1046 instance_attr = remove_nodes(instance_attr, DelAttr) 854 instance_attr = remove_nodes(instance_attr, DelAttr)
1047 855
1048 def instanciate_class(self): 856 def instanciate_class(self):
1049 """return Instance of Class node, else return self""" 857 """return Instance of Class node, else return self"""
1050 return Instance(self) 858 return Instance(self)
1051 859
1052 def getattr(self, name, context=None): 860 def getattr(self, name, context=None):
1053 """this method doesn't look in the instance_attrs dictionary since it's 861 """this method doesn't look in the instance_attrs dictionary since it's
1054 done by an Instance proxy at inference time. 862 done by an Instance proxy at inference time.
1055 863
1056 It may return a YES object if the attribute has not been actually 864 It may return a YES object if the attribute has not been actually
1057 found but a __getattr__ or __getattribute__ method is defined 865 found but a __getattr__ or __getattribute__ method is defined
1058 """ 866 """
1059 values = self.locals.get(name, []) 867 values = self.locals.get(name, [])
1060 if name in self.special_attributes: 868 if name in self.special_attributes:
1061 if name == '__module__': 869 if name == '__module__':
1062 return [cf(self.root().qname())] + values 870 return [cf(self.root().qname())] + values
1063 # FIXME: do we really need the actual list of ancestors? 871 # FIXME : what is expected by passing the list of ancestors to cf:
1064 # returning [Tuple()] + values don't break any test 872 # you can just do [cf(tuple())] + values without breaking any test
1065 # this is ticket http://www.logilab.org/ticket/52785 873 # this is ticket http://www.logilab.org/ticket/52785
874 if name == '__bases__':
875 return [cf(tuple(self.ancestors(recurs=False, context=context))) ] + values
1066 # XXX need proper meta class handling + MRO implementation 876 # XXX need proper meta class handling + MRO implementation
1067 if name == '__bases__' or (name == '__mro__' and self.newstyle): 877 if name == '__mro__' and self.newstyle:
1068 node = Tuple() 878 # XXX mro is read-only but that's not our job to detect that
1069 node.items = self.ancestors(recurs=True, context=context) 879 return [cf(tuple(self.ancestors(recurs=True, context=context)))] + values
1070 return [node] + values
1071 return std_special_attributes(self, name) 880 return std_special_attributes(self, name)
1072 # don't modify the list in self.locals! 881 # don't modify the list in self.locals!
1073 values = list(values) 882 values = list(values)
1074 for classnode in self.ancestors(recurs=True, context=context): 883 for classnode in self.ancestors(recurs=True, context=context):
1075 values += classnode.locals.get(name, []) 884 values += classnode.locals.get(name, [])
1076 if not values: 885 if not values:
1077 raise NotFoundError(name) 886 raise NotFoundError(name)
1078 return values 887 return values
1079 888
1080 def igetattr(self, name, context=None): 889 def igetattr(self, name, context=None):
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 # need to explicitly handle optparse.Values (setattr is not detected) 921 # need to explicitly handle optparse.Values (setattr is not detected)
1113 if self.name == 'Values' and self.root().name == 'optparse': 922 if self.name == 'Values' and self.root().name == 'optparse':
1114 return True 923 return True
1115 try: 924 try:
1116 self.getattr('__getattr__', context) 925 self.getattr('__getattr__', context)
1117 return True 926 return True
1118 except NotFoundError: 927 except NotFoundError:
1119 #if self.newstyle: XXX cause an infinite recursion error 928 #if self.newstyle: XXX cause an infinite recursion error
1120 try: 929 try:
1121 getattribute = self.getattr('__getattribute__', context)[0] 930 getattribute = self.getattr('__getattribute__', context)[0]
1122 if getattribute.root().name != BUILTINS: 931 if getattribute.root().name != BUILTINS_NAME:
1123 # class has a custom __getattribute__ defined 932 # class has a custom __getattribute__ defined
1124 return True 933 return True
1125 except NotFoundError: 934 except NotFoundError:
1126 pass 935 pass
1127 return False 936 return False
1128 937
1129 def methods(self): 938 def methods(self):
1130 """return an iterator on all methods defined in the class and 939 """return an iterator on all methods defined in the class and
1131 its ancestors 940 its ancestors
1132 """ 941 """
1133 done = {} 942 done = {}
1134 for astroid in chain(iter((self,)), self.ancestors()): 943 for astng in chain(iter((self,)), self.ancestors()):
1135 for meth in astroid.mymethods(): 944 for meth in astng.mymethods():
1136 if meth.name in done: 945 if meth.name in done:
1137 continue 946 continue
1138 done[meth.name] = None 947 done[meth.name] = None
1139 yield meth 948 yield meth
1140 949
1141 def mymethods(self): 950 def mymethods(self):
1142 """return an iterator on all methods defined in the class""" 951 """return an iterator on all methods defined in the class"""
1143 for member in self.values(): 952 for member in self.values():
1144 if isinstance(member, Function): 953 if isinstance(member, Function):
1145 yield member 954 yield member
(...skipping 13 matching lines...) Expand all
1159 missing = False 968 missing = False
1160 for iface in unpack_infer(implements): 969 for iface in unpack_infer(implements):
1161 if iface is YES: 970 if iface is YES:
1162 missing = True 971 missing = True
1163 continue 972 continue
1164 if not iface in found and handler_func(iface): 973 if not iface in found and handler_func(iface):
1165 found.add(iface) 974 found.add(iface)
1166 yield iface 975 yield iface
1167 if missing: 976 if missing:
1168 raise InferenceError() 977 raise InferenceError()
1169
1170 _metaclass = None
1171 def _explicit_metaclass(self):
1172 """ Return the explicit defined metaclass
1173 for the current class.
1174
1175 An explicit defined metaclass is defined
1176 either by passing the ``metaclass`` keyword argument
1177 in the class definition line (Python 3) or (Python 2) by
1178 having a ``__metaclass__`` class attribute, or if there are
1179 no explicit bases but there is a global ``__metaclass__`` variable.
1180 """
1181 if self._metaclass:
1182 # Expects this from Py3k TreeRebuilder
1183 try:
1184 return next(node for node in self._metaclass.infer()
1185 if node is not YES)
1186 except (InferenceError, StopIteration):
1187 return None
1188 if sys.version_info >= (3, ):
1189 return None
1190
1191 if '__metaclass__' in self.locals:
1192 assignment = self.locals['__metaclass__'][-1]
1193 elif self.bases:
1194 return None
1195 elif '__metaclass__' in self.root().locals:
1196 assignments = [ass for ass in self.root().locals['__metaclass__']
1197 if ass.lineno < self.lineno]
1198 if not assignments:
1199 return None
1200 assignment = assignments[-1]
1201 else:
1202 return None
1203
1204 try:
1205 infered = assignment.infer().next()
1206 except InferenceError:
1207 return
1208 if infered is YES: # don't expose this
1209 return None
1210 return infered
1211
1212 def metaclass(self):
1213 """ Return the metaclass of this class.
1214
1215 If this class does not define explicitly a metaclass,
1216 then the first defined metaclass in ancestors will be used
1217 instead.
1218 """
1219 klass = self._explicit_metaclass()
1220 if klass is None:
1221 for parent in self.ancestors():
1222 klass = parent.metaclass()
1223 if klass is not None:
1224 break
1225 return klass
1226
1227 def _islots(self):
1228 """ Return an iterator with the inferred slots. """
1229 if '__slots__' not in self.locals:
1230 return
1231 for slots in self.igetattr('__slots__'):
1232 # check if __slots__ is a valid type
1233 for meth in ITER_METHODS:
1234 try:
1235 slots.getattr(meth)
1236 break
1237 except NotFoundError:
1238 continue
1239 else:
1240 continue
1241
1242 if isinstance(slots, Const):
1243 # a string. Ignore the following checks,
1244 # but yield the node, only if it has a value
1245 if slots.value:
1246 yield slots
1247 continue
1248 if not hasattr(slots, 'itered'):
1249 # we can't obtain the values, maybe a .deque?
1250 continue
1251
1252 if isinstance(slots, Dict):
1253 values = [item[0] for item in slots.items]
1254 else:
1255 values = slots.itered()
1256 if values is YES:
1257 continue
1258
1259 for elt in values:
1260 try:
1261 for infered in elt.infer():
1262 if infered is YES:
1263 continue
1264 if (not isinstance(infered, Const) or
1265 not isinstance(infered.value, str)):
1266 continue
1267 if not infered.value:
1268 continue
1269 yield infered
1270 except InferenceError:
1271 continue
1272
1273 # Cached, because inferring them all the time is expensive
1274 @cached
1275 def slots(self):
1276 """ Return all the slots for this node. """
1277 return list(self._islots())
OLDNEW
« no previous file with comments | « third_party/logilab/astng/rebuilder.py ('k') | third_party/logilab/astng/utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698