diff options
Diffstat (limited to 'node_classes.py')
-rw-r--r-- | node_classes.py | 143 |
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 |