Make sure that typeddict py__getitem__ works

This commit is contained in:
Dave Halter
2020-02-07 16:45:03 +01:00
parent 7ef07b576f
commit 87161df2f0
4 changed files with 17 additions and 10 deletions

View File

@@ -389,7 +389,13 @@ class TypedDict(LazyValueWrapper):
return ValueName(self, self.tree_node.name)
def py__simple_getitem__(self, index):
return ValueSet({self.inference_state.builtins_module})
if isinstance(index, str):
return ValueSet.from_sets(
name.infer()
for filter in self._definition_class.get_filters(is_instance=True)
for name in filter.get(index)
)
return NO_VALUES
def get_key_values(self):
from jedi.inference.compiled import create_simple_object

View File

@@ -547,10 +547,10 @@ class InstanceClassFilter(AbstractFilter):
self._class_filter = class_filter
def get(self, name):
return self._convert(self._class_filter.get(name, from_instance=True))
return self._convert(self._class_filter.get(name))
def values(self):
return self._convert(self._class_filter.values(from_instance=True))
return self._convert(self._class_filter.values())
def _convert(self, names):
return [
@@ -586,7 +586,7 @@ class SelfAttributeFilter(ClassFilter):
if trailer.type == 'trailer' \
and len(trailer.parent.children) == 2 \
and trailer.children[0] == '.':
if name.is_definition() and self._access_possible(name, from_instance=True):
if name.is_definition() and self._access_possible(name):
# TODO filter non-self assignments instead of this bad
# filter.
if self._is_in_right_scope(trailer.parent.children[0], name):

View File

@@ -104,12 +104,12 @@ class ClassFilter(ParserTreeFilter):
node = get_cached_parent_scope(self._used_names, node)
return False
def _access_possible(self, name, from_instance=False):
def _access_possible(self, name):
# Filter for ClassVar variables
# TODO this is not properly done, yet. It just checks for the string
# ClassVar in the annotation, which can be quite imprecise. If we
# wanted to do this correct, we would have to infer the ClassVar.
if not from_instance:
if not self._is_instance:
expr_stmt = name.get_definition()
if expr_stmt is not None and expr_stmt.type == 'expr_stmt':
annassign = expr_stmt.children[1]
@@ -122,9 +122,9 @@ class ClassFilter(ParserTreeFilter):
return not name.value.startswith('__') or name.value.endswith('__') \
or self._equals_origin_scope()
def _filter(self, names, from_instance=False):
def _filter(self, names):
names = super(ClassFilter, self)._filter(names)
return [name for name in names if self._access_possible(name, from_instance)]
return [name for name in names if self._access_possible(name)]
class ClassMixin(object):
@@ -270,6 +270,7 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
self.inference_state.builtins_module.py__getattribute__('object')
)]
@inference_state_method_cache(default=False)
def is_typeddict(self):
# TODO Do a proper mro resolution. Currently we are just listing
# classes. However, it's a complicated algorithm.

View File

@@ -508,7 +508,7 @@ dynamic_annotation('')
class Foo(typing.TypedDict):
foo: str
bar: List[int]
bar: typing.List[float]
foo
#! ['foo: str']
foo
@@ -519,7 +519,7 @@ class Foo(typing.TypedDict):
d: Foo
#? str()
d['foo']
#? str()
#? float()
d['bar'][0]
#?
d['baz']