Completed
Push — appveyor ( 280314...2c0e2c )
by Konstantinos
02:09
created

so_magic.utils.notification   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 42
dl 0
loc 82
rs 10
c 0
b 0
f 0
wmc 13

11 Methods

Rating   Name   Duplication   Size   Complexity  
A Subject.detach() 0 2 1
A SubjectInterface.notify() 0 4 1
A SubjectInterface.detach() 0 4 1
A SubjectInterface.attach() 0 4 1
A Subject.add() 0 2 1
A ObserverInterface.update() 0 4 1
A Subject.attach() 0 2 1
A Subject.state() 0 3 1
A Subject.__new__() 0 5 1
A Subject.notify() 0 4 2
A Observer.update() 0 2 1
1
from abc import ABC, abstractmethod
2
from typing import List
3
4
__all__ = ['Subject', 'Observer']
5
6
7
class ObserverInterface(ABC):
8
    """The Observer interface declares the update method, used by subjects. Whenever an 'event' happens the update
9
    callback executes."""
10
    @abstractmethod
11
    def update(self, *args, **kwargs) -> None:
12
        """Receive update from subject."""
13
        raise NotImplementedError
14
15
16
class SubjectInterface(ABC):
17
    """The Subject interface declares a set of methods for managing subscribers.
18
    Use it to model objects as "subjects of observations" (notify observers/listeners/subscribers).
19
    """
20
21
    @abstractmethod
22
    def attach(self, observer: ObserverInterface) -> None:
23
        """Attach an observer to the subject."""
24
        raise NotImplementedError
25
26
    @abstractmethod
27
    def detach(self, observer: ObserverInterface) -> None:
28
        """Detach an observer from the subject."""
29
        raise NotImplementedError
30
31
    @abstractmethod
32
    def notify(self) -> None:
33
        """Notify all observers about an event."""
34
        raise NotImplementedError
35
36
37
class Subject(SubjectInterface):
38
    """The Subject owns some important state and notifies observers when the state changes. Both the _state and _observers
39
    attributes can be overriden to accomodate for more complex scenarios."""
40
    def __new__(cls, *args, **kwargs):
41
        self_object = super().__new__(cls)
42
        self_object._observers = []  # type=List[ObserverInterface]
43
        self_object._state = None
44
        return self_object
45
46
    def add(self, *observers):
47
        self._observers.extend([_ for _ in observers])
48
    """
49
    List of subscribers. In real life, the list of subscribers can be stored
50
    more comprehensively (categorized by event type, etc.).
51
    """
52
    @property
53
    def state(self):
54
        return self._state
55
56
    @state.setter
57
    def state(self, state):
58
        self._state = state
59
60
    def attach(self, observer: ObserverInterface) -> None:
61
        self._observers.append(observer)
62
63
    def detach(self, observer: ObserverInterface) -> None:
64
        self._observers.remove(observer)
65
66
    """
67
    The subscription management methods.
68
    """
69
70
    def notify(self) -> None:
71
        """Trigger an update in each subscriber/observer."""
72
        for observer in self._observers:
73
            observer.update(self)
74
75
"""
76
Concrete Observers react to the updates issued by the Subject they had been
77
attached to.
78
"""
79
class Observer(ObserverInterface):
80
    def update(self, subject: Subject) -> None:
81
        pass
82