busline 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- busline/client/client.py +27 -0
- {eventbus_client → busline/client}/eventbus_connector.py +5 -10
- busline/client/multiclient.py +41 -0
- busline/client/publisher/publisher.py +60 -0
- busline/client/pubsub_client.py +128 -0
- busline/client/subscriber/event_handler/closure_event_handler.py +18 -0
- busline/client/subscriber/event_handler/event_handler.py +15 -0
- busline/client/subscriber/event_handler/multi_handler.py +30 -0
- busline/client/subscriber/subscriber.py +109 -0
- busline/client/subscriber/topic_subscriber.py +79 -0
- busline/event/event.py +47 -0
- busline/event/registry.py +67 -0
- busline/event/test.py +47 -0
- busline/exceptions.py +8 -0
- busline/local/__init__.py +3 -0
- busline/local/eventbus/__init__.py +0 -0
- busline/local/eventbus/async_local_eventbus.py +26 -0
- busline/local/eventbus/eventbus.py +86 -0
- busline/local/eventbus/local_eventbus.py +23 -0
- busline/local/local_pubsub_client.py +54 -0
- busline/local/publisher/__init__.py +0 -0
- busline/local/publisher/local_publisher.py +38 -0
- busline/local/subscriber/__init__.py +0 -0
- busline/local/subscriber/local_subscriber.py +43 -0
- busline/local/test.py +156 -0
- busline-0.5.0.dist-info/METADATA +215 -0
- busline-0.5.0.dist-info/RECORD +36 -0
- {busline-0.3.0.dist-info → busline-0.5.0.dist-info}/WHEEL +1 -1
- busline-0.5.0.dist-info/top_level.txt +1 -0
- busline-0.3.0.dist-info/METADATA +0 -104
- busline-0.3.0.dist-info/RECORD +0 -30
- busline-0.3.0.dist-info/top_level.txt +0 -4
- event/event.py +0 -25
- event/event_content.py +0 -18
- event/event_metadata.py +0 -26
- eventbus/async_local_eventbus.py +0 -32
- eventbus/eventbus.py +0 -112
- eventbus/exceptions.py +0 -2
- eventbus/queued_local_eventbus.py +0 -50
- eventbus/topic.py +0 -35
- eventbus_client/eventbus_client.py +0 -99
- eventbus_client/exceptions.py +0 -4
- eventbus_client/local_eventbus_client.py +0 -25
- eventbus_client/publisher/local_eventbus_publisher.py +0 -35
- eventbus_client/publisher/publisher.py +0 -59
- eventbus_client/subscriber/closure_event_listener.py +0 -19
- eventbus_client/subscriber/event_listener.py +0 -15
- eventbus_client/subscriber/local_eventbus_closure_subscriber.py +0 -17
- eventbus_client/subscriber/local_eventbus_subscriber.py +0 -40
- eventbus_client/subscriber/subscriber.py +0 -93
- /__init__.py → /busline/__init__.py +0 -0
- {event → busline/client}/__init__.py +0 -0
- {eventbus → busline/client/publisher}/__init__.py +0 -0
- {eventbus_client → busline/client/subscriber}/__init__.py +0 -0
- {eventbus_client/publisher → busline/client/subscriber/event_handler}/__init__.py +0 -0
- {eventbus_client/subscriber → busline/event}/__init__.py +0 -0
- {busline-0.3.0.dist-info → busline-0.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: busline
|
3
|
+
Version: 0.5.0
|
4
|
+
Summary: Agnostic eventbus for Python
|
5
|
+
Author-email: Nicola Ricciardi <ricciardincl@gmail.com>
|
6
|
+
Project-URL: Homepage, https://github.com/nricciardi/py-busline
|
7
|
+
Project-URL: Issues, https://github.com/nricciardi/py-busline/issues
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Requires-Python: >=3.8
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
License-File: LICENSE
|
14
|
+
Dynamic: license-file
|
15
|
+
|
16
|
+
from busline.local.subscriber.local_subscriber import LocalEventBusSubscriberfrom busline.local.eventbus.local_eventbus import LocalEventBus
|
17
|
+
|
18
|
+
# Busline for Python
|
19
|
+
|
20
|
+
Agnostic eventbus for Python.
|
21
|
+
|
22
|
+
Official eventbus library for [Orbitalis](https://github.com/orbitalis-framework/py-orbitalis)
|
23
|
+
|
24
|
+
## Get Start
|
25
|
+
|
26
|
+
### Local EventBus
|
27
|
+
|
28
|
+
#### Using Publisher/Subscriber
|
29
|
+
|
30
|
+
```python
|
31
|
+
local_eventbus_instance1 = LocalEventBus() # singleton
|
32
|
+
local_eventbus_instance2 = LocalEventBus() # singleton
|
33
|
+
|
34
|
+
subscriber = LocalEventBusSubscriber(
|
35
|
+
eventbus=local_eventbus_instance1,
|
36
|
+
fallback_event_handler=ClosureEventHandler(lambda t, e: ...)
|
37
|
+
)
|
38
|
+
publisher = LocalEventBusPublisher(eventbus=local_eventbus_instance2)
|
39
|
+
|
40
|
+
await subscriber.connect()
|
41
|
+
await publisher.connect()
|
42
|
+
|
43
|
+
await subscriber.subscribe("topic-name")
|
44
|
+
|
45
|
+
await publisher.publish("topic-name", Event()) # publish empty event
|
46
|
+
|
47
|
+
# ...subscriber receives Event() thanks to singleton LocalEventBus()
|
48
|
+
|
49
|
+
await subscriber.disconnect()
|
50
|
+
await publisher.disconnect()
|
51
|
+
```
|
52
|
+
|
53
|
+
#### Using EventBusClient
|
54
|
+
|
55
|
+
```python
|
56
|
+
client = LocalPubSubClientBuilder()\
|
57
|
+
.with_default_publisher()\
|
58
|
+
.with_closure_subscriber(lambda t, e: ...)\
|
59
|
+
.build()
|
60
|
+
|
61
|
+
# NOTE: both publisher and subscriber will use singleton local eventbus (default)
|
62
|
+
|
63
|
+
await client.connect()
|
64
|
+
|
65
|
+
await client.subscribe("topic-name")
|
66
|
+
|
67
|
+
await client.publish("topic-name", Event()) # publish empty event
|
68
|
+
|
69
|
+
# ...client receives Event()
|
70
|
+
|
71
|
+
await client.disconnect()
|
72
|
+
```
|
73
|
+
|
74
|
+
#### MultiClient
|
75
|
+
|
76
|
+
```python
|
77
|
+
local_eventbus_instance1 = AsyncLocalEventBus() # not singleton
|
78
|
+
local_eventbus_instance2 = AsyncLocalEventBus() # not singleton
|
79
|
+
|
80
|
+
client1 = LocalPubSubClientBuilder(local_eventbus_instance1)\
|
81
|
+
.with_default_publisher()\
|
82
|
+
.with_closure_subscriber(lambda t, e: ...)\
|
83
|
+
.build()
|
84
|
+
|
85
|
+
# NOTE: client1 pub/sub use `local_eventbus_instance1`
|
86
|
+
|
87
|
+
client2 = LocalPubSubClientBuilder(local_eventbus_instance2)\
|
88
|
+
.with_default_publisher()\
|
89
|
+
.with_closure_subscriber(lambda t, e: ...)\
|
90
|
+
.build()
|
91
|
+
|
92
|
+
# NOTE: client2 pub/sub use `local_eventbus_instance2`
|
93
|
+
|
94
|
+
multi_client = EventBusMultiClient([
|
95
|
+
client1,
|
96
|
+
client2
|
97
|
+
])
|
98
|
+
|
99
|
+
await multi_client.connect()
|
100
|
+
|
101
|
+
await multi_client.subscribe("topic-name", handler=ClosureEventHandler(lambda t, e: ...))
|
102
|
+
|
103
|
+
await multi_client.publish("topic-name", Event())
|
104
|
+
|
105
|
+
# ...both clients receive Event() and handle it using `on_event_callback`
|
106
|
+
|
107
|
+
await multi_client.disconnect()
|
108
|
+
```
|
109
|
+
|
110
|
+
#### Specifying EventBus
|
111
|
+
|
112
|
+
Local eventbuses use an internal implemented `EventBus`, this sort of architecture is not required in other scenarios such
|
113
|
+
as MQTT, because the "eventbus" is the broken.
|
114
|
+
|
115
|
+
Anyway, you may want to specify what `EventBus` instance your pub/sub components should use:
|
116
|
+
|
117
|
+
```python
|
118
|
+
local_eventbus_instance = AsyncLocalEventBus()
|
119
|
+
|
120
|
+
subscriber = LocalEventBusClosureSubscriber(callback, eventbus_instance=local_eventbus_instance)
|
121
|
+
publisher = LocalEventBusPublisher(eventbus_instance=local_eventbus_instance2)
|
122
|
+
```
|
123
|
+
|
124
|
+
### EventRegistry
|
125
|
+
|
126
|
+
In order to help `event_type` management, a basic `EventRegistry` is provided to auto-build right inherited class of `Event`:
|
127
|
+
|
128
|
+
```python
|
129
|
+
class Event1(Event):
|
130
|
+
def my_value1(self) -> int:
|
131
|
+
return self.content
|
132
|
+
|
133
|
+
class Event2(Event):
|
134
|
+
def my_value2(self) -> int:
|
135
|
+
return self.content
|
136
|
+
|
137
|
+
|
138
|
+
event_registry = EventRegistry() # singleton
|
139
|
+
|
140
|
+
event_registry.register("event1", Event1)
|
141
|
+
event_registry.register("event2", Event2)
|
142
|
+
|
143
|
+
generic_event1 = Event(content=1, event_type="event1")
|
144
|
+
generic_event2 = Event(content=2, event_type="event2")
|
145
|
+
generic_unknown_event = Event(content=2, event_type="unknown")
|
146
|
+
|
147
|
+
# first approach
|
148
|
+
event1_class = event_registry.retrive_class(generic_event1)
|
149
|
+
event1_class: Type[Event1] = event1_class
|
150
|
+
event1 = event1_class.from_event(generic_event1)
|
151
|
+
|
152
|
+
# second approach
|
153
|
+
event2: Event2 = event_registry.convert(generic_event2)
|
154
|
+
```
|
155
|
+
|
156
|
+
### Create Agnostic EventBus
|
157
|
+
|
158
|
+
Implement business logic of your `Publisher` and `Subscriber` and... done. Nothing more.
|
159
|
+
|
160
|
+
```python
|
161
|
+
class YourEventBusPublisher(Publisher):
|
162
|
+
|
163
|
+
async def _internal_publish(self, topic_name: str, event: Event, **kwargs):
|
164
|
+
pass # send events to your eventbus (maybe in cloud?)
|
165
|
+
```
|
166
|
+
|
167
|
+
```python
|
168
|
+
class YourEventBusSubscriber(Subscriber):
|
169
|
+
|
170
|
+
async def on_event(self, topic_name: str, event: Event, **kwargs):
|
171
|
+
pass # receive your events
|
172
|
+
```
|
173
|
+
|
174
|
+
You could create a client to allow components to use it instead of become a publisher or subscriber.
|
175
|
+
|
176
|
+
```python
|
177
|
+
subscriber = YourEventBusSubscriber(...)
|
178
|
+
publisher = YourEventBusPublisher(...)
|
179
|
+
|
180
|
+
client = PubSubClient(publisher, subscriber)
|
181
|
+
```
|
182
|
+
|
183
|
+
|
184
|
+
## Subscriber
|
185
|
+
|
186
|
+
`Subscriber` is the component which receives events. It is a `EventHandler`, therefore it has `on_event` method in which
|
187
|
+
every event (and related topic) is passed.
|
188
|
+
|
189
|
+
### TopicSubscriber
|
190
|
+
|
191
|
+
`TopicSubscriber` is an enhanced subscriber which manages an handler for each topic. We can specify a _fallback handler_,
|
192
|
+
which is run if no handler is spefied for a subscribed topic.
|
193
|
+
|
194
|
+
If the subscriber is not subscribed to a topic, fallback handler is not called.
|
195
|
+
|
196
|
+
A local implementation is already provided:
|
197
|
+
|
198
|
+
```python
|
199
|
+
subscriber = LocalEventBusSubscriber(fallback_event_handler=...)
|
200
|
+
|
201
|
+
await subscriber.subscribe("t1")
|
202
|
+
await subscriber.subscribe("t2", handler=...)
|
203
|
+
```
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
busline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
busline/exceptions.py,sha256=T83gWMYpQor7DQZsg-UinsxJ9Xe2PldOYeA7mBjAMDw,144
|
3
|
+
busline/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
busline/client/client.py,sha256=4IGMJXp_46cPOXJaMeix45rUkxRNlSFJXch2hLy0C70,553
|
5
|
+
busline/client/eventbus_connector.py,sha256=V3D5f4bddlQW1oiZzjvNTsVa0yIHAjYHG03YV3zwz5c,596
|
6
|
+
busline/client/multiclient.py,sha256=QnKK8ShrwbuS1fnsXVhRgMnBzIbPgnDkBPGjswDilR8,1251
|
7
|
+
busline/client/pubsub_client.py,sha256=QzzJf_Uap9d1Y18PB_rZwU4fNOtSnG3MmFUykxCGt2g,3449
|
8
|
+
busline/client/publisher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
busline/client/publisher/publisher.py,sha256=FUht2eeV25lrQzgHxB0OjijEGUiTSan8AEjb-IqYjX8,1521
|
10
|
+
busline/client/subscriber/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
+
busline/client/subscriber/subscriber.py,sha256=QHMEi6PbzoiY6SywVGPjOBUL86PD3OYRVH6fCTeZPfw,2713
|
12
|
+
busline/client/subscriber/topic_subscriber.py,sha256=uUdgmwkGSn0A1aM81CxuitmKLxNL3QMxAlO0AkD1xE4,3157
|
13
|
+
busline/client/subscriber/event_handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
busline/client/subscriber/event_handler/closure_event_handler.py,sha256=YvgHEDgsWkW5shZ4r11pPSXnPotcXcr56xQQJDnkmxg,497
|
15
|
+
busline/client/subscriber/event_handler/event_handler.py,sha256=az-zyJpZykowWN9M0x7PzO1qsUUOgVcEqi15crX8txc,296
|
16
|
+
busline/client/subscriber/event_handler/multi_handler.py,sha256=bU2bEfIlOcSm6vGf_3ewDQMja6lZFsfRJ_7pOq159Qk,825
|
17
|
+
busline/event/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
busline/event/event.py,sha256=a1-COH-0hOwFQnbFpwWWJHpr0GqwsyV0JUgqPiI4iRs,1308
|
19
|
+
busline/event/registry.py,sha256=2Yr-UE7rOuJGEawsybfKiK1HZUNxyDovlaXJh0tdct8,1709
|
20
|
+
busline/event/test.py,sha256=SkPH0IB3x5WbJCv6dr_wP_dP8_-mQRz9MRWnipHzBDY,1361
|
21
|
+
busline/local/__init__.py,sha256=th_6FPU7d8l4CQ_Rp21FM7NCLMFBWkt0Cyy6mCMJeUY,125
|
22
|
+
busline/local/local_pubsub_client.py,sha256=F8IK83PgmRUV1pBqCv6BhF0YQn_B9nn18DmSVTFdwnk,1698
|
23
|
+
busline/local/test.py,sha256=HxJBNWBqY-0L7salT_XzILF2i6WMCitnGO8LwQx6D8o,4438
|
24
|
+
busline/local/eventbus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
busline/local/eventbus/async_local_eventbus.py,sha256=aettYF1W7G3agKVneGMU6kBr_-Gy2M10Lx40vQ2k66M,649
|
26
|
+
busline/local/eventbus/eventbus.py,sha256=BH2zzoEeeqveqcgfrNXSsuE5kBGSL2LJcjOwuEtPEmI,2437
|
27
|
+
busline/local/eventbus/local_eventbus.py,sha256=2wK2NMlWXm_9CTYR39y7Z40C8yOQ8RdViAQOnYS5g7M,611
|
28
|
+
busline/local/publisher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
|
+
busline/local/publisher/local_publisher.py,sha256=FngthjSMZyswYK2Ka1LHrTqFkZ6yvGUjn0COGEzI0hI,1076
|
30
|
+
busline/local/subscriber/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
busline/local/subscriber/local_subscriber.py,sha256=tWQ5YCRH78wiFlwO6I_dSAvCyhkQLox0GhoeVPKWxro,1237
|
32
|
+
busline-0.5.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
33
|
+
busline-0.5.0.dist-info/METADATA,sha256=_8Cwu2T1kNnYJK_nV9fVMPScbxnzHB8hPNboQKawSUE,5904
|
34
|
+
busline-0.5.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
35
|
+
busline-0.5.0.dist-info/top_level.txt,sha256=bZY0fK2wgNEI5igR7DBF3CyXHGkzujGvmoqdSzG6Zp0,8
|
36
|
+
busline-0.5.0.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
busline
|
busline-0.3.0.dist-info/METADATA
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: busline
|
3
|
-
Version: 0.3.0
|
4
|
-
Summary: Agnostic eventbus for Python
|
5
|
-
Author-email: Nicola Ricciardi <ricciardincl@gmail.com>
|
6
|
-
Project-URL: Homepage, https://github.com/nricciardi/py-busline
|
7
|
-
Project-URL: Issues, https://github.com/nricciardi/py-busline/issues
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
10
|
-
Classifier: Operating System :: OS Independent
|
11
|
-
Requires-Python: >=3.8
|
12
|
-
Description-Content-Type: text/markdown
|
13
|
-
License-File: LICENSE
|
14
|
-
|
15
|
-
# Busline for Python
|
16
|
-
|
17
|
-
Agnostic eventbus for Python.
|
18
|
-
|
19
|
-
Official eventbus library for [Orbitalis](https://github.com/nricciardi/orbitalis)
|
20
|
-
|
21
|
-
## Local EventBus
|
22
|
-
|
23
|
-
### Using Publisher/Subscriber
|
24
|
-
|
25
|
-
```python
|
26
|
-
from src.eventbus.async_local_eventbus import AsyncLocalEventBus
|
27
|
-
from src.eventbus_client.publisher.local_eventbus_publisher import LocalEventBusPublisher
|
28
|
-
from src.event.event import Event
|
29
|
-
from src.eventbus_client.subscriber.local_eventbus_closure_subscriber import LocalEventBusClosureSubscriber
|
30
|
-
|
31
|
-
|
32
|
-
local_eventbus_instance = AsyncLocalEventBus() # singleton
|
33
|
-
|
34
|
-
def callback(topic_name: str, event: Event):
|
35
|
-
print(event)
|
36
|
-
|
37
|
-
subscriber = LocalEventBusClosureSubscriber(local_eventbus_instance, callback)
|
38
|
-
publisher = LocalEventBusPublisher(local_eventbus_instance)
|
39
|
-
|
40
|
-
await subscriber.subscribe("test-topic")
|
41
|
-
|
42
|
-
await publisher.publish("test-topic", Event()) # publish empty event
|
43
|
-
```
|
44
|
-
|
45
|
-
### Using EventBusClient
|
46
|
-
|
47
|
-
```python
|
48
|
-
from src.event.event import Event
|
49
|
-
from src.eventbus_client.local_eventbus_client import LocalEventBusClient
|
50
|
-
|
51
|
-
def callback(topic_name: str, event: Event):
|
52
|
-
print(event)
|
53
|
-
|
54
|
-
client = LocalEventBusClient(callback)
|
55
|
-
|
56
|
-
await client.subscribe("test")
|
57
|
-
|
58
|
-
await client.publish("test", Event())
|
59
|
-
```
|
60
|
-
|
61
|
-
|
62
|
-
## Create Agnostic EventBus
|
63
|
-
|
64
|
-
Implement business logic of your `Publisher` and `Subscriber` and... done. Nothing more.
|
65
|
-
|
66
|
-
```python
|
67
|
-
from src.event.event import Event
|
68
|
-
from src.eventbus_client.publisher.publisher import Publisher
|
69
|
-
|
70
|
-
class YourEventBusPublisher(Publisher):
|
71
|
-
|
72
|
-
async def _internal_publish(self, topic_name: str, event: Event, **kwargs):
|
73
|
-
pass # send events to your eventbus (maybe in cloud?)
|
74
|
-
```
|
75
|
-
|
76
|
-
```python
|
77
|
-
from src.eventbus_client.subscriber.subscriber import Subscriber
|
78
|
-
from src.event.event import Event
|
79
|
-
|
80
|
-
class YourEventBusSubscriber(Subscriber):
|
81
|
-
|
82
|
-
async def on_event(self, topic_name: str, event: Event, **kwargs):
|
83
|
-
pass # receive your events
|
84
|
-
```
|
85
|
-
|
86
|
-
You could create a client to allow components to use it instead of become a publisher or subscriber.
|
87
|
-
|
88
|
-
```python
|
89
|
-
from src.eventbus_client.eventbus_client import EventBusClient
|
90
|
-
from src.event.event import Event
|
91
|
-
|
92
|
-
def client_callback(topic_name: str, e: Event):
|
93
|
-
print(e)
|
94
|
-
|
95
|
-
subscriber = YourEventBusSubscriber(...)
|
96
|
-
publisher = YourEventBusPublisher(...)
|
97
|
-
|
98
|
-
client = EventBusClient(publisher, subscriber, ClosureEventListener(client_callback))
|
99
|
-
```
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
busline-0.3.0.dist-info/RECORD
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
event/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
event/event.py,sha256=X5HSO6SDoxUFrxMJ9gzll2lr_M5li_09o2we5hMLbUI,587
|
4
|
-
event/event_content.py,sha256=tPvltxfs66yRmUppHvdw5ThYR_K2WitvE5sLybg6vZE,341
|
5
|
-
event/event_metadata.py,sha256=7aaSG4Z9uQzJKRe7Jz8zD6jo6WEo3PORNbJA_RElp8I,556
|
6
|
-
eventbus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
eventbus/async_local_eventbus.py,sha256=cRAnUPfb22q9CzNS-48aGIdxhEgwg-nGHaAhvaeVIgI,764
|
8
|
-
eventbus/eventbus.py,sha256=INT1DYL_rlyViLTGfEpPisDFp8JUuNJ55ZOuQUjh2E4,2981
|
9
|
-
eventbus/exceptions.py,sha256=sjWa3Eyeqyci2yVWO9jSlnaZggM3SFDbTKzMtdBX1-E,40
|
10
|
-
eventbus/queued_local_eventbus.py,sha256=7Gog7Xy6ytBTkXvUKXsSqXSkarZtiCvGg-qdiQPAQDo,1368
|
11
|
-
eventbus/topic.py,sha256=rzbdYrv0YLbC6CDoFGhbc8dOVc19OHCQknkTP4fZHh4,950
|
12
|
-
eventbus_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
eventbus_client/eventbus_client.py,sha256=1n53QBf-lvoe_lJhg7gttpOWnl3db9WoKRoJj7z7dBM,3079
|
14
|
-
eventbus_client/eventbus_connector.py,sha256=zys73X8ul1UHyJHbIcmXBLucqCQhnLLVj9xDOVc1arU,702
|
15
|
-
eventbus_client/exceptions.py,sha256=gm7oZsXHlymheYDZb209T4FqeZN9Saft0Xklk4rOg54,55
|
16
|
-
eventbus_client/local_eventbus_client.py,sha256=gep5sO6Oek8y-wQEe-VMlbrboAlUI4QlrNihROY9A5E,867
|
17
|
-
eventbus_client/publisher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
eventbus_client/publisher/local_eventbus_publisher.py,sha256=fizpHwZGEDuZJHMbBC76jzzcCzbvrp1oIXYKb7KsXi4,1107
|
19
|
-
eventbus_client/publisher/publisher.py,sha256=QzaXlKwlURA4UXUgbkyKwUxaKWbayt5tYNGHy5TtI_Q,1536
|
20
|
-
eventbus_client/subscriber/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
eventbus_client/subscriber/closure_event_listener.py,sha256=1vou3bedIIeuDzdYRJeoEvdNMZtJP_SgnxLboTgFiEg,599
|
22
|
-
eventbus_client/subscriber/event_listener.py,sha256=nBnPA-Jt5_L0qCV-IaTfmr1RTnKe_zMRF3Ce8ciX-4M,327
|
23
|
-
eventbus_client/subscriber/local_eventbus_closure_subscriber.py,sha256=7KPlkMXqwKMBgPhp4U6xkca-oGErdO8ch3W7Ab0XpbI,748
|
24
|
-
eventbus_client/subscriber/local_eventbus_subscriber.py,sha256=f7Vf4IpLeQ2IaMd9kwFUGT7hXrp1AeKHintyQONJ7YE,1331
|
25
|
-
eventbus_client/subscriber/subscriber.py,sha256=MMw_iOVEflBTLiYuEbS--hZ_fOJ3Y82wk6N0BOJXNVA,2246
|
26
|
-
busline-0.3.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
27
|
-
busline-0.3.0.dist-info/METADATA,sha256=EzrREZWnK4NQ3ycylqWGSeNPwlRDfaOiijgm_nxiSX8,2891
|
28
|
-
busline-0.3.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
29
|
-
busline-0.3.0.dist-info/top_level.txt,sha256=tVHbqJlz1BKM3vq9VKiyjRf2irKCgXPV22iae_fcMss,40
|
30
|
-
busline-0.3.0.dist-info/RECORD,,
|
event/event.py
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
import uuid
|
2
|
-
from src.event.event_content import EventContent
|
3
|
-
from src.event.event_metadata import EventMetadata
|
4
|
-
|
5
|
-
|
6
|
-
class Event:
|
7
|
-
|
8
|
-
def __init__(self, content: EventContent = None, metadata: EventMetadata = EventMetadata()):
|
9
|
-
|
10
|
-
self._identifier = str(uuid.uuid4())
|
11
|
-
self._content = content
|
12
|
-
self._metadata = metadata
|
13
|
-
|
14
|
-
|
15
|
-
@property
|
16
|
-
def identifier(self) -> str:
|
17
|
-
return self._identifier
|
18
|
-
|
19
|
-
@property
|
20
|
-
def content(self) -> EventContent:
|
21
|
-
return self._content
|
22
|
-
|
23
|
-
@property
|
24
|
-
def metadata(self) -> EventMetadata:
|
25
|
-
return self._metadata
|
event/event_content.py
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
|
3
|
-
|
4
|
-
class EventContent:
|
5
|
-
|
6
|
-
def __init__(self, content: Any, content_type: str):
|
7
|
-
|
8
|
-
self.__content = content
|
9
|
-
self.__content_type = content_type
|
10
|
-
|
11
|
-
|
12
|
-
@property
|
13
|
-
def content(self) -> Any:
|
14
|
-
return self.__content
|
15
|
-
|
16
|
-
@property
|
17
|
-
def content_type(self) -> str:
|
18
|
-
return self.__content_type
|
event/event_metadata.py
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
from datetime import timezone
|
2
|
-
import datetime
|
3
|
-
|
4
|
-
|
5
|
-
def utc_timestamp() -> float:
|
6
|
-
dt = datetime.datetime.now(timezone.utc)
|
7
|
-
|
8
|
-
utc_time = dt.replace(tzinfo=timezone.utc)
|
9
|
-
utc_timestamp = utc_time.timestamp()
|
10
|
-
|
11
|
-
return utc_timestamp
|
12
|
-
|
13
|
-
|
14
|
-
class EventMetadata:
|
15
|
-
|
16
|
-
def __init__(self, timestamp: float = utc_timestamp(), **extra: dict):
|
17
|
-
self.__timestamp = timestamp
|
18
|
-
self.__extra = extra
|
19
|
-
|
20
|
-
@property
|
21
|
-
def timestamp(self) -> float:
|
22
|
-
return self.__timestamp
|
23
|
-
|
24
|
-
@property
|
25
|
-
def extra(self) -> dict:
|
26
|
-
return self.__extra
|
eventbus/async_local_eventbus.py
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import asyncio
|
3
|
-
|
4
|
-
from src.event.event import Event
|
5
|
-
from src.eventbus.eventbus import EventBus
|
6
|
-
|
7
|
-
|
8
|
-
class AsyncLocalEventBus(EventBus):
|
9
|
-
"""
|
10
|
-
Async local eventbus (singleton)
|
11
|
-
|
12
|
-
Author: Nicola Ricciardi
|
13
|
-
"""
|
14
|
-
|
15
|
-
async def put_event(self, topic_name: str, event: Event):
|
16
|
-
|
17
|
-
topic_subscriptions = self.subscriptions.get(topic_name, [])
|
18
|
-
|
19
|
-
logging.debug(f"new event {event} on topic {topic_name}, notify subscribers: {topic_subscriptions}")
|
20
|
-
|
21
|
-
if len(topic_subscriptions) == 0:
|
22
|
-
return
|
23
|
-
|
24
|
-
tasks = []
|
25
|
-
|
26
|
-
for subscriber in topic_subscriptions:
|
27
|
-
task = asyncio.create_task(subscriber.on_event(topic_name, event))
|
28
|
-
tasks.append(task)
|
29
|
-
|
30
|
-
await asyncio.gather(*tasks)
|
31
|
-
|
32
|
-
|
eventbus/eventbus.py
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import Dict, List
|
3
|
-
from src.eventbus.exceptions import TopicNotFound
|
4
|
-
from src.eventbus_client.subscriber.subscriber import Subscriber
|
5
|
-
from src.eventbus.topic import Topic
|
6
|
-
from src.event.event import Event
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class EventBus(ABC):
|
11
|
-
"""
|
12
|
-
Abstract class used as base for new eventbus implemented in local projects.
|
13
|
-
|
14
|
-
Eventbus are *singleton*
|
15
|
-
|
16
|
-
Author: Nicola Ricciardi
|
17
|
-
"""
|
18
|
-
|
19
|
-
# === SINGLETON pattern ===
|
20
|
-
_instance = None
|
21
|
-
|
22
|
-
def __new__(cls, *args, **kwargs):
|
23
|
-
if cls._instance is None:
|
24
|
-
cls._instance = super().__new__(cls)
|
25
|
-
|
26
|
-
return cls._instance
|
27
|
-
|
28
|
-
def __init__(self):
|
29
|
-
|
30
|
-
self.__subscriptions = None
|
31
|
-
self.__topics = None
|
32
|
-
|
33
|
-
self.reset_topics()
|
34
|
-
|
35
|
-
def reset_topics(self):
|
36
|
-
self.__topics: Dict[str, Topic] = {}
|
37
|
-
self.__subscriptions: Dict[str, List[Subscriber]] = {}
|
38
|
-
|
39
|
-
def add_topic(self, topic: Topic):
|
40
|
-
self.__topics[topic.name] = topic
|
41
|
-
self.__subscriptions[topic.name] = []
|
42
|
-
|
43
|
-
def remove_topic(self, topic_name: str):
|
44
|
-
"""
|
45
|
-
Remove topic by name
|
46
|
-
|
47
|
-
:param topic_name:
|
48
|
-
:return:
|
49
|
-
"""
|
50
|
-
|
51
|
-
del self.__topics[topic_name]
|
52
|
-
del self.__subscriptions[topic_name]
|
53
|
-
|
54
|
-
@property
|
55
|
-
def topics(self) -> Dict[str, Topic]:
|
56
|
-
return self.__topics
|
57
|
-
|
58
|
-
@property
|
59
|
-
def subscriptions(self) -> Dict[str, List[Subscriber]]:
|
60
|
-
return self.__subscriptions
|
61
|
-
|
62
|
-
def add_subscriber(self, topic_name: str, subscriber: Subscriber, raise_if_topic_missed: bool = False):
|
63
|
-
"""
|
64
|
-
Add subscriber to topic
|
65
|
-
|
66
|
-
:param raise_if_topic_missed:
|
67
|
-
:param topic_name:
|
68
|
-
:param subscriber:
|
69
|
-
:return:
|
70
|
-
"""
|
71
|
-
|
72
|
-
if topic_name not in self.__topics:
|
73
|
-
if raise_if_topic_missed:
|
74
|
-
raise TopicNotFound(f"topic '{topic_name}' not found")
|
75
|
-
|
76
|
-
else:
|
77
|
-
self.add_topic(Topic(topic_name))
|
78
|
-
|
79
|
-
self.__subscriptions[topic_name].append(subscriber)
|
80
|
-
|
81
|
-
def remove_subscriber(self, subscriber: Subscriber, topic_name: str = None, raise_if_topic_missed: bool = False):
|
82
|
-
"""
|
83
|
-
Remove subscriber from topic selected or from all if topic is None
|
84
|
-
|
85
|
-
:param raise_if_topic_missed:
|
86
|
-
:param subscriber:
|
87
|
-
:param topic_name:
|
88
|
-
:return:
|
89
|
-
"""
|
90
|
-
|
91
|
-
if raise_if_topic_missed and isinstance(topic_name, str) and topic_name not in self.__topics.keys():
|
92
|
-
raise TopicNotFound(f"topic '{topic_name}' not found")
|
93
|
-
|
94
|
-
for name in self.__topics.keys():
|
95
|
-
|
96
|
-
if topic_name is None or topic_name == name:
|
97
|
-
self.__subscriptions[name].remove(subscriber)
|
98
|
-
|
99
|
-
|
100
|
-
@abstractmethod
|
101
|
-
async def put_event(self, topic_name: str, event: Event):
|
102
|
-
"""
|
103
|
-
Put a new event in the bus and notify subscribers of corresponding
|
104
|
-
event's topic
|
105
|
-
|
106
|
-
:param topic_name:
|
107
|
-
:param event:
|
108
|
-
:return:
|
109
|
-
"""
|
110
|
-
|
111
|
-
raise NotImplemented()
|
112
|
-
|
eventbus/exceptions.py
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
import asyncio
|
2
|
-
import logging
|
3
|
-
from queue import Queue
|
4
|
-
from concurrent.futures import ThreadPoolExecutor
|
5
|
-
from src.event.event import Event
|
6
|
-
from src.eventbus.eventbus import EventBus
|
7
|
-
|
8
|
-
|
9
|
-
MAX_WORKERS = 3
|
10
|
-
MAX_QUEUE_SIZE = 0
|
11
|
-
|
12
|
-
|
13
|
-
class QueuedLocalEventBus(EventBus):
|
14
|
-
"""
|
15
|
-
Queued local eventbus (singleton). It uses a queue to store and forward events.
|
16
|
-
|
17
|
-
Author: Nicola Ricciardi
|
18
|
-
"""
|
19
|
-
|
20
|
-
def __init__(self, max_queue_size=MAX_QUEUE_SIZE, n_workers=MAX_WORKERS):
|
21
|
-
|
22
|
-
super().__init__()
|
23
|
-
|
24
|
-
self.__queue = Queue(maxsize=max_queue_size)
|
25
|
-
self.__n_workers = n_workers
|
26
|
-
|
27
|
-
self.__tpool = ThreadPoolExecutor(max_workers=self.__n_workers)
|
28
|
-
|
29
|
-
for i in range(self.__n_workers):
|
30
|
-
self.__tpool.submit(self.__elaborate_queue)
|
31
|
-
|
32
|
-
async def put_event(self, topic_name: str, event: Event):
|
33
|
-
self.__queue.put((topic_name, event))
|
34
|
-
|
35
|
-
def __elaborate_queue(self):
|
36
|
-
|
37
|
-
while True:
|
38
|
-
|
39
|
-
topic_name, event = self.__queue.get()
|
40
|
-
|
41
|
-
topic_subscriptions = self.subscriptions.get(topic_name, [])
|
42
|
-
|
43
|
-
logging.debug(
|
44
|
-
f"new event {event} on topic {topic_name}, notify subscribers: {topic_subscriptions}")
|
45
|
-
|
46
|
-
if len(topic_subscriptions) == 0:
|
47
|
-
return
|
48
|
-
|
49
|
-
for subscriber in topic_subscriptions:
|
50
|
-
asyncio.run(subscriber.on_event(topic_name, event))
|