mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
Make it possible to use __getitem__ in interpreter
This commit is contained in:
@@ -121,7 +121,13 @@ class AbstractInstanceValue(Value):
|
||||
return [s.bind(self) for s in call_funcs.get_signatures()]
|
||||
|
||||
def get_function_slot_names(self, name):
|
||||
# Searches for Python functions in classes.
|
||||
# Python classes don't look at the dictionary of the instance when
|
||||
# looking up `__call__`. This is something that has to do with Python's
|
||||
# internal slot system (note: not __slots__, but C slots).
|
||||
for filter in self.get_filters(include_self_names=False):
|
||||
names = filter.get(name)
|
||||
if names:
|
||||
return names
|
||||
return []
|
||||
|
||||
def execute_function_slots(self, names, *inferred_args):
|
||||
@@ -133,6 +139,17 @@ class AbstractInstanceValue(Value):
|
||||
def get_type_hint(self, add_class_info=True):
|
||||
return self.py__name__()
|
||||
|
||||
def py__getitem__(self, index_value_set, contextualized_node):
|
||||
names = self.get_function_slot_names('__getitem__')
|
||||
if not names:
|
||||
return super().py__getitem__(
|
||||
index_value_set,
|
||||
contextualized_node,
|
||||
)
|
||||
|
||||
args = ValuesArguments([index_value_set])
|
||||
return ValueSet.from_sets(name.infer().execute(args) for name in names)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s of %s>" % (self.__class__.__name__, self.class_value)
|
||||
|
||||
@@ -237,17 +254,6 @@ class _BaseTreeInstance(AbstractInstanceValue):
|
||||
or self.get_function_slot_names('__getattribute__'))
|
||||
return self.execute_function_slots(names, name)
|
||||
|
||||
def py__getitem__(self, index_value_set, contextualized_node):
|
||||
names = self.get_function_slot_names('__getitem__')
|
||||
if not names:
|
||||
return super().py__getitem__(
|
||||
index_value_set,
|
||||
contextualized_node,
|
||||
)
|
||||
|
||||
args = ValuesArguments([index_value_set])
|
||||
return ValueSet.from_sets(name.infer().execute(args) for name in names)
|
||||
|
||||
def py__iter__(self, contextualized_node=None):
|
||||
iter_slot_names = self.get_function_slot_names('__iter__')
|
||||
if not iter_slot_names:
|
||||
@@ -295,16 +301,6 @@ class _BaseTreeInstance(AbstractInstanceValue):
|
||||
else:
|
||||
return ValueSet([self])
|
||||
|
||||
def get_function_slot_names(self, name):
|
||||
# Python classes don't look at the dictionary of the instance when
|
||||
# looking up `__call__`. This is something that has to do with Python's
|
||||
# internal slot system (note: not __slots__, but C slots).
|
||||
for filter in self.get_filters(include_self_names=False):
|
||||
names = filter.get(name)
|
||||
if names:
|
||||
return names
|
||||
return []
|
||||
|
||||
|
||||
class TreeInstance(_BaseTreeInstance):
|
||||
def __init__(self, inference_state, parent_context, class_value, arguments):
|
||||
|
||||
@@ -599,6 +599,19 @@ def test_dict_getitem(code, types):
|
||||
assert [c.name for c in comps] == types
|
||||
|
||||
|
||||
@pytest.mark.parametrize('class_is_findable', [False, True])
|
||||
def test__getitem__(class_is_findable):
|
||||
class GetitemCls:
|
||||
def __getitem__(self, key) -> int:
|
||||
pass
|
||||
|
||||
if not class_is_findable:
|
||||
GetitemCls.__name__ = 'asdf'
|
||||
|
||||
n, = jedi.Interpreter('GetitemCls()[0]', [locals()]).infer()
|
||||
assert n.name == 'int'
|
||||
|
||||
|
||||
def foo():
|
||||
raise KeyError
|
||||
|
||||
|
||||
Reference in New Issue
Block a user