aiomisc 17.7.8__tar.gz → 17.8.1__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.
- {aiomisc-17.7.8 → aiomisc-17.8.1}/PKG-INFO +1 -1
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/entrypoint.py +1 -1
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/iterator_wrapper.py +14 -13
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/base.py +2 -4
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/thread_pool.py +186 -50
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/version.py +2 -2
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/forking.py +2 -2
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/process.py +1 -1
- {aiomisc-17.7.8 → aiomisc-17.8.1}/pyproject.toml +1 -2
- {aiomisc-17.7.8 → aiomisc-17.8.1}/COPYING +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/README.rst +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/_context_vars.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/aggregate.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/backoff.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/circuit_breaker.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/compat.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/context.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/counters.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/cron.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/io.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/log.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/periodic.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/plugins/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/plugins/__main__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/pool.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/process_pool.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/py.typed +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/recurring.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/aiohttp.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/asgi.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/carbon.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/cron.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/records.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/service.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/store.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/tree.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/zone.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/grpc_server.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/periodic.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/process.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/profiler.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/raven.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/sdwatchdog.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tcp.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tls.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tracer.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/udp.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/uvicorn.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/signal.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/timeout.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/utils.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/worker_pool.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/enum.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/color.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/journald.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/json.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/rich.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/py.typed +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/__init__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/__main__.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/process_inner.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/protocol.py +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/py.typed +0 -0
- {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/worker.py +0 -0
@@ -9,7 +9,7 @@ from time import time
|
|
9
9
|
from types import TracebackType
|
10
10
|
from typing import (
|
11
11
|
Any, AsyncIterator, Awaitable, Callable, Deque, Generator, NoReturn,
|
12
|
-
Optional, Type, TypeVar, Union,
|
12
|
+
Optional, Type, TypeVar, Union, Generic, ParamSpec,
|
13
13
|
)
|
14
14
|
from weakref import finalize
|
15
15
|
|
@@ -19,8 +19,9 @@ from aiomisc.counters import Statistic
|
|
19
19
|
|
20
20
|
T = TypeVar("T")
|
21
21
|
R = TypeVar("R")
|
22
|
+
P = ParamSpec("P")
|
22
23
|
|
23
|
-
GenType = Generator[T,
|
24
|
+
GenType = Generator[T, None, None]
|
24
25
|
FuncType = Callable[[], GenType]
|
25
26
|
|
26
27
|
|
@@ -144,7 +145,7 @@ class IteratorWrapperStatistic(Statistic):
|
|
144
145
|
enqueued: int
|
145
146
|
|
146
147
|
|
147
|
-
class IteratorWrapper(AsyncIterator, EventLoopMixin):
|
148
|
+
class IteratorWrapper(Generic[P, T], AsyncIterator, EventLoopMixin):
|
148
149
|
__slots__ = (
|
149
150
|
"__channel",
|
150
151
|
"__close_event",
|
@@ -155,9 +156,11 @@ class IteratorWrapper(AsyncIterator, EventLoopMixin):
|
|
155
156
|
) + EventLoopMixin.__slots__
|
156
157
|
|
157
158
|
def __init__(
|
158
|
-
self,
|
159
|
+
self,
|
160
|
+
gen_func: Callable[P, Generator[T, None, None]],
|
159
161
|
loop: Optional[asyncio.AbstractEventLoop] = None,
|
160
|
-
max_size: int = 0,
|
162
|
+
max_size: int = 0,
|
163
|
+
executor: Optional[Executor] = None,
|
161
164
|
statistic_name: Optional[str] = None,
|
162
165
|
):
|
163
166
|
|
@@ -227,11 +230,9 @@ class IteratorWrapper(AsyncIterator, EventLoopMixin):
|
|
227
230
|
await asyncio.gather(self.__gen_task, return_exceptions=True)
|
228
231
|
|
229
232
|
def _run(self) -> Any:
|
230
|
-
return self.loop.run_in_executor(
|
231
|
-
self.executor, self._in_thread,
|
232
|
-
)
|
233
|
+
return self.loop.run_in_executor(self.executor, self._in_thread)
|
233
234
|
|
234
|
-
def __aiter__(self) -> AsyncIterator[
|
235
|
+
def __aiter__(self) -> AsyncIterator[T]:
|
235
236
|
if not self.loop.is_running():
|
236
237
|
raise RuntimeError("Event loop is not running")
|
237
238
|
|
@@ -242,7 +243,7 @@ class IteratorWrapper(AsyncIterator, EventLoopMixin):
|
|
242
243
|
self.__gen_task = gen_task
|
243
244
|
return IteratorProxy(self, self.close)
|
244
245
|
|
245
|
-
async def __anext__(self) ->
|
246
|
+
async def __anext__(self) -> T:
|
246
247
|
try:
|
247
248
|
item, is_exc = await self.__channel.get()
|
248
249
|
except ChannelClosed:
|
@@ -269,13 +270,13 @@ class IteratorWrapper(AsyncIterator, EventLoopMixin):
|
|
269
270
|
await self.close()
|
270
271
|
|
271
272
|
|
272
|
-
class IteratorProxy(AsyncIterator):
|
273
|
+
class IteratorProxy(Generic[T], AsyncIterator):
|
273
274
|
def __init__(
|
274
|
-
self, iterator: AsyncIterator,
|
275
|
+
self, iterator: AsyncIterator[T],
|
275
276
|
finalizer: Callable[[], Any],
|
276
277
|
):
|
277
278
|
self.__iterator = iterator
|
278
279
|
finalize(self, finalizer)
|
279
280
|
|
280
|
-
def __anext__(self) -> Awaitable[
|
281
|
+
def __anext__(self) -> Awaitable[T]:
|
281
282
|
return self.__iterator.__anext__()
|
@@ -1,15 +1,13 @@
|
|
1
1
|
import asyncio
|
2
2
|
from abc import ABC, ABCMeta, abstractmethod
|
3
|
-
from typing import
|
4
|
-
Any, Coroutine, Dict, Generator, Optional, Set, Tuple, TypeVar, Union,
|
5
|
-
)
|
3
|
+
from typing import Any, Coroutine, Dict, Optional, Set, Tuple, TypeVar, Union
|
6
4
|
|
7
5
|
from ..context import Context, get_context
|
8
6
|
from ..utils import cancel_tasks
|
9
7
|
|
10
8
|
|
11
9
|
T = TypeVar("T")
|
12
|
-
CoroutineType = Union[Coroutine[Any, Any, T]
|
10
|
+
CoroutineType = Union[Coroutine[Any, Any, T]]
|
13
11
|
|
14
12
|
|
15
13
|
class ServiceMeta(ABCMeta):
|
@@ -2,18 +2,19 @@ import asyncio
|
|
2
2
|
import contextvars
|
3
3
|
import inspect
|
4
4
|
import logging
|
5
|
+
import os
|
5
6
|
import threading
|
6
7
|
import time
|
7
8
|
import warnings
|
8
9
|
from concurrent.futures import ThreadPoolExecutor as ThreadPoolExecutorBase
|
9
10
|
from dataclasses import dataclass, field
|
10
|
-
from functools import partial
|
11
|
+
from functools import partial
|
11
12
|
from multiprocessing import cpu_count
|
12
13
|
from queue import SimpleQueue
|
13
14
|
from types import MappingProxyType
|
14
15
|
from typing import (
|
15
|
-
Any, Awaitable, Callable, Coroutine, Dict, FrozenSet,
|
16
|
-
TypeVar,
|
16
|
+
Any, Awaitable, Callable, Coroutine, Dict, FrozenSet, Generic,
|
17
|
+
Optional, Set, Tuple, TypeVar, Generator, overload, Union
|
17
18
|
)
|
18
19
|
|
19
20
|
from ._context_vars import EVENT_LOOP
|
@@ -21,12 +22,15 @@ from .compat import ParamSpec
|
|
21
22
|
from .counters import Statistic
|
22
23
|
from .iterator_wrapper import IteratorWrapper
|
23
24
|
|
24
|
-
|
25
25
|
P = ParamSpec("P")
|
26
26
|
T = TypeVar("T")
|
27
27
|
F = TypeVar("F", bound=Callable[..., Any])
|
28
28
|
log = logging.getLogger(__name__)
|
29
29
|
|
30
|
+
THREADED_ITERABLE_DEFAULT_MAX_SIZE = int(
|
31
|
+
os.getenv("THREADED_ITERABLE_DEFAULT_MAX_SIZE", 1024)
|
32
|
+
)
|
33
|
+
|
30
34
|
|
31
35
|
def context_partial(
|
32
36
|
func: F, *args: Any,
|
@@ -327,6 +331,7 @@ def run_in_executor(
|
|
327
331
|
return await loop.run_in_executor(
|
328
332
|
executor, partial(func, *args, **kwargs),
|
329
333
|
)
|
334
|
+
|
330
335
|
return lazy_wrapper()
|
331
336
|
|
332
337
|
|
@@ -340,22 +345,56 @@ async def _awaiter(future: asyncio.Future) -> T:
|
|
340
345
|
raise
|
341
346
|
|
342
347
|
|
348
|
+
class Threaded(Generic[P, T]):
|
349
|
+
__slots__ = ("func",)
|
350
|
+
|
351
|
+
def __init__(self, func: Callable[P, T]) -> None:
|
352
|
+
if asyncio.iscoroutinefunction(func):
|
353
|
+
raise TypeError("Can not wrap coroutine")
|
354
|
+
if inspect.isgeneratorfunction(func):
|
355
|
+
raise TypeError("Can not wrap generator function")
|
356
|
+
self.func = func
|
357
|
+
|
358
|
+
def sync_call(self, *args: P.args, **kwargs: P.kwargs) -> T:
|
359
|
+
return self.func(*args, **kwargs)
|
360
|
+
|
361
|
+
def async_call(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]:
|
362
|
+
return run_in_executor(func=self.func, args=args, kwargs=kwargs)
|
363
|
+
|
364
|
+
def __repr__(self) -> str:
|
365
|
+
return f"<Threaded {self.func.__name__} at {id(self):#x}>"
|
366
|
+
|
367
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]:
|
368
|
+
return self.async_call(*args, **kwargs)
|
369
|
+
|
370
|
+
def __get__(self, instance: Any, owner: Optional[type] = None) -> Any:
|
371
|
+
if instance is None:
|
372
|
+
return self
|
373
|
+
return partial(self.async_call, instance)
|
374
|
+
|
375
|
+
|
376
|
+
@overload
|
377
|
+
def threaded(func: Callable[P, T]) -> Threaded[P, T]:
|
378
|
+
...
|
379
|
+
|
380
|
+
|
381
|
+
@overload
|
343
382
|
def threaded(
|
344
|
-
func: Callable[P, T]
|
345
|
-
) -> Callable[P,
|
346
|
-
|
347
|
-
raise TypeError("Can not wrap coroutine")
|
383
|
+
func: Callable[P, Generator[T, None, None]]
|
384
|
+
) -> Callable[P, IteratorWrapper[P, T]]:
|
385
|
+
...
|
348
386
|
|
349
|
-
if inspect.isgeneratorfunction(func):
|
350
|
-
return threaded_iterable(func)
|
351
387
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
)
|
356
|
-
return
|
388
|
+
def threaded(
|
389
|
+
func: Callable[P, T] | Callable[P, Generator[T, None, None]]
|
390
|
+
) -> Threaded[P, T] | Callable[P, IteratorWrapper[P, T]]:
|
391
|
+
if inspect.isgeneratorfunction(func):
|
392
|
+
return threaded_iterable(
|
393
|
+
func,
|
394
|
+
max_size=THREADED_ITERABLE_DEFAULT_MAX_SIZE
|
395
|
+
)
|
357
396
|
|
358
|
-
return
|
397
|
+
return Threaded(func) # type: ignore
|
359
398
|
|
360
399
|
|
361
400
|
def run_in_new_thread(
|
@@ -390,43 +429,112 @@ def run_in_new_thread(
|
|
390
429
|
return future
|
391
430
|
|
392
431
|
|
432
|
+
class ThreadedSeparate(Threaded[P, T]):
|
433
|
+
"""
|
434
|
+
A decorator to run a function in a separate thread.
|
435
|
+
It returns an `asyncio.Future` that can be awaited.
|
436
|
+
"""
|
437
|
+
|
438
|
+
def __init__(self, func: Callable[P, T], detach: bool = True) -> None:
|
439
|
+
super().__init__(func)
|
440
|
+
self.detach = detach
|
441
|
+
|
442
|
+
def async_call(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]:
|
443
|
+
return run_in_new_thread(
|
444
|
+
self.func, args=args, kwargs=kwargs, detach=self.detach,
|
445
|
+
)
|
446
|
+
|
447
|
+
|
393
448
|
def threaded_separate(
|
394
|
-
func:
|
449
|
+
func: Callable[P, T],
|
395
450
|
detach: bool = True,
|
396
|
-
) ->
|
451
|
+
) -> ThreadedSeparate[P, T]:
|
397
452
|
if isinstance(func, bool):
|
398
453
|
return partial(threaded_separate, detach=detach)
|
399
454
|
|
400
455
|
if asyncio.iscoroutinefunction(func):
|
401
456
|
raise TypeError("Can not wrap coroutine")
|
402
457
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
458
|
+
return ThreadedSeparate(func, detach=detach)
|
459
|
+
|
460
|
+
|
461
|
+
class ThreadedIterable(Generic[P, T]):
|
462
|
+
def __init__(
|
463
|
+
self,
|
464
|
+
func: Callable[P, Generator[T, None, None]],
|
465
|
+
max_size: int = 0
|
466
|
+
) -> None:
|
467
|
+
self.func = func
|
468
|
+
self.max_size = max_size
|
469
|
+
|
470
|
+
def sync_call(
|
471
|
+
self, *args: P.args, **kwargs: P.kwargs
|
472
|
+
) -> Generator[T, None, None]:
|
473
|
+
return self.func(*args, **kwargs)
|
474
|
+
|
475
|
+
def async_call(
|
476
|
+
self, *args: P.args, **kwargs: P.kwargs
|
477
|
+
) -> IteratorWrapper[P, T]:
|
478
|
+
return self.create_wrapper(*args, **kwargs)
|
479
|
+
|
480
|
+
def create_wrapper(
|
481
|
+
self, *args: P.args, **kwargs: P.kwargs
|
482
|
+
) -> IteratorWrapper[P, T]:
|
483
|
+
return IteratorWrapper(
|
484
|
+
partial(self.func, *args, **kwargs),
|
485
|
+
max_size=self.max_size,
|
407
486
|
)
|
408
|
-
return future
|
409
487
|
|
410
|
-
|
488
|
+
def __call__(
|
489
|
+
self,
|
490
|
+
*args: P.args,
|
491
|
+
**kwargs: P.kwargs
|
492
|
+
) -> IteratorWrapper[P, T]:
|
493
|
+
return self.async_call(*args, **kwargs)
|
494
|
+
|
495
|
+
def __get__(
|
496
|
+
self,
|
497
|
+
instance: Any,
|
498
|
+
owner: Optional[type] = None
|
499
|
+
) -> Any:
|
500
|
+
if instance is None:
|
501
|
+
return self
|
502
|
+
return partial(self.async_call, instance)
|
411
503
|
|
412
504
|
|
505
|
+
@overload
|
413
506
|
def threaded_iterable(
|
414
|
-
func:
|
507
|
+
func: Callable[P, Generator[T, None, None]],
|
508
|
+
*,
|
415
509
|
max_size: int = 0,
|
416
|
-
) ->
|
417
|
-
|
418
|
-
return partial(threaded_iterable, max_size=func)
|
419
|
-
if func is None:
|
420
|
-
return partial(threaded_iterable, max_size=max_size)
|
510
|
+
) -> "ThreadedIterable[P, T]":
|
511
|
+
...
|
421
512
|
|
422
|
-
@wraps(func)
|
423
|
-
def wrap(*args: Any, **kwargs: Any) -> Any:
|
424
|
-
return IteratorWrapper(
|
425
|
-
partial(func, *args, **kwargs),
|
426
|
-
max_size=max_size,
|
427
|
-
)
|
428
513
|
|
429
|
-
|
514
|
+
@overload
|
515
|
+
def threaded_iterable(
|
516
|
+
*,
|
517
|
+
max_size: int = 0,
|
518
|
+
) -> Callable[
|
519
|
+
[Callable[P, Generator[T, None, None]]], ThreadedIterable[P, T]
|
520
|
+
]:
|
521
|
+
...
|
522
|
+
|
523
|
+
|
524
|
+
def threaded_iterable(
|
525
|
+
func: Optional[Callable[P, Generator[T, None, None]]] = None,
|
526
|
+
*,
|
527
|
+
max_size: int = 0,
|
528
|
+
) -> Union[
|
529
|
+
ThreadedIterable[P, T],
|
530
|
+
Callable[
|
531
|
+
[Callable[P, Generator[T, None, None]]], ThreadedIterable[P, T]
|
532
|
+
]
|
533
|
+
]:
|
534
|
+
if func is None:
|
535
|
+
return lambda f: ThreadedIterable(f, max_size=max_size)
|
536
|
+
|
537
|
+
return ThreadedIterable(func, max_size=max_size)
|
430
538
|
|
431
539
|
|
432
540
|
class IteratorWrapperSeparate(IteratorWrapper):
|
@@ -434,23 +542,50 @@ class IteratorWrapperSeparate(IteratorWrapper):
|
|
434
542
|
return run_in_new_thread(self._in_thread)
|
435
543
|
|
436
544
|
|
545
|
+
class ThreadedIterableSeparate(ThreadedIterable[P, T]):
|
546
|
+
def create_wrapper(
|
547
|
+
self, *args: P.args, **kwargs: P.kwargs
|
548
|
+
) -> IteratorWrapperSeparate:
|
549
|
+
return IteratorWrapperSeparate(
|
550
|
+
partial(self.func, *args, **kwargs),
|
551
|
+
max_size=self.max_size,
|
552
|
+
)
|
553
|
+
|
554
|
+
|
555
|
+
@overload
|
437
556
|
def threaded_iterable_separate(
|
438
|
-
func:
|
557
|
+
func: Callable[P, Generator[T, None, None]],
|
558
|
+
*,
|
439
559
|
max_size: int = 0,
|
440
|
-
) ->
|
441
|
-
|
442
|
-
return partial(threaded_iterable_separate, max_size=func)
|
443
|
-
if func is None:
|
444
|
-
return partial(threaded_iterable_separate, max_size=max_size)
|
560
|
+
) -> "ThreadedIterable[P, T]":
|
561
|
+
...
|
445
562
|
|
446
|
-
@wraps(func)
|
447
|
-
def wrap(*args: Any, **kwargs: Any) -> Any:
|
448
|
-
return IteratorWrapperSeparate(
|
449
|
-
partial(func, *args, **kwargs),
|
450
|
-
max_size=max_size,
|
451
|
-
)
|
452
563
|
|
453
|
-
|
564
|
+
@overload
|
565
|
+
def threaded_iterable_separate(
|
566
|
+
*,
|
567
|
+
max_size: int = 0,
|
568
|
+
) -> Callable[
|
569
|
+
[Callable[P, Generator[T, None, None]]],
|
570
|
+
ThreadedIterableSeparate[P, T]
|
571
|
+
]:
|
572
|
+
...
|
573
|
+
|
574
|
+
|
575
|
+
def threaded_iterable_separate(
|
576
|
+
func: Optional[Callable[P, Generator[T, None, None]]] = None,
|
577
|
+
*,
|
578
|
+
max_size: int = 0,
|
579
|
+
) -> Union[
|
580
|
+
ThreadedIterable[P, T],
|
581
|
+
Callable[
|
582
|
+
[Callable[P, Generator[T, None, None]]], ThreadedIterableSeparate[P, T]
|
583
|
+
]
|
584
|
+
]:
|
585
|
+
if func is None:
|
586
|
+
return lambda f: ThreadedIterableSeparate(f, max_size=max_size)
|
587
|
+
|
588
|
+
return ThreadedIterableSeparate(func, max_size=max_size)
|
454
589
|
|
455
590
|
|
456
591
|
class CoroutineWaiter:
|
@@ -509,4 +644,5 @@ def sync_await(
|
|
509
644
|
) -> T:
|
510
645
|
async def awaiter() -> T:
|
511
646
|
return await func(*args, **kwargs)
|
647
|
+
|
512
648
|
return wait_coroutine(awaiter())
|
@@ -20,7 +20,7 @@ EXIT_LOCK = Lock()
|
|
20
20
|
|
21
21
|
|
22
22
|
def at_exit() -> None:
|
23
|
-
global PROCESSES
|
23
|
+
global PROCESSES # noqa
|
24
24
|
|
25
25
|
with EXIT_LOCK:
|
26
26
|
pids = tuple(PROCESSES.keys())
|
@@ -61,7 +61,7 @@ def fork(worker_id: bytes, cookie: bytes, address: AddressType) -> None:
|
|
61
61
|
|
62
62
|
|
63
63
|
def main() -> int:
|
64
|
-
global STOPPING
|
64
|
+
global STOPPING # noqa
|
65
65
|
|
66
66
|
proto_stdin = FileIOProtocol(sys.stdin.buffer)
|
67
67
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "aiomisc"
|
3
3
|
# This is a dummy version which will be rewritten with poem-plugins
|
4
|
-
version = "17.
|
4
|
+
version = "17.8.1"
|
5
5
|
description = "aiomisc - miscellaneous utils for asyncio"
|
6
6
|
authors = ["Dmitry Orlov <me@mosquito.su>"]
|
7
7
|
readme = "README.rst"
|
@@ -24,7 +24,6 @@ classifiers = [
|
|
24
24
|
"Operating System :: POSIX :: Linux",
|
25
25
|
"Operating System :: POSIX",
|
26
26
|
"Programming Language :: Python :: 3",
|
27
|
-
"Programming Language :: Python :: 3.9",
|
28
27
|
"Programming Language :: Python :: 3.10",
|
29
28
|
"Programming Language :: Python :: 3.11",
|
30
29
|
"Programming Language :: Python :: 3.12",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|