summaryrefslogtreecommitdiff
path: root/astroid
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-10-11 19:06:30 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2015-10-11 19:06:30 +0300
commitfe16fb4d0ef01db3eb1411a8a278cb5839b078f6 (patch)
tree69f3fc8d88b9cf14beea339dfbae22b2ec28ed0c /astroid
parent68632aebe9b150925280d0abfd62552d7201727a (diff)
downloadastroid-fe16fb4d0ef01db3eb1411a8a278cb5839b078f6.tar.gz
Move bases.NodeNG and bases.Statement in node_classes
We're doing this in order to reduce the dependency hell which occurs when a module such as bases.py wants to use classes defined in node_classes.
Diffstat (limited to 'astroid')
-rw-r--r--astroid/bases.py478
-rw-r--r--astroid/node_classes.py585
-rw-r--r--astroid/objects.py2
-rw-r--r--astroid/scoped_nodes.py10
4 files changed, 537 insertions, 538 deletions
diff --git a/astroid/bases.py b/astroid/bases.py
index c2ea55e..01f7bde 100644
--- a/astroid/bases.py
+++ b/astroid/bases.py
@@ -23,20 +23,12 @@ from __future__ import print_function
import collections
import functools
-import pprint
import sys
import warnings
-try:
- from functools import singledispatch as _singledispatch
-except ImportError:
- from singledispatch import singledispatch as _singledispatch
-
import wrapt
-from astroid import as_string
from astroid import context as contextmod
-from astroid import decorators as decoratorsmod
from astroid import exceptions
from astroid import util
@@ -475,473 +467,3 @@ def raise_if_nothing_inferred(func, instance, args, kwargs):
yield node
if not inferred:
raise exceptions.InferenceError()
-
-
-# Node ######################################################################
-
-class NodeNG(object):
- """Base Class for all Astroid node classes.
-
- It represents a node of the new abstract syntax tree.
- """
- is_statement = False
- optional_assign = False # True for For (and for Comprehension if py <3.0)
- is_function = False # True for FunctionDef nodes
- # attributes below are set by the builder module or by raw factories
- lineno = None
- col_offset = None
- # parent node in the tree
- parent = None
- # attributes containing child node(s) redefined in most concrete classes:
- _astroid_fields = ()
- # attributes containing non-nodes:
- _other_fields = ()
- # attributes containing AST-dependent fields:
- _other_other_fields = ()
- # instance specific inference function infer(node, context)
- _explicit_inference = None
-
- def __init__(self, lineno=None, col_offset=None, parent=None):
- self.lineno = lineno
- self.col_offset = col_offset
- self.parent = parent
-
- def infer(self, context=None, **kwargs):
- """main interface to the interface system, return a generator on inferred
- values.
-
- If the instance has some explicit inference function set, it will be
- called instead of the default interface.
- """
- if self._explicit_inference is not None:
- # explicit_inference is not bound, give it self explicitly
- try:
- # pylint: disable=not-callable
- return self._explicit_inference(self, context, **kwargs)
- except exceptions.UseInferenceDefault:
- pass
-
- if not context:
- return self._infer(context, **kwargs)
-
- key = (self, context.lookupname,
- context.callcontext, context.boundnode)
- if key in context.inferred:
- return iter(context.inferred[key])
-
- return context.cache_generator(key, self._infer(context, **kwargs))
-
- def _repr_name(self):
- """return self.name or self.attrname or '' for nice representation"""
- return getattr(self, 'name', getattr(self, 'attrname', ''))
-
- def __str__(self):
- rname = self._repr_name()
- cname = type(self).__name__
- if rname:
- string = '%(cname)s.%(rname)s(%(fields)s)'
- alignment = len(cname) + len(rname) + 2
- else:
- string = '%(cname)s(%(fields)s)'
- alignment = len(cname) + 1
- result = []
- for field in self._other_fields + self._astroid_fields:
- value = getattr(self, field)
- width = 80 - len(field) - alignment
- lines = pprint.pformat(value, indent=2,
- width=width).splitlines(True)
-
- inner = [lines[0]]
- for line in lines[1:]:
- inner.append(' ' * alignment + line)
- result.append('%s=%s' % (field, ''.join(inner)))
-
- return string % {'cname': cname,
- 'rname': rname,
- 'fields': (',\n' + ' ' * alignment).join(result)}
-
- def __repr__(self):
- rname = self._repr_name()
- if rname:
- string = '<%(cname)s.%(rname)s l.%(lineno)s at 0x%(id)x>'
- else:
- string = '<%(cname)s l.%(lineno)s at 0x%(id)x>'
- return string % {'cname': type(self).__name__,
- 'rname': rname,
- 'lineno': self.fromlineno,
- 'id': id(self)}
-
- def accept(self, visitor):
- func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
- return func(self)
-
- def get_children(self):
- for field in self._astroid_fields:
- attr = getattr(self, field)
- if attr is None:
- continue
- if isinstance(attr, (list, tuple)):
- for elt in attr:
- yield elt
- else:
- yield attr
-
- def last_child(self):
- """an optimized version of list(get_children())[-1]"""
- for field in self._astroid_fields[::-1]:
- attr = getattr(self, field)
- if not attr: # None or empty listy / tuple
- continue
- if isinstance(attr, (list, tuple)):
- return attr[-1]
- else:
- return attr
- return None
-
- def parent_of(self, node):
- """return true if i'm a parent of the given node"""
- parent = node.parent
- while parent is not None:
- if self is parent:
- return True
- parent = parent.parent
- return False
-
- def statement(self):
- """return the first parent node marked as statement node"""
- if self.is_statement:
- return self
- return self.parent.statement()
-
- def frame(self):
- """return the first parent frame node (i.e. Module, FunctionDef or
- ClassDef)
-
- """
- return self.parent.frame()
-
- def scope(self):
- """return the first node defining a new scope (i.e. Module,
- FunctionDef, ClassDef, Lambda but also GenExpr)
-
- """
- return self.parent.scope()
-
- def root(self):
- """return the root node of the tree, (i.e. a Module)"""
- if self.parent:
- return self.parent.root()
- return self
-
- def child_sequence(self, child):
- """search for the right sequence where the child lies in"""
- for field in self._astroid_fields:
- node_or_sequence = getattr(self, field)
- if node_or_sequence is child:
- return [node_or_sequence]
- # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
- if (isinstance(node_or_sequence, (tuple, list))
- and child in node_or_sequence):
- return node_or_sequence
-
- msg = 'Could not find %s in %s\'s children'
- raise exceptions.AstroidError(msg % (repr(child), repr(self)))
-
- def locate_child(self, child):
- """return a 2-uple (child attribute name, sequence or node)"""
- for field in self._astroid_fields:
- node_or_sequence = getattr(self, field)
- # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
- if child is node_or_sequence:
- return field, child
- if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
- return field, node_or_sequence
- msg = 'Could not find %s in %s\'s children'
- raise exceptions.AstroidError(msg % (repr(child), repr(self)))
- # FIXME : should we merge child_sequence and locate_child ? locate_child
- # is only used in are_exclusive, child_sequence one time in pylint.
-
- def next_sibling(self):
- """return the next sibling statement"""
- return self.parent.next_sibling()
-
- def previous_sibling(self):
- """return the previous sibling statement"""
- return self.parent.previous_sibling()
-
- def nearest(self, nodes):
- """return the node which is the nearest before this one in the
- given list of nodes
- """
- myroot = self.root()
- mylineno = self.fromlineno
- nearest = None, 0
- for node in nodes:
- assert node.root() is myroot, \
- 'nodes %s and %s are not from the same module' % (self, node)
- lineno = node.fromlineno
- if node.fromlineno > mylineno:
- break
- if lineno > nearest[1]:
- nearest = node, lineno
- # FIXME: raise an exception if nearest is None ?
- return nearest[0]
-
- # these are lazy because they're relatively expensive to compute for every
- # single node, and they rarely get looked at
-
- @decoratorsmod.cachedproperty
- def fromlineno(self):
- if self.lineno is None:
- return self._fixed_source_line()
- else:
- return self.lineno
-
- @decoratorsmod.cachedproperty
- def tolineno(self):
- if not self._astroid_fields:
- # can't have children
- lastchild = None
- else:
- lastchild = self.last_child()
- if lastchild is None:
- return self.fromlineno
- else:
- return lastchild.tolineno
-
- # TODO / FIXME:
- assert self.fromlineno is not None, self
- assert self.tolineno is not None, self
-
- def _fixed_source_line(self):
- """return the line number where the given node appears
-
- we need this method since not all nodes have the lineno attribute
- correctly set...
- """
- line = self.lineno
- _node = self
- try:
- while line is None:
- _node = next(_node.get_children())
- line = _node.lineno
- except StopIteration:
- _node = self.parent
- while _node and line is None:
- line = _node.lineno
- _node = _node.parent
- return line
-
- def block_range(self, lineno):
- """handle block line numbers range for non block opening statements
- """
- return lineno, self.tolineno
-
- def set_local(self, name, stmt):
- """delegate to a scoped parent handling a locals dictionary"""
- self.parent.set_local(name, stmt)
-
- def nodes_of_class(self, klass, skip_klass=None):
- """return an iterator on nodes which are instance of the given class(es)
-
- klass may be a class object or a tuple of class objects
- """
- if isinstance(self, klass):
- yield self
- for child_node in self.get_children():
- if skip_klass is not None and isinstance(child_node, skip_klass):
- continue
- for matching in child_node.nodes_of_class(klass, skip_klass):
- yield matching
-
- def _infer_name(self, frame, name):
- # overridden for ImportFrom, Import, Global, TryExcept and Arguments
- return None
-
- def _infer(self, context=None):
- """we don't know how to resolve a statement by default"""
- # this method is overridden by most concrete classes
- raise exceptions.InferenceError(self.__class__.__name__)
-
- def inferred(self):
- '''return list of inferred values for a more simple inference usage'''
- return list(self.infer())
-
- def infered(self):
- warnings.warn('%s.infered() is deprecated and slated for removal '
- 'in astroid 2.0, use %s.inferred() instead.'
- % (type(self).__name__, type(self).__name__),
- PendingDeprecationWarning, stacklevel=2)
- return self.inferred()
-
- def instanciate_class(self):
- """instanciate a node if it is a ClassDef node, else return self"""
- return self
-
- def has_base(self, node):
- return False
-
- def callable(self):
- return False
-
- def eq(self, value):
- return False
-
- def as_string(self):
- return as_string.to_code(self)
-
- def repr_tree(self, ids=False, include_linenos=False,
- ast_state=False, indent=' ', max_depth=0, max_width=80):
- """Returns a string representation of the AST from this node.
-
- :param ids: If true, includes the ids with the node type names.
-
- :param include_linenos: If true, includes the line numbers and
- column offsets.
-
- :param ast_state: If true, includes information derived from
- the whole AST like local and global variables.
-
- :param indent: A string to use to indent the output string.
-
- :param max_depth: If set to a positive integer, won't return
- nodes deeper than max_depth in the string.
-
- :param max_width: Only positive integer values are valid, the
- default is 80. Attempts to format the output string to stay
- within max_width characters, but can exceed it under some
- circumstances.
- """
- @_singledispatch
- def _repr_tree(node, result, done, cur_indent='', depth=1):
- """Outputs a representation of a non-tuple/list, non-node that's
- contained within an AST, including strings.
- """
- lines = pprint.pformat(node,
- width=max(max_width - len(cur_indent),
- 1)).splitlines(True)
- result.append(lines[0])
- result.extend([cur_indent + line for line in lines[1:]])
- return len(lines) != 1
-
- # pylint: disable=unused-variable; doesn't understand singledispatch
- @_repr_tree.register(tuple)
- @_repr_tree.register(list)
- def _repr_seq(node, result, done, cur_indent='', depth=1):
- """Outputs a representation of a sequence that's contained within an AST."""
- cur_indent += indent
- result.append('[')
- if len(node) == 0:
- broken = False
- elif len(node) == 1:
- broken = _repr_tree(node[0], result, done, cur_indent, depth)
- elif len(node) == 2:
- broken = _repr_tree(node[0], result, done, cur_indent, depth)
- if not broken:
- result.append(', ')
- else:
- result.append(',\n')
- result.append(cur_indent)
- broken = (_repr_tree(node[1], result, done, cur_indent, depth)
- or broken)
- else:
- result.append('\n')
- result.append(cur_indent)
- for child in node[:-1]:
- _repr_tree(child, result, done, cur_indent, depth)
- result.append(',\n')
- result.append(cur_indent)
- _repr_tree(node[-1], result, done, cur_indent, depth)
- broken = True
- result.append(']')
- return broken
-
- # pylint: disable=unused-variable; doesn't understand singledispatch
- @_repr_tree.register(NodeNG)
- def _repr_node(node, result, done, cur_indent='', depth=1):
- """Outputs a strings representation of an astroid node."""
- if node in done:
- result.append(indent + '<Recursion on %s with id=%s' %
- (type(node).__name__, id(node)))
- return False
- else:
- done.add(node)
- if max_depth and depth > max_depth:
- result.append('...')
- return False
- depth += 1
- cur_indent += indent
- if ids:
- result.append('%s<0x%x>(\n' % (type(node).__name__, id(node)))
- else:
- result.append('%s(' % type(node).__name__)
- fields = []
- if include_linenos:
- fields.extend(('lineno', 'col_offset'))
- fields.extend(node._other_fields)
- fields.extend(node._astroid_fields)
- if ast_state:
- fields.extend(node._other_other_fields)
- if len(fields) == 0:
- broken = False
- elif len(fields) == 1:
- result.append('%s=' % fields[0])
- broken = _repr_tree(getattr(node, fields[0]), result, done,
- cur_indent, depth)
- else:
- result.append('\n')
- result.append(cur_indent)
- for field in fields[:-1]:
- result.append('%s=' % field)
- _repr_tree(getattr(node, field), result, done, cur_indent,
- depth)
- result.append(',\n')
- result.append(cur_indent)
- result.append('%s=' % fields[-1])
- _repr_tree(getattr(node, fields[-1]), result, done, cur_indent,
- depth)
- broken = True
- result.append(')')
- return broken
-
- result = []
- _repr_tree(self, result, set())
- return ''.join(result)
-
- def bool_value(self):
- """Determine the bool value of this node
-
- The boolean value of a node can have three
- possible values:
-
- * False. For instance, empty data structures,
- False, empty strings, instances which return
- explicitly False from the __nonzero__ / __bool__
- method.
- * True. Most of constructs are True by default:
- classes, functions, modules etc
- * YES: the inference engine is uncertain of the
- node's value.
- """
- return util.YES
-
-
-class Statement(NodeNG):
- """Statement node adding a few attributes"""
- is_statement = True
-
- def next_sibling(self):
- """return the next sibling statement"""
- stmts = self.parent.child_sequence(self)
- index = stmts.index(self)
- try:
- return stmts[index +1]
- except IndexError:
- pass
-
- def previous_sibling(self):
- """return the previous sibling statement"""
- stmts = self.parent.child_sequence(self)
- index = stmts.index(self)
- if index >= 1:
- return stmts[index -1]
diff --git a/astroid/node_classes.py b/astroid/node_classes.py
index ebe4fd8..c314a50 100644
--- a/astroid/node_classes.py
+++ b/astroid/node_classes.py
@@ -19,11 +19,17 @@
"""
import abc
+import pprint
import warnings
+try:
+ from functools import singledispatch as _singledispatch
+except ImportError:
+ from singledispatch import singledispatch as _singledispatch
import lazy_object_proxy
import six
+from astroid import as_string
from astroid import bases
from astroid import context as contextmod
from astroid import decorators
@@ -124,10 +130,479 @@ def _container_getitem(instance, elts, index):
return elts[index]
+
+class NodeNG(object):
+ """Base Class for all Astroid node classes.
+
+ It represents a node of the new abstract syntax tree.
+ """
+ is_statement = False
+ optional_assign = False # True for For (and for Comprehension if py <3.0)
+ is_function = False # True for FunctionDef nodes
+ # attributes below are set by the builder module or by raw factories
+ lineno = None
+ col_offset = None
+ # parent node in the tree
+ parent = None
+ # attributes containing child node(s) redefined in most concrete classes:
+ _astroid_fields = ()
+ # attributes containing non-nodes:
+ _other_fields = ()
+ # attributes containing AST-dependent fields:
+ _other_other_fields = ()
+ # instance specific inference function infer(node, context)
+ _explicit_inference = None
+
+ def __init__(self, lineno=None, col_offset=None, parent=None):
+ self.lineno = lineno
+ self.col_offset = col_offset
+ self.parent = parent
+
+ def infer(self, context=None, **kwargs):
+ """main interface to the interface system, return a generator on inferred
+ values.
+
+ If the instance has some explicit inference function set, it will be
+ called instead of the default interface.
+ """
+ if self._explicit_inference is not None:
+ # explicit_inference is not bound, give it self explicitly
+ try:
+ # pylint: disable=not-callable
+ return self._explicit_inference(self, context, **kwargs)
+ except exceptions.UseInferenceDefault:
+ pass
+
+ if not context:
+ return self._infer(context, **kwargs)
+
+ key = (self, context.lookupname,
+ context.callcontext, context.boundnode)
+ if key in context.inferred:
+ return iter(context.inferred[key])
+
+ return context.cache_generator(key, self._infer(context, **kwargs))
+
+ def _repr_name(self):
+ """return self.name or self.attrname or '' for nice representation"""
+ return getattr(self, 'name', getattr(self, 'attrname', ''))
+
+ def __str__(self):
+ rname = self._repr_name()
+ cname = type(self).__name__
+ if rname:
+ string = '%(cname)s.%(rname)s(%(fields)s)'
+ alignment = len(cname) + len(rname) + 2
+ else:
+ string = '%(cname)s(%(fields)s)'
+ alignment = len(cname) + 1
+ result = []
+ for field in self._other_fields + self._astroid_fields:
+ value = getattr(self, field)
+ width = 80 - len(field) - alignment
+ lines = pprint.pformat(value, indent=2,
+ width=width).splitlines(True)
+
+ inner = [lines[0]]
+ for line in lines[1:]:
+ inner.append(' ' * alignment + line)
+ result.append('%s=%s' % (field, ''.join(inner)))
+
+ return string % {'cname': cname,
+ 'rname': rname,
+ 'fields': (',\n' + ' ' * alignment).join(result)}
+
+ def __repr__(self):
+ rname = self._repr_name()
+ if rname:
+ string = '<%(cname)s.%(rname)s l.%(lineno)s at 0x%(id)x>'
+ else:
+ string = '<%(cname)s l.%(lineno)s at 0x%(id)x>'
+ return string % {'cname': type(self).__name__,
+ 'rname': rname,
+ 'lineno': self.fromlineno,
+ 'id': id(self)}
+
+ def accept(self, visitor):
+ func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
+ return func(self)
+
+ def get_children(self):
+ for field in self._astroid_fields:
+ attr = getattr(self, field)
+ if attr is None:
+ continue
+ if isinstance(attr, (list, tuple)):
+ for elt in attr:
+ yield elt
+ else:
+ yield attr
+
+ def last_child(self):
+ """an optimized version of list(get_children())[-1]"""
+ for field in self._astroid_fields[::-1]:
+ attr = getattr(self, field)
+ if not attr: # None or empty listy / tuple
+ continue
+ if isinstance(attr, (list, tuple)):
+ return attr[-1]
+ else:
+ return attr
+ return None
+
+ def parent_of(self, node):
+ """return true if i'm a parent of the given node"""
+ parent = node.parent
+ while parent is not None:
+ if self is parent:
+ return True
+ parent = parent.parent
+ return False
+
+ def statement(self):
+ """return the first parent node marked as statement node"""
+ if self.is_statement:
+ return self
+ return self.parent.statement()
+
+ def frame(self):
+ """return the first parent frame node (i.e. Module, FunctionDef or
+ ClassDef)
+
+ """
+ return self.parent.frame()
+
+ def scope(self):
+ """return the first node defining a new scope (i.e. Module,
+ FunctionDef, ClassDef, Lambda but also GenExpr)
+
+ """
+ return self.parent.scope()
+
+ def root(self):
+ """return the root node of the tree, (i.e. a Module)"""
+ if self.parent:
+ return self.parent.root()
+ return self
+
+ def child_sequence(self, child):
+ """search for the right sequence where the child lies in"""
+ for field in self._astroid_fields:
+ node_or_sequence = getattr(self, field)
+ if node_or_sequence is child:
+ return [node_or_sequence]
+ # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
+ if (isinstance(node_or_sequence, (tuple, list))
+ and child in node_or_sequence):
+ return node_or_sequence
+
+ msg = 'Could not find %s in %s\'s children'
+ raise exceptions.AstroidError(msg % (repr(child), repr(self)))
+
+ def locate_child(self, child):
+ """return a 2-uple (child attribute name, sequence or node)"""
+ for field in self._astroid_fields:
+ node_or_sequence = getattr(self, field)
+ # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
+ if child is node_or_sequence:
+ return field, child
+ if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
+ return field, node_or_sequence
+ msg = 'Could not find %s in %s\'s children'
+ raise exceptions.AstroidError(msg % (repr(child), repr(self)))
+ # FIXME : should we merge child_sequence and locate_child ? locate_child
+ # is only used in are_exclusive, child_sequence one time in pylint.
+
+ def next_sibling(self):
+ """return the next sibling statement"""
+ return self.parent.next_sibling()
+
+ def previous_sibling(self):
+ """return the previous sibling statement"""
+ return self.parent.previous_sibling()
+
+ def nearest(self, nodes):
+ """return the node which is the nearest before this one in the
+ given list of nodes
+ """
+ myroot = self.root()
+ mylineno = self.fromlineno
+ nearest = None, 0
+ for node in nodes:
+ assert node.root() is myroot, \
+ 'nodes %s and %s are not from the same module' % (self, node)
+ lineno = node.fromlineno
+ if node.fromlineno > mylineno:
+ break
+ if lineno > nearest[1]:
+ nearest = node, lineno
+ # FIXME: raise an exception if nearest is None ?
+ return nearest[0]
+
+ # these are lazy because they're relatively expensive to compute for every
+ # single node, and they rarely get looked at
+
+ @decorators.cachedproperty
+ def fromlineno(self):
+ if self.lineno is None:
+ return self._fixed_source_line()
+ else:
+ return self.lineno
+
+ @decorators.cachedproperty
+ def tolineno(self):
+ if not self._astroid_fields:
+ # can't have children
+ lastchild = None
+ else:
+ lastchild = self.last_child()
+ if lastchild is None:
+ return self.fromlineno
+ else:
+ return lastchild.tolineno
+
+ # TODO / FIXME:
+ assert self.fromlineno is not None, self
+ assert self.tolineno is not None, self
+
+ def _fixed_source_line(self):
+ """return the line number where the given node appears
+
+ we need this method since not all nodes have the lineno attribute
+ correctly set...
+ """
+ line = self.lineno
+ _node = self
+ try:
+ while line is None:
+ _node = next(_node.get_children())
+ line = _node.lineno
+ except StopIteration:
+ _node = self.parent
+ while _node and line is None:
+ line = _node.lineno
+ _node = _node.parent
+ return line
+
+ def block_range(self, lineno):
+ """handle block line numbers range for non block opening statements
+ """
+ return lineno, self.tolineno
+
+ def set_local(self, name, stmt):
+ """delegate to a scoped parent handling a locals dictionary"""
+ self.parent.set_local(name, stmt)
+
+ def nodes_of_class(self, klass, skip_klass=None):
+ """return an iterator on nodes which are instance of the given class(es)
+
+ klass may be a class object or a tuple of class objects
+ """
+ if isinstance(self, klass):
+ yield self
+ for child_node in self.get_children():
+ if skip_klass is not None and isinstance(child_node, skip_klass):
+ continue
+ for matching in child_node.nodes_of_class(klass, skip_klass):
+ yield matching
+
+ def _infer_name(self, frame, name):
+ # overridden for ImportFrom, Import, Global, TryExcept and Arguments
+ return None
+
+ def _infer(self, context=None):
+ """we don't know how to resolve a statement by default"""
+ # this method is overridden by most concrete classes
+ raise exceptions.InferenceError(self.__class__.__name__)
+
+ def inferred(self):
+ '''return list of inferred values for a more simple inference usage'''
+ return list(self.infer())
+
+ def infered(self):
+ warnings.warn('%s.infered() is deprecated and slated for removal '
+ 'in astroid 2.0, use %s.inferred() instead.'
+ % (type(self).__name__, type(self).__name__),
+ PendingDeprecationWarning, stacklevel=2)
+ return self.inferred()
+
+ def instanciate_class(self):
+ """instanciate a node if it is a ClassDef node, else return self"""
+ return self
+
+ def has_base(self, node):
+ return False
+
+ def callable(self):
+ return False
+
+ def eq(self, value):
+ return False
+
+ def as_string(self):
+ return as_string.to_code(self)
+
+ def repr_tree(self, ids=False, include_linenos=False,
+ ast_state=False, indent=' ', max_depth=0, max_width=80):
+ """Returns a string representation of the AST from this node.
+
+ :param ids: If true, includes the ids with the node type names.
+
+ :param include_linenos: If true, includes the line numbers and
+ column offsets.
+
+ :param ast_state: If true, includes information derived from
+ the whole AST like local and global variables.
+
+ :param indent: A string to use to indent the output string.
+
+ :param max_depth: If set to a positive integer, won't return
+ nodes deeper than max_depth in the string.
+
+ :param max_width: Only positive integer values are valid, the
+ default is 80. Attempts to format the output string to stay
+ within max_width characters, but can exceed it under some
+ circumstances.
+ """
+ @_singledispatch
+ def _repr_tree(node, result, done, cur_indent='', depth=1):
+ """Outputs a representation of a non-tuple/list, non-node that's
+ contained within an AST, including strings.
+ """
+ lines = pprint.pformat(node,
+ width=max(max_width - len(cur_indent),
+ 1)).splitlines(True)
+ result.append(lines[0])
+ result.extend([cur_indent + line for line in lines[1:]])
+ return len(lines) != 1
+
+ # pylint: disable=unused-variable; doesn't understand singledispatch
+ @_repr_tree.register(tuple)
+ @_repr_tree.register(list)
+ def _repr_seq(node, result, done, cur_indent='', depth=1):
+ """Outputs a representation of a sequence that's contained within an AST."""
+ cur_indent += indent
+ result.append('[')
+ if len(node) == 0:
+ broken = False
+ elif len(node) == 1:
+ broken = _repr_tree(node[0], result, done, cur_indent, depth)
+ elif len(node) == 2:
+ broken = _repr_tree(node[0], result, done, cur_indent, depth)
+ if not broken:
+ result.append(', ')
+ else:
+ result.append(',\n')
+ result.append(cur_indent)
+ broken = (_repr_tree(node[1], result, done, cur_indent, depth)
+ or broken)
+ else:
+ result.append('\n')
+ result.append(cur_indent)
+ for child in node[:-1]:
+ _repr_tree(child, result, done, cur_indent, depth)
+ result.append(',\n')
+ result.append(cur_indent)
+ _repr_tree(node[-1], result, done, cur_indent, depth)
+ broken = True
+ result.append(']')
+ return broken
+
+ # pylint: disable=unused-variable; doesn't understand singledispatch
+ @_repr_tree.register(NodeNG)
+ def _repr_node(node, result, done, cur_indent='', depth=1):
+ """Outputs a strings representation of an astroid node."""
+ if node in done:
+ result.append(indent + '<Recursion on %s with id=%s' %
+ (type(node).__name__, id(node)))
+ return False
+ else:
+ done.add(node)
+ if max_depth and depth > max_depth:
+ result.append('...')
+ return False
+ depth += 1
+ cur_indent += indent
+ if ids:
+ result.append('%s<0x%x>(\n' % (type(node).__name__, id(node)))
+ else:
+ result.append('%s(' % type(node).__name__)
+ fields = []
+ if include_linenos:
+ fields.extend(('lineno', 'col_offset'))
+ fields.extend(node._other_fields)
+ fields.extend(node._astroid_fields)
+ if ast_state:
+ fields.extend(node._other_other_fields)
+ if len(fields) == 0:
+ broken = False
+ elif len(fields) == 1:
+ result.append('%s=' % fields[0])
+ broken = _repr_tree(getattr(node, fields[0]), result, done,
+ cur_indent, depth)
+ else:
+ result.append('\n')
+ result.append(cur_indent)
+ for field in fields[:-1]:
+ result.append('%s=' % field)
+ _repr_tree(getattr(node, field), result, done, cur_indent,
+ depth)
+ result.append(',\n')
+ result.append(cur_indent)
+ result.append('%s=' % fields[-1])
+ _repr_tree(getattr(node, fields[-1]), result, done, cur_indent,
+ depth)
+ broken = True
+ result.append(')')
+ return broken
+
+ result = []
+ _repr_tree(self, result, set())
+ return ''.join(result)
+
+ def bool_value(self):
+ """Determine the bool value of this node
+
+ The boolean value of a node can have three
+ possible values:
+
+ * False. For instance, empty data structures,
+ False, empty strings, instances which return
+ explicitly False from the __nonzero__ / __bool__
+ method.
+ * True. Most of constructs are True by default:
+ classes, functions, modules etc
+ * YES: the inference engine is uncertain of the
+ node's value.
+ """
+ return util.YES
+
+
+class Statement(NodeNG):
+ """Statement node adding a few attributes"""
+ is_statement = True
+
+ def next_sibling(self):
+ """return the next sibling statement"""
+ stmts = self.parent.child_sequence(self)
+ index = stmts.index(self)
+ try:
+ return stmts[index +1]
+ except IndexError:
+ pass
+
+ def previous_sibling(self):
+ """return the previous sibling statement"""
+ stmts = self.parent.child_sequence(self)
+ index = stmts.index(self)
+ if index >= 1:
+ return stmts[index -1]
+
+
+
@six.add_metaclass(abc.ABCMeta)
class _BaseContainer(mixins.ParentAssignTypeMixin,
- bases.NodeNG,
- bases.Instance):
+ NodeNG, bases.Instance):
"""Base class for Set, FrozenSet, Tuple and List."""
_astroid_fields = ('elts',)
@@ -309,7 +784,7 @@ class LookupMixIn(object):
# Name classes
-class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
+class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG):
"""class representing an AssignName node"""
_other_fields = ('name',)
@@ -318,7 +793,7 @@ class AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
super(AssignName, self).__init__(lineno, col_offset, parent)
-class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
+class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG):
"""class representing a DelName node"""
_other_fields = ('name',)
@@ -327,7 +802,7 @@ class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
super(DelName, self).__init__(lineno, col_offset, parent)
-class Name(LookupMixIn, bases.NodeNG):
+class Name(LookupMixIn, NodeNG):
"""class representing a Name node"""
_other_fields = ('name',)
@@ -336,7 +811,7 @@ class Name(LookupMixIn, bases.NodeNG):
super(Name, self).__init__(lineno, col_offset, parent)
-class Arguments(mixins.AssignTypeMixin, bases.NodeNG):
+class Arguments(mixins.AssignTypeMixin, NodeNG):
"""class representing an Arguments node"""
if six.PY3:
# Python 3.4+ uses a different approach regarding annotations,
@@ -479,7 +954,7 @@ def _format_args(args, defaults=None, annotations=None):
return ', '.join(values)
-class AssignAttr(mixins.ParentAssignTypeMixin, bases.NodeNG):
+class AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):
"""class representing an AssignAttr node"""
_astroid_fields = ('expr',)
_other_fields = ('attrname',)
@@ -493,7 +968,7 @@ class AssignAttr(mixins.ParentAssignTypeMixin, bases.NodeNG):
self.expr = expr
-class Assert(bases.Statement):
+class Assert(Statement):
"""class representing an Assert node"""
_astroid_fields = ('test', 'fail',)
test = None
@@ -504,7 +979,7 @@ class Assert(bases.Statement):
self.test = test
-class Assign(mixins.AssignTypeMixin, bases.Statement):
+class Assign(mixins.AssignTypeMixin, Statement):
"""class representing an Assign node"""
_astroid_fields = ('targets', 'value',)
targets = None
@@ -515,7 +990,7 @@ class Assign(mixins.AssignTypeMixin, bases.Statement):
self.value = value
-class AugAssign(mixins.AssignTypeMixin, bases.Statement):
+class AugAssign(mixins.AssignTypeMixin, Statement):
"""class representing an AugAssign node"""
_astroid_fields = ('target', 'value')
_other_fields = ('op',)
@@ -548,7 +1023,7 @@ class AugAssign(mixins.AssignTypeMixin, bases.Statement):
return []
-class Repr(bases.NodeNG):
+class Repr(NodeNG):
"""class representing a Repr node"""
_astroid_fields = ('value',)
value = None
@@ -557,7 +1032,7 @@ class Repr(bases.NodeNG):
self.value = value
-class BinOp(bases.NodeNG):
+class BinOp(NodeNG):
"""class representing a BinOp node"""
_astroid_fields = ('left', 'right')
_other_fields = ('op',)
@@ -590,7 +1065,7 @@ class BinOp(bases.NodeNG):
return []
-class BoolOp(bases.NodeNG):
+class BoolOp(NodeNG):
"""class representing a BoolOp node"""
_astroid_fields = ('values',)
_other_fields = ('op',)
@@ -604,11 +1079,11 @@ class BoolOp(bases.NodeNG):
self.values = values
-class Break(bases.Statement):
+class Break(Statement):
"""class representing a Break node"""
-class Call(bases.NodeNG):
+class Call(NodeNG):
"""class representing a Call node"""
_astroid_fields = ('func', 'args', 'keywords')
func = None
@@ -631,7 +1106,7 @@ class Call(bases.NodeNG):
return [keyword for keyword in keywords if keyword.arg is None]
-class Compare(bases.NodeNG):
+class Compare(NodeNG):
"""class representing a Compare node"""
_astroid_fields = ('left', 'ops',)
left = None
@@ -654,7 +1129,7 @@ class Compare(bases.NodeNG):
#return self.left
-class Comprehension(bases.NodeNG):
+class Comprehension(NodeNG):
"""class representing a Comprehension node"""
_astroid_fields = ('target', 'iter', 'ifs')
target = None
@@ -695,7 +1170,7 @@ class Comprehension(bases.NodeNG):
return stmts, False
-class Const(bases.NodeNG, bases.Instance):
+class Const(NodeNG, bases.Instance):
"""represent a constant node like num, str, bool, None, bytes"""
_other_fields = ('value',)
@@ -728,11 +1203,11 @@ class Const(bases.NodeNG, bases.Instance):
return bool(self.value)
-class Continue(bases.Statement):
+class Continue(Statement):
"""class representing a Continue node"""
-class Decorators(bases.NodeNG):
+class Decorators(NodeNG):
"""class representing a Decorators node"""
_astroid_fields = ('nodes',)
nodes = None
@@ -745,7 +1220,7 @@ class Decorators(bases.NodeNG):
return self.parent.parent.scope()
-class DelAttr(mixins.ParentAssignTypeMixin, bases.NodeNG):
+class DelAttr(mixins.ParentAssignTypeMixin, NodeNG):
"""class representing a DelAttr node"""
_astroid_fields = ('expr',)
_other_fields = ('attrname',)
@@ -759,7 +1234,7 @@ class DelAttr(mixins.ParentAssignTypeMixin, bases.NodeNG):
self.expr = expr
-class Delete(mixins.AssignTypeMixin, bases.Statement):
+class Delete(mixins.AssignTypeMixin, Statement):
"""class representing a Delete node"""
_astroid_fields = ('targets',)
targets = None
@@ -768,7 +1243,7 @@ class Delete(mixins.AssignTypeMixin, bases.Statement):
self.targets = targets
-class Dict(bases.NodeNG, bases.Instance):
+class Dict(NodeNG, bases.Instance):
"""class representing a Dict node"""
_astroid_fields = ('items',)
@@ -830,7 +1305,7 @@ class Dict(bases.NodeNG, bases.Instance):
return bool(self.items)
-class Expr(bases.Statement):
+class Expr(Statement):
"""class representing a Expr node"""
_astroid_fields = ('value',)
value = None
@@ -839,18 +1314,18 @@ class Expr(bases.Statement):
self.value = value
-class Ellipsis(bases.NodeNG): # pylint: disable=redefined-builtin
+class Ellipsis(NodeNG): # pylint: disable=redefined-builtin
"""class representing an Ellipsis node"""
def bool_value(self):
return True
-class EmptyNode(bases.NodeNG):
+class EmptyNode(NodeNG):
"""class representing an EmptyNode node"""
-class ExceptHandler(mixins.AssignTypeMixin, bases.Statement):
+class ExceptHandler(mixins.AssignTypeMixin, Statement):
"""class representing an ExceptHandler node"""
_astroid_fields = ('type', 'name', 'body',)
type = None
@@ -879,7 +1354,7 @@ class ExceptHandler(mixins.AssignTypeMixin, bases.Statement):
return True
-class Exec(bases.Statement):
+class Exec(Statement):
"""class representing an Exec node"""
_astroid_fields = ('expr', 'globals', 'locals',)
expr = None
@@ -892,7 +1367,7 @@ class Exec(bases.Statement):
self.locals = locals
-class ExtSlice(bases.NodeNG):
+class ExtSlice(NodeNG):
"""class representing an ExtSlice node"""
_astroid_fields = ('dims',)
dims = None
@@ -901,7 +1376,7 @@ class ExtSlice(bases.NodeNG):
self.dims = dims
-class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement):
+class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, Statement):
"""class representing a For node"""
_astroid_fields = ('target', 'iter', 'body', 'orelse',)
target = None
@@ -925,7 +1400,7 @@ class AsyncFor(For):
"""Asynchronous For built with `async` keyword."""
-class Await(bases.NodeNG):
+class Await(NodeNG):
"""Await node for the `await` keyword."""
_astroid_fields = ('value', )
@@ -935,7 +1410,7 @@ class Await(bases.NodeNG):
self.value = value
-class ImportFrom(mixins.ImportFromMixin, bases.Statement):
+class ImportFrom(mixins.ImportFromMixin, Statement):
"""class representing a ImportFrom node"""
_other_fields = ('modname', 'names', 'level')
@@ -947,7 +1422,7 @@ class ImportFrom(mixins.ImportFromMixin, bases.Statement):
super(ImportFrom, self).__init__(lineno, col_offset, parent)
-class Attribute(bases.NodeNG):
+class Attribute(NodeNG):
"""class representing a Attribute node"""
_astroid_fields = ('expr',)
_other_fields = ('attrname',)
@@ -961,7 +1436,7 @@ class Attribute(bases.NodeNG):
self.expr = expr
-class Global(bases.Statement):
+class Global(Statement):
"""class representing a Global node"""
_other_fields = ('names',)
@@ -973,7 +1448,7 @@ class Global(bases.Statement):
return name
-class If(mixins.BlockRangeMixIn, bases.Statement):
+class If(mixins.BlockRangeMixIn, Statement):
"""class representing an If node"""
_astroid_fields = ('test', 'body', 'orelse')
test = None
@@ -999,7 +1474,7 @@ class If(mixins.BlockRangeMixIn, bases.Statement):
self.body[0].fromlineno - 1)
-class IfExp(bases.NodeNG):
+class IfExp(NodeNG):
"""class representing an IfExp node"""
_astroid_fields = ('test', 'body', 'orelse')
test = None
@@ -1012,7 +1487,7 @@ class IfExp(bases.NodeNG):
self.orelse = orelse
-class Import(mixins.ImportFromMixin, bases.Statement):
+class Import(mixins.ImportFromMixin, Statement):
"""class representing an Import node"""
_other_fields = ('names',)
@@ -1021,7 +1496,7 @@ class Import(mixins.ImportFromMixin, bases.Statement):
super(Import, self).__init__(lineno, col_offset, parent)
-class Index(bases.NodeNG):
+class Index(NodeNG):
"""class representing an Index node"""
_astroid_fields = ('value',)
value = None
@@ -1030,7 +1505,7 @@ class Index(bases.NodeNG):
self.value = value
-class Keyword(bases.NodeNG):
+class Keyword(NodeNG):
"""class representing a Keyword node"""
_astroid_fields = ('value',)
_other_fields = ('arg',)
@@ -1054,7 +1529,7 @@ class List(_BaseContainer):
return _container_getitem(self, self.elts, index)
-class Nonlocal(bases.Statement):
+class Nonlocal(Statement):
"""class representing a Nonlocal node"""
_other_fields = ('names',)
@@ -1066,11 +1541,11 @@ class Nonlocal(bases.Statement):
return name
-class Pass(bases.Statement):
+class Pass(Statement):
"""class representing a Pass node"""
-class Print(bases.Statement):
+class Print(Statement):
"""class representing a Print node"""
_astroid_fields = ('dest', 'values',)
dest = None
@@ -1085,7 +1560,7 @@ class Print(bases.Statement):
self.values = values
-class Raise(bases.Statement):
+class Raise(Statement):
"""class representing a Raise node"""
exc = None
if six.PY2:
@@ -1114,7 +1589,7 @@ class Raise(bases.Statement):
return True
-class Return(bases.Statement):
+class Return(Statement):
"""class representing a Return node"""
_astroid_fields = ('value',)
value = None
@@ -1130,7 +1605,7 @@ class Set(_BaseContainer):
return '%s.set' % BUILTINS
-class Slice(bases.NodeNG):
+class Slice(NodeNG):
"""class representing a Slice node"""
_astroid_fields = ('lower', 'upper', 'step')
lower = None
@@ -1173,7 +1648,7 @@ class Slice(bases.NodeNG):
return self._proxied.getattr(attrname, context)
-class Starred(mixins.ParentAssignTypeMixin, bases.NodeNG):
+class Starred(mixins.ParentAssignTypeMixin, NodeNG):
"""class representing a Starred node"""
_astroid_fields = ('value',)
value = None
@@ -1182,7 +1657,7 @@ class Starred(mixins.ParentAssignTypeMixin, bases.NodeNG):
self.value = value
-class Subscript(bases.NodeNG):
+class Subscript(NodeNG):
"""class representing a Subscript node"""
_astroid_fields = ('value', 'slice')
value = None
@@ -1193,7 +1668,7 @@ class Subscript(bases.NodeNG):
self.slice = slice
-class TryExcept(mixins.BlockRangeMixIn, bases.Statement):
+class TryExcept(mixins.BlockRangeMixIn, Statement):
"""class representing a TryExcept node"""
_astroid_fields = ('body', 'handlers', 'orelse',)
body = None
@@ -1221,7 +1696,7 @@ class TryExcept(mixins.BlockRangeMixIn, bases.Statement):
return self._elsed_block_range(lineno, self.orelse, last)
-class TryFinally(mixins.BlockRangeMixIn, bases.Statement):
+class TryFinally(mixins.BlockRangeMixIn, Statement):
"""class representing a TryFinally node"""
_astroid_fields = ('body', 'finalbody',)
body = None
@@ -1251,7 +1726,7 @@ class Tuple(_BaseContainer):
return _container_getitem(self, self.elts, index)
-class UnaryOp(bases.NodeNG):
+class UnaryOp(NodeNG):
"""class representing an UnaryOp node"""
_astroid_fields = ('operand',)
_other_fields = ('op',)
@@ -1282,7 +1757,7 @@ class UnaryOp(bases.NodeNG):
return []
-class While(mixins.BlockRangeMixIn, bases.Statement):
+class While(mixins.BlockRangeMixIn, Statement):
"""class representing a While node"""
_astroid_fields = ('test', 'body', 'orelse',)
test = None
@@ -1303,7 +1778,7 @@ class While(mixins.BlockRangeMixIn, bases.Statement):
return self. _elsed_block_range(lineno, self.orelse)
-class With(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement):
+class With(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, Statement):
"""class representing a With node"""
_astroid_fields = ('items', 'body')
items = None
@@ -1330,7 +1805,7 @@ class AsyncWith(With):
"""Asynchronous `with` built with the `async` keyword."""
-class Yield(bases.NodeNG):
+class Yield(NodeNG):
"""class representing a Yield node"""
_astroid_fields = ('value',)
value = None
@@ -1343,7 +1818,7 @@ class YieldFrom(Yield):
""" Class representing a YieldFrom node. """
-class DictUnpack(bases.NodeNG):
+class DictUnpack(NodeNG):
"""Represents the unpacking of dicts into dicts using PEP 448."""
@@ -1376,7 +1851,7 @@ def const_factory(value):
# we should rather recall the builder on this value than returning an empty
# node (another option being that const_factory shouldn't be called with something
# not in CONST_CLS)
- assert not isinstance(value, bases.NodeNG)
+ assert not isinstance(value, NodeNG)
try:
return CONST_CLS[value.__class__](value)
except (KeyError, AttributeError):
diff --git a/astroid/objects.py b/astroid/objects.py
index f80cf54..3ab0a65 100644
--- a/astroid/objects.py
+++ b/astroid/objects.py
@@ -54,7 +54,7 @@ class FrozenSet(node_classes._BaseContainer):
return builtins.getattr('frozenset')[0]
-class Super(bases.NodeNG):
+class Super(node_classes.NodeNG):
"""Proxy class over a super call.
This class offers almost the same behaviour as Python's super,
diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py
index fd43752..b1d5042 100644
--- a/astroid/scoped_nodes.py
+++ b/astroid/scoped_nodes.py
@@ -138,7 +138,8 @@ def builtin_lookup(name):
# TODO move this Mixin to mixins.py; problem: 'FunctionDef' in _scope_lookup
-class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG):
+class LocalsDictNodeNG(node_classes.LookupMixIn,
+ node_classes.NodeNG):
""" this class provides locals handling common to Module, FunctionDef
and ClassDef nodes, including a dict like interface for direct access
to locals information
@@ -577,7 +578,7 @@ class SetComp(ComprehensionScope):
return util.YES
-class _ListComp(bases.NodeNG):
+class _ListComp(node_classes.NodeNG):
"""class representing a ListComp node"""
_astroid_fields = ('elt', 'generators')
elt = None
@@ -690,7 +691,7 @@ class Lambda(mixins.FilterStmtsMixin, LocalsDictNodeNG):
return True
-class FunctionDef(bases.Statement, Lambda):
+class FunctionDef(node_classes.Statement, Lambda):
if six.PY3:
_astroid_fields = ('decorators', 'args', 'body', 'returns')
returns = None
@@ -1056,7 +1057,8 @@ def get_wrapping_class(node):
-class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement):
+class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG,
+ node_classes.Statement):
# some of the attributes below are set by the builder module or
# by a raw factories