Properly handle no __getitem__ on CompiledObject

This commit is contained in:
Dave Halter
2018-12-20 00:34:15 +01:00
parent fcda62862c
commit fcda3f7bc5
3 changed files with 22 additions and 3 deletions

View File

@@ -233,6 +233,9 @@ class DirectObjectAccess(object):
return self._create_access_path(self._obj[index])
def py__iter__list(self):
if not hasattr(self._obj, '__getitem__'):
return None
if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
# Get rid of side effects, we won't call custom `__getitem__`s.
return []

View File

@@ -157,11 +157,15 @@ class CompiledObject(Context):
return ContextSet([create_from_access_path(self.evaluator, access)])
@CheckAttribute()
def py__getitem__(self, index_context_set, contextualized_node):
all_access_paths = self.access_handle.py__getitem__all_values()
if all_access_paths is None:
# This means basically that no __getitem__ has been defined on this
# object.
return super(CompiledObject, self).py__getitem__(index_context_set, contextualized_node)
return ContextSet(
create_from_access_path(self.evaluator, access)
for access in self.access_handle.py__getitem__all_values()
for access in all_access_paths
)
def py__iter__(self, contextualized_node=None):
@@ -173,7 +177,12 @@ class CompiledObject(Context):
for x in super(CompiledObject, self).py__iter__(contextualized_node):
yield x
for access in self.access_handle.py__iter__list():
access_path_list = self.access_handle.py__iter__list()
if access_path_list is None:
# There is no __iter__ method on this object.
return
for access in access_path_list:
yield LazyKnownContext(create_from_access_path(self.evaluator, access))
def py__name__(self):

View File

@@ -92,3 +92,10 @@ def test_dict_values(Script, environment):
# It looks like typeshed for Python 2 returns Any.
pytest.skip()
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').goto_definitions()
def test_getitem_on_none(Script):
script = Script('None[1j]')
assert not script.goto_definitions()
issue, = script._evaluator.analysis
assert issue.name == 'type-error-not-subscriptable'