moat-lib-micro 0.3.0__tar.gz → 0.3.2__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.
- {moat_lib_micro-0.3.0/src/moat_lib_micro.egg-info → moat_lib_micro-0.3.2}/PKG-INFO +2 -2
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/debian/changelog +24 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/pyproject.toml +2 -2
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/src/moat/lib/micro/__init__.py +133 -9
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2/src/moat_lib_micro.egg-info}/PKG-INFO +2 -2
- moat_lib_micro-0.3.2/src/moat_lib_micro.egg-info/requires.txt +2 -0
- moat_lib_micro-0.3.0/src/moat_lib_micro.egg-info/requires.txt +0 -2
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/LICENSE.txt +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/Makefile +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/README.md +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/debian/.gitignore +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/debian/control +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/debian/rules +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/setup.cfg +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/src/moat_lib_micro.egg-info/SOURCES.txt +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/src/moat_lib_micro.egg-info/dependency_links.txt +0 -0
- {moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/src/moat_lib_micro.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moat-lib-micro
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Compatibility layer for CPython/anyio and MicroPython/uasyncio
|
|
5
5
|
Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
|
|
6
6
|
Project-URL: homepage, https://m-o-a-t.org
|
|
@@ -16,7 +16,7 @@ Requires-Python: >=3.8
|
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: anyio~=4.0
|
|
19
|
-
Requires-Dist: moat-util~=0.
|
|
19
|
+
Requires-Dist: moat-util~=0.63.0
|
|
20
20
|
Dynamic: license-file
|
|
21
21
|
|
|
22
22
|
# moat-lib-micro
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
moat-lib-micro (0.3.2-1) unstable; urgency=medium
|
|
2
|
+
|
|
3
|
+
* New release for 26.1.10
|
|
4
|
+
|
|
5
|
+
-- Matthias Urlichs <matthias@urlichs.de> Thu, 23 Apr 2026 21:16:05 +0200
|
|
6
|
+
|
|
7
|
+
moat-lib-micro (0.3.1-2) unstable; urgency=medium
|
|
8
|
+
|
|
9
|
+
* New release for 26.0.12
|
|
10
|
+
|
|
11
|
+
-- Matthias Urlichs <matthias@urlichs.de> Wed, 04 Mar 2026 11:00:47 +0100
|
|
12
|
+
|
|
13
|
+
moat-lib-micro (0.3.1-1) unstable; urgency=medium
|
|
14
|
+
|
|
15
|
+
* New release for 26.0.11
|
|
16
|
+
|
|
17
|
+
-- Matthias Urlichs <matthias@urlichs.de> Mon, 02 Mar 2026 11:21:43 +0100
|
|
18
|
+
|
|
19
|
+
moat-lib-micro (0.3.0-5) unstable; urgency=medium
|
|
20
|
+
|
|
21
|
+
* New release for 26.0.1
|
|
22
|
+
|
|
23
|
+
-- Matthias Urlichs <matthias@urlichs.de> Wed, 18 Feb 2026 18:08:18 +0100
|
|
24
|
+
|
|
1
25
|
moat-lib-micro (0.3.0-3) unstable; urgency=medium
|
|
2
26
|
|
|
3
27
|
* New release for 26.0.0
|
|
@@ -13,7 +13,7 @@ classifiers = [
|
|
|
13
13
|
]
|
|
14
14
|
dependencies = [
|
|
15
15
|
"anyio ~= 4.0",
|
|
16
|
-
"moat-util ~= 0.
|
|
16
|
+
"moat-util ~= 0.63.0",
|
|
17
17
|
]
|
|
18
18
|
keywords = ["MoaT"]
|
|
19
19
|
requires-python = ">=3.8"
|
|
@@ -21,7 +21,7 @@ name = "moat-lib-micro"
|
|
|
21
21
|
maintainers = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
|
|
22
22
|
description='Compatibility layer for CPython/anyio and MicroPython/uasyncio'
|
|
23
23
|
readme = "README.md"
|
|
24
|
-
version = "0.3.
|
|
24
|
+
version = "0.3.2"
|
|
25
25
|
|
|
26
26
|
[project.urls]
|
|
27
27
|
homepage = "https://m-o-a-t.org"
|
|
@@ -39,12 +39,101 @@ R = TypeVar("R")
|
|
|
39
39
|
|
|
40
40
|
if TYPE_CHECKING:
|
|
41
41
|
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
42
|
+
from types import TracebackType
|
|
42
43
|
|
|
43
44
|
from collections.abc import Awaitable, Callable
|
|
44
|
-
from typing import NoReturn, Self
|
|
45
|
+
from typing import NoReturn, ParamSpec, Protocol, Self
|
|
46
|
+
|
|
47
|
+
P = ParamSpec("P")
|
|
48
|
+
|
|
49
|
+
class _EveryProto(Protocol):
|
|
50
|
+
@overload
|
|
51
|
+
def __call__(
|
|
52
|
+
self, t: float, p: None = None, /, *a: Any, **k: Any
|
|
53
|
+
) -> AsyncIterator[None]: ...
|
|
54
|
+
|
|
55
|
+
@overload
|
|
56
|
+
def __call__(
|
|
57
|
+
self,
|
|
58
|
+
t: float,
|
|
59
|
+
p: Callable[P, Awaitable[R]],
|
|
60
|
+
/,
|
|
61
|
+
*a: P.args,
|
|
62
|
+
**k: P.kwargs,
|
|
63
|
+
) -> AsyncIterator[R]: ...
|
|
64
|
+
|
|
65
|
+
class _RunProto(Protocol):
|
|
66
|
+
def __call__(
|
|
67
|
+
self,
|
|
68
|
+
p: Callable[P, Awaitable[R]],
|
|
69
|
+
*a: P.args,
|
|
70
|
+
**k: P.kwargs,
|
|
71
|
+
) -> R | None: ...
|
|
72
|
+
|
|
73
|
+
class _WaitForProto(Protocol):
|
|
74
|
+
def __call__(
|
|
75
|
+
self,
|
|
76
|
+
timeout: float,
|
|
77
|
+
p: Callable[P, Awaitable[R]],
|
|
78
|
+
*a: P.args,
|
|
79
|
+
**k: P.kwargs,
|
|
80
|
+
) -> Awaitable[R]: ...
|
|
81
|
+
|
|
82
|
+
class _TaskGroupProto(AbstractAsyncContextManager[Any], Protocol):
|
|
83
|
+
async def __aenter__(self) -> Self: ...
|
|
84
|
+
|
|
85
|
+
async def __aexit__(
|
|
86
|
+
self,
|
|
87
|
+
exc_type: type[BaseException] | None,
|
|
88
|
+
exc_value: BaseException | None,
|
|
89
|
+
traceback: TracebackType | None,
|
|
90
|
+
/,
|
|
91
|
+
) -> bool | None: ...
|
|
92
|
+
|
|
93
|
+
async def spawn(
|
|
94
|
+
self,
|
|
95
|
+
p: Callable[P, Awaitable[Any]],
|
|
96
|
+
*a: P.args,
|
|
97
|
+
_name: str | None = None, # ty:ignore[invalid-paramspec]
|
|
98
|
+
**k: P.kwargs,
|
|
99
|
+
) -> _anyio.CancelScope: ...
|
|
100
|
+
|
|
101
|
+
def start_soon(
|
|
102
|
+
self,
|
|
103
|
+
p: Callable[P, Awaitable[Any]],
|
|
104
|
+
*a: P.args,
|
|
105
|
+
_name: str | None = None, # ty:ignore[invalid-paramspec]
|
|
106
|
+
**k: P.kwargs,
|
|
107
|
+
) -> None: ...
|
|
108
|
+
|
|
109
|
+
def cancel(self) -> None: ...
|
|
110
|
+
|
|
111
|
+
class _TaskGroupFactoryProto(Protocol):
|
|
112
|
+
def __call__(self) -> _TaskGroupProto: ...
|
|
113
|
+
|
|
45
114
|
|
|
46
115
|
logger = logging.getLogger(__name__)
|
|
47
116
|
|
|
117
|
+
|
|
118
|
+
def _ac_task_id() -> int | None:
|
|
119
|
+
"""Return the current task ID if the backend exposes one."""
|
|
120
|
+
try:
|
|
121
|
+
return _anyio.get_current_task().id
|
|
122
|
+
except Exception:
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _ac_check_owner(obj: Any, acm: AsyncExitStack, op: str) -> None:
|
|
127
|
+
"""Reject cross-task use of an object's attached AC stack."""
|
|
128
|
+
owner = getattr(acm, "_moat_ac_task", None)
|
|
129
|
+
if owner is None:
|
|
130
|
+
return
|
|
131
|
+
cur = _ac_task_id()
|
|
132
|
+
if cur is None or cur == owner:
|
|
133
|
+
return
|
|
134
|
+
raise RuntimeError(f"{op}: cross-task AC use on {obj!r} (owner={owner}, current={cur})")
|
|
135
|
+
|
|
136
|
+
|
|
48
137
|
# Monkeypatch aclosing's docstring to be Sphinx-compatible
|
|
49
138
|
aclosing.__doc__ = """
|
|
50
139
|
Async context manager for safely finalizing an asynchronously cleaned-up
|
|
@@ -74,6 +163,7 @@ __all__ = [
|
|
|
74
163
|
"Event",
|
|
75
164
|
"L",
|
|
76
165
|
"Lock",
|
|
166
|
+
"ModuleNotFoundError",
|
|
77
167
|
"ObjSequence",
|
|
78
168
|
"Queue",
|
|
79
169
|
"QueueEmpty",
|
|
@@ -92,6 +182,8 @@ __all__ = [
|
|
|
92
182
|
"log",
|
|
93
183
|
"log_exc",
|
|
94
184
|
"print_exc",
|
|
185
|
+
"retry",
|
|
186
|
+
"retry_ms",
|
|
95
187
|
"run",
|
|
96
188
|
"run_server",
|
|
97
189
|
"shield",
|
|
@@ -116,6 +208,7 @@ EndOfStream = _anyio.EndOfStream
|
|
|
116
208
|
BrokenResourceError = _anyio.BrokenResourceError
|
|
117
209
|
ClosedResourceError = _anyio.ClosedResourceError
|
|
118
210
|
TimeoutError = TimeoutError # noqa:PLW0127,A001
|
|
211
|
+
ModuleNotFoundError = ModuleNotFoundError # noqa:PLW0127,A001
|
|
119
212
|
ExceptionGroup = ExceptionGroup # noqa: A001, PLW0127
|
|
120
213
|
BaseExceptionGroup = BaseExceptionGroup # noqa: A001, PLW0127
|
|
121
214
|
|
|
@@ -233,7 +326,7 @@ async def every_ms(
|
|
|
233
326
|
tt = ticks_add(ticks_ms(), int(t))
|
|
234
327
|
while True:
|
|
235
328
|
try:
|
|
236
|
-
yield None if p is None else await p(*a, **k)
|
|
329
|
+
yield (None if p is None else await p(*a, **k))
|
|
237
330
|
except StopAsyncIteration:
|
|
238
331
|
return
|
|
239
332
|
tn = ticks_ms()
|
|
@@ -251,6 +344,24 @@ def every(t: float, *a, **k) -> AsyncIterator[Any]:
|
|
|
251
344
|
return every_ms(t * 1000, *a, **k)
|
|
252
345
|
|
|
253
346
|
|
|
347
|
+
async def retry_ms(n: int, t: float, p: Callable[..., Awaitable[R]], *a, _exc=Exception, **k) -> R:
|
|
348
|
+
"every t milliseconds, call ``p(*a,**k)``"
|
|
349
|
+
while True:
|
|
350
|
+
try:
|
|
351
|
+
return await p(*a, **k)
|
|
352
|
+
except _exc:
|
|
353
|
+
if n >= 0:
|
|
354
|
+
n -= 1
|
|
355
|
+
if n == 0:
|
|
356
|
+
raise
|
|
357
|
+
await sleep_ms(t)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def retry(n: int, t: float, p: Callable[..., Awaitable[R]], *a, **k) -> Awaitable[R]:
|
|
361
|
+
"every t seconds, call ``p(*a,**k)``"
|
|
362
|
+
return retry_ms(n, t * 1000, p, *a, **k)
|
|
363
|
+
|
|
364
|
+
|
|
254
365
|
async def idle() -> None:
|
|
255
366
|
"sleep forever"
|
|
256
367
|
await _anyio.sleep_forever()
|
|
@@ -275,7 +386,7 @@ _tg = None
|
|
|
275
386
|
_tgt = None
|
|
276
387
|
|
|
277
388
|
|
|
278
|
-
def TaskGroup() ->
|
|
389
|
+
def TaskGroup() -> _TaskGroupProto: # Returns augmented TaskGroup instance
|
|
279
390
|
"A TaskGroup subclass that supports ``spawn`` and ``cancel``"
|
|
280
391
|
|
|
281
392
|
global _tg, _tgt
|
|
@@ -286,7 +397,7 @@ def TaskGroup() -> Any: # Returns augmented TaskGroup instance
|
|
|
286
397
|
if tgt is not _tgt:
|
|
287
398
|
_tgt = tgt
|
|
288
399
|
|
|
289
|
-
class TaskGroup_(_tgt): #
|
|
400
|
+
class TaskGroup_(_tgt): # ty:ignore[unsupported-base]
|
|
290
401
|
"""An augmented taskgroup"""
|
|
291
402
|
|
|
292
403
|
async def spawn(
|
|
@@ -314,6 +425,15 @@ def TaskGroup() -> Any: # Returns augmented TaskGroup instance
|
|
|
314
425
|
return _tg()
|
|
315
426
|
|
|
316
427
|
|
|
428
|
+
if TYPE_CHECKING:
|
|
429
|
+
every: _EveryProto = every # noqa: PLW0127
|
|
430
|
+
every_ms: _EveryProto = every_ms # noqa: PLW0127
|
|
431
|
+
run: _RunProto = run # noqa: PLW0127
|
|
432
|
+
wait_for: _WaitForProto = wait_for # noqa: PLW0127
|
|
433
|
+
wait_for_ms: _WaitForProto = wait_for_ms # noqa: PLW0127
|
|
434
|
+
TaskGroup: _TaskGroupFactoryProto = TaskGroup # noqa: PLW0127
|
|
435
|
+
|
|
436
|
+
|
|
317
437
|
async def run_server(
|
|
318
438
|
cb: Callable,
|
|
319
439
|
host: str,
|
|
@@ -406,10 +526,11 @@ def ACM(obj: Any) -> Callable[[Any], Awaitable[Any]]:
|
|
|
406
526
|
obj._AC_ = []
|
|
407
527
|
|
|
408
528
|
cm = AsyncExitStack()
|
|
529
|
+
cm._moat_ac_task = _ac_task_id() # noqa:SLF001 # ty:ignore[unresolved-attribute]
|
|
409
530
|
obj._AC_.append(cm)
|
|
410
531
|
|
|
411
|
-
# AsyncExitStack.__aenter__ is a no-op. We don't depend on that but at
|
|
412
|
-
# least it shouldn't yield
|
|
532
|
+
# AsyncExitStack.__aenter__ is a no-op. We don't depend on that, but at
|
|
533
|
+
# least it shouldn't yield.
|
|
413
534
|
# log("AC_Enter",nback=2)
|
|
414
535
|
try:
|
|
415
536
|
# pylint:disable=no-member,unnecessary-dunder-call
|
|
@@ -452,6 +573,7 @@ async def AC_use(obj: Any, ctx: Any) -> Any:
|
|
|
452
573
|
Otherwise it's a callable and will run on exit.
|
|
453
574
|
"""
|
|
454
575
|
acm: AsyncExitStack = obj._AC_[-1]
|
|
576
|
+
_ac_check_owner(obj, acm, "AC_use")
|
|
455
577
|
if hasattr(ctx, "__aenter__"):
|
|
456
578
|
return await acm.enter_async_context(ctx)
|
|
457
579
|
elif hasattr(ctx, "__enter__"):
|
|
@@ -469,7 +591,9 @@ async def AC_exit(obj: Any, *exc) -> bool | None:
|
|
|
469
591
|
"""End the latest AsyncExitStack opened by `ACM`."""
|
|
470
592
|
if not exc:
|
|
471
593
|
exc = (None, None, None)
|
|
472
|
-
|
|
594
|
+
acm = obj._AC_.pop()
|
|
595
|
+
_ac_check_owner(obj, acm, "AC_exit")
|
|
596
|
+
return await acm.__aexit__(*exc)
|
|
473
597
|
|
|
474
598
|
|
|
475
599
|
def is_async(obj: Any) -> bool:
|
|
@@ -482,5 +606,5 @@ def is_async(obj: Any) -> bool:
|
|
|
482
606
|
async def to_thread(p: Callable[..., R], *a, **k) -> R:
|
|
483
607
|
"""run this function in a thread"""
|
|
484
608
|
if k:
|
|
485
|
-
return await _anyio.to_thread.run_sync(partial(p, *a, **k), abandon_on_cancel=True) #
|
|
486
|
-
return await _anyio.to_thread.run_sync(p, *a, abandon_on_cancel=True) #
|
|
609
|
+
return await _anyio.to_thread.run_sync(partial(p, *a, **k), abandon_on_cancel=True) # ty:ignore[unresolved-attribute]
|
|
610
|
+
return await _anyio.to_thread.run_sync(p, *a, abandon_on_cancel=True) # ty:ignore[unresolved-attribute]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moat-lib-micro
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Compatibility layer for CPython/anyio and MicroPython/uasyncio
|
|
5
5
|
Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
|
|
6
6
|
Project-URL: homepage, https://m-o-a-t.org
|
|
@@ -16,7 +16,7 @@ Requires-Python: >=3.8
|
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: anyio~=4.0
|
|
19
|
-
Requires-Dist: moat-util~=0.
|
|
19
|
+
Requires-Dist: moat-util~=0.63.0
|
|
20
20
|
Dynamic: license-file
|
|
21
21
|
|
|
22
22
|
# moat-lib-micro
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moat_lib_micro-0.3.0 → moat_lib_micro-0.3.2}/src/moat_lib_micro.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|