-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmultiplexer2.py
130 lines (96 loc) · 4.26 KB
/
multiplexer2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python3
# Copyright © 2012-13 Qtrac Ltd. All rights reserved.
# This program or module is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. It is provided for educational
# purposes and is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
import collections
import random
random.seed(917) # Not truly random for ease of regression testing
def main():
totalCounter = Counter()
carCounter = Counter("cars")
commercialCounter = Counter("trucks", "vans")
multiplexer = Multiplexer()
for eventName, callback in (("cars", carCounter),
("vans", commercialCounter), ("trucks", commercialCounter)):
multiplexer.connect(eventName, callback)
multiplexer.connect(eventName, totalCounter)
for event in generate_random_events(100):
multiplexer.send(event)
print("After 100 active events: cars={} vans={} trucks={} total={}"
.format(carCounter.cars, commercialCounter.vans,
commercialCounter.trucks, totalCounter.count))
multiplexer.state = Multiplexer.DORMANT
for event in generate_random_events(100):
multiplexer.send(event)
print("After 100 dormant events: cars={} vans={} trucks={} total={}"
.format(carCounter.cars, commercialCounter.vans,
commercialCounter.trucks, totalCounter.count))
multiplexer.state = Multiplexer.ACTIVE
for event in generate_random_events(100):
multiplexer.send(event)
print("After 100 active events: cars={} vans={} trucks={} total={}"
.format(carCounter.cars, commercialCounter.vans,
commercialCounter.trucks, totalCounter.count))
def generate_random_events(count):
vehicles = (("cars",) * 11) + (("vans",) * 3) + ("trucks",)
for _ in range(count):
yield Event(random.choice(vehicles), random.randint(1, 3))
class Counter:
def __init__(self, *names):
self.anonymous = not bool(names)
if self.anonymous:
self.count = 0
else:
for name in names:
if not name.isidentifier():
raise ValueError("names must be valid identifiers")
setattr(self, name, 0)
def __call__(self, event):
if self.anonymous:
self.count += event.count
else:
count = getattr(self, event.name)
setattr(self, event.name, count + event.count)
class Event:
def __init__(self, name, count=1):
if not name.isidentifier():
raise ValueError("names must be valid identifiers")
self.name = name
self.count = count
class Multiplexer:
ACTIVE, DORMANT = ("ACTIVE", "DORMANT")
def __init__(self):
self.callbacksForEvent = collections.defaultdict(list)
self.state = Multiplexer.ACTIVE
@property
def state(self):
return (Multiplexer.ACTIVE if self.send == self.__active_send
else Multiplexer.DORMANT)
@state.setter
def state(self, state):
if state == Multiplexer.ACTIVE:
self.connect = self.__active_connect
self.disconnect = self.__active_disconnect
self.send = self.__active_send
else:
self.connect = lambda *args: None
self.disconnect = lambda *args: None
self.send = lambda *args: None
def __active_connect(self, eventName, callback):
self.callbacksForEvent[eventName].append(callback)
def __active_disconnect(self, eventName, callback=None):
if callback is None:
del self.callbacksForEvent[eventName]
else:
self.callbacksForEvent[eventName].remove(callback)
def __active_send(self, event):
for callback in self.callbacksForEvent.get(event.name, ()):
callback(event)
if __name__ == "__main__":
main()