mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Move py__mro__ to a separate function
This commit is contained in:
@@ -12,7 +12,8 @@ from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments, \
|
|||||||
ValuesArguments
|
ValuesArguments
|
||||||
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
||||||
FunctionContext, AbstractFunction, OverloadedFunctionContext
|
FunctionContext, AbstractFunction, OverloadedFunctionContext
|
||||||
from jedi.evaluate.context.klass import ClassContext, apply_py__get__, ClassFilter
|
from jedi.evaluate.context.klass import ClassContext, apply_py__get__, \
|
||||||
|
py__mro__, ClassFilter
|
||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ class AbstractInstanceContext(Context):
|
|||||||
def get_filters(self, search_global=None, until_position=None,
|
def get_filters(self, search_global=None, until_position=None,
|
||||||
origin_scope=None, include_self_names=True):
|
origin_scope=None, include_self_names=True):
|
||||||
if include_self_names:
|
if include_self_names:
|
||||||
for cls in self.class_context.py__mro__():
|
for cls in py__mro__(self.class_context):
|
||||||
if not isinstance(cls, compiled.CompiledObject) \
|
if not isinstance(cls, compiled.CompiledObject) \
|
||||||
or cls.tree_node is not None:
|
or cls.tree_node is not None:
|
||||||
# In this case we're excluding compiled objects that are
|
# In this case we're excluding compiled objects that are
|
||||||
@@ -121,7 +122,7 @@ 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 self.class_context.py__mro__():
|
for cls in py__mro__(self.class_context):
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
yield CompiledInstanceClassFilter(self.evaluator, self, cls)
|
yield CompiledInstanceClassFilter(self.evaluator, self, cls)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ py__call__(arguments: Array) On callable objects, returns types.
|
|||||||
py__bool__() Returns True/False/None; None means that
|
py__bool__() Returns True/False/None; None means that
|
||||||
there's no certainty.
|
there's no certainty.
|
||||||
py__bases__() Returns a list of base classes.
|
py__bases__() Returns a list of base classes.
|
||||||
py__mro__() Returns a list of classes (the mro).
|
|
||||||
py__iter__() Returns a generator of a set of types.
|
py__iter__() Returns a generator of a set of types.
|
||||||
py__class__() Returns the class of an instance.
|
py__class__() Returns the class of an instance.
|
||||||
py__simple_getitem__(index: int/str) Returns a a set of types of the index.
|
py__simple_getitem__(index: int/str) Returns a a set of types of the index.
|
||||||
@@ -60,6 +59,51 @@ def apply_py__get__(context, base_context):
|
|||||||
yield descriptor_context
|
yield descriptor_context
|
||||||
|
|
||||||
|
|
||||||
|
@evaluator_method_cache(default=())
|
||||||
|
def py__mro__(context):
|
||||||
|
try:
|
||||||
|
method = context.py__mro__
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Currently only used for compiled objects.
|
||||||
|
return method()
|
||||||
|
|
||||||
|
def add(cls):
|
||||||
|
if cls not in mro:
|
||||||
|
mro.append(cls)
|
||||||
|
|
||||||
|
mro = [context]
|
||||||
|
# TODO Do a proper mro resolution. Currently we are just listing
|
||||||
|
# classes. However, it's a complicated algorithm.
|
||||||
|
for lazy_cls in context.py__bases__():
|
||||||
|
# TODO there's multiple different mro paths possible if this yields
|
||||||
|
# multiple possibilities. Could be changed to be more correct.
|
||||||
|
for cls in lazy_cls.infer():
|
||||||
|
# TODO detect for TypeError: duplicate base class str,
|
||||||
|
# e.g. `class X(str, str): pass`
|
||||||
|
try:
|
||||||
|
mro_method = py__mro__(cls)
|
||||||
|
except AttributeError:
|
||||||
|
# TODO add a TypeError like:
|
||||||
|
"""
|
||||||
|
>>> class Y(lambda: test): pass
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
TypeError: function() argument 1 must be code, not str
|
||||||
|
>>> class Y(1): pass
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
TypeError: int() takes at most 2 arguments (3 given)
|
||||||
|
"""
|
||||||
|
debug.warning('Super class of %s is not a class: %s', context, cls)
|
||||||
|
else:
|
||||||
|
add(cls)
|
||||||
|
for cls_new in mro_method():
|
||||||
|
add(cls_new)
|
||||||
|
return tuple(mro)
|
||||||
|
|
||||||
|
|
||||||
class ClassName(TreeNameDefinition):
|
class ClassName(TreeNameDefinition):
|
||||||
def __init__(self, parent_context, tree_name, name_context, apply_decorators):
|
def __init__(self, parent_context, tree_name, name_context, apply_decorators):
|
||||||
super(ClassName, self).__init__(parent_context, tree_name)
|
super(ClassName, self).__init__(parent_context, tree_name)
|
||||||
@@ -122,42 +166,6 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
|
|||||||
"""
|
"""
|
||||||
api_type = u'class'
|
api_type = u'class'
|
||||||
|
|
||||||
@evaluator_method_cache(default=())
|
|
||||||
def py__mro__(self):
|
|
||||||
def add(cls):
|
|
||||||
if cls not in mro:
|
|
||||||
mro.append(cls)
|
|
||||||
|
|
||||||
mro = [self]
|
|
||||||
# TODO Do a proper mro resolution. Currently we are just listing
|
|
||||||
# classes. However, it's a complicated algorithm.
|
|
||||||
for lazy_cls in self.py__bases__():
|
|
||||||
# TODO there's multiple different mro paths possible if this yields
|
|
||||||
# multiple possibilities. Could be changed to be more correct.
|
|
||||||
for cls in lazy_cls.infer():
|
|
||||||
# TODO detect for TypeError: duplicate base class str,
|
|
||||||
# e.g. `class X(str, str): pass`
|
|
||||||
try:
|
|
||||||
mro_method = cls.py__mro__
|
|
||||||
except AttributeError:
|
|
||||||
# TODO add a TypeError like:
|
|
||||||
"""
|
|
||||||
>>> class Y(lambda: test): pass
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in <module>
|
|
||||||
TypeError: function() argument 1 must be code, not str
|
|
||||||
>>> class Y(1): pass
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in <module>
|
|
||||||
TypeError: int() takes at most 2 arguments (3 given)
|
|
||||||
"""
|
|
||||||
debug.warning('Super class of %s is not a class: %s', self, cls)
|
|
||||||
else:
|
|
||||||
add(cls)
|
|
||||||
for cls_new in mro_method():
|
|
||||||
add(cls_new)
|
|
||||||
return tuple(mro)
|
|
||||||
|
|
||||||
@evaluator_method_cache(default=())
|
@evaluator_method_cache(default=())
|
||||||
def py__bases__(self):
|
def py__bases__(self):
|
||||||
arglist = self.tree_node.get_super_arglist()
|
arglist = self.tree_node.get_super_arglist()
|
||||||
@@ -185,7 +193,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
|
|||||||
origin_scope=origin_scope
|
origin_scope=origin_scope
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
for cls in self.py__mro__():
|
for cls in py__mro__(self):
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
for filter in cls.get_filters(is_instance=is_instance):
|
for filter in cls.get_filters(is_instance=is_instance):
|
||||||
yield filter
|
yield filter
|
||||||
@@ -226,9 +234,8 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
|
|||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_context_set, contextualized_node):
|
||||||
from jedi.evaluate.context.typing import TypingClassMixin, AnnotatedClass
|
from jedi.evaluate.context.typing import TypingClassMixin, AnnotatedClass
|
||||||
for cls in self.py__mro__():
|
for cls in py__mro__(self):
|
||||||
if isinstance(cls, TypingClassMixin):
|
if isinstance(cls, TypingClassMixin):
|
||||||
#print('ha', self, list(self.py__mro__()))
|
|
||||||
# TODO get the right classes.
|
# TODO get the right classes.
|
||||||
return ContextSet.from_iterable(
|
return ContextSet.from_iterable(
|
||||||
AnnotatedClass(
|
AnnotatedClass(
|
||||||
|
|||||||
@@ -185,9 +185,6 @@ class TypingContext(_BaseTypingContext):
|
|||||||
|
|
||||||
|
|
||||||
class TypingClassMixin(object):
|
class TypingClassMixin(object):
|
||||||
def py__mro__(self):
|
|
||||||
return [self, builtin_from_name(self.evaluator, u'object')]
|
|
||||||
|
|
||||||
def py__bases__(self,):
|
def py__bases__(self,):
|
||||||
return [LazyKnownContext(builtin_from_name(self.evaluator, u'object'))]
|
return [LazyKnownContext(builtin_from_name(self.evaluator, u'object'))]
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from jedi.evaluate.base_context import ContextualizedNode, \
|
|||||||
NO_CONTEXTS, ContextSet, ContextWrapper
|
NO_CONTEXTS, ContextSet, ContextWrapper
|
||||||
from jedi.evaluate.context import ClassContext, ModuleContext, \
|
from jedi.evaluate.context import ClassContext, ModuleContext, \
|
||||||
FunctionExecutionContext
|
FunctionExecutionContext
|
||||||
|
from jedi.evaluate.context.klass import py__mro__
|
||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
from jedi.evaluate.lazy_context import LazyTreeContext
|
from jedi.evaluate.lazy_context import LazyTreeContext
|
||||||
from jedi.evaluate.syntax_tree import is_string
|
from jedi.evaluate.syntax_tree import is_string
|
||||||
@@ -229,7 +230,7 @@ def builtins_isinstance(objects, types, arguments, evaluator):
|
|||||||
for o in objects:
|
for o in objects:
|
||||||
cls = o.py__class__()
|
cls = o.py__class__()
|
||||||
try:
|
try:
|
||||||
mro_func = cls.py__mro__
|
mro_func = py__mro__(cls)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# This is temporary. Everything should have a class attribute in
|
# This is temporary. Everything should have a class attribute in
|
||||||
# Python?! Maybe we'll leave it here, because some numpy objects or
|
# Python?! Maybe we'll leave it here, because some numpy objects or
|
||||||
|
|||||||
Reference in New Issue
Block a user