diff --git a/jedi/evaluate/base_context.py b/jedi/evaluate/base_context.py index 489147f9..140891bf 100644 --- a/jedi/evaluate/base_context.py +++ b/jedi/evaluate/base_context.py @@ -124,6 +124,8 @@ def iterate_contexts(contexts, contextualized_node=None, is_async=False): class ContextWrapper(object): + py__getattribute__ = Context.py__getattribute__ + def __init__(self, wrapped_context): self._wrapped_context = wrapped_context diff --git a/jedi/evaluate/compiled/context.py b/jedi/evaluate/compiled/context.py index ea9519f0..eb8649cd 100644 --- a/jedi/evaluate/compiled/context.py +++ b/jedi/evaluate/compiled/context.py @@ -321,7 +321,7 @@ class CompiledObjectFilter(AbstractFilter): def __init__(self, evaluator, compiled_object, is_instance=False): self._evaluator = evaluator self._compiled_object = compiled_object - self._is_instance = is_instance + self.is_instance = is_instance def get(self, name): return self._get( @@ -345,7 +345,7 @@ class CompiledObjectFilter(AbstractFilter): if is_descriptor or not has_attribute: return [self._get_cached_name(name, is_empty=True)] - if self._is_instance and name not in dir_callback(): + if self.is_instance and name not in dir_callback(): return [] return [self._get_cached_name(name)] @@ -368,7 +368,7 @@ class CompiledObjectFilter(AbstractFilter): ) # ``dir`` doesn't include the type names. - if not self._is_instance and needs_type_completions: + if not self.is_instance and needs_type_completions: for filter in builtin_from_name(self._evaluator, u'type').get_filters(): names += filter.values() return names diff --git a/jedi/evaluate/context/klass.py b/jedi/evaluate/context/klass.py index 5bbddc30..53c0a897 100644 --- a/jedi/evaluate/context/klass.py +++ b/jedi/evaluate/context/klass.py @@ -203,6 +203,15 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)): origin_scope=origin_scope, is_instance=is_instance ) + if not is_instance and self: + # Return completions of the meta class. + from jedi.evaluate.compiled import builtin_from_name + type_ = builtin_from_name(self.evaluator, u'type') + yield ClassFilter( + self.evaluator, self, node_context=type_, + origin_scope=origin_scope, + is_instance=is_instance + ) def is_class(self): return True diff --git a/jedi/plugins/typeshed.py b/jedi/plugins/typeshed.py index b43d28e5..53511d64 100644 --- a/jedi/plugins/typeshed.py +++ b/jedi/plugins/typeshed.py @@ -189,7 +189,7 @@ class NameWithStubMixin(object): # This basically merges stub contexts with actual contexts. for actual_context in actual_contexts: for stub_context in stub_contexts: - if isinstance(actual_context, CompiledObject): + if False and isinstance(actual_context, CompiledObject): if isinstance(stub_context, ClassContext): yield CompiledStubClassContext(stub_context, actual_context) elif isinstance(stub_context, FunctionContext): @@ -433,6 +433,15 @@ class CompiledStubClassContext(_StubContextWithCompiled): for f in filters: yield f + def get_class_filter(self, original_class, origin_scope, is_instance): + return StubParserTreeFilter( + [next(self.compiled_context.get_filters(search_global=False))], + self.evaluator, + context=self, + origin_scope=origin_scope, + search_global=False, + ) + class CompiledStubFunctionContext(_StubContextWithCompiled): pass