bubus 1.0.0__tar.gz
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.
- bubus-1.0.0/.gitignore +31 -0
- bubus-1.0.0/LICENSE +21 -0
- bubus-1.0.0/PKG-INFO +267 -0
- bubus-1.0.0/README.md +249 -0
- bubus-1.0.0/bubus/__init__.py +14 -0
- bubus-1.0.0/bubus/models.py +367 -0
- bubus-1.0.0/bubus/service.py +628 -0
- bubus-1.0.0/pyproject.toml +95 -0
bubus-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Cache files
|
|
2
|
+
.DS_Store
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.ipynb_checkpoints
|
|
10
|
+
~/
|
|
11
|
+
|
|
12
|
+
# Virtual Environments
|
|
13
|
+
.venv*
|
|
14
|
+
venv/
|
|
15
|
+
|
|
16
|
+
# IDEs
|
|
17
|
+
.vscode/
|
|
18
|
+
.idea/
|
|
19
|
+
CLAUDE.local.md
|
|
20
|
+
|
|
21
|
+
# Build files
|
|
22
|
+
dist/
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Secrets and sensitive files
|
|
26
|
+
secrets.env
|
|
27
|
+
.env
|
|
28
|
+
|
|
29
|
+
uv.lock
|
|
30
|
+
temp
|
|
31
|
+
tmp
|
bubus-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Browser Use
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bubus-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bubus
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Advanced Pydantic-powered event bus with async support
|
|
5
|
+
Project-URL: Repository, https://github.com/browser-use/bubus
|
|
6
|
+
Author: Nick Sweeting
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: <4.0,>=3.11
|
|
12
|
+
Requires-Dist: aiofiles>=24.1.0
|
|
13
|
+
Requires-Dist: anyio>=4.9.0
|
|
14
|
+
Requires-Dist: pydantic>=2.11.5
|
|
15
|
+
Requires-Dist: typing-extensions>=4.12.2
|
|
16
|
+
Requires-Dist: uuid7>=0.1.0
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# `bubus`: Pydantic-based event bus for async Python
|
|
20
|
+
|
|
21
|
+
Bubus is an advanced Pydantic-powered event bus with async support, designed for building reactive, event-driven applications with Python. It provides a powerful yet simple API for implementing publish-subscribe patterns with type safety, async handlers, and advanced features like event forwarding between buses.
|
|
22
|
+
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
Install bubus and get started with a simple event-driven application:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install bubus
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import asyncio
|
|
33
|
+
from bubus import EventBus, BaseEvent
|
|
34
|
+
|
|
35
|
+
class UserLoginEvent(BaseEvent):
|
|
36
|
+
username: str
|
|
37
|
+
timestamp: float
|
|
38
|
+
|
|
39
|
+
async def handle_login(event: UserLoginEvent):
|
|
40
|
+
print(f"User {event.username} logged in at {event.timestamp}")
|
|
41
|
+
return {"status": "success", "user": event.username}
|
|
42
|
+
|
|
43
|
+
bus = EventBus()
|
|
44
|
+
bus.on('UserLoginEvent', handle_login)
|
|
45
|
+
|
|
46
|
+
event = bus.dispatch(UserLoginEvent(username="alice", timestamp=1234567890))
|
|
47
|
+
result = await event
|
|
48
|
+
print(f"Login handled: {result.event_results}")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
<br/>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
<br/>
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
### Type-Safe Events with Pydantic
|
|
60
|
+
|
|
61
|
+
Define events as Pydantic models with full type checking and validation:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from typing import Any
|
|
65
|
+
from bubus import BaseEvent
|
|
66
|
+
|
|
67
|
+
class OrderCreatedEvent(BaseEvent):
|
|
68
|
+
order_id: str
|
|
69
|
+
customer_id: str
|
|
70
|
+
total_amount: float
|
|
71
|
+
items: list[dict[str, Any]]
|
|
72
|
+
|
|
73
|
+
# Events are automatically validated
|
|
74
|
+
event = OrderCreatedEvent(
|
|
75
|
+
order_id="ORD-123",
|
|
76
|
+
customer_id="CUST-456",
|
|
77
|
+
total_amount=99.99,
|
|
78
|
+
items=[{"sku": "ITEM-1", "quantity": 2}]
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Async and Sync Handler Support
|
|
83
|
+
|
|
84
|
+
Register both synchronous and asynchronous handlers for maximum flexibility:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# Async handler
|
|
88
|
+
async def async_handler(event: BaseEvent):
|
|
89
|
+
await asyncio.sleep(0.1) # Simulate async work
|
|
90
|
+
return "async result"
|
|
91
|
+
|
|
92
|
+
# Sync handler
|
|
93
|
+
def sync_handler(event: BaseEvent):
|
|
94
|
+
return "sync result"
|
|
95
|
+
|
|
96
|
+
bus.on('MyEvent', async_handler)
|
|
97
|
+
bus.on('MyEvent', sync_handler)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Event Pattern Matching
|
|
101
|
+
|
|
102
|
+
Subscribe to events using multiple patterns:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# By event type string
|
|
106
|
+
bus.on('UserActionEvent', handler)
|
|
107
|
+
|
|
108
|
+
# By event model class
|
|
109
|
+
bus.on(UserActionEvent, handler)
|
|
110
|
+
|
|
111
|
+
# Wildcard - handle all events
|
|
112
|
+
bus.on('*', universal_handler)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Hierarchical Event Bus Networks
|
|
116
|
+
|
|
117
|
+
Create networks of event buses that forward events between each other:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# Create a hierarchy of buses
|
|
121
|
+
main_bus = EventBus(name='MainBus')
|
|
122
|
+
auth_bus = EventBus(name='AuthBus')
|
|
123
|
+
data_bus = EventBus(name='DataBus')
|
|
124
|
+
|
|
125
|
+
# Forward events between buses
|
|
126
|
+
main_bus.on('*', auth_bus.dispatch)
|
|
127
|
+
auth_bus.on('*', data_bus.dispatch)
|
|
128
|
+
|
|
129
|
+
# Events flow through the hierarchy with tracking
|
|
130
|
+
event = main_bus.dispatch(MyEvent())
|
|
131
|
+
await event
|
|
132
|
+
print(event.event_path) # ['MainBus', 'AuthBus', 'DataBus']
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Event Results Aggregation
|
|
136
|
+
|
|
137
|
+
Collect and aggregate results from multiple handlers:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
async def config_handler_1(event):
|
|
141
|
+
return {"debug": True, "port": 8080}
|
|
142
|
+
|
|
143
|
+
async def config_handler_2(event):
|
|
144
|
+
return {"debug": False, "timeout": 30}
|
|
145
|
+
|
|
146
|
+
bus.on('GetConfig', config_handler_1)
|
|
147
|
+
bus.on('GetConfig', config_handler_2)
|
|
148
|
+
|
|
149
|
+
event = await bus.dispatch(BaseEvent(event_type='GetConfig'))
|
|
150
|
+
|
|
151
|
+
# Merge all dict results
|
|
152
|
+
config = await event.event_results_flat_dict()
|
|
153
|
+
# {'debug': False, 'port': 8080, 'timeout': 30}
|
|
154
|
+
|
|
155
|
+
# Or get individual results
|
|
156
|
+
results = await event.event_results_by_handler_id()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### FIFO Event Processing
|
|
160
|
+
|
|
161
|
+
Events are processed in strict FIFO order, maintaining consistency:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
# Events are processed in the order they were dispatched
|
|
165
|
+
for i in range(10):
|
|
166
|
+
bus.dispatch(ProcessTaskEvent(task_id=i))
|
|
167
|
+
|
|
168
|
+
# Even with async handlers, order is preserved
|
|
169
|
+
await bus.wait_until_idle()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Parallel Handler Execution
|
|
173
|
+
|
|
174
|
+
Enable parallel processing of handlers for better performance:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# Create bus with parallel handler execution
|
|
178
|
+
bus = EventBus(parallel_handlers=True)
|
|
179
|
+
|
|
180
|
+
# Multiple handlers run concurrently for each event
|
|
181
|
+
bus.on('DataEvent', slow_handler_1) # Takes 1 second
|
|
182
|
+
bus.on('DataEvent', slow_handler_2) # Takes 1 second
|
|
183
|
+
|
|
184
|
+
start = time.time()
|
|
185
|
+
await bus.dispatch(DataEvent())
|
|
186
|
+
# Total time: ~1 second (not 2)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Event Expectation (Async Waiting)
|
|
190
|
+
|
|
191
|
+
Wait for specific events with optional filtering:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
# Wait for any response event
|
|
195
|
+
response = await bus.expect('ResponseEvent', timeout=30)
|
|
196
|
+
|
|
197
|
+
# Wait with predicate filtering
|
|
198
|
+
response = await bus.expect(
|
|
199
|
+
'ResponseEvent',
|
|
200
|
+
predicate=lambda e: e.request_id == my_request_id,
|
|
201
|
+
timeout=30
|
|
202
|
+
)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Write-Ahead Logging
|
|
206
|
+
|
|
207
|
+
Persist events automatically for durability and debugging:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
# Enable WAL persistence
|
|
211
|
+
bus = EventBus(name='MyBus', wal_path='./events.jsonl')
|
|
212
|
+
|
|
213
|
+
# All completed events are automatically persisted
|
|
214
|
+
bus.dispatch(ImportantEvent(data="critical"))
|
|
215
|
+
|
|
216
|
+
# Events are saved as JSONL for easy processing
|
|
217
|
+
# {"event_type": "ImportantEvent", "data": "critical", ...}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Event Context and Parent Tracking
|
|
221
|
+
|
|
222
|
+
Automatically track event relationships and causality:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
async def parent_handler(event: BaseEvent):
|
|
226
|
+
# Child events automatically get parent_id set
|
|
227
|
+
child_event = bus.dispatch(ChildEvent())
|
|
228
|
+
return await child_event
|
|
229
|
+
|
|
230
|
+
# Parent-child relationships are tracked
|
|
231
|
+
parent = bus.dispatch(ParentEvent())
|
|
232
|
+
await parent
|
|
233
|
+
# Child events will have event_parent_id = parent.event_id
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Development
|
|
239
|
+
|
|
240
|
+
Set up the development environment using `uv`:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
git clone https://github.com/browser-use/bubus && cd bubus
|
|
244
|
+
|
|
245
|
+
# Create virtual environment with Python 3.12
|
|
246
|
+
uv venv --python 3.12
|
|
247
|
+
|
|
248
|
+
# Activate virtual environment (varies by OS)
|
|
249
|
+
source .venv/bin/activate # On Unix/macOS
|
|
250
|
+
# or
|
|
251
|
+
.venv\Scripts\activate # On Windows
|
|
252
|
+
|
|
253
|
+
# Install dependencies
|
|
254
|
+
uv sync --dev --all-extras
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Run all tests
|
|
259
|
+
pytest tests -v x --full-trace
|
|
260
|
+
|
|
261
|
+
# Run specific test file
|
|
262
|
+
pytest tests/test_eventbus.py
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
This project is licensed under the MIT License. For more information, see the main browser-use repository: https://github.com/browser-use/browser-use
|
bubus-1.0.0/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# `bubus`: Pydantic-based event bus for async Python
|
|
2
|
+
|
|
3
|
+
Bubus is an advanced Pydantic-powered event bus with async support, designed for building reactive, event-driven applications with Python. It provides a powerful yet simple API for implementing publish-subscribe patterns with type safety, async handlers, and advanced features like event forwarding between buses.
|
|
4
|
+
|
|
5
|
+
## Quickstart
|
|
6
|
+
|
|
7
|
+
Install bubus and get started with a simple event-driven application:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install bubus
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import asyncio
|
|
15
|
+
from bubus import EventBus, BaseEvent
|
|
16
|
+
|
|
17
|
+
class UserLoginEvent(BaseEvent):
|
|
18
|
+
username: str
|
|
19
|
+
timestamp: float
|
|
20
|
+
|
|
21
|
+
async def handle_login(event: UserLoginEvent):
|
|
22
|
+
print(f"User {event.username} logged in at {event.timestamp}")
|
|
23
|
+
return {"status": "success", "user": event.username}
|
|
24
|
+
|
|
25
|
+
bus = EventBus()
|
|
26
|
+
bus.on('UserLoginEvent', handle_login)
|
|
27
|
+
|
|
28
|
+
event = bus.dispatch(UserLoginEvent(username="alice", timestamp=1234567890))
|
|
29
|
+
result = await event
|
|
30
|
+
print(f"Login handled: {result.event_results}")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
<br/>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
<br/>
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
### Type-Safe Events with Pydantic
|
|
42
|
+
|
|
43
|
+
Define events as Pydantic models with full type checking and validation:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from typing import Any
|
|
47
|
+
from bubus import BaseEvent
|
|
48
|
+
|
|
49
|
+
class OrderCreatedEvent(BaseEvent):
|
|
50
|
+
order_id: str
|
|
51
|
+
customer_id: str
|
|
52
|
+
total_amount: float
|
|
53
|
+
items: list[dict[str, Any]]
|
|
54
|
+
|
|
55
|
+
# Events are automatically validated
|
|
56
|
+
event = OrderCreatedEvent(
|
|
57
|
+
order_id="ORD-123",
|
|
58
|
+
customer_id="CUST-456",
|
|
59
|
+
total_amount=99.99,
|
|
60
|
+
items=[{"sku": "ITEM-1", "quantity": 2}]
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Async and Sync Handler Support
|
|
65
|
+
|
|
66
|
+
Register both synchronous and asynchronous handlers for maximum flexibility:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
# Async handler
|
|
70
|
+
async def async_handler(event: BaseEvent):
|
|
71
|
+
await asyncio.sleep(0.1) # Simulate async work
|
|
72
|
+
return "async result"
|
|
73
|
+
|
|
74
|
+
# Sync handler
|
|
75
|
+
def sync_handler(event: BaseEvent):
|
|
76
|
+
return "sync result"
|
|
77
|
+
|
|
78
|
+
bus.on('MyEvent', async_handler)
|
|
79
|
+
bus.on('MyEvent', sync_handler)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Event Pattern Matching
|
|
83
|
+
|
|
84
|
+
Subscribe to events using multiple patterns:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# By event type string
|
|
88
|
+
bus.on('UserActionEvent', handler)
|
|
89
|
+
|
|
90
|
+
# By event model class
|
|
91
|
+
bus.on(UserActionEvent, handler)
|
|
92
|
+
|
|
93
|
+
# Wildcard - handle all events
|
|
94
|
+
bus.on('*', universal_handler)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Hierarchical Event Bus Networks
|
|
98
|
+
|
|
99
|
+
Create networks of event buses that forward events between each other:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
# Create a hierarchy of buses
|
|
103
|
+
main_bus = EventBus(name='MainBus')
|
|
104
|
+
auth_bus = EventBus(name='AuthBus')
|
|
105
|
+
data_bus = EventBus(name='DataBus')
|
|
106
|
+
|
|
107
|
+
# Forward events between buses
|
|
108
|
+
main_bus.on('*', auth_bus.dispatch)
|
|
109
|
+
auth_bus.on('*', data_bus.dispatch)
|
|
110
|
+
|
|
111
|
+
# Events flow through the hierarchy with tracking
|
|
112
|
+
event = main_bus.dispatch(MyEvent())
|
|
113
|
+
await event
|
|
114
|
+
print(event.event_path) # ['MainBus', 'AuthBus', 'DataBus']
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Event Results Aggregation
|
|
118
|
+
|
|
119
|
+
Collect and aggregate results from multiple handlers:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
async def config_handler_1(event):
|
|
123
|
+
return {"debug": True, "port": 8080}
|
|
124
|
+
|
|
125
|
+
async def config_handler_2(event):
|
|
126
|
+
return {"debug": False, "timeout": 30}
|
|
127
|
+
|
|
128
|
+
bus.on('GetConfig', config_handler_1)
|
|
129
|
+
bus.on('GetConfig', config_handler_2)
|
|
130
|
+
|
|
131
|
+
event = await bus.dispatch(BaseEvent(event_type='GetConfig'))
|
|
132
|
+
|
|
133
|
+
# Merge all dict results
|
|
134
|
+
config = await event.event_results_flat_dict()
|
|
135
|
+
# {'debug': False, 'port': 8080, 'timeout': 30}
|
|
136
|
+
|
|
137
|
+
# Or get individual results
|
|
138
|
+
results = await event.event_results_by_handler_id()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### FIFO Event Processing
|
|
142
|
+
|
|
143
|
+
Events are processed in strict FIFO order, maintaining consistency:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
# Events are processed in the order they were dispatched
|
|
147
|
+
for i in range(10):
|
|
148
|
+
bus.dispatch(ProcessTaskEvent(task_id=i))
|
|
149
|
+
|
|
150
|
+
# Even with async handlers, order is preserved
|
|
151
|
+
await bus.wait_until_idle()
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Parallel Handler Execution
|
|
155
|
+
|
|
156
|
+
Enable parallel processing of handlers for better performance:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
# Create bus with parallel handler execution
|
|
160
|
+
bus = EventBus(parallel_handlers=True)
|
|
161
|
+
|
|
162
|
+
# Multiple handlers run concurrently for each event
|
|
163
|
+
bus.on('DataEvent', slow_handler_1) # Takes 1 second
|
|
164
|
+
bus.on('DataEvent', slow_handler_2) # Takes 1 second
|
|
165
|
+
|
|
166
|
+
start = time.time()
|
|
167
|
+
await bus.dispatch(DataEvent())
|
|
168
|
+
# Total time: ~1 second (not 2)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Event Expectation (Async Waiting)
|
|
172
|
+
|
|
173
|
+
Wait for specific events with optional filtering:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
# Wait for any response event
|
|
177
|
+
response = await bus.expect('ResponseEvent', timeout=30)
|
|
178
|
+
|
|
179
|
+
# Wait with predicate filtering
|
|
180
|
+
response = await bus.expect(
|
|
181
|
+
'ResponseEvent',
|
|
182
|
+
predicate=lambda e: e.request_id == my_request_id,
|
|
183
|
+
timeout=30
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Write-Ahead Logging
|
|
188
|
+
|
|
189
|
+
Persist events automatically for durability and debugging:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
# Enable WAL persistence
|
|
193
|
+
bus = EventBus(name='MyBus', wal_path='./events.jsonl')
|
|
194
|
+
|
|
195
|
+
# All completed events are automatically persisted
|
|
196
|
+
bus.dispatch(ImportantEvent(data="critical"))
|
|
197
|
+
|
|
198
|
+
# Events are saved as JSONL for easy processing
|
|
199
|
+
# {"event_type": "ImportantEvent", "data": "critical", ...}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Event Context and Parent Tracking
|
|
203
|
+
|
|
204
|
+
Automatically track event relationships and causality:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
async def parent_handler(event: BaseEvent):
|
|
208
|
+
# Child events automatically get parent_id set
|
|
209
|
+
child_event = bus.dispatch(ChildEvent())
|
|
210
|
+
return await child_event
|
|
211
|
+
|
|
212
|
+
# Parent-child relationships are tracked
|
|
213
|
+
parent = bus.dispatch(ParentEvent())
|
|
214
|
+
await parent
|
|
215
|
+
# Child events will have event_parent_id = parent.event_id
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
Set up the development environment using `uv`:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git clone https://github.com/browser-use/bubus && cd bubus
|
|
226
|
+
|
|
227
|
+
# Create virtual environment with Python 3.12
|
|
228
|
+
uv venv --python 3.12
|
|
229
|
+
|
|
230
|
+
# Activate virtual environment (varies by OS)
|
|
231
|
+
source .venv/bin/activate # On Unix/macOS
|
|
232
|
+
# or
|
|
233
|
+
.venv\Scripts\activate # On Windows
|
|
234
|
+
|
|
235
|
+
# Install dependencies
|
|
236
|
+
uv sync --dev --all-extras
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Run all tests
|
|
241
|
+
pytest tests -v x --full-trace
|
|
242
|
+
|
|
243
|
+
# Run specific test file
|
|
244
|
+
pytest tests/test_eventbus.py
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
This project is licensed under the MIT License. For more information, see the main browser-use repository: https://github.com/browser-use/browser-use
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Event bus for the browser-use agent."""
|
|
2
|
+
|
|
3
|
+
from bubus.models import BaseEvent, EventHandler, EventResult, PythonIdentifierStr, PythonIdStr, UUIDStr
|
|
4
|
+
from bubus.service import EventBus
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'EventBus',
|
|
8
|
+
'BaseEvent',
|
|
9
|
+
'EventResult',
|
|
10
|
+
'EventHandler',
|
|
11
|
+
'UUIDStr',
|
|
12
|
+
'PythonIdStr',
|
|
13
|
+
'PythonIdentifierStr',
|
|
14
|
+
]
|