summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--astroid/inference.py7
-rw-r--r--tests/unittest_inference.py21
3 files changed, 32 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 117f7a08..cf25e0d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,13 @@ Release Date: TBA
Close PyCQA/pylint#3209
+* Reverse the order of decorators for `infer_subscript`
+
+ `path_wrapper` needs to come first, followed by `raise_if_nothing_inferred`,
+ otherwise we won't handle `StopIteration` correctly.
+
+ Close #762
+
* Numpy `datetime64.astype` return value is inferred as a `ndarray`.
Close PyCQA/pylint#3332
diff --git a/astroid/inference.py b/astroid/inference.py
index 7bbf9241..975b7d97 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -350,7 +350,6 @@ nodes.Global._infer = infer_global
_SUBSCRIPT_SENTINEL = object()
-@decorators.raise_if_nothing_inferred
def infer_subscript(self, context=None):
"""Inference for subscripts
@@ -407,8 +406,10 @@ def infer_subscript(self, context=None):
return None
-nodes.Subscript._infer = decorators.path_wrapper(infer_subscript)
-nodes.Subscript.infer_lhs = infer_subscript
+nodes.Subscript._infer = decorators.raise_if_nothing_inferred(
+ decorators.path_wrapper(infer_subscript)
+)
+nodes.Subscript.infer_lhs = decorators.raise_if_nothing_inferred(infer_subscript)
@decorators.raise_if_nothing_inferred
diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py
index 91a14ec6..ec396f8a 100644
--- a/tests/unittest_inference.py
+++ b/tests/unittest_inference.py
@@ -5646,5 +5646,26 @@ def test_custom_decorators_for_classmethod_and_staticmethods(code, obj, obj_type
assert inferred.type == obj_type
+@pytest.mark.skipif(sys.version_info < (3, 8), reason="Needs dataclasses available")
+def test_dataclasses_subscript_inference_recursion_error():
+ code = """
+ from dataclasses import dataclass, replace
+
+ @dataclass
+ class ProxyConfig:
+ auth: str = "/auth"
+
+
+ a = ProxyConfig("")
+ test_dict = {"proxy" : {"auth" : "", "bla" : "f"}}
+
+ foo = test_dict['proxy']
+ replace(a, **test_dict['proxy']) # This fails
+ """
+ node = extract_node(code)
+ # Reproduces only with safe_infer()
+ assert helpers.safe_infer(node) is None
+
+
if __name__ == "__main__":
unittest.main()