Passed
Push — develop ( 3c901c...de3ad7 )
by Dean
02:43
created

Engine.process()   A

Complexity

Conditions 4

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.0466
Metric Value
cc 4
dl 0
loc 9
ccs 6
cts 7
cp 0.8571
crap 4.0466
rs 9.2
1 1
from plugin.scrobbler.core.constants import IGNORED_EVENTS
2
3 1
import logging
4
5 1
log = logging.getLogger(__name__)
6
7
8 1
class Engine(object):
9 1
    handlers = {}
10
11 1
    def __init__(self):
12 1
        self.handlers = self._construct_handlers(self.handlers)
13
14 1
    def process(self, obj, events):
15 1
        for key, payload in events:
16 1
            result = self.process_one(obj, key, payload)
17
18 1
            if not result:
19
                continue
20
21 1
            for item in result:
22 1
                yield item
23
24 1
    def process_one(self, obj, key, payload):
25
        # Ensure the event hasn't been ignored
26 1
        if key in IGNORED_EVENTS:
27
            log.debug('Ignored %r event', key)
28
            return
29
30
        # Try find handler for event
31 1
        handlers = self.handlers.get(key)
32
33 1
        if not handlers:
34
            raise Exception('No handlers found for %r event' % key)
35
36
        # Run handlers until we get a result
37 1
        result = None
38
39 1
        for h in handlers:
40 1
            if not h.is_valid_source(obj.state):
41 1
                log.info('Ignoring %r event for %r, invalid state transition', key, obj)
42 1
                continue
43
44 1
            result = h.process(obj, payload)
45 1
            break
46
47 1
        if result is None:
48 1
            return
49
50 1
        for item in result:
51 1
            if not item:
52
                continue
53
54 1
            state, data = item
55
56
            # Update current state/data
57 1
            self._set_attributes(obj, **data)
58
59 1
            if state is None:
60 1
                continue
61
62
            # New event
63 1
            obj.state = state
64
65
            # Save
66 1
            obj.save()
67
68 1
            yield state, data
69
70 1
    @staticmethod
71
    def find_handlers(handlers, func):
72
        result = []
73
74
        for h in handlers:
75
            if not func(h):
76
                continue
77
78
            result.append(h)
79
80
        return result
81
82 1
    @classmethod
83
    def register(cls, kls):
84 1
        key = kls.__event__
85
86 1
        if not key:
87
            raise Exception('Unable to register %r, missing "__key__" attribute' % kls)
88
89 1
        if key not in cls.handlers:
90 1
            cls.handlers[key] = []
91
92 1
        cls.handlers[key].append(kls)
93
94 1
    @staticmethod
95
    def _construct_handlers(handlers):
96 1
        result = {}
97
98 1
        for key, classes in handlers.items():
99 1
            objects = []
100
101 1
            for kls in classes:
102 1
                objects.append(kls())
103
104 1
            result[key] = objects
105
106 1
        return result
107
108 1
    @staticmethod
109
    def _set_attributes(obj, **kwargs):
110 1
        for key, value in kwargs.items():
111 1
            if not hasattr(obj, key):
112
                raise Exception('Object %r is missing the attribute %r' % (obj, key))
113
114 1
            setattr(obj, key, value)
115
116
117 1
class SessionEngine(Engine):
118
    handlers = {}
119