loading
open in
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
"""
Taken from our Complete Python Course: https://www.udemy.com/the-complete-python-course/?couponCode=REPLIT

Purely as an example, a function can have multiple decorators.

Decorators are applied from bottom to top, which means the top decorator is the first one to be evaluated when the function is executed.

In this example, we have two decorators. One checks the user's access_level, the other checks the user's username (must start with the letter 'j').
"""

import functools

# Try the various combinations below!
user = {'username': 'jose123', 'access_level': 'admin'}
# user = {'username': 'bob', 'access_level': 'admin'}
# user = {'username': 'jose123', 'access_level': 'user'}
user = {'username': 'bob', 'access_level': 'user'}


def user_name_starts_with_j(func):
    """
    This decorator only runs the function passed if the user's username starts with a j.
    """
    @functools.wraps(func)
    def secure_func(*args, **kwargs):
        if user.get('username').startswith('j'):
            return func(*args, **kwargs)
        else:
            print("User's username did not start with 'j'.")
    return secure_func


def user_has_permission(func):
    """
    This decorator only runs the function passed if the user's access_level is admin.
    """
    @functools.wraps(func)
    def secure_func(*args, **kwargs):
        if user.get('access_level') == 'admin':
            return func(*args, **kwargs)
        else:
            print("User's access_level was not 'admin'.")
    return secure_func


@user_has_permission
@user_name_starts_with_j
def double_decorator():
    return 'I ran.'

print(double_decorator())

"""
When `double_decorator()` runs, this chain of "functions" runs:

user_has_permission -> user_name_starts_with_j -> double_decorator

That is because `user_name_starts_with_j` is the first decorator to be applied. It replaces `double_decorator` by the function it returns.

Then, `user_has_permission` is applied—and it replaces the function the other decorator returned by the function it returns.
"""
Python 3.6.1 (default, Dec 2015, 13:05:11) [GCC 4.8.2] on linux