diff options
author | Emile Anclin <emile.anclin@logilab.fr> | 2009-11-25 18:45:19 +0100 |
---|---|---|
committer | Emile Anclin <emile.anclin@logilab.fr> | 2009-11-25 18:45:19 +0100 |
commit | 61df5384faee1c38e4881a81a00183be6861ed6f (patch) | |
tree | 622dec29438dc1f942298ac694384fca0deb674e /node_classes.py | |
parent | 6b59dfa123bb3cfb7474ba321f3ea813bf07e3c8 (diff) | |
download | astroid-git-61df5384faee1c38e4881a81a00183be6861ed6f.tar.gz |
moving stuff around to avoid circular imports
--HG--
branch : rebuild
Diffstat (limited to 'node_classes.py')
-rw-r--r-- | node_classes.py | 108 |
1 files changed, 94 insertions, 14 deletions
diff --git a/node_classes.py b/node_classes.py index 8598311c..d7deb76b 100644 --- a/node_classes.py +++ b/node_classes.py @@ -1,14 +1,79 @@ # from logilab.astng import (ASTNGBuildingException, InferenceError, NotFoundError, NoDefault) -from logilab.astng._nodes import NodeNG, StmtMixIn, BlockRangeMixIn -from logilab.astng.lookup import LookupMixIn +from logilab.astng._nodes import NodeNG, StmtMixIn, BlockRangeMixIn, BaseClass, _const_factory from logilab.astng.infutils import Instance """ Module for all nodes (except scoped nodes). """ +def unpack_infer(stmt, context=None): + """return an iterator on nodes inferred by the given statement if the inferred + value is a list or a tuple, recurse on it to get values inferred by its + content + """ + if isinstance(stmt, (List, Tuple)): + # XXX loosing context + return chain(*imap(unpack_infer, stmt.elts)) + infered = stmt.infer(context).next() + if infered is stmt: + return iter( (stmt,) ) + return chain(*imap(unpack_infer, stmt.infer(context))) + + + +def are_exclusive(stmt1, stmt2, exceptions=None): + """return true if the two given statements are mutually exclusive + + `exceptions` may be a list of exception names. If specified, discard If + branches and check one of the statement is in an exception handler catching + one of the given exceptions. + + algorithm : + 1) index stmt1's parents + 2) climb among stmt2's parents until we find a common parent + 3) if the common parent is a If or TryExcept statement, look if nodes are + in exclusive branches + """ + # index stmt1's parents + stmt1_parents = {} + children = {} + node = stmt1.parent + previous = stmt1 + while node: + stmt1_parents[node] = 1 + children[node] = previous + previous = node + node = node.parent + # climb among stmt2's parents until we find a common parent + node = stmt2.parent + previous = stmt2 + while node: + if stmt1_parents.has_key(node): + # if the common parent is a If or TryExcept statement, look if + # nodes are in exclusive branches + if isinstance(node, If) and exceptions is None: + if (node.locate_child(previous)[1] + is not node.locate_child(children[node])[1]): + return True + elif isinstance(node, TryExcept): + c2attr, c2node = node.locate_child(previous) + c1attr, c1node = node.locate_child(children[node]) + if c1node is not c2node: + if ((c2attr == 'body' and c1attr == 'handlers' and children[node].catch(exceptions)) or + (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or + (c2attr == 'handlers' and c1attr == 'orelse') or + (c2attr == 'orelse' and c1attr == 'handlers')): + return True + elif c2attr == 'handlers' and c1attr == 'handlers': + return previous is not children[node] + return False + previous = node + node = node.parent + return False + + class Arguments(NodeNG): """class representing an Arguments node""" @@ -86,10 +151,6 @@ class AssAttr(NodeNG): """class representing an AssAttr node""" -class AssName(LookupMixIn, NodeNG): - """class representing an AssName node""" - - class Assert(StmtMixIn, NodeNG): """class representing an Assert node""" @@ -166,10 +227,6 @@ class DelAttr(NodeNG): """class representing a DelAttr node""" -class DelName(LookupMixIn, NodeNG): - """class representing a DelName node""" - - class Delete(StmtMixIn, NodeNG): """class representing a Delete node""" @@ -351,10 +408,6 @@ class ListComp(NodeNG): """class representing a ListComp node""" -class Name(LookupMixIn, NodeNG): - """class representing a Name node""" - - class Pass(StmtMixIn, NodeNG): """class representing a Pass node""" @@ -456,3 +509,30 @@ class With(BlockRangeMixIn, StmtMixIn, NodeNG): class Yield(NodeNG): """class representing a Yield node""" +# constants ############################################################## + +CONST_CLS = { + list: List, + tuple: Tuple, + dict: Dict, + } + +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: + try: + node = Const(value) + except KeyError: + node = _const_factory(value) + return node + + + |