diff options
author | Emile Anclin <emile.anclin@logilab.fr> | 2010-03-15 14:55:42 +0100 |
---|---|---|
committer | Emile Anclin <emile.anclin@logilab.fr> | 2010-03-15 14:55:42 +0100 |
commit | 7f263c79e19db7cfc39455e9016c33aa30b02db5 (patch) | |
tree | ef33d78cb78ee7298dc33c5b5b2992446c2c7fcd | |
parent | 6a35b89b319a2fe27b3ca8532c72142c0b25ae27 (diff) | |
download | astroid-git-7f263c79e19db7cfc39455e9016c33aa30b02db5.tar.gz |
add FilterStmtsMixin and AssignTypeMixins; use polymorphism
- we put "ass_type" into this mixin and add "_get_filtered_stmts";
- this breaks circular import when trying to remove LookupMixin from scoped_nodes
* * *
step by step use _get_filtered_stmts
--HG--
branch : rebuild
-rw-r--r-- | node_classes.py | 79 | ||||
-rw-r--r-- | protocols.py | 32 | ||||
-rw-r--r-- | scoped_nodes.py | 27 |
3 files changed, 76 insertions, 62 deletions
diff --git a/node_classes.py b/node_classes.py index 5250f975..98b4ea76 100644 --- a/node_classes.py +++ b/node_classes.py @@ -75,9 +75,45 @@ def are_exclusive(stmt1, stmt2, exceptions=None): node = node.parent return False +class FilterStmtsMixin(object): + """Mixin for statement filtering and assignment type""" + def _get_filtered_stmts(self, _, node, _stmts, mystmt): + """method used in _filter_stmts to get statemtents and trigger break""" + if self.statement() is mystmt: + # original node's statement is the assignment, only keep + # current node (gen exp, list comp) + return [node], True + return _stmts, False -class Arguments(NodeNG): + def ass_type(self): + return self + + +class AssignTypeMixin(object): + + def ass_type(self): + return self + + def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt): + """method used in filter_stmts""" + if self is mystmt: + return _stmts, True + if self.statement() is mystmt: + # original node's statement is the assignment, only keep + # current node (gen exp, list comp) + return [node], True + return _stmts, False + + +class ParentAssignTypeMixin(AssignTypeMixin): + + def ass_type(self): + return self.parent.ass_type() + + + +class Arguments(NodeNG, AssignTypeMixin): """class representing an Arguments node""" def __init__(self, vararg=None, kwarg=None): self.vararg = vararg @@ -152,7 +188,7 @@ def _format_args(args, defaults=None): return ', '.join(values) -class AssAttr(NodeNG): +class AssAttr(NodeNG, ParentAssignTypeMixin): """class representing an AssAttr node""" @@ -160,11 +196,11 @@ class Assert(StmtMixIn, NodeNG): """class representing an Assert node""" -class Assign(StmtMixIn, NodeNG): +class Assign(StmtMixIn, NodeNG, AssignTypeMixin): """class representing an Assign node""" -class AugAssign(StmtMixIn, NodeNG): +class AugAssign(StmtMixIn, NodeNG, AssignTypeMixin): """class representing an AugAssign node""" @@ -209,6 +245,24 @@ class Compare(NodeNG): class Comprehension(NodeNG): """class representing a Comprehension node""" + def ass_type(self): + return self + + def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt): + """method used in filter_stmts""" + if self is mystmt: + from logilab.astng.nodes import Name # XXX remove me + if isinstance(lookup_node, (Const, Name)): + return [lookup_node], True + + elif self.statement() is mystmt: + # original node's statement is the assignment, only keeps + # current node (gen exp, list comp) + + return [node], True + + return stmts, False + class Const(NodeNG, Instance): """represent a Str or Num node""" @@ -241,11 +295,11 @@ class Decorators(NodeNG): # skip the function node to go directly to the upper level scope return self.parent.parent.scope() -class DelAttr(NodeNG): +class DelAttr(NodeNG, ParentAssignTypeMixin): """class representing a DelAttr node""" -class Delete(StmtMixIn, NodeNG): +class Delete(StmtMixIn, NodeNG, AssignTypeMixin): """class representing a Delete node""" @@ -293,7 +347,7 @@ class EmptyNode(NodeNG): """class representing an EmptyNode node""" -class ExceptHandler(StmtMixIn, NodeNG): +class ExceptHandler(StmtMixIn, NodeNG, AssignTypeMixin): """class representing an ExceptHandler node""" def __init__(self): @@ -340,14 +394,14 @@ class ExtSlice(NodeNG): """class representing an ExtSlice node""" -class For(BlockRangeMixIn, StmtMixIn, NodeNG): +class For(BlockRangeMixIn, StmtMixIn, AssignTypeMixin, NodeNG): """class representing a For node""" def _blockstart_toline(self): return self.iter.tolineno -class FromImportMixIn(BaseClass): +class FromImportMixIn(BaseClass, FilterStmtsMixin): """MixIn for From and Import Nodes""" def _infer_name(self, frame, name): @@ -437,7 +491,7 @@ class Keyword(NodeNG): """class representing a Keyword node""" -class List(NodeNG, Instance): +class List(NodeNG, Instance, ParentAssignTypeMixin): """class representing a List node""" def pytype(self): @@ -450,6 +504,7 @@ class List(NodeNG, Instance): return self.elts + class ListComp(NodeNG): """class representing a ListComp node""" @@ -515,7 +570,7 @@ class TryFinally(BlockRangeMixIn, StmtMixIn, NodeNG): return self._elsed_block_range(lineno, self.finalbody) -class Tuple(NodeNG, Instance): +class Tuple(NodeNG, Instance, ParentAssignTypeMixin): """class representing a Tuple node""" def pytype(self): @@ -542,7 +597,7 @@ 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, NodeNG): +class With(BlockRangeMixIn, StmtMixIn, AssignTypeMixin, NodeNG): """class representing a With node""" def _blockstart_toline(self): diff --git a/protocols.py b/protocols.py index 9b5c744b..40de339c 100644 --- a/protocols.py +++ b/protocols.py @@ -303,35 +303,3 @@ def with_assigned_stmts(self, node, context=None, asspath=None): nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts) -def parent_ass_type(self, context=None): - return self.parent.ass_type() - -nodes.Tuple.ass_type = parent_ass_type -nodes.List.ass_type = parent_ass_type -nodes.AssName.ass_type = parent_ass_type -nodes.AssAttr.ass_type = parent_ass_type -nodes.DelName.ass_type = parent_ass_type -nodes.DelAttr.ass_type = parent_ass_type - -def end_ass_type(self): - return self - -# XXX if you add ass_type to a class, you should probably modify -# lookup.LookupMixIn.filter_stmts around line :: -# -# if ass_type is mystmt and not isinstance(ass_type, (nodes.Class, ...)): -nodes.Arguments.ass_type = end_ass_type -nodes.Assign.ass_type = end_ass_type -nodes.AugAssign.ass_type = end_ass_type -nodes.Class.ass_type = end_ass_type -nodes.Comprehension.ass_type = end_ass_type -nodes.Delete.ass_type = end_ass_type -nodes.ExceptHandler.ass_type = end_ass_type -nodes.For.ass_type = end_ass_type -nodes.From.ass_type = end_ass_type -nodes.Function.ass_type = end_ass_type -nodes.Import.ass_type = end_ass_type -nodes.With.ass_type = end_ass_type - - - diff --git a/scoped_nodes.py b/scoped_nodes.py index a40de8cb..c6851bad 100644 --- a/scoped_nodes.py +++ b/scoped_nodes.py @@ -38,7 +38,8 @@ from logilab.astng import MANAGER, NotFoundError, NoDefault, \ ASTNGBuildingException, InferenceError from logilab.astng.node_classes import (Const, Comprehension, Dict, From, For, Import, List, Pass, Raise, Return, Tuple, Yield, DelAttr, - are_exclusive, const_factory as cf, unpack_infer) + are_exclusive, const_factory as cf, unpack_infer, FilterStmtsMixin, + ParentAssignTypeMixin) from logilab.astng.bases import (NodeNG, StmtMixIn, BaseClass, YES, InferenceContext, Instance, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context) @@ -152,20 +153,10 @@ class LookupMixIn(BaseClass): if node.has_base(self): break - if ass_type is mystmt and not isinstance(ass_type, (Class, - Function, Import, From, Lambda)): - if not isinstance(ass_type, Comprehension): - break - if isinstance(self, (Const, Name)): - _stmts = [self] - break - elif ass_type.statement() is mystmt: - # original node's statement is the assignment, only keeps - # current node (gen exp, list comp) - _stmts = [node] + _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, mystmt) + if done: break - optional_assign = isinstance(ass_type, (For, Comprehension)) if optional_assign and ass_type.parent_of(self): # we are inside a loop, loop var assigment is hidding previous @@ -361,11 +352,11 @@ class LocalsDictNodeNG(LookupMixIn, NodeNG): # Name classses -class AssName(LookupMixIn, NodeNG): +class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG): """class representing an AssName node""" -class DelName(LookupMixIn, NodeNG): +class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG): """class representing a DelName node""" @@ -572,7 +563,8 @@ GenExpr.scope_lookup = LocalsDictNodeNG._scope_lookup # Function ################################################################### -class Lambda(LocalsDictNodeNG): + +class Lambda(LocalsDictNodeNG, FilterStmtsMixin): # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' type = 'function' @@ -620,7 +612,6 @@ class Lambda(LocalsDictNodeNG): frame = self return frame._scope_lookup(node, name, offset) - class Function(StmtMixIn, Lambda): def __init__(self): @@ -782,7 +773,7 @@ def _iface_hdlr(iface_node): return True -class Class(StmtMixIn, LocalsDictNodeNG): +class Class(StmtMixIn, LocalsDictNodeNG, FilterStmtsMixin): # some of the attributes below are set by the builder module or # by a raw factories |