summaryrefslogtreecommitdiff
path: root/node_classes.py
diff options
context:
space:
mode:
Diffstat (limited to 'node_classes.py')
-rw-r--r--node_classes.py143
1 files changed, 86 insertions, 57 deletions
diff --git a/node_classes.py b/node_classes.py
index c41cba00..9bc6c568 100644
--- a/node_classes.py
+++ b/node_classes.py
@@ -22,10 +22,10 @@
import sys
-from logilab.astng import NoDefault
-from logilab.astng.bases import NodeNG, BaseClass, Instance, copy_context, \
- _infer_stmts, YES
-from logilab.astng.mixins import StmtMixIn, BlockRangeMixIn, AssignTypeMixin, \
+from logilab.astng.exceptions import NoDefault
+from logilab.astng.bases import (NodeNG, Statement, Instance, InferenceContext,
+ _infer_stmts, YES)
+from logilab.astng.mixins import BlockRangeMixIn, AssignTypeMixin, \
ParentAssignTypeMixin, FromImportMixIn
@@ -98,7 +98,7 @@ def are_exclusive(stmt1, stmt2, exceptions=None):
return False
-class LookupMixIn(BaseClass):
+class LookupMixIn(object):
"""Mixin looking up a name in the right scope
"""
@@ -115,15 +115,14 @@ class LookupMixIn(BaseClass):
"""
return self.scope().scope_lookup(self, name)
- def ilookup(self, name, context=None):
+ def ilookup(self, name):
"""infered lookup
return an iterator on infered values of the statements returned by
the lookup method
"""
frame, stmts = self.lookup(name)
- context = copy_context(context)
- context.lookupname = name
+ context = InferenceContext()
return _infer_stmts(stmts, context, frame)
def _filter_stmts(self, stmts, frame, offset):
@@ -333,19 +332,19 @@ class AssAttr(NodeNG, ParentAssignTypeMixin):
_astng_fields = ('expr',)
expr = None
-class Assert(StmtMixIn, NodeNG):
+class Assert(Statement):
"""class representing an Assert node"""
_astng_fields = ('test', 'fail',)
test = None
fail = None
-class Assign(StmtMixIn, NodeNG, AssignTypeMixin):
+class Assign(Statement, AssignTypeMixin):
"""class representing an Assign node"""
_astng_fields = ('targets', 'value',)
targets = None
value = None
-class AugAssign(StmtMixIn, NodeNG, AssignTypeMixin):
+class AugAssign(Statement, AssignTypeMixin):
"""class representing an AugAssign node"""
_astng_fields = ('target', 'value',)
target = None
@@ -367,7 +366,7 @@ class BoolOp(NodeNG):
_astng_fields = ('values',)
values = None
-class Break(StmtMixIn, NodeNG):
+class Break(Statement):
"""class representing a Break node"""
@@ -428,7 +427,7 @@ class Comprehension(NodeNG):
class Const(NodeNG, Instance):
- """represent a Str or Num node"""
+ """represent a constant node like num, str, bool, None, bytes"""
def __init__(self, value=None):
self.value = value
@@ -446,7 +445,11 @@ class Const(NodeNG, Instance):
return self.value
raise TypeError()
-class Continue(StmtMixIn, NodeNG):
+ def pytype(self):
+ return self._proxied.qname()
+
+
+class Continue(Statement):
"""class representing a Continue node"""
@@ -468,7 +471,7 @@ class DelAttr(NodeNG, ParentAssignTypeMixin):
expr = None
-class Delete(StmtMixIn, NodeNG, AssignTypeMixin):
+class Delete(Statement, AssignTypeMixin):
"""class representing a Delete node"""
_astng_fields = ('targets',)
targets = None
@@ -477,7 +480,13 @@ class Delete(StmtMixIn, NodeNG, AssignTypeMixin):
class Dict(NodeNG, Instance):
"""class representing a Dict node"""
_astng_fields = ('items',)
- items = None
+
+ def __init__(self, items=None):
+ if items is None:
+ self.items = []
+ else:
+ self.items = [(const_factory(k), const_factory(v))
+ for k,v in items.iteritems()]
def pytype(self):
return '__builtin__.dict'
@@ -508,7 +517,7 @@ class Dict(NodeNG, Instance):
raise IndexError(key)
-class Discard(StmtMixIn, NodeNG):
+class Discard(Statement):
"""class representing a Discard node"""
_astng_fields = ('value',)
value = None
@@ -522,7 +531,7 @@ class EmptyNode(NodeNG):
"""class representing an EmptyNode node"""
-class ExceptHandler(StmtMixIn, NodeNG, AssignTypeMixin):
+class ExceptHandler(Statement, AssignTypeMixin):
"""class representing an ExceptHandler node"""
_astng_fields = ('type', 'name', 'body',)
type = None
@@ -550,7 +559,7 @@ class ExceptHandler(StmtMixIn, NodeNG, AssignTypeMixin):
return True
-class Exec(StmtMixIn, NodeNG):
+class Exec(Statement):
"""class representing an Exec node"""
_astng_fields = ('expr', 'globals', 'locals',)
expr = None
@@ -563,8 +572,7 @@ class ExtSlice(NodeNG):
_astng_fields = ('dims',)
dims = None
-
-class For(BlockRangeMixIn, StmtMixIn, AssignTypeMixin, NodeNG):
+class For(BlockRangeMixIn, AssignTypeMixin, Statement):
"""class representing a For node"""
_astng_fields = ('target', 'iter', 'body', 'orelse',)
target = None
@@ -577,7 +585,7 @@ class For(BlockRangeMixIn, StmtMixIn, AssignTypeMixin, NodeNG):
return self.iter.tolineno
-class From(FromImportMixIn, StmtMixIn, NodeNG):
+class From(FromImportMixIn, Statement):
"""class representing a From node"""
def __init__(self, fromname, names, level=0):
@@ -591,7 +599,7 @@ class Getattr(NodeNG):
expr = None
-class Global(StmtMixIn, NodeNG):
+class Global(Statement):
"""class representing a Global node"""
def __init__(self, names):
@@ -601,7 +609,7 @@ class Global(StmtMixIn, NodeNG):
return name
-class If(BlockRangeMixIn, StmtMixIn, NodeNG):
+class If(BlockRangeMixIn, Statement):
"""class representing an If node"""
_astng_fields = ('test', 'body', 'orelse')
test = None
@@ -629,7 +637,7 @@ class IfExp(NodeNG):
orelse = None
-class Import(FromImportMixIn, StmtMixIn, NodeNG):
+class Import(FromImportMixIn, Statement):
"""class representing an Import node"""
@@ -647,8 +655,13 @@ class Keyword(NodeNG):
class List(NodeNG, Instance, ParentAssignTypeMixin):
"""class representing a List node"""
- _astng_fields = ('elts',)
- elts = None
+ _astng_fields = ('elts',)
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
def pytype(self):
return '__builtin__.list'
@@ -660,7 +673,7 @@ class List(NodeNG, Instance, ParentAssignTypeMixin):
return self.elts
-class Nonlocal(StmtMixIn, NodeNG):
+class Nonlocal(Statement):
"""class representing a Nonlocal node"""
def __init__(self, names):
@@ -670,19 +683,18 @@ class Nonlocal(StmtMixIn, NodeNG):
return name
-class Pass(StmtMixIn, NodeNG):
+class Pass(Statement):
"""class representing a Pass node"""
-class Print(StmtMixIn, NodeNG):
+class Print(Statement):
"""class representing a Print node"""
_astng_fields = ('dest', 'values',)
dest = None
values = None
-
-class Raise(StmtMixIn, NodeNG):
+class Raise(Statement):
"""class representing a Raise node"""
exc = None
if sys.version_info < (3, 0):
@@ -691,8 +703,8 @@ class Raise(StmtMixIn, NodeNG):
tback = None
else:
_astng_fields = ('exc', 'cause')
- inst = None
- tback = None
+ exc = None
+ cause = None
def raises_not_implemented(self):
if not self.exc:
@@ -702,7 +714,7 @@ class Raise(StmtMixIn, NodeNG):
return True
-class Return(StmtMixIn, NodeNG):
+class Return(Statement):
"""class representing a Return node"""
_astng_fields = ('value',)
value = None
@@ -711,7 +723,12 @@ class Return(StmtMixIn, NodeNG):
class Set(NodeNG, Instance, ParentAssignTypeMixin):
"""class representing a Set node"""
_astng_fields = ('elts',)
- elts = None
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
def pytype(self):
return '__builtin__.set' # XXX __builtin__ vs builtins
@@ -740,7 +757,7 @@ class Subscript(NodeNG):
slice = None
-class TryExcept(BlockRangeMixIn, StmtMixIn, NodeNG):
+class TryExcept(BlockRangeMixIn, Statement):
"""class representing a TryExcept node"""
_astng_fields = ('body', 'handlers', 'orelse',)
body = None
@@ -766,7 +783,7 @@ class TryExcept(BlockRangeMixIn, StmtMixIn, NodeNG):
return self._elsed_block_range(lineno, self.orelse, last)
-class TryFinally(BlockRangeMixIn, StmtMixIn, NodeNG):
+class TryFinally(BlockRangeMixIn, Statement):
"""class representing a TryFinally node"""
_astng_fields = ('body', 'finalbody',)
body = None
@@ -788,7 +805,12 @@ class TryFinally(BlockRangeMixIn, StmtMixIn, NodeNG):
class Tuple(NodeNG, Instance, ParentAssignTypeMixin):
"""class representing a Tuple node"""
_astng_fields = ('elts',)
- elts = None
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
def pytype(self):
return '__builtin__.tuple'
@@ -806,7 +828,7 @@ class UnaryOp(NodeNG):
operand = None
-class While(BlockRangeMixIn, StmtMixIn, NodeNG):
+class While(BlockRangeMixIn, Statement):
"""class representing a While node"""
_astng_fields = ('test', 'body', 'orelse',)
test = None
@@ -820,7 +842,8 @@ class While(BlockRangeMixIn, StmtMixIn, NodeNG):
"""handle block line numbers range for for and while statements"""
return self. _elsed_block_range(lineno, self.orelse)
-class With(BlockRangeMixIn, StmtMixIn, AssignTypeMixin, NodeNG):
+
+class With(BlockRangeMixIn, AssignTypeMixin, Statement):
"""class representing a With node"""
_astng_fields = ('expr', 'vars', 'body')
expr = None
@@ -845,24 +868,30 @@ CONST_CLS = {
list: List,
tuple: Tuple,
dict: Dict,
+ set: Set,
+ type(None): Const,
}
+def _update_const_classes():
+ """update constant classes, so the keys of CONST_CLS can be reused"""
+ klasses = (bool, int, float, complex, str)
+ if sys.version_info < (3, 0):
+ klasses += (unicode, long)
+ if sys.version_info >= (2, 6):
+ klasses += (bytes,)
+ for kls in klasses:
+ CONST_CLS[kls] = Const
+_update_const_classes()
+
def const_factory(value):
"""return an astng node for a python value"""
try:
- # if value is of class list, tuple, dict use specific class, not Const
- cls = CONST_CLS[value.__class__]
- node = cls()
- if isinstance(node, Dict):
- node.items = ()
- else:
- node.elts = ()
- except KeyError:
- # why was value in (None, False, True) not OK?
- assert isinstance(value, (int, long, complex, float, basestring)) or value in (None, False, True)
- node = Const()
- node.value = value
- return node
-
-
-
+ return CONST_CLS[value.__class__](value)
+ except (KeyError, AttributeError):
+ # some constants (like from gtk._gtk) don't have their class in
+ # CONST_CLS, though we can "assert isinstance(value, tuple(CONST_CLS))"
+ if isinstance(value, tuple(CONST_CLS)):
+ return Const(value)
+ node = EmptyNode()
+ node.object = value
+ return None