futured


Namefutured JSON
Version 1.4 PyPI version JSON
download
home_page
SummaryFunctional interface for concurrent futures, including asynchronous I/O.
upload_time2023-05-06 18:56:17
maintainer
docs_urlNone
author
requires_python>=3.8
licenseCopyright 2022 Aric Coady Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
keywords concurrent futures threads processes async asyncio
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![image](https://img.shields.io/pypi/v/futured.svg)](https://pypi.org/project/futured/)
![image](https://img.shields.io/pypi/pyversions/futured.svg)
[![image](https://pepy.tech/badge/futured)](https://pepy.tech/project/futured)
![image](https://img.shields.io/pypi/status/futured.svg)
[![image](https://github.com/coady/futured/workflows/build/badge.svg)](https://github.com/coady/futured/actions)
[![image](https://codecov.io/gh/coady/futured/branch/main/graph/badge.svg)](https://codecov.io/github/coady/futured)
[![image](https://github.com/coady/futured/workflows/codeql/badge.svg)](https://github.com/coady/futured/security/code-scanning)
[![image](https://img.shields.io/badge/code%20style-black-000000.svg)](https://pypi.org/project/black/)
[![image](http://mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)

Futured provides a consistent interface for concurrent functional programming in Python. It wraps any callable to return a `concurrent.futures.Future`, wraps any async coroutine to return an `asyncio.Future`, and provides concurrent iterators and context managers for futures.

## Usage
### threaded, processed
Transform any callable into one which runs in a thread or process pool, and returns a future.

```python
from futured import threaded, processed
import httpx

fetch = threaded(httpx.Client().get)
fetch(url)  # return Future

fs = (fetch(url + path) for path in paths)
threaded.results(fs)  # generate results from futures
threaded.results(fs, timeout=...)  # generate results as completed

fetch.map(urls)  # generate results in order
fetch.map(urls, timeout=...)  # generate results as completed
fetch.mapzip(urls)  # generate (url, result) pairs as completed
```

Thread and process pool executors may be used as context managers, customized with options, and reused with different callables.

```python
threaded(max_workers=...)(func, ...)
processed(max_workers=...)(func, ...)
```

`futured` classes have a `waiting` context manager which collects results from tasks. Futures can be registered at creation, or appended to the list of tasks.

```python
with threaded.waiting(*fs) as tasks:
    tasks.append(future)
tasks  # list of completed results
```

`futured` classes provide a `tasks` interface which generalizes `futures.as_completed` and `futures.wait`, while allowing the set of tasks to be modified, e.g., for retries.

```python
threaded.tasks(fs, timeout=...)  # mutable set of running tasks which iterate as completed
```

### asynced
The same interface works for `asyncio`.

```python
from futured import asynced
import httpx

fetch = asynced(httpx.AsyncClient().get)
fetch(url)  # return coroutine

asynced.results(fs)  # generate results from futures
asynced.results(fs, timeout=...)  # generate results as completed

fetch.map(urls)  # generate results in order
fetch.map(urls, timeout=...)  # generate results as completed
fetch.mapzip(urls)  # generate (url, result) pairs as completed
```

`asynced` provides utilities for calling coroutines from a synchronous context. `waiting` is similar to [trio's nursery](https://trio.readthedocs.io/en/latest/reference-core.html#nurseries-and-spawning), but returns results from a synchronous `with` block.

```python
asynced.run(async_func, ...)  # call and run until complete
asynced.run(async_gen, ...)  # call and run synchronous iterator
with asynced.waiting(*fs) as tasks:  # concurrent coroutines completed in a block
asynced.tasks(fs, timeout=...)  # mutable set of running tasks which iterate as completed
```

### decorators
Naturally `futured` wrappers can be used as decorators, but arguments can also be partially bound.

```python
@threaded
def slow():
   ...

fetch = threaded(httpx.Client().get, url)
fetch(params=...)
```

Methods are supported, as well as a `decorated` utility for automatically subclassing.

```python
from futured import decorated

FutureClient = decorated(httpx.Client, request=threaded)

 # equivalent to
class FutureClient(httpx.Client):
    request = threaded(httpx.Client.request)
```

### command
`command` wraps `subprocess.Popen` to provide a `Future` compatible interface.

```python
from futured import futured, command

command('ls').result()  # return stdout or raises stderr
command('ls').pipe('wc')  # pipes into next command, or | ('wc',... )
for line in command('ls'):  # iterable lines
command.coroutine('ls')  # return coroutine

futured(command, 'ls')  # supports `map` interface
asynced(command.coroutine, 'ls')  # supports `map` interface with timeout
```

### forked
`forked` allows iteration in separate child processes.

```python
from futured import forked

for value in forked(values, max_workers=...):
    # in a child process
 # in parent after children have exited
```

## Installation
```console
% pip install futured
```

## Tests
100% branch coverage.

```console
% pytest [--cov]
```

## Changes
1.4

* Python >=3.8 required

1.3

* Python >=3.7 required
* Python 3.10 event loop changes
* Streams replaced with tasks

1.2

* Python >=3.6 required

1.1

* Stream completed futures from a pending pool

1.0

* Executed functions are context managers
* `starmap` supported

0.3

* `forked` has optional maximum number of workers
* `waiting` context manager
* `command` pipes (`|`)
* `distributed.Client` support

0.2

* `command.coroutine` creates asyncio subprocesses
* `futured.mapzip` generates results zipped with arguments
* `asynced.run` supports asynchronous iterators

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "futured",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "concurrent,futures,threads,processes,async,asyncio",
    "author": "",
    "author_email": "Aric Coady <aric.coady@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/cd/af/ff3a1a2f4ac4b12939a68ef08c5909c465a5ec1d051b1a2515923bb49ac8/futured-1.4.tar.gz",
    "platform": null,
    "description": "[![image](https://img.shields.io/pypi/v/futured.svg)](https://pypi.org/project/futured/)\n![image](https://img.shields.io/pypi/pyversions/futured.svg)\n[![image](https://pepy.tech/badge/futured)](https://pepy.tech/project/futured)\n![image](https://img.shields.io/pypi/status/futured.svg)\n[![image](https://github.com/coady/futured/workflows/build/badge.svg)](https://github.com/coady/futured/actions)\n[![image](https://codecov.io/gh/coady/futured/branch/main/graph/badge.svg)](https://codecov.io/github/coady/futured)\n[![image](https://github.com/coady/futured/workflows/codeql/badge.svg)](https://github.com/coady/futured/security/code-scanning)\n[![image](https://img.shields.io/badge/code%20style-black-000000.svg)](https://pypi.org/project/black/)\n[![image](http://mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)\n\nFutured provides a consistent interface for concurrent functional programming in Python. It wraps any callable to return a `concurrent.futures.Future`, wraps any async coroutine to return an `asyncio.Future`, and provides concurrent iterators and context managers for futures.\n\n## Usage\n### threaded, processed\nTransform any callable into one which runs in a thread or process pool, and returns a future.\n\n```python\nfrom futured import threaded, processed\nimport httpx\n\nfetch = threaded(httpx.Client().get)\nfetch(url)  # return Future\n\nfs = (fetch(url + path) for path in paths)\nthreaded.results(fs)  # generate results from futures\nthreaded.results(fs, timeout=...)  # generate results as completed\n\nfetch.map(urls)  # generate results in order\nfetch.map(urls, timeout=...)  # generate results as completed\nfetch.mapzip(urls)  # generate (url, result) pairs as completed\n```\n\nThread and process pool executors may be used as context managers, customized with options, and reused with different callables.\n\n```python\nthreaded(max_workers=...)(func, ...)\nprocessed(max_workers=...)(func, ...)\n```\n\n`futured` classes have a `waiting` context manager which collects results from tasks. Futures can be registered at creation, or appended to the list of tasks.\n\n```python\nwith threaded.waiting(*fs) as tasks:\n    tasks.append(future)\ntasks  # list of completed results\n```\n\n`futured` classes provide a `tasks` interface which generalizes `futures.as_completed` and `futures.wait`, while allowing the set of tasks to be modified, e.g., for retries.\n\n```python\nthreaded.tasks(fs, timeout=...)  # mutable set of running tasks which iterate as completed\n```\n\n### asynced\nThe same interface works for `asyncio`.\n\n```python\nfrom futured import asynced\nimport httpx\n\nfetch = asynced(httpx.AsyncClient().get)\nfetch(url)  # return coroutine\n\nasynced.results(fs)  # generate results from futures\nasynced.results(fs, timeout=...)  # generate results as completed\n\nfetch.map(urls)  # generate results in order\nfetch.map(urls, timeout=...)  # generate results as completed\nfetch.mapzip(urls)  # generate (url, result) pairs as completed\n```\n\n`asynced` provides utilities for calling coroutines from a synchronous context. `waiting` is similar to [trio's nursery](https://trio.readthedocs.io/en/latest/reference-core.html#nurseries-and-spawning), but returns results from a synchronous `with` block.\n\n```python\nasynced.run(async_func, ...)  # call and run until complete\nasynced.run(async_gen, ...)  # call and run synchronous iterator\nwith asynced.waiting(*fs) as tasks:  # concurrent coroutines completed in a block\nasynced.tasks(fs, timeout=...)  # mutable set of running tasks which iterate as completed\n```\n\n### decorators\nNaturally `futured` wrappers can be used as decorators, but arguments can also be partially bound.\n\n```python\n@threaded\ndef slow():\n   ...\n\nfetch = threaded(httpx.Client().get, url)\nfetch(params=...)\n```\n\nMethods are supported, as well as a `decorated` utility for automatically subclassing.\n\n```python\nfrom futured import decorated\n\nFutureClient = decorated(httpx.Client, request=threaded)\n\n # equivalent to\nclass FutureClient(httpx.Client):\n    request = threaded(httpx.Client.request)\n```\n\n### command\n`command` wraps `subprocess.Popen` to provide a `Future` compatible interface.\n\n```python\nfrom futured import futured, command\n\ncommand('ls').result()  # return stdout or raises stderr\ncommand('ls').pipe('wc')  # pipes into next command, or | ('wc',... )\nfor line in command('ls'):  # iterable lines\ncommand.coroutine('ls')  # return coroutine\n\nfutured(command, 'ls')  # supports `map` interface\nasynced(command.coroutine, 'ls')  # supports `map` interface with timeout\n```\n\n### forked\n`forked` allows iteration in separate child processes.\n\n```python\nfrom futured import forked\n\nfor value in forked(values, max_workers=...):\n    # in a child process\n # in parent after children have exited\n```\n\n## Installation\n```console\n% pip install futured\n```\n\n## Tests\n100% branch coverage.\n\n```console\n% pytest [--cov]\n```\n\n## Changes\n1.4\n\n* Python >=3.8 required\n\n1.3\n\n* Python >=3.7 required\n* Python 3.10 event loop changes\n* Streams replaced with tasks\n\n1.2\n\n* Python >=3.6 required\n\n1.1\n\n* Stream completed futures from a pending pool\n\n1.0\n\n* Executed functions are context managers\n* `starmap` supported\n\n0.3\n\n* `forked` has optional maximum number of workers\n* `waiting` context manager\n* `command` pipes (`|`)\n* `distributed.Client` support\n\n0.2\n\n* `command.coroutine` creates asyncio subprocesses\n* `futured.mapzip` generates results zipped with arguments\n* `asynced.run` supports asynchronous iterators\n",
    "bugtrack_url": null,
    "license": "Copyright 2022 Aric Coady  Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ",
    "summary": "Functional interface for concurrent futures, including asynchronous I/O.",
    "version": "1.4",
    "project_urls": {
        "Documentation": "https://coady.github.io/futured",
        "Homepage": "https://github.com/coady/futured"
    },
    "split_keywords": [
        "concurrent",
        "futures",
        "threads",
        "processes",
        "async",
        "asyncio"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "68f498814a163a3bc10a46a106f067c33ce91c0230741a8c1e27b42c62bd4a91",
                "md5": "f939018dd3a1b058e55aab1e9d6499ee",
                "sha256": "c2c605444cfed41a00b9349bd8c0fb5dcac37742b0f4133d4f43baf64f71267f"
            },
            "downloads": -1,
            "filename": "futured-1.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f939018dd3a1b058e55aab1e9d6499ee",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 6826,
            "upload_time": "2023-05-06T18:56:16",
            "upload_time_iso_8601": "2023-05-06T18:56:16.109209Z",
            "url": "https://files.pythonhosted.org/packages/68/f4/98814a163a3bc10a46a106f067c33ce91c0230741a8c1e27b42c62bd4a91/futured-1.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cdafff3a1a2f4ac4b12939a68ef08c5909c465a5ec1d051b1a2515923bb49ac8",
                "md5": "480d830789b85bc8d4a9fb8329a2cd52",
                "sha256": "156c85e16a658b7d0236ecc3acfffc31abaf81caaa357c68b0250b6579a7b747"
            },
            "downloads": -1,
            "filename": "futured-1.4.tar.gz",
            "has_sig": false,
            "md5_digest": "480d830789b85bc8d4a9fb8329a2cd52",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 7778,
            "upload_time": "2023-05-06T18:56:17",
            "upload_time_iso_8601": "2023-05-06T18:56:17.326493Z",
            "url": "https://files.pythonhosted.org/packages/cd/af/ff3a1a2f4ac4b12939a68ef08c5909c465a5ec1d051b1a2515923bb49ac8/futured-1.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-06 18:56:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "coady",
    "github_project": "futured",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "futured"
}
        
Elapsed time: 0.06797s