1# -----------------
2# normal decorators
3# -----------------
4
5def decorator(func):
6    def wrapper(*args):
7        return func(1, *args)
8    return wrapper
9
10@decorator
11def decorated(a,b):
12    return a,b
13
14exe = decorated(set, '')
15
16#? set
17exe[1]
18
19#? int()
20exe[0]
21
22# more complicated with args/kwargs
23def dec(func):
24    def wrapper(*args, **kwargs):
25        return func(*args, **kwargs)
26    return wrapper
27
28@dec
29def fu(a, b, c, *args, **kwargs):
30    return a, b, c, args, kwargs
31
32exe = fu(list, c=set, b=3, d='')
33
34#? list
35exe[0]
36#? int()
37exe[1]
38#? set
39exe[2]
40#? []
41exe[3][0].
42#? str()
43exe[4]['d']
44
45
46exe = fu(list, set, 3, '', d='')
47
48#? str()
49exe[3][0]
50
51# -----------------
52# multiple decorators
53# -----------------
54def dec2(func2):
55    def wrapper2(first_arg, *args2, **kwargs2):
56        return func2(first_arg, *args2, **kwargs2)
57    return wrapper2
58
59@dec2
60@dec
61def fu2(a, b, c, *args, **kwargs):
62    return a, b, c, args, kwargs
63
64exe = fu2(list, c=set, b=3, d='str')
65
66#? list
67exe[0]
68#? int()
69exe[1]
70#? set
71exe[2]
72#? []
73exe[3][0].
74#? str()
75exe[4]['d']
76
77
78# -----------------
79# Decorator is a class
80# -----------------
81def same_func(func):
82    return func
83
84class Decorator(object):
85    def __init__(self, func):
86        self.func = func
87
88    def __call__(self, *args, **kwargs):
89        return self.func(1, *args, **kwargs)
90
91@Decorator
92def nothing(a,b,c):
93    return a,b,c
94
95#? int()
96nothing("")[0]
97#? str()
98nothing("")[1]
99
100
101@same_func
102@Decorator
103def nothing(a,b,c):
104    return a,b,c
105
106#? int()
107nothing("")[0]
108
109class MethodDecoratorAsClass():
110    class_var = 3
111    @Decorator
112    def func_without_self(arg, arg2):
113        return arg, arg2
114
115    @Decorator
116    def func_with_self(self, arg):
117        return self.class_var
118
119#? int()
120MethodDecoratorAsClass().func_without_self('')[0]
121#? str()
122MethodDecoratorAsClass().func_without_self('')[1]
123#?
124MethodDecoratorAsClass().func_with_self(1)
125
126
127class SelfVars():
128    """Init decorator problem as an instance, #247"""
129    @Decorator
130    def __init__(self):
131        """
132        __init__ decorators should be ignored when looking up variables in the
133        class.
134        """
135        self.c = list
136
137    @Decorator
138    def shouldnt_expose_var(not_self):
139        """
140        Even though in real Python this shouldn't expose the variable, in this
141        case Jedi exposes the variable, because these kind of decorators are
142        normally descriptors, which SHOULD be exposed (at least 90%).
143        """
144        not_self.b = 1.0
145
146    def other_method(self):
147        #? float()
148        self.b
149        #? list
150        self.c
151
152# -----------------
153# not found decorators (are just ignored)
154# -----------------
155@not_found_decorator
156def just_a_func():
157    return 1
158
159#? int()
160just_a_func()
161
162#? ['__closure__']
163just_a_func.__closure__
164
165
166class JustAClass:
167    @not_found_decorator2
168    def a(self):
169        return 1
170
171#? ['__call__']
172JustAClass().a.__call__
173#? int()
174JustAClass().a()
175#? ['__call__']
176JustAClass.a.__call__
177#? int()
178JustAClass.a()
179
180# -----------------
181# illegal decorators
182# -----------------
183
184class DecoratorWithoutCall():
185    def __init__(self, func):
186        self.func = func
187
188@DecoratorWithoutCall
189def f():
190    return 1
191
192# cannot be resolved - should be ignored
193@DecoratorWithoutCall(None)
194def g():
195    return 1
196
197#?
198f()
199#? int()
200g()
201
202
203class X():
204    @str
205    def x(self):
206        pass
207
208    def y(self):
209        #? str()
210        self.x
211        #?
212        self.x()
213
214
215def decorator_var_args(function, *args):
216    return function(*args)
217
218@decorator_var_args
219def function_var_args(param):
220    return param
221
222#? int()
223function_var_args(1)
224
225# -----------------
226# method decorators
227# -----------------
228
229def dec(f):
230    def wrapper(s):
231        return f(s)
232    return wrapper
233
234class MethodDecorators():
235    _class_var = 1
236    def __init__(self):
237        self._method_var = ''
238
239    @dec
240    def constant(self):
241        return 1.0
242
243    @dec
244    def class_var(self):
245        return self._class_var
246
247    @dec
248    def method_var(self):
249        return self._method_var
250
251#? float()
252MethodDecorators().constant()
253#? int()
254MethodDecorators().class_var()
255#? str()
256MethodDecorators().method_var()
257
258
259class Base():
260    @not_existing
261    def __init__(self):
262        pass
263    @not_existing
264    def b(self):
265        return ''
266    @dec
267    def c(self):
268        return 1
269
270class MethodDecoratorDoesntExist(Base):
271    """#272 github: combination of method decorators and super()"""
272    def a(self):
273        #?
274        super().__init__()
275        #? str()
276        super().b()
277        #? int()
278        super().c()
279        #? float()
280        self.d()
281
282    @doesnt_exist
283    def d(self):
284        return 1.0
285
286# -----------------
287# others
288# -----------------
289def memoize(function):
290        def wrapper(*args):
291            if random.choice([0, 1]):
292                pass
293            else:
294                rv = function(*args)
295                return rv
296        return wrapper
297
298@memoize
299def follow_statement(stmt):
300    return stmt
301
302# here we had problems with the else clause, because the parent was not right.
303#? int()
304follow_statement(1)
305
306# -----------------
307# class decorators
308# -----------------
309
310# class decorators should just be ignored
311@should_ignore
312class A():
313    x = 3
314    def ret(self):
315        return 1
316
317#? int()
318A().ret()
319#? int()
320A().x
321
322
323# -----------------
324# On decorator completions
325# -----------------
326
327import abc
328#? ['abc']
329@abc
330
331#? ['abstractmethod']
332@abc.abstractmethod
333
334# -----------------
335# Goto
336# -----------------
337x = 1
338
339#! 5 []
340@x.foo()
341def f(): pass
342
343#! 1 ['x = 1']
344@x.foo()
345def f(): pass
346