summaryrefslogtreecommitdiff
path: root/node_classes.py
diff options
context:
space:
mode:
authorEmile Anclin <emile.anclin@logilab.fr>2009-11-25 18:45:19 +0100
committerEmile Anclin <emile.anclin@logilab.fr>2009-11-25 18:45:19 +0100
commit61df5384faee1c38e4881a81a00183be6861ed6f (patch)
tree622dec29438dc1f942298ac694384fca0deb674e /node_classes.py
parent6b59dfa123bb3cfb7474ba321f3ea813bf07e3c8 (diff)
downloadastroid-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.py108
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
+
+
+