Metadata-Version: 1.2
Name: aiotools
Version: 0.5.4
Summary: Idiomatic asyncio utilities
Home-page: https://github.com/achimnol/aiotools
Author: Joongi Kim
Author-email: me@daybreaker.info
License: MIT
Description-Content-Type: UNKNOWN
Description: aiotools
        ========
        
        .. image:: https://badge.fury.io/py/aiotools.svg
           :target: https://badge.fury.io/py/aiotools
           :alt: PyPI version
        
        .. image:: https://img.shields.io/pypi/pyversions/aiotools.svg
           :target: https://pypi.org/project/aiotools/
           :alt: Python Versions
        
        .. image:: https://travis-ci.org/achimnol/aiotools.svg?branch=master
           :target: https://travis-ci.org/achimnol/aiotools
           :alt: Build Status
        
        .. image:: https://codecov.io/gh/achimnol/aiotools/branch/master/graph/badge.svg
           :target: https://codecov.io/gh/achimnol/aiotools
           :alt: Code Coverage
        
        Idiomatic asyncio utilties
        
        *NOTE:* This project is under early stage of developement. The public APIs may break version by version.
        
        
        Async Context Manager
        ---------------------
        
        This is an asynchronous version of `contextlib.contextmanager`_ to make it
        easier to write asynchronous context managers without creating boilerplate
        classes.
        
        .. code-block:: 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.
        
        .. code-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()`_.
        
        .. code-block:: 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.
        
        .. code-block:: python
        
           import asyncio
           import aiotools
           
           async def echo(reader, writer):
               data = await reader.read(100)
               writer.write(data)
               await writer.drain()
               writer.close()
           
           @aiotools.actxmgr
           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
        -----------
        
        .. code-block:: 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.
        
        .. code-block:: 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
        
        
        .. _contextlib.contextmanager: https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager
        .. _asyncio.gather(): https://docs.python.org/3/library/asyncio-task.html#asyncio.gather
        .. _asyncio.Task: https://docs.python.org/3/library/asyncio-task.html#asyncio.Task
        .. _asyncio.CancelledError: https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.CancelledError
        
        
        Changelog
        =========
        
        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: Topic :: Software Development
Requires-Python: >=3.6
