Skip to main content

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)

Project details


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)

Uploaded Source

Built Distribution

paco-0.2.0-py2.py3-none-any.whl (46.6 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page