diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-03 17:11:38 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-03 17:11:38 +0300 |
commit | 8d15769dfa80943e140a07704513c4cd26cd3ad0 (patch) | |
tree | 5feeab49ab1f2d5179f9ecd1be14e0397bf7cab8 | |
parent | 8ffc0c7a67532a5e51ad19aa8c93edd9abf4a2dc (diff) | |
download | astroid-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.py | 35 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 12 |
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): |