Metadata-Version: 2.1
Name: aiotools
Version: 0.8.1
Summary: Idiomatic asyncio utilities
Home-page: https://github.com/achimnol/aiotools
Author: Joongi Kim
Author-email: me@daybreaker.info
License: MIT
Project-URL: Documentation, https://aiotools.readthedocs.io
Project-URL: Tracker, https://github.com/achimnol/aiotools/issues
Project-URL: Source, https://github.com/achimnol/aiotools
Project-URL: CI: AppVeyor, https://ci.appveyor.com/project/achimnol/aiotools
Project-URL: CI: Travis, https://travis-ci.com/achimnol/aiotools
Project-URL: Code Coverage, https://codecov.io/github/achimnol/aiotools
Description: aiotools
        ========
        
        [![PyPI release version](https://badge.fury.io/py/aiotools.svg)](https://pypi.org/project/aiotools/)
        ![Supported Python versions](https://img.shields.io/pypi/pyversions/aiotools.svg)
        [![Build Status](https://travis-ci.org/achimnol/aiotools.svg?branch=master)](https://travis-ci.org/achimnol/aiotools)
        [![Code Coverage](https://codecov.io/gh/achimnol/aiotools/branch/master/graph/badge.svg)](https://codecov.io/gh/achimnol/aiotools)
        
        Idiomatic asyncio utilties
        
        *NOTE:* This project is under early stage of developement. The public APIs may break version by version.
        
        
        Modules
        -------
        
        * [Async Context Manager](http://aiotools.readthedocs.io/en/latest/aiotools.context.html)
        * [Async Functools](http://aiotools.readthedocs.io/en/latest/aiotools.func.html)
        * [Async Itertools](http://aiotools.readthedocs.io/en/latest/aiotools.iter.html)
        * [Async Server](http://aiotools.readthedocs.io/en/latest/aiotools.server.html)
        * [Async Timer](http://aiotools.readthedocs.io/en/latest/aiotools.timer.html)
        
        
        Examples
        --------
        
        ### Async Context Manager
        
        This is an asynchronous version of `contextlib.contextmanager` to make it
        easier to write asynchronous context managers without creating boilerplate
        classes.
        
        ```python
        import asyncio
        import aiotools
        
        @aiotools.actxmgr
        async def mygen(a):
           await asyncio.sleep(1)
           yield a + 1
           await asyncio.sleep(1)
        
        async def somewhere():
           async with mygen(1) as b:
               assert b == 2
        ```
        
        Note that you need to wrap `yield` with a try-finally block to
        ensure resource releases (e.g., locks), even in the case when
        an exception is ocurred inside the async-with block.
        
        ```python
        import asyncio
        import aiotools
        
        lock = asyncio.Lock()
        
        @aiotools.actxmgr
        async def mygen(a):
           await lock.acquire()
           try:
               yield a + 1
           finally:
               lock.release()
        
        async def somewhere():
           try:
               async with mygen(1) as b:
                   raise RuntimeError('oops')
           except RuntimeError:
               print('caught!')  # you can catch exceptions here.
        ```
        
        You can also create a group of async context managers, which
        are entered/exited all at once using `asyncio.gather()`.
        
        ```python
        import asyncio
        import aiotools
        
        @aiotools.actxmgr
        async def mygen(a):
           yield a + 10
        
        async def somewhere():
           ctxgrp = aiotools.actxgroup(mygen(i) for i in range(10))
           async with ctxgrp as values:
               assert len(values) == 10
               for i in range(10):
                   assert values[i] == i + 10
        ```
        
        ### Async Server
        
        This implements a common pattern to launch asyncio-based server daemons.
        
        ```python
        import asyncio
        import aiotools
        
        async def echo(reader, writer):
           data = await reader.read(100)
           writer.write(data)
           await writer.drain()
           writer.close()
        
        @aiotools.server
        async def myworker(loop, pidx, args):
           server = await asyncio.start_server(echo, '0.0.0.0', 8888,
               reuse_port=True, loop=loop)
           print(f'[{pidx}] started')
           yield  # wait until terminated
           server.close()
           await server.wait_closed()
           print(f'[{pidx}] terminated')
        
        if __name__ == '__main__':
           # Run the above server using 4 worker processes.
           aiotools.start_server(myworker, num_workers=4)
        ```
        
        It handles SIGINT/SIGTERM signals automatically to stop the server,
        as well as lifecycle management of event loops running on multiple processes.
        
        
        ### Async Timer
        
        ```python
        import aiotools
        
        i = 0
        
        async def mytick(interval):
           print(i)
           i += 1
        
        async def somewhere():
           t = aiotools.create_timer(mytick, 1.0)
           ...
           t.cancel()
           await t
        ```
        
        `t` is an `asyncio.Task` object.
        To stop the timer, call `t.cancel(); await t`.
        Please don't forget `await`-ing `t` because it requires extra steps to
        cancel and await all pending tasks.
        To make your timer function to be cancellable, add a try-except clause
        catching `asyncio.CancelledError` since we use it as a termination
        signal.
        
        You may add `TimerDelayPolicy` argument to control the behavior when the
        timer-fired task takes longer than the timer interval.
        `DEFAULT` is to accumulate them and cancel all the remainings at once when
        the timer is cancelled.
        `CANCEL` is to cancel any pending previously fired tasks on every interval.
        
        ```python
        import asyncio
        import aiotools
        
        async def mytick(interval):
           await asyncio.sleep(100)  # cancelled on every next interval.
        
        async def somewhere():
           t = aiotools.create_timer(mytick, 1.0, aiotools.TimerDelayPolicy.CANCEL)
           ...
           t.cancel()
           await t
        ```
        
        Changelog
        =========
        
        0.8.1 (2019-02-24)
        ------------------
        
        - server: Fix yields of the received stop signal in main/worker context managers
          when using threaded workers.
        
        0.8.0 (2018-11-18)
        ------------------
        
        - server: Updated stop signal handling and now user-defined worker/main context
          managers have a way to distinguish the stop signal received.  See the updated
          docs for more details.
        
        0.7.3 (2018-10-16)
        ------------------
        
        - This ia a technical release to fix a test case preventing the automated CI
          release procedure.
        
        0.7.2 (2018-10-16)
        ------------------
        
        - Improve support for Python 3.6/3.7 using a small compatibility module against asyncio.
        
        - func: Add `expire_after` option to `lru_cache()` function.
        
        0.7.1 (2018-08-24)
        ------------------
        
        - Minor updates to the documentation
        
        0.7.0 (2018-08-24)
        ------------------
        
        - Add support for Python 3.7
        
        - context: Updated to work like Python 3.7
        
        - context: Deprecated `AsyncContextDecorator` stuffs in Python 3.7+
        
        - context: Added an alias to `contextlib.AsyncExitStack` in the standard library.
        
        0.6.0 (2018-04-10)
        ------------------
        
        - Introduce a new module `aiotools.iter` with `aiter()` function which
          corresponds to an async version of the builtin `iter()`.
        
        0.5.4 (2018-02-01)
        ------------------
        
        - server: Remove use of unncessary setpgrp syscall, which is also blocked by
          Docker's default seccomp profile!
        
        0.5.3 (2018-01-12)
        ------------------
        
        - server: Ooops! (a finally block should have been an else block)
        
        0.5.2 (2018-01-12)
        ------------------
        
        - server: Improve inner beauty (code readability)
        
        - server: Improve reliability and portability of worker-to-main interrupts
        
        0.5.1 (2018-01-11)
        ------------------
        
        - server: Fix a race condition related to handling of worker
          initialization errors with multiple workers
        
        0.5.0 (2017-11-08)
        ------------------
        
        - func: Add `lru_cache()` which is a coroutine version of
          `functools.lru_cache()`
        
        0.4.5 (2017-10-14)
        ------------------
        
        - server: Fix a race condition related to signal handling in the
          multiprocessing module during termination
        
        - server: Improve error handling during initialization of workers
          (automatic shutdown of other workers and the main loop after
          logging the exception)
        
        0.4.4 (2017-09-12)
        ------------------
        
        - Add a new module `aiotools.func` with `apartial()` function which is an
          async version of `functools.partial()` in the standard library
        
        0.4.3 (2017-08-06)
        ------------------
        
        - Add `aclosing()` context manager like `closing()` in the standard library
        
        - Speed up Travis CI builds for packaging
        
        - Now provide README in rst as well as CHANGES (this file)
        
        0.4.2 (2017-08-01)
        ------------------
        
        - `server`: Fix spawning subprocesses in child workers
        
        - Add support for `uvloop`
        
        0.4.0 (2017-08-01)
        ------------------
        
        - Add `use_threading` argument to 
        
        - Add initial documentation (which currently not served
          on readthedocs.io due to Python version problem)
        
        0.3.2 (2017-07-31)
        ------------------
        
        - Add `extra_procs` argument to `start_server()` function
        
        - Add socket and ZeroMQ server examples
        
        - Improve CI configs
        
        0.3.1 (2017-07-26)
        ------------------
        
        - Improve CI scripts
        
        - Adopt editorconfig
        
        0.3.0 (2017-04-26)
        ------------------
        
        - Add `start_server()` function using multiprocessing
          with automatic children lifecycle management
        
        - Clarify the semantics of `AsyncContextGroup` using
          `asyncio.gather()` with `return_exceptions=True`
        
        0.2.0 (2017-04-20)
        ------------------
        
        - Add abstract types for `AsyncContextManager`
        
        - Rename `AsyncGenContextManager` to `AsyncContextManager`
        
        - Add `AsyncContextGroup`
        
        0.1.1 (2017-04-14)
        ------------------
        
        - Initial release
        
Platform: any
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Developers
Classifier: Framework :: AsyncIO
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: dev
Provides-Extra: build
Provides-Extra: test
Provides-Extra: ci
Provides-Extra: docs
