mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-15 18:17:07 +08:00
Function -> FunctionContext and fakes use the FunctionContext, too.
This commit is contained in:
@@ -581,7 +581,7 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
d = 'class ' + d.type
|
d = 'class ' + d.type
|
||||||
elif isinstance(d, (tree.Class, er.ClassContext, er.Instance)):
|
elif isinstance(d, (tree.Class, er.ClassContext, er.Instance)):
|
||||||
d = 'class ' + unicode(d.name)
|
d = 'class ' + unicode(d.name)
|
||||||
elif isinstance(d, (er.Function, tree.Function)):
|
elif isinstance(d, (er.FunctionContext, tree.Function)):
|
||||||
d = 'def ' + unicode(d.name)
|
d = 'def ' + unicode(d.name)
|
||||||
elif isinstance(d, tree.Module):
|
elif isinstance(d, tree.Module):
|
||||||
# only show module name
|
# only show module name
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class Evaluator(object):
|
|||||||
if element.type == 'classdef':
|
if element.type == 'classdef':
|
||||||
return er.ClassContext(self, element, parent_context)
|
return er.ClassContext(self, element, parent_context)
|
||||||
elif element.type == 'funcdef':
|
elif element.type == 'funcdef':
|
||||||
return er.Function(self, parent_context, element)
|
return er.FunctionContext(self, parent_context, element)
|
||||||
elif element.type == 'lambda':
|
elif element.type == 'lambda':
|
||||||
return er.LambdaWrapper(self, element)
|
return er.LambdaWrapper(self, element)
|
||||||
elif element.type == 'file_input':
|
elif element.type == 'file_input':
|
||||||
@@ -306,7 +306,7 @@ class Evaluator(object):
|
|||||||
types = self.eval_trailer(context, types, trailer)
|
types = self.eval_trailer(context, types, trailer)
|
||||||
elif element.type in ('testlist_star_expr', 'testlist',):
|
elif element.type in ('testlist_star_expr', 'testlist',):
|
||||||
# The implicit tuple in statements.
|
# The implicit tuple in statements.
|
||||||
types = set([iterable.ImplicitTuple(self, element)])
|
types = set([iterable.ArrayLiteralContext(self, context, element)])
|
||||||
elif element.type in ('not_test', 'factor'):
|
elif element.type in ('not_test', 'factor'):
|
||||||
types = self.eval_element(context, element.children[-1])
|
types = self.eval_element(context, element.children[-1])
|
||||||
for operator in element.children[:-1]:
|
for operator in element.children[:-1]:
|
||||||
@@ -406,13 +406,6 @@ class Evaluator(object):
|
|||||||
new_types |= self.execute(typ, arguments)
|
new_types |= self.execute(typ, arguments)
|
||||||
return new_types
|
return new_types
|
||||||
|
|
||||||
def execute_evaluated(self, obj, *args):
|
|
||||||
"""
|
|
||||||
Execute a function with already executed arguments.
|
|
||||||
"""
|
|
||||||
args = [iterable.AlreadyEvaluated([arg]) for arg in args]
|
|
||||||
return self.execute(obj, args)
|
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def execute(self, obj, arguments=None):
|
def execute(self, obj, arguments=None):
|
||||||
if not isinstance(arguments, param.Arguments):
|
if not isinstance(arguments, param.Arguments):
|
||||||
@@ -422,7 +415,7 @@ class Evaluator(object):
|
|||||||
if self.is_analysis:
|
if self.is_analysis:
|
||||||
arguments.eval_all()
|
arguments.eval_all()
|
||||||
|
|
||||||
if isinstance(obj, er.Function):
|
if isinstance(obj, er.FunctionContext):
|
||||||
obj = obj.get_decorated_func()
|
obj = obj.get_decorated_func()
|
||||||
|
|
||||||
debug.dbg('execute: %s %s', obj, arguments)
|
debug.dbg('execute: %s %s', obj, arguments)
|
||||||
|
|||||||
@@ -238,12 +238,13 @@ class CompiledObject(Context):
|
|||||||
Returns only the faked scopes - the other ones are not important for
|
Returns only the faked scopes - the other ones are not important for
|
||||||
internal analysis.
|
internal analysis.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
module = self.get_parent_until()
|
module = self.get_parent_until()
|
||||||
faked_subscopes = []
|
faked_subscopes = []
|
||||||
for name in dir(self.obj):
|
for name in dir(self.obj):
|
||||||
try:
|
try:
|
||||||
faked_subscopes.append(
|
faked_subscopes.append(
|
||||||
fake.get_faked(module, self.obj, parent=self, name=name)
|
fake.get_faked(self._evaluator, module, self.obj, parent=self, name=name)
|
||||||
)
|
)
|
||||||
except fake.FakeDoesNotExist:
|
except fake.FakeDoesNotExist:
|
||||||
pass
|
pass
|
||||||
@@ -512,20 +513,21 @@ def _parse_function_doc(doc):
|
|||||||
return param_str, ret
|
return param_str, ret
|
||||||
|
|
||||||
|
|
||||||
def _create_from_name(evaluator, module, parent, name):
|
def _create_from_name(evaluator, module, compiled_object, name):
|
||||||
|
obj = compiled_object.obj
|
||||||
try:
|
try:
|
||||||
return fake.get_faked(module, parent.obj, parent=parent, name=name)
|
return fake.get_faked(evaluator, module, obj, parent_context=compiled_object, name=name)
|
||||||
except fake.FakeDoesNotExist:
|
except fake.FakeDoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
obj = getattr(parent.obj, name)
|
obj = getattr(obj, name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# Happens e.g. in properties of
|
# Happens e.g. in properties of
|
||||||
# PyQt4.QtGui.QStyleOptionComboBox.currentText
|
# PyQt4.QtGui.QStyleOptionComboBox.currentText
|
||||||
# -> just set it to None
|
# -> just set it to None
|
||||||
obj = None
|
obj = None
|
||||||
return create(evaluator, obj, parent)
|
return create(evaluator, obj, parent_context=compiled_object)
|
||||||
|
|
||||||
|
|
||||||
def builtin_from_name(evaluator, string):
|
def builtin_from_name(evaluator, string):
|
||||||
@@ -550,7 +552,7 @@ _SPECIAL_OBJECTS = {
|
|||||||
|
|
||||||
def get_special_object(evaluator, identifier):
|
def get_special_object(evaluator, identifier):
|
||||||
obj = _SPECIAL_OBJECTS[identifier]
|
obj = _SPECIAL_OBJECTS[identifier]
|
||||||
return create(evaluator, obj, parent=create(evaluator, _builtins))
|
return create(evaluator, obj, parent_context=create(evaluator, _builtins))
|
||||||
|
|
||||||
|
|
||||||
def compiled_objects_cache(attribute_name):
|
def compiled_objects_cache(attribute_name):
|
||||||
@@ -560,21 +562,21 @@ def compiled_objects_cache(attribute_name):
|
|||||||
Caching the id has the advantage that an object doesn't need to be
|
Caching the id has the advantage that an object doesn't need to be
|
||||||
hashable.
|
hashable.
|
||||||
"""
|
"""
|
||||||
def wrapper(evaluator, obj, parent=None, module=None):
|
def wrapper(evaluator, obj, parent_context=None, module=None):
|
||||||
cache = getattr(evaluator, attribute_name)
|
cache = getattr(evaluator, attribute_name)
|
||||||
# Do a very cheap form of caching here.
|
# Do a very cheap form of caching here.
|
||||||
key = id(obj), id(parent)
|
key = id(obj), id(parent_context)
|
||||||
try:
|
try:
|
||||||
return cache[key][0]
|
return cache[key][0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# TODO this whole decorator looks way too ugly and this if
|
# TODO this whole decorator looks way too ugly and this if
|
||||||
# doesn't make it better. Find a more generic solution.
|
# doesn't make it better. Find a more generic solution.
|
||||||
if parent or module:
|
if parent_context or module:
|
||||||
result = func(evaluator, obj, parent, module)
|
result = func(evaluator, obj, parent_context, module)
|
||||||
else:
|
else:
|
||||||
result = func(evaluator, obj)
|
result = func(evaluator, obj)
|
||||||
# Need to cache all of them, otherwise the id could be overwritten.
|
# Need to cache all of them, otherwise the id could be overwritten.
|
||||||
cache[key] = result, obj, parent, module
|
cache[key] = result, obj, parent_context, module
|
||||||
return result
|
return result
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@@ -582,22 +584,22 @@ def compiled_objects_cache(attribute_name):
|
|||||||
|
|
||||||
|
|
||||||
@compiled_objects_cache('compiled_cache')
|
@compiled_objects_cache('compiled_cache')
|
||||||
def create(evaluator, obj, parent=None, module=None):
|
def create(evaluator, obj, parent_context=None, module=None):
|
||||||
"""
|
"""
|
||||||
A very weird interface class to this module. The more options provided the
|
A very weird interface class to this module. The more options provided the
|
||||||
more acurate loading compiled objects is.
|
more acurate loading compiled objects is.
|
||||||
"""
|
"""
|
||||||
if inspect.ismodule(obj):
|
if inspect.ismodule(obj):
|
||||||
if parent is not None:
|
if parent_context is not None:
|
||||||
# Modules don't have parents, be careful with caching: recurse.
|
# Modules don't have parents, be careful with caching: recurse.
|
||||||
return create(evaluator, obj)
|
return create(evaluator, obj)
|
||||||
else:
|
else:
|
||||||
if parent is None and obj != _builtins:
|
if parent_context is None and obj != _builtins:
|
||||||
return create(evaluator, obj, create(evaluator, _builtins))
|
return create(evaluator, obj, create(evaluator, _builtins))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return fake.get_faked(module, obj, parent=parent)
|
return fake.get_faked(evaluator, module, obj, parent_context=parent_context)
|
||||||
except fake.FakeDoesNotExist:
|
except fake.FakeDoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return CompiledObject(evaluator, obj, parent)
|
return CompiledObject(evaluator, obj, parent_context)
|
||||||
|
|||||||
@@ -172,12 +172,13 @@ def memoize_faked(obj):
|
|||||||
def _get_faked(module, obj, name=None):
|
def _get_faked(module, obj, name=None):
|
||||||
obj = type(obj) if is_class_instance(obj) else obj
|
obj = type(obj) if is_class_instance(obj) else obj
|
||||||
result, fake_module = _faked(module, obj, name)
|
result, fake_module = _faked(module, obj, name)
|
||||||
if result is None or isinstance(result, pt.Class):
|
if result is None or result.type == 'classdef':
|
||||||
# We're not interested in classes. What we want is functions.
|
# We're not interested in classes. What we want is functions.
|
||||||
raise FakeDoesNotExist
|
raise FakeDoesNotExist
|
||||||
else:
|
else:
|
||||||
# Set the docstr which was previously not set (faked modules don't
|
# Set the docstr which was previously not set (faked modules don't
|
||||||
# contain it).
|
# contain it).
|
||||||
|
assert result.type == 'funcdef'
|
||||||
doc = '"""%s"""' % obj.__doc__ # TODO need escapes.
|
doc = '"""%s"""' % obj.__doc__ # TODO need escapes.
|
||||||
suite = result.children[-1]
|
suite = result.children[-1]
|
||||||
string = pt.String(doc, (0, 0), '')
|
string = pt.String(doc, (0, 0), '')
|
||||||
@@ -187,12 +188,12 @@ def _get_faked(module, obj, name=None):
|
|||||||
return result, fake_module
|
return result, fake_module
|
||||||
|
|
||||||
|
|
||||||
def get_faked(module, obj, name=None, parent=None):
|
def get_faked(evaluator, module, obj, name=None, parent_context=None):
|
||||||
faked, fake_module = _get_faked(module and module.obj, obj, name)
|
faked, fake_module = _get_faked(module and module.obj, obj, name)
|
||||||
faked.parent = parent
|
|
||||||
if module is not None:
|
if module is not None:
|
||||||
module.used_names = fake_module.used_names
|
module.used_names = fake_module.used_names
|
||||||
return faked
|
from jedi.evaluate.representation import FunctionContext
|
||||||
|
return FunctionContext(evaluator, parent_context, faked)
|
||||||
|
|
||||||
|
|
||||||
def is_class_instance(obj):
|
def is_class_instance(obj):
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ class Context(object):
|
|||||||
def execute(self, arguments=None):
|
def execute(self, arguments=None):
|
||||||
return self._evaluator.execute(self, arguments)
|
return self._evaluator.execute(self, arguments)
|
||||||
|
|
||||||
|
def execute_evaluated(self, *args):
|
||||||
|
"""
|
||||||
|
Execute a function with already executed arguments.
|
||||||
|
"""
|
||||||
|
from jedi.evaluate.iterable import AlreadyEvaluated
|
||||||
|
# TODO UGLY
|
||||||
|
args = [AlreadyEvaluated([arg]) for arg in args]
|
||||||
|
return self.execute(args)
|
||||||
|
|
||||||
|
|
||||||
class TreeContext(Context):
|
class TreeContext(Context):
|
||||||
def eval_node(self, node):
|
def eval_node(self, node):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from abc import abstractmethod
|
|||||||
|
|
||||||
from jedi.parser.tree import search_ancestor
|
from jedi.parser.tree import search_ancestor
|
||||||
from jedi.evaluate import flow_analysis
|
from jedi.evaluate import flow_analysis
|
||||||
from jedi.common import to_list
|
from jedi.common import to_list, unite
|
||||||
|
|
||||||
|
|
||||||
class AbstractNameDefinition():
|
class AbstractNameDefinition():
|
||||||
@@ -28,6 +28,12 @@ class AbstractNameDefinition():
|
|||||||
return '<%s: %s>' % (type(self).__name__, self.string_name)
|
return '<%s: %s>' % (type(self).__name__, self.string_name)
|
||||||
return '<%s: %s@%s>' % (type(self).__name__, self.string_name, self.start_pos)
|
return '<%s: %s@%s>' % (type(self).__name__, self.string_name, self.start_pos)
|
||||||
|
|
||||||
|
def execute(self, arguments):
|
||||||
|
return unite(context.execute(arguments) for context in self.infer())
|
||||||
|
|
||||||
|
def execute_evaluated(self, *args, **kwargs):
|
||||||
|
return unite(context.execute(*args, **kwargs) for context in self.infer())
|
||||||
|
|
||||||
|
|
||||||
class ContextName(AbstractNameDefinition):
|
class ContextName(AbstractNameDefinition):
|
||||||
def __init__(self, parent_context, name):
|
def __init__(self, parent_context, name):
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from abc import abstractproperty
|
from abc import abstractproperty
|
||||||
|
|
||||||
|
from jedi.common import unite
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate.filters import ParserTreeFilter, ContextName
|
from jedi.evaluate.filters import ParserTreeFilter, ContextName
|
||||||
@@ -45,11 +46,8 @@ class AbstractInstanceContext(Context):
|
|||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
def execute(arguments):
|
def execute(arguments):
|
||||||
contexts = set()
|
return unite(name.execute(arguments) for name in names)
|
||||||
for name in names:
|
|
||||||
for context in name.infer():
|
|
||||||
context.execute(arguments)
|
|
||||||
return contexts
|
|
||||||
return execute
|
return execute
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
@@ -103,13 +101,13 @@ class AbstractInstanceContext(Context):
|
|||||||
|
|
||||||
def py__getitem__(self, index):
|
def py__getitem__(self, index):
|
||||||
try:
|
try:
|
||||||
method = self.get_subscope_by_name('__getitem__')
|
names = self._get_function_slot_names('__getitem__')
|
||||||
except KeyError:
|
except KeyError:
|
||||||
debug.warning('No __getitem__, cannot access the array.')
|
debug.warning('No __getitem__, cannot access the array.')
|
||||||
return set()
|
return set()
|
||||||
else:
|
else:
|
||||||
index_obj = compiled.create(self._evaluator, index)
|
index_obj = compiled.create(self._evaluator, index)
|
||||||
return self._evaluator.execute_evaluated(method, index_obj)
|
return unite(name.execute_evaluated(index_obj) for name in names)
|
||||||
|
|
||||||
def py__iter__(self):
|
def py__iter__(self):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ class AbstractArrayContext(Context):
|
|||||||
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
#return compiled.CompiledContextName(
|
||||||
|
return helpers.FakeName(self.type, parent=self)
|
||||||
|
|
||||||
|
|
||||||
class IterableWrapper(tree.Base):
|
class IterableWrapper(tree.Base):
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
@@ -354,8 +360,12 @@ class ArrayLiteralContext(AbstractArrayContext, ArrayMixin):
|
|||||||
def __init__(self, evaluator, parent_context, atom):
|
def __init__(self, evaluator, parent_context, atom):
|
||||||
super(ArrayLiteralContext, self).__init__(evaluator, parent_context)
|
super(ArrayLiteralContext, self).__init__(evaluator, parent_context)
|
||||||
self.atom = atom
|
self.atom = atom
|
||||||
self._array_type = ArrayLiteralContext.mapping[atom.children[0]]
|
|
||||||
"""The builtin name of the array (list, set, tuple or dict)."""
|
if self.atom.type in ('testlist_star_expr', 'testlist'):
|
||||||
|
self._array_type = 'tuple'
|
||||||
|
else:
|
||||||
|
self._array_type = ArrayLiteralContext.mapping[atom.children[0]]
|
||||||
|
"""The builtin name of the array (list, set, tuple or dict)."""
|
||||||
|
|
||||||
c = self.atom.children
|
c = self.atom.children
|
||||||
array_node = c[1]
|
array_node = c[1]
|
||||||
@@ -363,12 +373,6 @@ class ArrayLiteralContext(AbstractArrayContext, ArrayMixin):
|
|||||||
and (not hasattr(array_node, 'children') or ':' not in array_node.children):
|
and (not hasattr(array_node, 'children') or ':' not in array_node.children):
|
||||||
self._array_type = 'set'
|
self._array_type = 'set'
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
#return compiled.CompiledContextName(
|
|
||||||
return helpers.FakeName(self.type, parent=self)
|
|
||||||
|
|
||||||
def py__getitem__(self, index):
|
def py__getitem__(self, index):
|
||||||
"""Here the index is an int/str. Raises IndexError/KeyError."""
|
"""Here the index is an int/str. Raises IndexError/KeyError."""
|
||||||
if self.type == 'dict':
|
if self.type == 'dict':
|
||||||
@@ -423,6 +427,10 @@ class ArrayLiteralContext(AbstractArrayContext, ArrayMixin):
|
|||||||
|
|
||||||
def _items(self):
|
def _items(self):
|
||||||
c = self.atom.children
|
c = self.atom.children
|
||||||
|
|
||||||
|
if self.atom.type in ('testlist_star_expr', 'testlist'):
|
||||||
|
return c[::2]
|
||||||
|
|
||||||
array_node = c[1]
|
array_node = c[1]
|
||||||
if array_node in (']', '}', ')'):
|
if array_node in (']', '}', ')'):
|
||||||
return [] # Direct closing bracket, doesn't contain items.
|
return [] # Direct closing bracket, doesn't contain items.
|
||||||
@@ -458,6 +466,7 @@ class _FakeArray(ArrayLiteralContext):
|
|||||||
class ImplicitTuple(_FakeArray):
|
class ImplicitTuple(_FakeArray):
|
||||||
def __init__(self, evaluator, testlist):
|
def __init__(self, evaluator, testlist):
|
||||||
super(ImplicitTuple, self).__init__(evaluator, testlist, 'tuple')
|
super(ImplicitTuple, self).__init__(evaluator, testlist, 'tuple')
|
||||||
|
raise NotImplementedError
|
||||||
self._testlist = testlist
|
self._testlist = testlist
|
||||||
|
|
||||||
def _items(self):
|
def _items(self):
|
||||||
|
|||||||
@@ -385,7 +385,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
|
|||||||
# more complicated than we would it actually like to be.
|
# more complicated than we would it actually like to be.
|
||||||
return self.var.py__call__(params)
|
return self.var.py__call__(params)
|
||||||
else:
|
else:
|
||||||
return Function.py__call__(self, params)
|
return FunctionContext.py__call__(self, params)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (type(self).__name__, self.var)
|
return "<%s of %s>" % (type(self).__name__, self.var)
|
||||||
@@ -518,13 +518,13 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
return "<e%s of %s>" % (type(self).__name__, self.base)
|
return "<e%s of %s>" % (type(self).__name__, self.base)
|
||||||
|
|
||||||
|
|
||||||
class Function(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
class FunctionContext(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
||||||
"""
|
"""
|
||||||
Needed because of decorators. Decorators are evaluated here.
|
Needed because of decorators. Decorators are evaluated here.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, parent_context, func, is_decorated=False):
|
def __init__(self, evaluator, parent_context, func, is_decorated=False):
|
||||||
""" This should not be called directly """
|
""" This should not be called directly """
|
||||||
super(Function, self).__init__(evaluator, parent_context)
|
super(FunctionContext, self).__init__(evaluator, parent_context)
|
||||||
self.base = self.base_func = func
|
self.base = self.base_func = func
|
||||||
self.is_decorated = is_decorated
|
self.is_decorated = is_decorated
|
||||||
# A property that is set by the decorator resolution.
|
# A property that is set by the decorator resolution.
|
||||||
@@ -563,10 +563,10 @@ class Function(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
self.base_func, dec_results)
|
self.base_func, dec_results)
|
||||||
|
|
||||||
# Create param array.
|
# Create param array.
|
||||||
if isinstance(f, Function):
|
if isinstance(f, FunctionContext):
|
||||||
old_func = f # TODO this is just hacky. change.
|
old_func = f # TODO this is just hacky. change.
|
||||||
elif f.type == 'funcdef':
|
elif f.type == 'funcdef':
|
||||||
old_func = Function(self._evaluator, f, is_decorated=True)
|
old_func = FunctionContext(self._evaluator, f, is_decorated=True)
|
||||||
else:
|
else:
|
||||||
old_func = f
|
old_func = f
|
||||||
|
|
||||||
@@ -579,7 +579,7 @@ class Function(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
debug.warning('multiple wrappers found %s %s',
|
debug.warning('multiple wrappers found %s %s',
|
||||||
self.base_func, wrappers)
|
self.base_func, wrappers)
|
||||||
f = list(wrappers)[0]
|
f = list(wrappers)[0]
|
||||||
if isinstance(f, (Instance, Function)):
|
if isinstance(f, (Instance, FunctionContext)):
|
||||||
f.decorates = self
|
f.decorates = self
|
||||||
|
|
||||||
debug.dbg('decorator end %s', f)
|
debug.dbg('decorator end %s', f)
|
||||||
@@ -629,7 +629,7 @@ class Function(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
||||||
|
|
||||||
|
|
||||||
class LambdaWrapper(Function):
|
class LambdaWrapper(FunctionContext):
|
||||||
def get_decorated_func(self):
|
def get_decorated_func(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user