cs-naysync


Namecs-naysync JSON
Version 20241221.1 PyPI version JSON
download
home_pageNone
SummaryAn attempt at comingling async-code and nonasync-code-in-a-thread in an argonomic way.
upload_time2024-12-20 23:53:30
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseGNU General Public License v3 or later (GPLv3+)
keywords python3
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            An attempt at comingling async-code and nonasync-code-in-a-thread in an argonomic way.

*Latest release 20241221.1*:
Doc fix for amap().

One of the difficulties in adapting non-async code for use in
an async world is that anything asynchronous needs to be turtles
all the way down: a single blocking synchronous call anywhere
in the call stack blocks the async event loop.

This module presently provides:
- `@afunc`: a decorator to make a synchronous function asynchronous
- `@agen`: a decorator to make a synchronous generator asynchronous
- `amap(func,iterable)`: asynchronous mapping of `func` over an iterable
- `async_iter(iterable)`: return an asynchronous iterator of an iterable

## <a name="afunc"></a>`afunc(*da, **dkw)`

A decorator for a synchronous function which turns it into
an asynchronous function.

Example:

    @afunc
    def func(count):
        time.sleep(count)
        return count

    slept = await func(5)

## <a name="agen"></a>`agen(*da, **dkw)`

A decorator for a synchronous generator which turns it into
an asynchronous generator.
Exceptions in the synchronous generator are reraised in the asynchronous
generator.

Example:

    @agen
    def gen(count):
        for i in range(count):
            yield i
            time.sleep(1.0)

    async for item in gen(5):
        print(item)

## <a name="amap"></a>`amap(func: Callable[[Any], Any], it: Iterable, concurrent=False, unordered=False, indexed=False)`

An asynchronous generator yielding the results of `func(item)`
for each `item` in the iterable `it`.

`func` may be a synchronous or asynchronous callable.

If `concurrent` is `False` (the default), run each `func(item)`
call in series.

If `concurrent` is true run the function calls as `asyncio`
tasks concurrently.
If `unordered` is true (default `False`) yield results as
they arrive, otherwise yield results in the order of the items
in `it`, but as they arrive - tasks still evaluate concurrently
if `concurrent` is true.

If `indexed` is true (default `False`) yield 2-tuples of
`(i,result)` instead of just `result`, where `i` is the index
if each item from `it` counting from `0`.

Example of an async function to fetch URLs in parallel.

    async def get_urls(urls : List[str]):
        """ Fetch `urls` in parallel.
            Yield `(url,response)` 2-tuples.
        """
        async for i, response in amap(
            requests.get, urls,
            concurrent=True, unordered=True, indexed=True,
        ):
            yield urls[i], response

## <a name="async_iter"></a>`async_iter(it: Iterable)`

Return an asynchronous iterator yielding items from the iterable `it`.

# Release Log



*Release 20241221.1*:
Doc fix for amap().

*Release 20241221*:
* Simpler implementation of @afunc.
* Simplify implementation of @agen by using async_iter.
* Docstring improvements.

*Release 20241220*:
* New async_iter(Iterable) returning an asynchronous iterator of a synchronous iterable.
* New amap(func,iterable) asynchronously mapping a function over an iterable.

*Release 20241215*:
* @afunc: now uses asyncio.to_thread() instead of wrapping @agen, drop the decorator parameters since no queue or polling are now used.
* @agen: nonpolling implementation - now uses asyncio.to_thread() for the next(genfunc) step, drop the decorator parameters since no queue or polling are now used.

*Release 20241214.1*:
Doc update.

*Release 20241214*:
Initial release with @agen and @afunc decorators.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "cs-naysync",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python3",
    "author": null,
    "author_email": "Cameron Simpson <cs@cskk.id.au>",
    "download_url": "https://files.pythonhosted.org/packages/5a/c7/50afdb3f2a955e8e110e97265d6679b51a28c131db0e36895693dcec0812/cs_naysync-20241221.1.tar.gz",
    "platform": null,
    "description": "An attempt at comingling async-code and nonasync-code-in-a-thread in an argonomic way.\n\n*Latest release 20241221.1*:\nDoc fix for amap().\n\nOne of the difficulties in adapting non-async code for use in\nan async world is that anything asynchronous needs to be turtles\nall the way down: a single blocking synchronous call anywhere\nin the call stack blocks the async event loop.\n\nThis module presently provides:\n- `@afunc`: a decorator to make a synchronous function asynchronous\n- `@agen`: a decorator to make a synchronous generator asynchronous\n- `amap(func,iterable)`: asynchronous mapping of `func` over an iterable\n- `async_iter(iterable)`: return an asynchronous iterator of an iterable\n\n## <a name=\"afunc\"></a>`afunc(*da, **dkw)`\n\nA decorator for a synchronous function which turns it into\nan asynchronous function.\n\nExample:\n\n    @afunc\n    def func(count):\n        time.sleep(count)\n        return count\n\n    slept = await func(5)\n\n## <a name=\"agen\"></a>`agen(*da, **dkw)`\n\nA decorator for a synchronous generator which turns it into\nan asynchronous generator.\nExceptions in the synchronous generator are reraised in the asynchronous\ngenerator.\n\nExample:\n\n    @agen\n    def gen(count):\n        for i in range(count):\n            yield i\n            time.sleep(1.0)\n\n    async for item in gen(5):\n        print(item)\n\n## <a name=\"amap\"></a>`amap(func: Callable[[Any], Any], it: Iterable, concurrent=False, unordered=False, indexed=False)`\n\nAn asynchronous generator yielding the results of `func(item)`\nfor each `item` in the iterable `it`.\n\n`func` may be a synchronous or asynchronous callable.\n\nIf `concurrent` is `False` (the default), run each `func(item)`\ncall in series.\n\nIf `concurrent` is true run the function calls as `asyncio`\ntasks concurrently.\nIf `unordered` is true (default `False`) yield results as\nthey arrive, otherwise yield results in the order of the items\nin `it`, but as they arrive - tasks still evaluate concurrently\nif `concurrent` is true.\n\nIf `indexed` is true (default `False`) yield 2-tuples of\n`(i,result)` instead of just `result`, where `i` is the index\nif each item from `it` counting from `0`.\n\nExample of an async function to fetch URLs in parallel.\n\n    async def get_urls(urls : List[str]):\n        \"\"\" Fetch `urls` in parallel.\n            Yield `(url,response)` 2-tuples.\n        \"\"\"\n        async for i, response in amap(\n            requests.get, urls,\n            concurrent=True, unordered=True, indexed=True,\n        ):\n            yield urls[i], response\n\n## <a name=\"async_iter\"></a>`async_iter(it: Iterable)`\n\nReturn an asynchronous iterator yielding items from the iterable `it`.\n\n# Release Log\n\n\n\n*Release 20241221.1*:\nDoc fix for amap().\n\n*Release 20241221*:\n* Simpler implementation of @afunc.\n* Simplify implementation of @agen by using async_iter.\n* Docstring improvements.\n\n*Release 20241220*:\n* New async_iter(Iterable) returning an asynchronous iterator of a synchronous iterable.\n* New amap(func,iterable) asynchronously mapping a function over an iterable.\n\n*Release 20241215*:\n* @afunc: now uses asyncio.to_thread() instead of wrapping @agen, drop the decorator parameters since no queue or polling are now used.\n* @agen: nonpolling implementation - now uses asyncio.to_thread() for the next(genfunc) step, drop the decorator parameters since no queue or polling are now used.\n\n*Release 20241214.1*:\nDoc update.\n\n*Release 20241214*:\nInitial release with @agen and @afunc decorators.\n",
    "bugtrack_url": null,
    "license": "GNU General Public License v3 or later (GPLv3+)",
    "summary": "An attempt at comingling async-code and nonasync-code-in-a-thread in an argonomic way.",
    "version": "20241221.1",
    "project_urls": {
        "MonoRepo Commits": "https://bitbucket.org/cameron_simpson/css/commits/branch/main",
        "Monorepo Git Mirror": "https://github.com/cameron-simpson/css",
        "Monorepo Hg/Mercurial Mirror": "https://hg.sr.ht/~cameron-simpson/css",
        "Source": "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/naysync.py"
    },
    "split_keywords": [
        "python3"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "26bd5b059b76d6a1722830d73217938fc29fe1b5e65efb8e78f83ca621c14956",
                "md5": "b2d7f29206ddb7077e5ff380e0cdc4cd",
                "sha256": "d6c63c38e3eb143351ada515446bc8376fa9d8a5ed20d55a071293b5407e0115"
            },
            "downloads": -1,
            "filename": "cs_naysync-20241221.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b2d7f29206ddb7077e5ff380e0cdc4cd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 5249,
            "upload_time": "2024-12-20T23:53:29",
            "upload_time_iso_8601": "2024-12-20T23:53:29.020364Z",
            "url": "https://files.pythonhosted.org/packages/26/bd/5b059b76d6a1722830d73217938fc29fe1b5e65efb8e78f83ca621c14956/cs_naysync-20241221.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5ac750afdb3f2a955e8e110e97265d6679b51a28c131db0e36895693dcec0812",
                "md5": "22faad7e28a1827c03aa8cbdbc3c3608",
                "sha256": "d558ffb4309959026f45e69df66627657f9d54138e567f0f5148443b76621ccb"
            },
            "downloads": -1,
            "filename": "cs_naysync-20241221.1.tar.gz",
            "has_sig": false,
            "md5_digest": "22faad7e28a1827c03aa8cbdbc3c3608",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 4890,
            "upload_time": "2024-12-20T23:53:30",
            "upload_time_iso_8601": "2024-12-20T23:53:30.210851Z",
            "url": "https://files.pythonhosted.org/packages/5a/c7/50afdb3f2a955e8e110e97265d6679b51a28c131db0e36895693dcec0812/cs_naysync-20241221.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-20 23:53:30",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "cameron-simpson",
    "github_project": "css",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "cs-naysync"
}
        
Elapsed time: 0.40085s