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 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
+ ]