require_args()   F
last analyzed

Complexity

Conditions 10

Size

Total Lines 38

Duplication

Lines 1
Ratio 2.63 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 10
c 3
b 0
f 0
dl 1
loc 38
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like require_args() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""App view decorators."""
2
3
from functools import wraps
4
5
from flask import (
6
    abort,
7
    request,
8 View Code Duplication
)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
9
10
11
def require_headers(headers=[]):
12
    """Check for required headers in a view.
13
14
    @require_headers(headers=['X-Foo'])
15
    def view():
16
        pass
17
    """
18
    def outer(func, *args, **kwargs):
19
        @wraps(func)
20
        def inner(*args, **kwargs):
21
            if headers:
22
                s1, s2 = set(headers), set([h[0] for h in request.headers])
23
                matches = s1.intersection(s2)
24
                diff = s1.difference(s2)
25
                if len(s1) != len(matches):
26
                    raise ValueError(
27
                        'Missing required header(s): {}'.format(list(diff)))
28
            return func(*args, **kwargs)
29
        return inner
30 View Code Duplication
    return outer
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
31
32
33
def require_cookies(cookies=[]):
34
    """Check for required cookies in a view.
35
36
    @require_cookies(cookies=['csrftoken', 'session'])
37
    def view():
38
        pass
39
    """
40
    def outer(func, *args, **kwargs):
41
        @wraps(func)
42
        def inner(*args, **kwargs):
43
            if cookies:
44
                s1 = set(cookies)
45
                s2 = set([k for k, v in request.cookies.items()])
46
                matches = s1.intersection(s2)
47
                diff = s1.difference(s2)
48
                if len(s1) != len(matches):
49
                    raise ValueError(
50
                        'Missing required cookie(s): {}'.format(list(diff)))
51
            return func(*args, **kwargs)
52
        return inner
53
    return outer
54
55
56
def require_args(params=[]):
57
    """Check for required args (and values) in a view.
58
59
    @require_args(params=['paginate'])
60
    def view():
61
        pass
62
63
    or, if you want to check both key and value:
64
65
    @require_args(params={'paginate': True})
66
    def view():
67
        pass
68
    """
69
    def outer(func, *args, **kwargs):
70
        @wraps(func)
71
        def inner(*args, **kwargs):
72
            if params:
73
                if isinstance(params, list):
74
                    s1 = set(params)
75
                    s2 = set([k for k, v in request.args.items()])
76
                    matches = s1.intersection(s2)
77
                    diff = s1.difference(s2)
78
                    if len(s1) != len(matches):
79
                        raise ValueError(
80
                            'Missing required arg(s): {}'.format(list(diff)))
81
                else:
82
                    for param, val in params.items():
83
                        arg = request.args.get(param)
84
                        if arg is None:
85
                            raise ValueError(
86
                                'Missing param `{}`'.format(param))
87
                        if arg != val:
88
                            raise ValueError(
89
                                'Invalid value `{}` '
90
                                'for param {}.'.format(arg, param))
91
            return func(*args, **kwargs)
92
        return inner
93 View Code Duplication
    return outer
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
94
95
96
def require_form(values=[]):
97
    """Check for required form values.
98
99
    @require_form(values=['name', 'address'])
100
    def view():
101
        pass
102
    """
103
    def outer(func, *args, **kwargs):
104
        @wraps(func)
105
        def inner(*args, **kwargs):
106
            if request.method == 'POST':
107
                if values:
108
                    s1 = set(values)
109
                    s2 = set([k for k, v in request.form.items()])
110
                    matches = s1.intersection(s2)
111
                    diff = s1.difference(s2)
112
                    if len(s1) != len(matches):
113
                        raise ValueError(
114
                            'Missing required form '
115
                            'field(s): {}'.format(list(diff)))
116
            return func(*args, **kwargs)
117
        return inner
118
    return outer
119
120
121
def xhr_only(status_code=415):
122
    """Asssure request is XHR only.
123
124
    @xhr_only()
125
    def view():
126
        pass
127
    """
128
    def outer(func, *args, **kwargs):
129
        @wraps(func)
130
        def inner(*args, **kwargs):
131
            if not request.is_xhr:
132
                # Default to status "unsupported media type".
133
                abort(status_code)
134
            return func(*args, **kwargs)
135
        return inner
136
    return outer
137