From 57aefed6ea30f85bb8499f9f5f6f7415c1d55775 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 29 Jul 2023 00:33:09 +0200 Subject: [PATCH] Allow unsafe custom __getitem__ executions when allow unsafe executions is on --- jedi/inference/compiled/access.py | 4 ++-- jedi/inference/compiled/value.py | 5 ++++- test/test_api/test_interpreter.py | 21 +++++++++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/jedi/inference/compiled/access.py b/jedi/inference/compiled/access.py index e9eea5f89..09ed1b64d 100644 --- a/jedi/inference/compiled/access.py +++ b/jedi/inference/compiled/access.py @@ -230,8 +230,8 @@ def py__getitem__all_values(self): return [annotation] return None - def py__simple_getitem__(self, index): - if type(self._obj) not in ALLOWED_GETITEM_TYPES: + def py__simple_getitem__(self, index, *, safe=True): + if safe and type(self._obj) not in ALLOWED_GETITEM_TYPES: # Get rid of side effects, we won't call custom `__getitem__`s. return None diff --git a/jedi/inference/compiled/value.py b/jedi/inference/compiled/value.py index 48a1c01e8..b3a841b1a 100644 --- a/jedi/inference/compiled/value.py +++ b/jedi/inference/compiled/value.py @@ -162,7 +162,10 @@ def _ensure_one_filter(self, is_instance): def py__simple_getitem__(self, index): with reraise_getitem_errors(IndexError, KeyError, TypeError): try: - access = self.access_handle.py__simple_getitem__(index) + access = self.access_handle.py__simple_getitem__( + index, + safe=not self.inference_state.allow_unsafe_executions + ) except AttributeError: return super().py__simple_getitem__(index) if access is None: diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index 82a40b8ef..74f066b86 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -613,12 +613,12 @@ def test_dict_getitem(code, types): #('for x in dunder: x', 'str'), ] ) -def test_dunders(class_is_findable, code, expected): +def test_dunders(class_is_findable, code, expected, allow_unsafe_getattr): from typing import Iterator class DunderCls: def __getitem__(self, key) -> int: - pass + return 1 def __iter__(self, key) -> Iterator[str]: pass @@ -838,3 +838,20 @@ def test_nested__getitem__(): _assert_interpreter_complete('d["foo"]["ba', locals(), ['"bar"']) _assert_interpreter_complete('(d["foo"])["ba', locals(), ['"bar"']) _assert_interpreter_complete('((d["foo"]))["ba', locals(), ['"bar"']) + + +@pytest.mark.parametrize('class_is_findable', [False, True]) +def test_custom__getitem__(class_is_findable, allow_unsafe_getattr): + class CustomGetItem: + def __getitem__(self, x: int): + return "asdf" + + if not class_is_findable: + CustomGetItem.__name__ = "something_somewhere" + + namespace = {'c': CustomGetItem()} + if not class_is_findable and not allow_unsafe_getattr: + expected = [] + else: + expected = ['upper'] + _assert_interpreter_complete('c["a"].up', namespace, expected)