flo-python 0.1.0.dev3__tar.gz → 0.1.0.dev4__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.
Files changed (28) hide show
  1. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/PKG-INFO +1 -1
  2. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/examples/worker.py +30 -47
  3. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/pyproject.toml +1 -1
  4. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/client.py +4 -2
  5. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/worker.py +31 -3
  6. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/.github/workflows/ci.yml +0 -0
  7. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/.github/workflows/release.yml +0 -0
  8. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/.gitignore +0 -0
  9. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/LICENSE +0 -0
  10. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/README.md +0 -0
  11. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/examples/basic.py +0 -0
  12. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/examples/stream_worker.py +0 -0
  13. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/examples/test_decorator.py +0 -0
  14. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/__init__.py +0 -0
  15. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/actions.py +0 -0
  16. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/exceptions.py +0 -0
  17. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/kv.py +0 -0
  18. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/processing.py +0 -0
  19. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/queue.py +0 -0
  20. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/streams.py +0 -0
  21. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/types.py +0 -0
  22. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/wire.py +0 -0
  23. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/src/flo/workflows.py +0 -0
  24. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/tests/__init__.py +0 -0
  25. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/tests/conftest.py +0 -0
  26. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/tests/order-workflow.yaml +0 -0
  27. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/tests/test_wire.py +0 -0
  28. {flo_python-0.1.0.dev3 → flo_python-0.1.0.dev4}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flo-python
3
- Version: 0.1.0.dev3
3
+ Version: 0.1.0.dev4
4
4
  Summary: Python SDK for the Flo distributed systems platform
5
5
  Project-URL: Homepage, https://github.com/floruntime/flo-python
6
6
  Project-URL: Documentation, https://github.com/floruntime/flo-python#readme
@@ -158,56 +158,39 @@ async def generate_report(ctx: ActionContext) -> bytes:
158
158
 
159
159
 
160
160
  async def main():
161
- # Create and connect client (shared configuration)
162
- client = FloClient(
163
- os.getenv("FLO_ENDPOINT", "localhost:3000"),
161
+ async with FloClient(
162
+ os.getenv("FLO_ENDPOINT", "localhost:4455"),
164
163
  namespace=os.getenv("FLO_NAMESPACE", "myapp"),
165
164
  debug=os.getenv("FLO_DEBUG", "").lower() in ("1", "true"),
166
- )
167
- await client.connect()
168
-
169
- # Create a worker from the client
170
- worker = client.new_action_worker(
171
- concurrency=5,
172
- action_timeout=300, # 5 minutes
173
- )
165
+ ) as client:
166
+ worker = client.new_action_worker(
167
+ concurrency=5,
168
+ action_timeout=300, # 5 minutes
169
+ )
174
170
 
175
- # Register action handlers using register_action()
176
- worker.register_action("process-order", process_order)
177
- worker.register_action("send-notification", send_notification)
178
- worker.register_action("generate-report", generate_report)
179
-
180
- # Register using decorator syntax
181
- @worker.action("health-check")
182
- async def health_check(ctx: ActionContext) -> bytes:
183
- """Simple health check action."""
184
- return ctx.to_bytes({
185
- "status": "healthy",
186
- "worker_id": ctx.task_id,
187
- "timestamp": ctx.created_at,
188
- })
189
-
190
- # Handle shutdown signals
191
- stop_event = asyncio.Event()
192
-
193
- def signal_handler():
194
- logger.info("Received shutdown signal")
195
- worker.stop()
196
- stop_event.set()
197
-
198
- loop = asyncio.get_running_loop()
199
- for sig in (signal.SIGINT, signal.SIGTERM):
200
- loop.add_signal_handler(sig, signal_handler)
201
-
202
- # Start worker (blocks until stopped)
203
- logger.info("Starting worker...")
204
- try:
205
- await worker.start()
206
- except KeyboardInterrupt:
207
- logger.info("Interrupted")
208
- finally:
209
- await worker.close()
210
- await client.close()
171
+ # Register action handlers
172
+ worker.register_action("process-order", process_order)
173
+ worker.register_action("send-notification", send_notification)
174
+ worker.register_action("generate-report", generate_report)
175
+
176
+ # Register using decorator syntax
177
+ @worker.action("health-check")
178
+ async def health_check(ctx: ActionContext) -> bytes:
179
+ return ctx.to_bytes({"status": "healthy", "worker_id": ctx.task_id})
180
+
181
+ # Handle shutdown signals
182
+ def signal_handler():
183
+ logger.info("Received shutdown signal")
184
+ worker.stop()
185
+
186
+ loop = asyncio.get_running_loop()
187
+ for sig in (signal.SIGINT, signal.SIGTERM):
188
+ loop.add_signal_handler(sig, signal_handler)
189
+
190
+ # Start worker (blocks until stopped)
191
+ logger.info("Starting worker...")
192
+ async with worker:
193
+ await worker.start()
211
194
  logger.info("Worker shutdown complete")
212
195
 
213
196
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "flo-python"
7
- version = "0.1.0.dev3"
7
+ version = "0.1.0.dev4"
8
8
  description = "Python SDK for the Flo distributed systems platform"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -372,11 +372,13 @@ class FloClient:
372
372
  Returns:
373
373
  A new ActionWorker instance ready to register actions and start.
374
374
 
375
- Example:
375
+ Example::
376
+
376
377
  async with FloClient("localhost:3000", namespace="myapp") as client:
377
378
  worker = client.new_action_worker(concurrency=5)
378
379
  worker.register_action("process-order", process_order)
379
- await worker.start()
380
+ async with worker:
381
+ await worker.start()
380
382
  """
381
383
  from .worker import ActionWorker
382
384
 
@@ -3,7 +3,8 @@
3
3
  Provides ActionWorker for executing actions and StreamWorker for
4
4
  processing stream records via consumer groups.
5
5
 
6
- Example:
6
+ Example::
7
+
7
8
  from flo import FloClient, ActionContext
8
9
 
9
10
  async def process_order(ctx: ActionContext) -> bytes:
@@ -14,8 +15,9 @@ Example:
14
15
  async def main():
15
16
  async with FloClient("localhost:3000", namespace="myapp") as client:
16
17
  worker = client.new_action_worker(concurrency=5)
17
- worker.action("process-order")(process_order)
18
- await worker.start()
18
+ worker.register_action("process-order", process_order)
19
+ async with worker:
20
+ await worker.start()
19
21
  """
20
22
 
21
23
  import asyncio
@@ -626,6 +628,19 @@ class ActionWorker:
626
628
  if self._client:
627
629
  await self._client.close()
628
630
 
631
+ async def __aenter__(self) -> "ActionWorker":
632
+ """Async context manager entry."""
633
+ return self
634
+
635
+ async def __aexit__(
636
+ self,
637
+ exc_type: type[BaseException] | None,
638
+ exc_val: BaseException | None,
639
+ exc_tb: object,
640
+ ) -> None:
641
+ """Async context manager exit — closes the worker."""
642
+ await self.close()
643
+
629
644
 
630
645
  # =============================================================================
631
646
  # Stream Worker
@@ -977,3 +992,16 @@ class StreamWorker:
977
992
  self.stop()
978
993
  if self._client:
979
994
  await self._client.close()
995
+
996
+ async def __aenter__(self) -> "StreamWorker":
997
+ """Async context manager entry."""
998
+ return self
999
+
1000
+ async def __aexit__(
1001
+ self,
1002
+ exc_type: type[BaseException] | None,
1003
+ exc_val: BaseException | None,
1004
+ exc_tb: object,
1005
+ ) -> None:
1006
+ """Async context manager exit — closes the stream worker."""
1007
+ await self.close()
File without changes