OptionService.retrieve()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
crap 12
1
from plugin.api.core.base import Service, expose
2
from plugin.api.core.exceptions import ApiError
3
from plugin.preferences import OPTIONS_BY_KEY
4
5
import logging
6
7
log = logging.getLogger(__name__)
8
9
10
class InvalidScopeError(ApiError):
11
    code = 'option.invalid_scope'
12
    message = "Option doesn't match the current scope"
13
14
15
class InvalidUpdateError(ApiError):
16
    code = 'option.invalid_update'
17
    message = "Received an invalid update request"
18
19
20
class UnknownOptionError(ApiError):
21
    code = 'option.unknown_option'
22
    message = "Unknown option referenced"
23
24
25
class UpdateConflictError(ApiError):
26
    code = 'option.update_conflict'
27
    message = "Update conflict, options have been changed by another user"
28
29
30
class OptionService(Service):
31
    __key__ = 'option'
32
33
    @expose
34
    def list(self, account=None):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
35
        scope = 'account' if account is not None else 'server'
36
37
        def retrieve():
38
            for key, option in OPTIONS_BY_KEY.items():
0 ignored issues
show
Unused Code introduced by
The variable key seems to be unused.
Loading history...
39
                if option.scope != scope:
40
                    continue
41
42
                # Retrieve option details from database
43
                option = option.get(account)
44
45
                # Convert option to dictionary
46
                yield option.to_dict()
47
48
        return list(retrieve())
49
50
    @expose
51
    def update(self, changes, account=None):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
52
        scope = 'account' if account is not None else 'server'
53
54
        # Validate changes
55
        changed = {}
56
        ignored = []
57
58
        for key, change in changes.items():
59
            if 'from' not in change or 'to' not in change:
60
                raise InvalidUpdateError
61
62
            if key not in OPTIONS_BY_KEY:
63
                raise UnknownOptionError
64
            # Retrieve option
65
            option = OPTIONS_BY_KEY[key]
66
67
            if option.scope != scope:
68
                raise InvalidScopeError
69
70
            # Retrieve option details from database
71
            option = option.get(account)
72
73
            if option.value != change['from']:
74
                raise UpdateConflictError
75
76
            # Ensure option has changed
77
            if change['from'] == change['to']:
78
                ignored.append(key)
79
                continue
80
81
            changed[key] = change
82
83
        # Update options
84
        updated = []
85
86
        for key, change in changed.items():
87
            if key not in OPTIONS_BY_KEY:
88
                raise UnknownOptionError
89
90
            value = change['to']
91
92
            # Update value
93
            option = OPTIONS_BY_KEY[key]
94
            option.update(value, account)
95
96
            updated.append(key)
97
98
        return {
99
            'updated': updated,
100
            'ignored': ignored
101
        }
102