Skip to content

Commit a2c36d4

Browse files
committed
Add a package-level activate context manager
I believe that this has more staying power than the existing API. It could be that even this can eventually be eliminated, but I'm not sure about that just yet. Either way, this avoids exposing QueueIO as a public interface. Which is good, because I'm coming to think that the functions it provides probably all would better live in other places.
1 parent 44d4fe3 commit a2c36d4

9 files changed

Lines changed: 43 additions & 107 deletions

File tree

README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Create your routines:
2121
# basic.py
2222
from time import sleep as time_sleep
2323

24-
from queueio import QueueIO
24+
from queueio import activate
2525
from queueio import routine
2626
from queueio.gather import gather
2727
from queueio.sleep import sleep
@@ -43,11 +43,8 @@ async def yielding(iterations: int):
4343

4444

4545
if __name__ == "__main__":
46-
q = QueueIO()
47-
try:
48-
q.submit(yielding(7))
49-
finally:
50-
q.shutdown()
46+
with activate():
47+
yielding(7).start()
5148

5249
```
5350

queueio/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1-
from .queueio import QueueIO as QueueIO
1+
from contextlib import contextmanager
2+
3+
from .queueio import QueueIO as RealQueueIO
24
from .registry import routine as routine
5+
6+
7+
@contextmanager
8+
def activate():
9+
with RealQueueIO().activate():
10+
yield

queueio/queueio.md

Lines changed: 0 additions & 35 deletions
This file was deleted.

queueio/queueio.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
from collections.abc import Iterable
66
from concurrent.futures import Future
77
from contextlib import contextmanager
8+
from contextvars import ContextVar
89
from pathlib import Path
10+
from typing import Self
911

1012
from .broker import Broker
1113
from .consumer import Consumer
@@ -24,6 +26,15 @@
2426

2527

2628
class QueueIO:
29+
__active = ContextVar[Self | None]("active", default=None)
30+
31+
@classmethod
32+
def active(cls) -> Self:
33+
"""Find the currently active instance."""
34+
queueio = cls.__active.get()
35+
assert queueio is not None, "No active QueueIO instance"
36+
return queueio
37+
2738
def __init__(
2839
self,
2940
*,
@@ -35,6 +46,16 @@ def __init__(
3546
self.__invocations = dict[Invocation, Message]()
3647
self.__register_routines()
3748

49+
@contextmanager
50+
def activate(self):
51+
token = self.__active.set(self)
52+
try:
53+
with self.invocation_handler():
54+
yield
55+
finally:
56+
self.__active.reset(token)
57+
self.shutdown()
58+
3859
def __pyproject(self) -> Path | None:
3960
for path in [cwd := Path.cwd(), *cwd.parents]:
4061
candidate = path / "pyproject.toml"

queueio/samples/basic.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from time import sleep as time_sleep
44

5-
from queueio import QueueIO
5+
from queueio import activate
66
from queueio import routine
77
from queueio.gather import gather
88
from queueio.sleep import sleep
@@ -24,8 +24,5 @@ async def yielding(iterations: int):
2424

2525

2626
if __name__ == "__main__":
27-
q = QueueIO()
28-
try:
29-
q.submit(yielding(7))
30-
finally:
31-
q.shutdown()
27+
with activate():
28+
yielding(7).start()

queueio/samples/basic_test.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import pytest
55

6-
from queueio import QueueIO
76
from queueio.invocation import Invocation
7+
from queueio.queueio import QueueIO
88

99
from .basic import yielding
1010

@@ -13,7 +13,7 @@
1313
def test_integration():
1414
queueio = QueueIO()
1515

16-
try:
16+
with queueio.activate():
1717
queueio.purge(queue="queueio")
1818
events = queueio.subscribe({Invocation.Completed})
1919
invocation = yielding(7)
@@ -36,6 +36,3 @@ def test_integration():
3636
except subprocess.TimeoutExpired:
3737
proc.kill()
3838
proc.wait()
39-
40-
finally:
41-
queueio.shutdown()

queueio/samples/expanded.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from contextlib import suppress
22
from time import sleep as time_sleep
33

4-
from queueio import QueueIO
4+
from queueio import activate
55
from queueio import routine
66
from queueio.gather import gather
77
from queueio.sleep import sleep
@@ -47,8 +47,5 @@ async def irregular():
4747

4848

4949
if __name__ == "__main__":
50-
q = QueueIO()
51-
try:
52-
q.submit(irregular())
53-
finally:
54-
q.shutdown()
50+
with activate():
51+
irregular().start()

queueio/samples/expanded_test.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import pytest
55

6-
from queueio import QueueIO
76
from queueio.invocation import Invocation
7+
from queueio.queueio import QueueIO
88

99
from .expanded import irregular
1010

@@ -14,7 +14,7 @@ def test_integration():
1414
# Prefers a clean environment and queue
1515
queueio = QueueIO()
1616

17-
try:
17+
with queueio.activate():
1818
queueio.purge(queue="queueio")
1919
events = queueio.subscribe({Invocation.Completed})
2020
invocation = irregular()
@@ -39,7 +39,3 @@ def test_integration():
3939
# Force kill if it doesn't terminate gracefully
4040
proc.kill()
4141
proc.wait()
42-
43-
finally:
44-
# Always clean up the queueio instance
45-
queueio.shutdown()

queueio/worker.md

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)