eevent 0.1.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.
- eevent/__init__.py +114 -0
- eevent/py.typed +0 -0
- eevent-0.1.0.dist-info/METADATA +9 -0
- eevent-0.1.0.dist-info/RECORD +5 -0
- eevent-0.1.0.dist-info/WHEEL +4 -0
eevent/__init__.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
__all__ = ["Event", "EventBind", "OrEvent"]
|
|
4
|
+
|
|
5
|
+
# python
|
|
6
|
+
from asyncio import FIRST_COMPLETED
|
|
7
|
+
from asyncio import Future
|
|
8
|
+
from asyncio import create_task
|
|
9
|
+
from asyncio import wait
|
|
10
|
+
from functools import wraps
|
|
11
|
+
from typing import Any
|
|
12
|
+
from typing import Callable
|
|
13
|
+
from typing import Coroutine
|
|
14
|
+
from typing import Generator
|
|
15
|
+
from typing import Generic
|
|
16
|
+
from typing import Self
|
|
17
|
+
from typing import TypeVar
|
|
18
|
+
from weakref import WeakSet
|
|
19
|
+
from weakref import ref
|
|
20
|
+
|
|
21
|
+
_T = TypeVar("_T")
|
|
22
|
+
_T1 = TypeVar("_T1")
|
|
23
|
+
_T2 = TypeVar("_T2")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class EventBind(Generic[_T]):
|
|
27
|
+
_callback: Callable[[_T], Coroutine[Any, Any, None]] | None
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
callback: Callable[[_T], Coroutine[Any, Any, None]]
|
|
32
|
+
| ref[Callable[[_T], Coroutine[Any, Any, None]]],
|
|
33
|
+
):
|
|
34
|
+
if isinstance(callback, ref):
|
|
35
|
+
|
|
36
|
+
@wraps(callback)
|
|
37
|
+
async def weak_callback(data: _T) -> Any:
|
|
38
|
+
strong_callback = callback()
|
|
39
|
+
if strong_callback is None:
|
|
40
|
+
return
|
|
41
|
+
return await strong_callback(data)
|
|
42
|
+
|
|
43
|
+
self._callback = weak_callback
|
|
44
|
+
else:
|
|
45
|
+
self._callback = callback
|
|
46
|
+
|
|
47
|
+
def __enter__(self) -> Self:
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
def __exit__(self, *args: Any, **kwargs: Any) -> None:
|
|
51
|
+
self.close()
|
|
52
|
+
|
|
53
|
+
def close(self) -> None:
|
|
54
|
+
self._callback = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Event(Generic[_T]):
|
|
58
|
+
_future: Future[_T] | None = None
|
|
59
|
+
|
|
60
|
+
def __init__(self) -> None:
|
|
61
|
+
self._binds: WeakSet[EventBind[_T]] = WeakSet()
|
|
62
|
+
|
|
63
|
+
def __await__(self) -> Generator[Any, None, _T]:
|
|
64
|
+
return self._get_future().__await__()
|
|
65
|
+
|
|
66
|
+
def __call__(self, data: _T) -> None:
|
|
67
|
+
if self._future is not None:
|
|
68
|
+
self._future.set_result(data)
|
|
69
|
+
self._future = None
|
|
70
|
+
|
|
71
|
+
closed_binds: set[EventBind[_T]] = set()
|
|
72
|
+
for bind in self._binds:
|
|
73
|
+
if bind._callback is None:
|
|
74
|
+
closed_binds.add(bind)
|
|
75
|
+
else:
|
|
76
|
+
create_task(bind._callback(data))
|
|
77
|
+
self._binds -= closed_binds
|
|
78
|
+
|
|
79
|
+
def __or__(self: Event[_T1], other: Event[_T2]) -> OrEvent[_T1 | _T2]:
|
|
80
|
+
return OrEvent(self, other)
|
|
81
|
+
|
|
82
|
+
def _get_future(self) -> Future[_T]:
|
|
83
|
+
if self._future is None:
|
|
84
|
+
self._future = Future()
|
|
85
|
+
return self._future
|
|
86
|
+
|
|
87
|
+
def then(
|
|
88
|
+
self,
|
|
89
|
+
callback: Callable[[_T], Coroutine[Any, Any, None]]
|
|
90
|
+
| ref[Callable[[_T], Coroutine[Any, Any, None]]],
|
|
91
|
+
) -> EventBind[_T]:
|
|
92
|
+
event_bind = EventBind(callback)
|
|
93
|
+
self._binds.add(event_bind)
|
|
94
|
+
return event_bind
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class OrEvent(Generic[_T]):
|
|
98
|
+
_future: Future[_T] | None = None
|
|
99
|
+
|
|
100
|
+
def __init__(self, *events: Event):
|
|
101
|
+
self._events = events
|
|
102
|
+
|
|
103
|
+
def __await__(self) -> Generator[Any, None, tuple[Event, _T]]:
|
|
104
|
+
return self._await().__await__()
|
|
105
|
+
|
|
106
|
+
def __or__(self: OrEvent[_T1], other: Event[_T2]) -> OrEvent[_T1 | _T2]:
|
|
107
|
+
return OrEvent(*self._events, other)
|
|
108
|
+
|
|
109
|
+
async def _await(self) -> tuple[Event, _T]:
|
|
110
|
+
future_event = {e._get_future(): e for e in self._events}
|
|
111
|
+
done, _ = await wait(future_event.keys(), return_when=FIRST_COMPLETED)
|
|
112
|
+
for first in done:
|
|
113
|
+
return future_event[first], await first
|
|
114
|
+
assert False
|
eevent/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: eevent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Asyncio Events
|
|
5
|
+
Author: Erik Soma
|
|
6
|
+
Author-email: stillusingirc@gmail.com
|
|
7
|
+
Requires-Python: >=3.12,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
eevent/__init__.py,sha256=W6B8Px2yxYY5N_Gq4GqLJaICJm2xwXE2SRhQOHbHpic,3237
|
|
2
|
+
eevent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
eevent-0.1.0.dist-info/METADATA,sha256=qHVwLwz9ZylbKgSrDMEMuZaQ3NDrNe3F9Qlde2Gpxjc,258
|
|
4
|
+
eevent-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
5
|
+
eevent-0.1.0.dist-info/RECORD,,
|