mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
333 lines
5.3 KiB
Python
333 lines
5.3 KiB
Python
# -----------------
|
|
# normal decorators
|
|
# -----------------
|
|
|
|
def decorator(func):
|
|
def wrapper(*args):
|
|
return func(1, *args)
|
|
return wrapper
|
|
|
|
@decorator
|
|
def decorated(a,b):
|
|
return a,b
|
|
|
|
exe = decorated(set, '')
|
|
|
|
#? set
|
|
exe[1]
|
|
|
|
#? int()
|
|
exe[0]
|
|
|
|
# more complicated with args/kwargs
|
|
def dec(func):
|
|
def wrapper(*args, **kwargs):
|
|
return func(*args, **kwargs)
|
|
return wrapper
|
|
|
|
@dec
|
|
def fu(a, b, c, *args, **kwargs):
|
|
return a, b, c, args, kwargs
|
|
|
|
exe = fu(list, c=set, b=3, d='')
|
|
|
|
#? list
|
|
exe[0]
|
|
#? int()
|
|
exe[1]
|
|
#? set
|
|
exe[2]
|
|
#? []
|
|
exe[3][0].
|
|
#? str()
|
|
exe[4]['d']
|
|
|
|
|
|
exe = fu(list, set, 3, '', d='')
|
|
|
|
#? str()
|
|
exe[3][0]
|
|
|
|
# -----------------
|
|
# multiple decorators
|
|
# -----------------
|
|
def dec2(func2):
|
|
def wrapper2(first_arg, *args2, **kwargs2):
|
|
return func2(first_arg, *args2, **kwargs2)
|
|
return wrapper2
|
|
|
|
@dec2
|
|
@dec
|
|
def fu2(a, b, c, *args, **kwargs):
|
|
return a, b, c, args, kwargs
|
|
|
|
exe = fu2(list, c=set, b=3, d='str')
|
|
|
|
#? list
|
|
exe[0]
|
|
#? int()
|
|
exe[1]
|
|
#? set
|
|
exe[2]
|
|
#? []
|
|
exe[3][0].
|
|
#? str()
|
|
exe[4]['d']
|
|
|
|
|
|
# -----------------
|
|
# Decorator is a class
|
|
# -----------------
|
|
def same_func(func):
|
|
return func
|
|
|
|
class Decorator(object):
|
|
def __init__(self, func):
|
|
self.func = func
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
return self.func(1, *args, **kwargs)
|
|
|
|
@Decorator
|
|
def nothing(a,b,c):
|
|
return a,b,c
|
|
|
|
#? int()
|
|
nothing("")[0]
|
|
#? str()
|
|
nothing("")[1]
|
|
|
|
|
|
@same_func
|
|
@Decorator
|
|
def nothing(a,b,c):
|
|
return a,b,c
|
|
|
|
#? int()
|
|
nothing("")[0]
|
|
|
|
class MethodDecoratorAsClass():
|
|
class_var = 3
|
|
@Decorator
|
|
def func_without_self(arg, arg2):
|
|
return arg, arg2
|
|
|
|
@Decorator
|
|
def func_with_self(self, arg):
|
|
return self.class_var
|
|
|
|
#? int()
|
|
MethodDecoratorAsClass().func_without_self('')[0]
|
|
#? str()
|
|
MethodDecoratorAsClass().func_without_self('')[1]
|
|
#?
|
|
MethodDecoratorAsClass().func_with_self(1)
|
|
|
|
|
|
class SelfVars():
|
|
"""Init decorator problem as an instance, #247"""
|
|
@Decorator
|
|
def __init__(self):
|
|
"""
|
|
__init__ decorators should be ignored when looking up variables in the
|
|
class.
|
|
"""
|
|
self.c = list
|
|
|
|
@Decorator
|
|
def shouldnt_expose_var(not_self):
|
|
"""
|
|
Even though in real Python this shouldn't expose the variable, in this
|
|
case Jedi exposes the variable, because these kind of decorators are
|
|
normally descriptors, which SHOULD be exposed (at least 90%).
|
|
"""
|
|
not_self.b = 1.0
|
|
|
|
def other_method(self):
|
|
#? float()
|
|
self.b
|
|
#? list
|
|
self.c
|
|
|
|
# -----------------
|
|
# not found decorators (are just ignored)
|
|
# -----------------
|
|
@not_found_decorator
|
|
def just_a_func():
|
|
return 1
|
|
|
|
#? int()
|
|
just_a_func()
|
|
|
|
#? ['__closure__']
|
|
just_a_func.__closure__
|
|
|
|
|
|
class JustAClass:
|
|
@not_found_decorator2
|
|
def a(self):
|
|
return 1
|
|
|
|
#? ['__call__']
|
|
JustAClass().a.__call__
|
|
#? int()
|
|
JustAClass().a()
|
|
#? ['__call__']
|
|
JustAClass.a.__call__
|
|
#? int()
|
|
JustAClass.a()
|
|
|
|
# -----------------
|
|
# illegal decorators
|
|
# -----------------
|
|
|
|
class DecoratorWithoutCall():
|
|
def __init__(self, func):
|
|
self.func = func
|
|
|
|
@DecoratorWithoutCall
|
|
def f():
|
|
return 1
|
|
|
|
# cannot be resolved - should be ignored
|
|
@DecoratorWithoutCall(None)
|
|
def g():
|
|
return 1
|
|
|
|
#?
|
|
f()
|
|
#? int()
|
|
g()
|
|
|
|
|
|
class X():
|
|
@str
|
|
def x(self):
|
|
pass
|
|
|
|
def y(self):
|
|
#? str()
|
|
self.x
|
|
#?
|
|
self.x()
|
|
|
|
|
|
def decorator_var_args(function, *args):
|
|
return function(*args)
|
|
|
|
@decorator_var_args
|
|
def function_var_args(param):
|
|
return param
|
|
|
|
#? int()
|
|
function_var_args(1)
|
|
|
|
# -----------------
|
|
# method decorators
|
|
# -----------------
|
|
|
|
def dec(f):
|
|
def wrapper(s):
|
|
return f(s)
|
|
return wrapper
|
|
|
|
class MethodDecorators():
|
|
_class_var = 1
|
|
def __init__(self):
|
|
self._method_var = ''
|
|
|
|
@dec
|
|
def constant(self):
|
|
return 1.0
|
|
|
|
@dec
|
|
def class_var(self):
|
|
return self._class_var
|
|
|
|
@dec
|
|
def method_var(self):
|
|
return self._method_var
|
|
|
|
#? float()
|
|
MethodDecorators().constant()
|
|
#? int()
|
|
MethodDecorators().class_var()
|
|
#? str()
|
|
MethodDecorators().method_var()
|
|
|
|
|
|
class Base():
|
|
@not_existing
|
|
def __init__(self):
|
|
pass
|
|
@not_existing
|
|
def b(self):
|
|
return ''
|
|
@dec
|
|
def c(self):
|
|
return 1
|
|
|
|
class MethodDecoratorDoesntExist(Base):
|
|
"""#272 github: combination of method decorators and super()"""
|
|
def a(self):
|
|
#?
|
|
super().__init__()
|
|
#? str()
|
|
super().b()
|
|
#? int()
|
|
super().c()
|
|
#? float()
|
|
self.d()
|
|
|
|
@doesnt_exist
|
|
def d(self):
|
|
return 1.0
|
|
|
|
# -----------------
|
|
# others
|
|
# -----------------
|
|
def memoize(function):
|
|
def wrapper(*args):
|
|
if random.choice([0, 1]):
|
|
pass
|
|
else:
|
|
rv = function(*args)
|
|
return rv
|
|
return wrapper
|
|
|
|
@memoize
|
|
def follow_statement(stmt):
|
|
return stmt
|
|
|
|
# here we had problems with the else clause, because the parent was not right.
|
|
#? int()
|
|
follow_statement(1)
|
|
|
|
# -----------------
|
|
# class decorators
|
|
# -----------------
|
|
|
|
# class decorators should just be ignored
|
|
@should_ignore
|
|
class A():
|
|
x = 3
|
|
def ret(self):
|
|
return 1
|
|
|
|
#? int()
|
|
A().ret()
|
|
#? int()
|
|
A().x
|
|
|
|
|
|
# -----------------
|
|
# On decorator completions
|
|
# -----------------
|
|
|
|
import abc
|
|
#? ['abc']
|
|
@abc
|
|
|
|
#? ['abstractmethod']
|
|
@abc.abstractmethod
|