summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-10-03 17:11:38 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2015-10-03 17:11:38 +0300
commit8d15769dfa80943e140a07704513c4cd26cd3ad0 (patch)
tree5feeab49ab1f2d5179f9ecd1be14e0397bf7cab8
parent8ffc0c7a67532a5e51ad19aa8c93edd9abf4a2dc (diff)
downloadastroid-8d15769dfa80943e140a07704513c4cd26cd3ad0.tar.gz
Don't wrap instance's arguments into a Const, instead let the original index object to be used.
This prevents a crash when the original index object is a slice object, which was wrapped inadvertendly in a Const node, leading to a crash later on if the said object was inferred. Closes issue #200.
-rw-r--r--astroid/inference.py35
-rw-r--r--astroid/tests/unittest_inference.py12
2 files changed, 28 insertions, 19 deletions
diff --git a/astroid/inference.py b/astroid/inference.py
index f7ab2be..16d6913 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -57,6 +57,8 @@ nodes.List._infer = infer_end
nodes.Tuple._infer = infer_end
nodes.Dict._infer = infer_end
nodes.Set._infer = infer_end
+nodes.Slice._infer = infer_end
+
def _higher_function_scope(node):
""" Search for the first function which encloses the given
@@ -119,13 +121,6 @@ nodes.Call._infer = infer_call
@bases.path_wrapper
-def infer_slice(self, context=None):
- yield self
-
-nodes.Slice._infer = infer_slice
-
-
-@bases.path_wrapper
def infer_import(self, context=None, asname=True):
"""infer an Import node: return the imported module/object"""
name = context.lookupname
@@ -245,18 +240,21 @@ def infer_subscript(self, context=None):
yield util.YES
return
- index_value = _SLICE_SENTINEL
- if isinstance(index, nodes.Const):
- index_value = index.value
- elif isinstance(index, nodes.Slice):
- # Infer slices from the original object.
- lower = _slice_value(index.lower, context)
- upper = _slice_value(index.upper, context)
- step = _slice_value(index.step, context)
- if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
- index_value = slice(lower, upper, step)
+ if value.__class__ == bases.Instance:
+ index_value = index
else:
- raise exceptions.InferenceError()
+ index_value = _SLICE_SENTINEL
+ if isinstance(index, nodes.Const):
+ index_value = index.value
+ elif isinstance(index, nodes.Slice):
+ # Infer slices from the original object.
+ lower = _slice_value(index.lower, context)
+ upper = _slice_value(index.upper, context)
+ step = _slice_value(index.step, context)
+ if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
+ index_value = slice(lower, upper, step)
+ else:
+ raise exceptions.InferenceError()
if index_value is _SLICE_SENTINEL:
raise exceptions.InferenceError
@@ -700,7 +698,6 @@ nodes.Index._infer = infer_index
# will be solved.
def instance_getitem(self, index, context=None):
# Rewrap index to Const for this case
- index = nodes.Const(index)
if context:
new_context = context.clone()
else:
diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py
index fbd97e2..ef8888e 100644
--- a/astroid/tests/unittest_inference.py
+++ b/astroid/tests/unittest_inference.py
@@ -2817,6 +2817,18 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
self.assertIsInstance(inferred, nodes.List)
self.assertEqual([elt.value for elt in inferred.elts], expected)
+ def test_instance_slicing_slices(self):
+ ast_node = test_utils.extract_node('''
+ class A(object):
+ def __getitem__(self, index):
+ return index
+ A()[1:] #@
+ ''')
+ inferred = next(ast_node.infer())
+ self.assertIsInstance(inferred, nodes.Slice)
+ self.assertEqual(inferred.lower.value, 1)
+ self.assertIsNone(inferred.upper)
+
def test_instance_slicing_fails(self):
ast_nodes = test_utils.extract_node('''
class A(object):