diff --git a/jedi/inference/gradual/typing.py b/jedi/inference/gradual/typing.py index 64e1e43c..2d7d18ef 100644 --- a/jedi/inference/gradual/typing.py +++ b/jedi/inference/gradual/typing.py @@ -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 diff --git a/jedi/inference/value/instance.py b/jedi/inference/value/instance.py index 2eca9f9d..b884b14d 100644 --- a/jedi/inference/value/instance.py +++ b/jedi/inference/value/instance.py @@ -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): diff --git a/jedi/inference/value/klass.py b/jedi/inference/value/klass.py index 764644d6..41c669d7 100644 --- a/jedi/inference/value/klass.py +++ b/jedi/inference/value/klass.py @@ -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. diff --git a/test/completion/pep0484_typing.py b/test/completion/pep0484_typing.py index 8dc03d96..eef0bf13 100644 --- a/test/completion/pep0484_typing.py +++ b/test/completion/pep0484_typing.py @@ -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']