mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
Use class filters in instances differently so metaclass plugins work, fixes #1090
This commit is contained in:
@@ -380,14 +380,14 @@ class CompiledObjectFilter(AbstractFilter):
|
|||||||
|
|
||||||
def __init__(self, evaluator, compiled_object, is_instance=False):
|
def __init__(self, evaluator, compiled_object, is_instance=False):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._compiled_object = compiled_object
|
self.compiled_object = compiled_object
|
||||||
self.is_instance = is_instance
|
self.is_instance = is_instance
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
return self._get(
|
return self._get(
|
||||||
name,
|
name,
|
||||||
lambda: self._compiled_object.access_handle.is_allowed_getattr(name),
|
lambda: self.compiled_object.access_handle.is_allowed_getattr(name),
|
||||||
lambda: self._compiled_object.access_handle.dir(),
|
lambda: self.compiled_object.access_handle.dir(),
|
||||||
check_has_attribute=True
|
check_has_attribute=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ class CompiledObjectFilter(AbstractFilter):
|
|||||||
def values(self):
|
def values(self):
|
||||||
from jedi.evaluate.compiled import builtin_from_name
|
from jedi.evaluate.compiled import builtin_from_name
|
||||||
names = []
|
names = []
|
||||||
needs_type_completions, dir_infos = self._compiled_object.access_handle.get_dir_infos()
|
needs_type_completions, dir_infos = self.compiled_object.access_handle.get_dir_infos()
|
||||||
for name in dir_infos:
|
for name in dir_infos:
|
||||||
names += self._get(
|
names += self._get(
|
||||||
name,
|
name,
|
||||||
@@ -434,10 +434,10 @@ class CompiledObjectFilter(AbstractFilter):
|
|||||||
return names
|
return names
|
||||||
|
|
||||||
def _create_name(self, name):
|
def _create_name(self, name):
|
||||||
return self.name_class(self._evaluator, self._compiled_object, name)
|
return self.name_class(self._evaluator, self.compiled_object, name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: %s>" % (self.__class__.__name__, self._compiled_object)
|
return "<%s: %s>" % (self.__class__.__name__, self.compiled_object)
|
||||||
|
|
||||||
|
|
||||||
docstr_defaults = {
|
docstr_defaults = {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from abc import abstractproperty
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
|
from jedi.evaluate.compiled.context import CompiledObjectFilter
|
||||||
from jedi.evaluate.helpers import contexts_from_qualified_names
|
from jedi.evaluate.helpers import contexts_from_qualified_names
|
||||||
from jedi.evaluate.filters import AbstractFilter
|
from jedi.evaluate.filters import AbstractFilter
|
||||||
from jedi.evaluate.names import ContextName, TreeNameDefinition
|
from jedi.evaluate.names import ContextName, TreeNameDefinition
|
||||||
@@ -136,11 +137,19 @@ class AbstractInstanceContext(Context):
|
|||||||
# compiled objects to search for self variables.
|
# compiled objects to search for self variables.
|
||||||
yield SelfAttributeFilter(self.evaluator, self, cls, origin_scope)
|
yield SelfAttributeFilter(self.evaluator, self, cls, origin_scope)
|
||||||
|
|
||||||
for cls in class_context.py__mro__():
|
class_filters = class_context.get_filters(
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
search_global=False,
|
||||||
yield CompiledInstanceClassFilter(self.evaluator, self, cls)
|
origin_scope=origin_scope,
|
||||||
|
is_instance=True,
|
||||||
|
)
|
||||||
|
for f in class_filters:
|
||||||
|
if isinstance(f, ClassFilter):
|
||||||
|
yield InstanceClassFilter(self.evaluator, self, f)
|
||||||
|
elif isinstance(f, CompiledObjectFilter):
|
||||||
|
yield CompiledInstanceClassFilter(self.evaluator, self, f)
|
||||||
else:
|
else:
|
||||||
yield InstanceClassFilter(self.evaluator, self, cls, origin_scope)
|
# Propably from the metaclass.
|
||||||
|
yield f
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_context_set, contextualized_node):
|
||||||
names = self.get_function_slot_names(u'__getitem__')
|
names = self.get_function_slot_names(u'__getitem__')
|
||||||
@@ -328,7 +337,6 @@ class CompiledInstanceName(compiled.CompiledName):
|
|||||||
name.string_name
|
name.string_name
|
||||||
)
|
)
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
self._class = klass
|
|
||||||
self._class_member_name = name
|
self._class_member_name = name
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_context_set
|
||||||
@@ -343,11 +351,10 @@ class CompiledInstanceName(compiled.CompiledName):
|
|||||||
class CompiledInstanceClassFilter(AbstractFilter):
|
class CompiledInstanceClassFilter(AbstractFilter):
|
||||||
name_class = CompiledInstanceName
|
name_class = CompiledInstanceName
|
||||||
|
|
||||||
def __init__(self, evaluator, instance, klass):
|
def __init__(self, evaluator, instance, f):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
self._class = klass
|
self._class_filter = f
|
||||||
self._class_filter = next(klass.get_filters(is_instance=True))
|
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
return self._convert(self._class_filter.get(name))
|
return self._convert(self._class_filter.get(name))
|
||||||
@@ -356,8 +363,9 @@ class CompiledInstanceClassFilter(AbstractFilter):
|
|||||||
return self._convert(self._class_filter.values())
|
return self._convert(self._class_filter.values())
|
||||||
|
|
||||||
def _convert(self, names):
|
def _convert(self, names):
|
||||||
|
klass = self._class_filter.compiled_object
|
||||||
return [
|
return [
|
||||||
CompiledInstanceName(self._evaluator, self._instance, self._class, n)
|
CompiledInstanceName(self._evaluator, self._instance, klass, n)
|
||||||
for n in names
|
for n in names
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -454,15 +462,9 @@ class InstanceClassFilter(AbstractFilter):
|
|||||||
resulting names in LazyINstanceClassName. The idea is that the class name
|
resulting names in LazyINstanceClassName. The idea is that the class name
|
||||||
filtering can be very flexible and always be reflected in instances.
|
filtering can be very flexible and always be reflected in instances.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, context, class_context, origin_scope):
|
def __init__(self, evaluator, instance, class_filter):
|
||||||
self._instance = context
|
self._instance = instance
|
||||||
self._class_context = class_context
|
self._class_filter = class_filter
|
||||||
self._class_filter = next(class_context.get_filters(
|
|
||||||
search_global=False,
|
|
||||||
origin_scope=origin_scope,
|
|
||||||
is_instance=True,
|
|
||||||
))
|
|
||||||
assert isinstance(self._class_filter, ClassFilter), self._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, from_instance=True))
|
||||||
@@ -471,10 +473,10 @@ class InstanceClassFilter(AbstractFilter):
|
|||||||
return self._convert(self._class_filter.values(from_instance=True))
|
return self._convert(self._class_filter.values(from_instance=True))
|
||||||
|
|
||||||
def _convert(self, names):
|
def _convert(self, names):
|
||||||
return [LazyInstanceClassName(self._instance, self._class_context, n) for n in names]
|
return [LazyInstanceClassName(self._instance, self._class_filter.context, n) for n in names]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s for %s>' % (self.__class__.__name__, self._class_context)
|
return '<%s for %s>' % (self.__class__.__name__, self._class_filter.context)
|
||||||
|
|
||||||
|
|
||||||
class SelfAttributeFilter(ClassFilter):
|
class SelfAttributeFilter(ClassFilter):
|
||||||
|
|||||||
@@ -331,7 +331,8 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
|
|||||||
|
|
||||||
for lazy_base in self.py__bases__():
|
for lazy_base in self.py__bases__():
|
||||||
for context in lazy_base.infer():
|
for context in lazy_base.infer():
|
||||||
contexts = context.get_metaclasses()
|
if context.is_class():
|
||||||
if contexts:
|
contexts = context.get_metaclasses()
|
||||||
return contexts
|
if contexts:
|
||||||
|
return contexts
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|||||||
@@ -209,6 +209,9 @@ class _TypingClassMixin(object):
|
|||||||
self.evaluator.builtins_module.py__getattribute__('object')
|
self.evaluator.builtins_module.py__getattribute__('object')
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
def get_metaclasses(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class TypingClassContextWithIndex(_TypingClassMixin, TypingContextWithIndex, ClassMixin):
|
class TypingClassContextWithIndex(_TypingClassMixin, TypingContextWithIndex, ClassMixin):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -612,7 +612,6 @@ def get_metaclass_filters(func):
|
|||||||
for metaclass in metaclasses:
|
for metaclass in metaclasses:
|
||||||
if metaclass.py__name__() == 'EnumMeta' \
|
if metaclass.py__name__() == 'EnumMeta' \
|
||||||
and metaclass.get_root_context().py__name__() == 'enum':
|
and metaclass.get_root_context().py__name__() == 'enum':
|
||||||
print('cont', cls)
|
|
||||||
filter_ = ParserTreeFilter(cls.evaluator, context=cls)
|
filter_ = ParserTreeFilter(cls.evaluator, context=cls)
|
||||||
return [DictFilter({
|
return [DictFilter({
|
||||||
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
||||||
@@ -638,7 +637,7 @@ class EnumInstance(LazyContextWrapper):
|
|||||||
|
|
||||||
def get_filters(self, search_global=False, position=None, origin_scope=None):
|
def get_filters(self, search_global=False, position=None, origin_scope=None):
|
||||||
yield DictFilter(dict(
|
yield DictFilter(dict(
|
||||||
name=self._name.string_name,
|
name=compiled.create_simple_object(self.evaluator, self._name.string_name).name,
|
||||||
value=self._name,
|
value=self._name,
|
||||||
))
|
))
|
||||||
for f in self._get_wrapped_context().get_filters():
|
for f in self._get_wrapped_context().get_filters():
|
||||||
|
|||||||
Reference in New Issue
Block a user