mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Make sure that typeddict py__getitem__ works
This commit is contained in:
@@ -389,7 +389,13 @@ class TypedDict(LazyValueWrapper):
|
|||||||
return ValueName(self, self.tree_node.name)
|
return ValueName(self, self.tree_node.name)
|
||||||
|
|
||||||
def py__simple_getitem__(self, index):
|
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):
|
def get_key_values(self):
|
||||||
from jedi.inference.compiled import create_simple_object
|
from jedi.inference.compiled import create_simple_object
|
||||||
|
|||||||
@@ -547,10 +547,10 @@ class InstanceClassFilter(AbstractFilter):
|
|||||||
self._class_filter = class_filter
|
self._class_filter = class_filter
|
||||||
|
|
||||||
def get(self, name):
|
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):
|
def values(self):
|
||||||
return self._convert(self._class_filter.values(from_instance=True))
|
return self._convert(self._class_filter.values())
|
||||||
|
|
||||||
def _convert(self, names):
|
def _convert(self, names):
|
||||||
return [
|
return [
|
||||||
@@ -586,7 +586,7 @@ class SelfAttributeFilter(ClassFilter):
|
|||||||
if trailer.type == 'trailer' \
|
if trailer.type == 'trailer' \
|
||||||
and len(trailer.parent.children) == 2 \
|
and len(trailer.parent.children) == 2 \
|
||||||
and trailer.children[0] == '.':
|
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
|
# TODO filter non-self assignments instead of this bad
|
||||||
# filter.
|
# filter.
|
||||||
if self._is_in_right_scope(trailer.parent.children[0], name):
|
if self._is_in_right_scope(trailer.parent.children[0], name):
|
||||||
|
|||||||
@@ -104,12 +104,12 @@ class ClassFilter(ParserTreeFilter):
|
|||||||
node = get_cached_parent_scope(self._used_names, node)
|
node = get_cached_parent_scope(self._used_names, node)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _access_possible(self, name, from_instance=False):
|
def _access_possible(self, name):
|
||||||
# Filter for ClassVar variables
|
# Filter for ClassVar variables
|
||||||
# TODO this is not properly done, yet. It just checks for the string
|
# TODO this is not properly done, yet. It just checks for the string
|
||||||
# ClassVar in the annotation, which can be quite imprecise. If we
|
# ClassVar in the annotation, which can be quite imprecise. If we
|
||||||
# wanted to do this correct, we would have to infer the ClassVar.
|
# 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()
|
expr_stmt = name.get_definition()
|
||||||
if expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
if expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
||||||
annassign = expr_stmt.children[1]
|
annassign = expr_stmt.children[1]
|
||||||
@@ -122,9 +122,9 @@ class ClassFilter(ParserTreeFilter):
|
|||||||
return not name.value.startswith('__') or name.value.endswith('__') \
|
return not name.value.startswith('__') or name.value.endswith('__') \
|
||||||
or self._equals_origin_scope()
|
or self._equals_origin_scope()
|
||||||
|
|
||||||
def _filter(self, names, from_instance=False):
|
def _filter(self, names):
|
||||||
names = super(ClassFilter, self)._filter(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):
|
class ClassMixin(object):
|
||||||
@@ -270,6 +270,7 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
|||||||
self.inference_state.builtins_module.py__getattribute__('object')
|
self.inference_state.builtins_module.py__getattribute__('object')
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
@inference_state_method_cache(default=False)
|
||||||
def is_typeddict(self):
|
def is_typeddict(self):
|
||||||
# TODO Do a proper mro resolution. Currently we are just listing
|
# TODO Do a proper mro resolution. Currently we are just listing
|
||||||
# classes. However, it's a complicated algorithm.
|
# classes. However, it's a complicated algorithm.
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ dynamic_annotation('')
|
|||||||
|
|
||||||
class Foo(typing.TypedDict):
|
class Foo(typing.TypedDict):
|
||||||
foo: str
|
foo: str
|
||||||
bar: List[int]
|
bar: typing.List[float]
|
||||||
foo
|
foo
|
||||||
#! ['foo: str']
|
#! ['foo: str']
|
||||||
foo
|
foo
|
||||||
@@ -519,7 +519,7 @@ class Foo(typing.TypedDict):
|
|||||||
d: Foo
|
d: Foo
|
||||||
#? str()
|
#? str()
|
||||||
d['foo']
|
d['foo']
|
||||||
#? str()
|
#? float()
|
||||||
d['bar'][0]
|
d['bar'][0]
|
||||||
#?
|
#?
|
||||||
d['baz']
|
d['baz']
|
||||||
|
|||||||
Reference in New Issue
Block a user