Small utility library for coroutine-based asynchronous generic programming
Project description
paco |Build Status| |PyPI| |Coverage Status| |Documentation Status| |Stability| |Quality| |Versions|
====================================================================================================
Small and idiomatic utility library for coroutine-driven asynchronous generic programming in Python +3.4.
Built on top of `asyncio`_, ``paco`` provides missing capabilities from Python `stdlib`
in order to write asynchronous cooperative multitasking in a nice-ish way.
Also, paco aims to port some of `functools`_ and `itertools`_ standard functions to the asynchronous world.
``paco`` can be your utility belt to deal with asynchronous, I/O-bound, non-blocking concurrent code in a cleaner and idiomatic way.
.. raw:: html
<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/1MpD3pzt63uUeG43NP4tDHPY/h2non/paco'>
<img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/1MpD3pzt63uUeG43NP4tDHPY/h2non/paco.svg' /></a>
Features
--------
- Simple and idiomatic API, extending Python ``stdlib`` with async coroutines gotchas.
- Built-in configurable control-flow concurrency support (throttle).
- No fancy abstractions: it just works with the plain async coroutines.
- Useful iterables, decorators, functors and convenient helpers.
- Coroutine-based functional helpers: compose, throttle, partial, timeout, times, until, race...
- Asynchronous coroutine port of Python built-in functions: `filter`, `map`, `dropwhile`, `filterfalse`, `reduce`...
- Supports asynchronous iterables and generators (`PEP0525`_)
- Concurrent iterables and higher-order functions.
- Better ``asyncio.gather()`` and ``asyncio.wait()`` with optional concurrency control and ordered results.
- Works with both `async/await`_ and `yield from`_ coroutines syntax.
- Reliable coroutine timeout limit handler via context manager.
- Designed for intensive I/O-bound concurrent non-blocking tasks.
- Good interoperability with ``asyncio`` and Python ``stdlib`` functions.
- `Composable pipelines`_ of functors for transducers-like chain via ``|`` operator overloading.
- Small and dependency free.
- Compatible with Python +3.4.
Installation
------------
Using ``pip`` package manager:
.. code-block:: bash
pip install --upgrade paco
Or install the latest sources from Github:
.. code-block:: bash
pip install -e git+git://github.com/h2non/paco.git#egg=paco
API
---
- paco.ConcurrentExecutor_
- paco.apply_
- paco.compose_
- paco.concurrent_
- paco.constant_
- paco.curry_
- paco.defer_
- paco.dropwhile_
- paco.each_
- paco.every_
- paco.filter_
- paco.filterfalse_
- paco.flat_map_
- paco.gather_
- paco.identity_
- paco.interval_
- paco.map_
- paco.once_
- paco.partial_
- paco.race_
- paco.reduce_
- paco.repeat_
- paco.run_
- paco.series_
- paco.some_
- paco.throttle_
- paco.thunk_
- paco.timeout_
- paco.TimeoutLimit_
- paco.times_
- paco.until_
- paco.wait_
- paco.whilst_
- paco.wraps_
.. _paco.ConcurrentExecutor: http://paco.readthedocs.io/en/latest/api.html#paco.ConcurrentExecutor
.. _paco.apply: http://paco.readthedocs.io/en/latest/api.html#paco.apply
.. _paco.compose: http://paco.readthedocs.io/en/latest/api.html#paco.compose
.. _paco.concurrent: http://paco.readthedocs.io/en/latest/api.html#paco.concurrent
.. _paco.constant: http://paco.readthedocs.io/en/latest/api.html#paco.constant
.. _paco.curry: http://paco.readthedocs.io/en/latest/api.html#paco.curry
.. _paco.defer: http://paco.readthedocs.io/en/latest/api.html#paco.defer
.. _paco.dropwhile: http://paco.readthedocs.io/en/latest/api.html#paco.dropwhile
.. _paco.each: http://paco.readthedocs.io/en/latest/api.html#paco.each
.. _paco.every: http://paco.readthedocs.io/en/latest/api.html#paco.every
.. _paco.filter: http://paco.readthedocs.io/en/latest/api.html#paco.filter
.. _paco.filterfalse: http://paco.readthedocs.io/en/latest/api.html#paco.filterfalse
.. _paco.flat_map: http://paco.readthedocs.io/en/latest/api.html#paco.flat_map
.. _paco.gather: http://paco.readthedocs.io/en/latest/api.html#paco.gather
.. _paco.identity: http://paco.readthedocs.io/en/latest/api.html#paco.identity
.. _paco.interval: http://paco.readthedocs.io/en/latest/api.html#paco.interval
.. _paco.map: http://paco.readthedocs.io/en/latest/api.html#paco.map
.. _paco.once: http://paco.readthedocs.io/en/latest/api.html#paco.once
.. _paco.partial: http://paco.readthedocs.io/en/latest/api.html#paco.partial
.. _paco.race: http://paco.readthedocs.io/en/latest/api.html#paco.race
.. _paco.reduce: http://paco.readthedocs.io/en/latest/api.html#paco.reduce
.. _paco.repeat: http://paco.readthedocs.io/en/latest/api.html#paco.repeat
.. _paco.run: http://paco.readthedocs.io/en/latest/api.html#paco.run
.. _paco.series: http://paco.readthedocs.io/en/latest/api.html#paco.searies
.. _paco.some: http://paco.readthedocs.io/en/latest/api.html#paco.some
.. _paco.throttle: http://paco.readthedocs.io/en/latest/api.html#paco.throttle
.. _paco.thunk: http://paco.readthedocs.io/en/latest/api.html#paco.thunk
.. _paco.timeout: http://paco.readthedocs.io/en/latest/api.html#paco.timeout
.. _paco.TimeoutLimit: http://paco.readthedocs.io/en/latest/api.html#paco.TimeoutLimit
.. _paco.times: http://paco.readthedocs.io/en/latest/api.html#paco.times
.. _paco.until: http://paco.readthedocs.io/en/latest/api.html#paco.until
.. _paco.wait: http://paco.readthedocs.io/en/latest/api.html#paco.wait
.. _paco.whilst: http://paco.readthedocs.io/en/latest/api.html#paco.whilst
.. _paco.wraps: http://paco.readthedocs.io/en/latest/api.html#paco.wraps
Examples
^^^^^^^^
Asynchronously and concurrently execute multiple HTTP requests.
.. code-block:: python
import paco
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as res:
return res
async def fetch_urls():
urls = [
'https://www.google.com',
'https://www.yahoo.com',
'https://www.bing.com',
'https://www.baidu.com',
'https://duckduckgo.com',
]
# Map concurrent executor with concurrent limit of 3
responses = await paco.map(fetch, urls, limit=3)
for res in responses:
print('Status:', res.status)
# Run in event loop
paco.run(fetch_urls())
Concurrent pipeline-style composition of transform functors over an iterable object.
.. code-block:: python
import paco
async def filterer(x):
return x < 8
async def mapper(x):
return x * 2
async def drop(x):
return x < 10
async def reducer(acc, x):
return acc + x
async def task(numbers):
return await (numbers
| paco.filter(filterer)
| paco.map(mapper)
| paco.dropwhile(drop)
| paco.reduce(reducer, initializer=0))
# Run in event loop
number = paco.run(task((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
print('Number:', number) # => 36
License
-------
MIT - Tomas Aparicio
.. _asynchronous: http://python.org
.. _asyncio: https://docs.python.org/3.5/library/asyncio.html
.. _Python: http://python.org
.. _annotated API reference: https://h2non.github.io/paco
.. _async/await: https://www.python.org/dev/peps/pep-0492/
.. _yield from: https://www.python.org/dev/peps/pep-0380/
.. _Composable pipelines: #examples
.. _itertools: https://docs.python.org/3/library/itertools.html
.. _functools: https://docs.python.org/3/library/functools.html
.. _PEP0525: https://www.python.org/dev/peps/pep-0525/
.. |Build Status| image:: https://travis-ci.org/h2non/paco.svg?branch=master
:target: https://travis-ci.org/h2non/paco
.. |PyPI| image:: https://img.shields.io/pypi/v/paco.svg?maxAge=2592000?style=flat-square
:target: https://pypi.python.org/pypi/paco
.. |Coverage Status| image:: https://coveralls.io/repos/github/h2non/paco/badge.svg?branch=master
:target: https://coveralls.io/github/h2non/paco?branch=master
.. |Documentation Status| image:: https://img.shields.io/badge/docs-latest-green.svg?style=flat
:target: http://paco.readthedocs.io/en/latest/?badge=latest
.. |Quality| image:: https://codeclimate.com/github/h2non/paco/badges/gpa.svg
:target: https://codeclimate.com/github/h2non/paco
.. |Stability| image:: https://img.shields.io/pypi/status/paco.svg
:target: https://pypi.python.org/pypi/paco
.. |Versions| image:: https://img.shields.io/pypi/pyversions/paco.svg
:target: https://pypi.python.org/pypi/paco
History
=======
v0.2.0 / 2017-10-21
-------------------
* refactor(api): API breaking change that modifies behavior by raising any legit exception generated by a coroutine.
* feat(examples): add examples file
* feat(v2): v2 pre-release, propagate raise exception if return_exceptions is False
* refactor(tests): add map error exception assertion test
* Merge branch 'master' of https://github.com/h2non/paco
* refactor(tests): add map error exception assertion test
* feat(docs): add sponsor banner
* feat(docs): add sponsor banner
* feat(LICENSE): update copyright year
* Update setup.py
v0.1.11 / 2017-01-28
--------------------
* feat(api): add ``paco.interval`` function.
v0.1.10 / 2017-01-11
--------------------
* fix(each.py,map.py): fixed `return_exceptions` kwarg
* fix(setup.py): add author email
* fix(Makefile): remove package file
v0.1.9 / 2017-01-06
-------------------
* feat(api): add identity function
* feat(#31): add thunk function
* feat(package): add wheel package distribution
* refactor(wraps): simplify implementation
* fix(History): remove indentation
v0.1.8 / 2016-12-29
-------------------
* feat(requirements): force upgrade setuptools
* feat(#29): support async iterable and generators
* fix(docs): link to examples
* chore(travis): use Python 3.6 stable release
0.1.7 / 2016-12-18
------------------
* feat(#26): add curry function.
0.1.6 / 2016-12-11
------------------
* feat(pipe): isolate pipe operator overload code
* refactor: decorator and util functions
* feat(#11): timeout limit context manager.
* refactor(core): several minor refactors
* fix(docs): comment out latex sphinx settings
* fix(docs): use current package version
* Documentation examples improvements (#27)
* feat(history): update
* feat: add pool length magic method
0.1.5 (2016-12-04)
------------------
* fix(#25): allow empty iterables in iterators functions, such as ``map``, ``filter``, ``reduce``.
0.1.4 (2016-11-28)
------------------
* fix(#24): explicitly pass loop instance to ``asyncio.wait``.
0.1.3 (2016-10-27)
------------------
* feat(#17): add ``flat_map`` function.
* feat(#18): add pipeline-style operator overloading composition.
0.1.2 (2016-10-25)
------------------
* fix(setup.py): fix pip installation.
* refactor(api): minor refactors in several functions and tests.
0.1.1 (2016-10-24)
------------------
* refactor(name): use new project name.
0.1.0 (2016-10-23)
------------------
* First version (beta)
====================================================================================================
Small and idiomatic utility library for coroutine-driven asynchronous generic programming in Python +3.4.
Built on top of `asyncio`_, ``paco`` provides missing capabilities from Python `stdlib`
in order to write asynchronous cooperative multitasking in a nice-ish way.
Also, paco aims to port some of `functools`_ and `itertools`_ standard functions to the asynchronous world.
``paco`` can be your utility belt to deal with asynchronous, I/O-bound, non-blocking concurrent code in a cleaner and idiomatic way.
.. raw:: html
<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/1MpD3pzt63uUeG43NP4tDHPY/h2non/paco'>
<img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/1MpD3pzt63uUeG43NP4tDHPY/h2non/paco.svg' /></a>
Features
--------
- Simple and idiomatic API, extending Python ``stdlib`` with async coroutines gotchas.
- Built-in configurable control-flow concurrency support (throttle).
- No fancy abstractions: it just works with the plain async coroutines.
- Useful iterables, decorators, functors and convenient helpers.
- Coroutine-based functional helpers: compose, throttle, partial, timeout, times, until, race...
- Asynchronous coroutine port of Python built-in functions: `filter`, `map`, `dropwhile`, `filterfalse`, `reduce`...
- Supports asynchronous iterables and generators (`PEP0525`_)
- Concurrent iterables and higher-order functions.
- Better ``asyncio.gather()`` and ``asyncio.wait()`` with optional concurrency control and ordered results.
- Works with both `async/await`_ and `yield from`_ coroutines syntax.
- Reliable coroutine timeout limit handler via context manager.
- Designed for intensive I/O-bound concurrent non-blocking tasks.
- Good interoperability with ``asyncio`` and Python ``stdlib`` functions.
- `Composable pipelines`_ of functors for transducers-like chain via ``|`` operator overloading.
- Small and dependency free.
- Compatible with Python +3.4.
Installation
------------
Using ``pip`` package manager:
.. code-block:: bash
pip install --upgrade paco
Or install the latest sources from Github:
.. code-block:: bash
pip install -e git+git://github.com/h2non/paco.git#egg=paco
API
---
- paco.ConcurrentExecutor_
- paco.apply_
- paco.compose_
- paco.concurrent_
- paco.constant_
- paco.curry_
- paco.defer_
- paco.dropwhile_
- paco.each_
- paco.every_
- paco.filter_
- paco.filterfalse_
- paco.flat_map_
- paco.gather_
- paco.identity_
- paco.interval_
- paco.map_
- paco.once_
- paco.partial_
- paco.race_
- paco.reduce_
- paco.repeat_
- paco.run_
- paco.series_
- paco.some_
- paco.throttle_
- paco.thunk_
- paco.timeout_
- paco.TimeoutLimit_
- paco.times_
- paco.until_
- paco.wait_
- paco.whilst_
- paco.wraps_
.. _paco.ConcurrentExecutor: http://paco.readthedocs.io/en/latest/api.html#paco.ConcurrentExecutor
.. _paco.apply: http://paco.readthedocs.io/en/latest/api.html#paco.apply
.. _paco.compose: http://paco.readthedocs.io/en/latest/api.html#paco.compose
.. _paco.concurrent: http://paco.readthedocs.io/en/latest/api.html#paco.concurrent
.. _paco.constant: http://paco.readthedocs.io/en/latest/api.html#paco.constant
.. _paco.curry: http://paco.readthedocs.io/en/latest/api.html#paco.curry
.. _paco.defer: http://paco.readthedocs.io/en/latest/api.html#paco.defer
.. _paco.dropwhile: http://paco.readthedocs.io/en/latest/api.html#paco.dropwhile
.. _paco.each: http://paco.readthedocs.io/en/latest/api.html#paco.each
.. _paco.every: http://paco.readthedocs.io/en/latest/api.html#paco.every
.. _paco.filter: http://paco.readthedocs.io/en/latest/api.html#paco.filter
.. _paco.filterfalse: http://paco.readthedocs.io/en/latest/api.html#paco.filterfalse
.. _paco.flat_map: http://paco.readthedocs.io/en/latest/api.html#paco.flat_map
.. _paco.gather: http://paco.readthedocs.io/en/latest/api.html#paco.gather
.. _paco.identity: http://paco.readthedocs.io/en/latest/api.html#paco.identity
.. _paco.interval: http://paco.readthedocs.io/en/latest/api.html#paco.interval
.. _paco.map: http://paco.readthedocs.io/en/latest/api.html#paco.map
.. _paco.once: http://paco.readthedocs.io/en/latest/api.html#paco.once
.. _paco.partial: http://paco.readthedocs.io/en/latest/api.html#paco.partial
.. _paco.race: http://paco.readthedocs.io/en/latest/api.html#paco.race
.. _paco.reduce: http://paco.readthedocs.io/en/latest/api.html#paco.reduce
.. _paco.repeat: http://paco.readthedocs.io/en/latest/api.html#paco.repeat
.. _paco.run: http://paco.readthedocs.io/en/latest/api.html#paco.run
.. _paco.series: http://paco.readthedocs.io/en/latest/api.html#paco.searies
.. _paco.some: http://paco.readthedocs.io/en/latest/api.html#paco.some
.. _paco.throttle: http://paco.readthedocs.io/en/latest/api.html#paco.throttle
.. _paco.thunk: http://paco.readthedocs.io/en/latest/api.html#paco.thunk
.. _paco.timeout: http://paco.readthedocs.io/en/latest/api.html#paco.timeout
.. _paco.TimeoutLimit: http://paco.readthedocs.io/en/latest/api.html#paco.TimeoutLimit
.. _paco.times: http://paco.readthedocs.io/en/latest/api.html#paco.times
.. _paco.until: http://paco.readthedocs.io/en/latest/api.html#paco.until
.. _paco.wait: http://paco.readthedocs.io/en/latest/api.html#paco.wait
.. _paco.whilst: http://paco.readthedocs.io/en/latest/api.html#paco.whilst
.. _paco.wraps: http://paco.readthedocs.io/en/latest/api.html#paco.wraps
Examples
^^^^^^^^
Asynchronously and concurrently execute multiple HTTP requests.
.. code-block:: python
import paco
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as res:
return res
async def fetch_urls():
urls = [
'https://www.google.com',
'https://www.yahoo.com',
'https://www.bing.com',
'https://www.baidu.com',
'https://duckduckgo.com',
]
# Map concurrent executor with concurrent limit of 3
responses = await paco.map(fetch, urls, limit=3)
for res in responses:
print('Status:', res.status)
# Run in event loop
paco.run(fetch_urls())
Concurrent pipeline-style composition of transform functors over an iterable object.
.. code-block:: python
import paco
async def filterer(x):
return x < 8
async def mapper(x):
return x * 2
async def drop(x):
return x < 10
async def reducer(acc, x):
return acc + x
async def task(numbers):
return await (numbers
| paco.filter(filterer)
| paco.map(mapper)
| paco.dropwhile(drop)
| paco.reduce(reducer, initializer=0))
# Run in event loop
number = paco.run(task((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
print('Number:', number) # => 36
License
-------
MIT - Tomas Aparicio
.. _asynchronous: http://python.org
.. _asyncio: https://docs.python.org/3.5/library/asyncio.html
.. _Python: http://python.org
.. _annotated API reference: https://h2non.github.io/paco
.. _async/await: https://www.python.org/dev/peps/pep-0492/
.. _yield from: https://www.python.org/dev/peps/pep-0380/
.. _Composable pipelines: #examples
.. _itertools: https://docs.python.org/3/library/itertools.html
.. _functools: https://docs.python.org/3/library/functools.html
.. _PEP0525: https://www.python.org/dev/peps/pep-0525/
.. |Build Status| image:: https://travis-ci.org/h2non/paco.svg?branch=master
:target: https://travis-ci.org/h2non/paco
.. |PyPI| image:: https://img.shields.io/pypi/v/paco.svg?maxAge=2592000?style=flat-square
:target: https://pypi.python.org/pypi/paco
.. |Coverage Status| image:: https://coveralls.io/repos/github/h2non/paco/badge.svg?branch=master
:target: https://coveralls.io/github/h2non/paco?branch=master
.. |Documentation Status| image:: https://img.shields.io/badge/docs-latest-green.svg?style=flat
:target: http://paco.readthedocs.io/en/latest/?badge=latest
.. |Quality| image:: https://codeclimate.com/github/h2non/paco/badges/gpa.svg
:target: https://codeclimate.com/github/h2non/paco
.. |Stability| image:: https://img.shields.io/pypi/status/paco.svg
:target: https://pypi.python.org/pypi/paco
.. |Versions| image:: https://img.shields.io/pypi/pyversions/paco.svg
:target: https://pypi.python.org/pypi/paco
History
=======
v0.2.0 / 2017-10-21
-------------------
* refactor(api): API breaking change that modifies behavior by raising any legit exception generated by a coroutine.
* feat(examples): add examples file
* feat(v2): v2 pre-release, propagate raise exception if return_exceptions is False
* refactor(tests): add map error exception assertion test
* Merge branch 'master' of https://github.com/h2non/paco
* refactor(tests): add map error exception assertion test
* feat(docs): add sponsor banner
* feat(docs): add sponsor banner
* feat(LICENSE): update copyright year
* Update setup.py
v0.1.11 / 2017-01-28
--------------------
* feat(api): add ``paco.interval`` function.
v0.1.10 / 2017-01-11
--------------------
* fix(each.py,map.py): fixed `return_exceptions` kwarg
* fix(setup.py): add author email
* fix(Makefile): remove package file
v0.1.9 / 2017-01-06
-------------------
* feat(api): add identity function
* feat(#31): add thunk function
* feat(package): add wheel package distribution
* refactor(wraps): simplify implementation
* fix(History): remove indentation
v0.1.8 / 2016-12-29
-------------------
* feat(requirements): force upgrade setuptools
* feat(#29): support async iterable and generators
* fix(docs): link to examples
* chore(travis): use Python 3.6 stable release
0.1.7 / 2016-12-18
------------------
* feat(#26): add curry function.
0.1.6 / 2016-12-11
------------------
* feat(pipe): isolate pipe operator overload code
* refactor: decorator and util functions
* feat(#11): timeout limit context manager.
* refactor(core): several minor refactors
* fix(docs): comment out latex sphinx settings
* fix(docs): use current package version
* Documentation examples improvements (#27)
* feat(history): update
* feat: add pool length magic method
0.1.5 (2016-12-04)
------------------
* fix(#25): allow empty iterables in iterators functions, such as ``map``, ``filter``, ``reduce``.
0.1.4 (2016-11-28)
------------------
* fix(#24): explicitly pass loop instance to ``asyncio.wait``.
0.1.3 (2016-10-27)
------------------
* feat(#17): add ``flat_map`` function.
* feat(#18): add pipeline-style operator overloading composition.
0.1.2 (2016-10-25)
------------------
* fix(setup.py): fix pip installation.
* refactor(api): minor refactors in several functions and tests.
0.1.1 (2016-10-24)
------------------
* refactor(name): use new project name.
0.1.0 (2016-10-23)
------------------
* First version (beta)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
paco-0.2.0.tar.gz
(26.5 kB
view hashes)
Built Distribution
paco-0.2.0-py2.py3-none-any.whl
(46.6 kB
view hashes)