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.
Files changed (69) hide show
  1. {aiomisc-17.7.8 → aiomisc-17.8.1}/PKG-INFO +1 -1
  2. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/entrypoint.py +1 -1
  3. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/iterator_wrapper.py +14 -13
  4. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/base.py +2 -4
  5. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/thread_pool.py +186 -50
  6. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/version.py +2 -2
  7. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/forking.py +2 -2
  8. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/process.py +1 -1
  9. {aiomisc-17.7.8 → aiomisc-17.8.1}/pyproject.toml +1 -2
  10. {aiomisc-17.7.8 → aiomisc-17.8.1}/COPYING +0 -0
  11. {aiomisc-17.7.8 → aiomisc-17.8.1}/README.rst +0 -0
  12. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/__init__.py +0 -0
  13. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/_context_vars.py +0 -0
  14. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/aggregate.py +0 -0
  15. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/backoff.py +0 -0
  16. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/circuit_breaker.py +0 -0
  17. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/compat.py +0 -0
  18. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/context.py +0 -0
  19. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/counters.py +0 -0
  20. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/cron.py +0 -0
  21. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/io.py +0 -0
  22. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/log.py +0 -0
  23. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/periodic.py +0 -0
  24. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/plugins/__init__.py +0 -0
  25. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/plugins/__main__.py +0 -0
  26. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/pool.py +0 -0
  27. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/process_pool.py +0 -0
  28. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/py.typed +0 -0
  29. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/recurring.py +0 -0
  30. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/__init__.py +0 -0
  31. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/aiohttp.py +0 -0
  32. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/asgi.py +0 -0
  33. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/carbon.py +0 -0
  34. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/cron.py +0 -0
  35. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/__init__.py +0 -0
  36. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/records.py +0 -0
  37. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/service.py +0 -0
  38. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/store.py +0 -0
  39. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/tree.py +0 -0
  40. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/dns/zone.py +0 -0
  41. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/grpc_server.py +0 -0
  42. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/periodic.py +0 -0
  43. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/process.py +0 -0
  44. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/profiler.py +0 -0
  45. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/raven.py +0 -0
  46. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/sdwatchdog.py +0 -0
  47. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tcp.py +0 -0
  48. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tls.py +0 -0
  49. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/tracer.py +0 -0
  50. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/udp.py +0 -0
  51. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/service/uvicorn.py +0 -0
  52. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/signal.py +0 -0
  53. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/timeout.py +0 -0
  54. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/utils.py +0 -0
  55. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc/worker_pool.py +0 -0
  56. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/__init__.py +0 -0
  57. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/enum.py +0 -0
  58. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/__init__.py +0 -0
  59. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/color.py +0 -0
  60. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/journald.py +0 -0
  61. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/json.py +0 -0
  62. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/formatter/rich.py +0 -0
  63. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_log/py.typed +0 -0
  64. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/__init__.py +0 -0
  65. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/__main__.py +0 -0
  66. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/process_inner.py +0 -0
  67. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/protocol.py +0 -0
  68. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/py.typed +0 -0
  69. {aiomisc-17.7.8 → aiomisc-17.8.1}/aiomisc_worker/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: aiomisc
3
- Version: 17.7.8
3
+ Version: 17.8.1
4
4
  Summary: aiomisc - miscellaneous utils for asyncio
5
5
  License: MIT
6
6
  Author: Dmitry Orlov
@@ -419,7 +419,7 @@ class Entrypoint:
419
419
  handle = loop.call_later(self.shutdown_timeout, task.cancel)
420
420
 
421
421
  def on_shutdown_finish(task: asyncio.Future) -> None:
422
- nonlocal handle, loop
422
+ nonlocal handle, loop # noqa
423
423
 
424
424
  if task.cancelled():
425
425
  log.warning(
@@ -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, R, None]
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, gen_func: FuncType,
159
+ self,
160
+ gen_func: Callable[P, Generator[T, None, None]],
159
161
  loop: Optional[asyncio.AbstractEventLoop] = None,
160
- max_size: int = 0, executor: Optional[Executor] = None,
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[Any]:
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) -> Awaitable[T]:
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[Any]:
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], Generator[Any, None, 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, wraps
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, Optional, Set, Tuple,
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, Awaitable[T]]:
346
- if asyncio.iscoroutinefunction(func):
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
- @wraps(func)
353
- def wrap(
354
- *args: P.args, **kwargs: P.kwargs,
355
- ) -> Awaitable[T]:
356
- return run_in_executor(func=func, args=args, kwargs=kwargs)
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 wrap
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: F,
449
+ func: Callable[P, T],
395
450
  detach: bool = True,
396
- ) -> Callable[..., Awaitable[Any]]:
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
- @wraps(func)
404
- def wrap(*args: Any, **kwargs: Any) -> Any:
405
- future = run_in_new_thread(
406
- func, args=args, kwargs=kwargs, detach=detach,
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
- return wrap
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: Optional[F] = None,
507
+ func: Callable[P, Generator[T, None, None]],
508
+ *,
415
509
  max_size: int = 0,
416
- ) -> Any:
417
- if isinstance(func, int):
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
- return wrap
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: Optional[F] = None,
557
+ func: Callable[P, Generator[T, None, None]],
558
+ *,
439
559
  max_size: int = 0,
440
- ) -> Any:
441
- if isinstance(func, int):
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
- return wrap
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())
@@ -2,5 +2,5 @@
2
2
  # BY: poem-plugins "git" plugin
3
3
  # NEVER EDIT THIS FILE MANUALLY
4
4
 
5
- version_info = (17, 7, 8)
6
- __version__ = "17.7.8"
5
+ version_info = (17, 8, 1)
6
+ __version__ = "17.8.1"
@@ -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
 
@@ -86,7 +86,7 @@ def main() -> int:
86
86
  env["AIOMISC_NO_PLUGINS"] = ""
87
87
 
88
88
  def create_worker() -> Worker:
89
- nonlocal env
89
+ nonlocal env # noqa
90
90
  return Worker(
91
91
  log_level, log_format, address, cookie, worker_id, env,
92
92
  initializer, initializer_args, initializer_kwargs,
@@ -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.7.8"
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