Passed
Push — develop ( 6a842a...4ffa71 )
by Dean
03:09
created

Engine.process_one()   F

Complexity

Conditions 9

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

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