summaryrefslogtreecommitdiff
path: root/protocols.py
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2014-08-13 18:07:11 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2014-08-13 18:07:11 +0300
commitd8b19eae5e855b5453f399858aadeb7cf218ee70 (patch)
tree8361c6365dce7f5ccbbc50afff201b400c0af115 /protocols.py
parent52ae161026cdc83721d5c4af7d34a9f9131966f7 (diff)
downloadastroid-git-d8b19eae5e855b5453f399858aadeb7cf218ee70.tar.gz
The inference engine handles binary operations (add, mul etc.) between instances.
Diffstat (limited to 'protocols.py')
-rw-r--r--protocols.py41
1 files changed, 40 insertions, 1 deletions
diff --git a/protocols.py b/protocols.py
index d621ffb6..e7703a06 100644
--- a/protocols.py
+++ b/protocols.py
@@ -21,13 +21,33 @@ where it makes sense.
__doctype__ = "restructuredtext en"
-from astroid.exceptions import InferenceError, NoDefault
+from astroid.exceptions import InferenceError, NoDefault, NotFoundError
from astroid.node_classes import unpack_infer
from astroid.bases import copy_context, \
raise_if_nothing_infered, yes_if_nothing_infered, Instance, YES
from astroid.nodes import const_factory
from astroid import nodes
+BIN_OP_METHOD = {'+': '__add__',
+ '-': '__sub__',
+ '/': '__div__',
+ '//': '__floordiv__',
+ '*': '__mul__',
+ '**': '__power__',
+ '%': '__mod__',
+ '&': '__and__',
+ '|': '__or__',
+ '^': '__xor__',
+ '<<': '__lshift__',
+ '>>': '__rshift__',
+ }
+
+UNARY_OP_METHOD = {'+': '__pos__',
+ '-': '__neg__',
+ '~': '__invert__',
+ 'not': None, # XXX not '__nonzero__'
+ }
+
# unary operations ############################################################
def tl_infer_unary_op(self, operator):
@@ -133,6 +153,25 @@ def dict_infer_binary_op(self, operator, other, context):
# XXX else log TypeError
nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op)
+def instance_infer_binary_op(self, operator, other, context):
+ try:
+ methods = self.getattr(BIN_OP_METHOD[operator])
+ except (NotFoundError, KeyError):
+ # Unknown operator
+ yield YES
+ else:
+ for method in methods:
+ if not isinstance(method, nodes.Function):
+ continue
+ for result in method.infer_call_result(self, context):
+ if result is not YES:
+ yield result
+ # We are interested only in the first infered method,
+ # don't go looking in the rest of the methods of the ancestors.
+ break
+
+Instance.infer_binary_op = yes_if_nothing_infered(instance_infer_binary_op)
+
# assignment ##################################################################