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.
Files changed (57) hide show
  1. busline/client/client.py +27 -0
  2. {eventbus_client → busline/client}/eventbus_connector.py +5 -10
  3. busline/client/multiclient.py +41 -0
  4. busline/client/publisher/publisher.py +60 -0
  5. busline/client/pubsub_client.py +128 -0
  6. busline/client/subscriber/event_handler/closure_event_handler.py +18 -0
  7. busline/client/subscriber/event_handler/event_handler.py +15 -0
  8. busline/client/subscriber/event_handler/multi_handler.py +30 -0
  9. busline/client/subscriber/subscriber.py +109 -0
  10. busline/client/subscriber/topic_subscriber.py +79 -0
  11. busline/event/event.py +47 -0
  12. busline/event/registry.py +67 -0
  13. busline/event/test.py +47 -0
  14. busline/exceptions.py +8 -0
  15. busline/local/__init__.py +3 -0
  16. busline/local/eventbus/__init__.py +0 -0
  17. busline/local/eventbus/async_local_eventbus.py +26 -0
  18. busline/local/eventbus/eventbus.py +86 -0
  19. busline/local/eventbus/local_eventbus.py +23 -0
  20. busline/local/local_pubsub_client.py +54 -0
  21. busline/local/publisher/__init__.py +0 -0
  22. busline/local/publisher/local_publisher.py +38 -0
  23. busline/local/subscriber/__init__.py +0 -0
  24. busline/local/subscriber/local_subscriber.py +43 -0
  25. busline/local/test.py +156 -0
  26. busline-0.5.0.dist-info/METADATA +215 -0
  27. busline-0.5.0.dist-info/RECORD +36 -0
  28. {busline-0.3.0.dist-info → busline-0.5.0.dist-info}/WHEEL +1 -1
  29. busline-0.5.0.dist-info/top_level.txt +1 -0
  30. busline-0.3.0.dist-info/METADATA +0 -104
  31. busline-0.3.0.dist-info/RECORD +0 -30
  32. busline-0.3.0.dist-info/top_level.txt +0 -4
  33. event/event.py +0 -25
  34. event/event_content.py +0 -18
  35. event/event_metadata.py +0 -26
  36. eventbus/async_local_eventbus.py +0 -32
  37. eventbus/eventbus.py +0 -112
  38. eventbus/exceptions.py +0 -2
  39. eventbus/queued_local_eventbus.py +0 -50
  40. eventbus/topic.py +0 -35
  41. eventbus_client/eventbus_client.py +0 -99
  42. eventbus_client/exceptions.py +0 -4
  43. eventbus_client/local_eventbus_client.py +0 -25
  44. eventbus_client/publisher/local_eventbus_publisher.py +0 -35
  45. eventbus_client/publisher/publisher.py +0 -59
  46. eventbus_client/subscriber/closure_event_listener.py +0 -19
  47. eventbus_client/subscriber/event_listener.py +0 -15
  48. eventbus_client/subscriber/local_eventbus_closure_subscriber.py +0 -17
  49. eventbus_client/subscriber/local_eventbus_subscriber.py +0 -40
  50. eventbus_client/subscriber/subscriber.py +0 -93
  51. /__init__.py → /busline/__init__.py +0 -0
  52. {event → busline/client}/__init__.py +0 -0
  53. {eventbus → busline/client/publisher}/__init__.py +0 -0
  54. {eventbus_client → busline/client/subscriber}/__init__.py +0 -0
  55. {eventbus_client/publisher → busline/client/subscriber/event_handler}/__init__.py +0 -0
  56. {eventbus_client/subscriber → busline/event}/__init__.py +0 -0
  57. {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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ busline
@@ -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
-
@@ -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,,
@@ -1,4 +0,0 @@
1
- __init__
2
- event
3
- eventbus
4
- eventbus_client
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
@@ -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,2 +0,0 @@
1
- class TopicNotFound(Exception):
2
- pass
@@ -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))