asyncly


Nameasyncly JSON
Version 0.3.2 PyPI version JSON
download
home_pagehttps://github.com/andy-takker/asyncly
SummarySimple HTTP client and server for your integrations based on aiohttp
upload_time2024-11-03 21:14:50
maintainerNone
docs_urlNone
authorSergey Natalenko
requires_python<4.0,>=3.10
licenseMIT
keywords aiohttp http client
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Asyncly
=======

.. image:: https://img.shields.io/pypi/v/asyncly.svg
   :target: https://pypi.python.org/pypi/asyncly/
   :alt: Latest Version

.. image:: https://img.shields.io/pypi/wheel/asyncly.svg
   :target: https://pypi.python.org/pypi/asyncly/

.. image:: https://img.shields.io/pypi/pyversions/asyncly.svg
   :target: https://pypi.python.org/pypi/asyncly/

.. image:: https://img.shields.io/pypi/l/asyncly.svg
   :target: https://pypi.python.org/pypi/asyncly/

Simple HTTP client and server for your integrations based on aiohttp_.

Installation
------------

Installation is possible in standard ways, such as PyPI or
installation from a git repository directly.

Installing from PyPI_:

.. code-block:: bash

   pip install asyncly

Installing from github.com:

.. code-block:: bash

   pip install git+https://github.com/andy-takker/asyncly

The package contains several extras and you can install additional dependencies
if you specify them in this way.

For example, with msgspec_:

.. code-block:: bash

   pip install "asyncly[msgspec]"

Complete table of extras below:

+-------------------------------------+----------------------------------+
| example                             | description                      |
+=====================================+==================================+
| ``pip install "asyncly[msgspec]"``  | For using msgspec_ structs       |
+-------------------------------------+----------------------------------+
| ``pip install "asyncly[orjson]"``   | For fast parsing json by orjson_ |
+-------------------------------------+----------------------------------+
| ``pip install "asyncly[pydantic]"`` | For using pydantic_ models       |
+-------------------------------------+----------------------------------+

Quick start guide
-----------------

HttpClient
~~~~~~~~~~~~~~

Simple HTTP Client for `https://catfact.ninja`. See full example in `examples/catfact_client.py`_

.. code-block:: python

   from asyncly import DEFAULT_TIMEOUT, BaseHttpClient, ResponseHandlersType
   from asyncly.client.handlers.pydantic import parse_model
   from asyncly.client.timeout import TimeoutType


   class CatfactClient(BaseHttpClient):
       RANDOM_CATFACT_HANDLERS: ResponseHandlersType = MappingProxyType(
            {
                 HTTPStatus.OK: parse_model(CatfactSchema),
            }
       )

      async def fetch_random_cat_fact(
          self,
          timeout: TimeoutType = DEFAULT_TIMEOUT,
      ) -> CatfactSchema:
          return await self._make_req(
              method=hdrs.METH_GET,
              url=self._url / "fact",
              handlers=self.RANDOM_CATFACT_HANDLERS,
              timeout=timeout,
          )

Test Async Server for client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For the HTTP client, we create a server to which he will go and simulate real
responses. You can dynamically change the responses from the server in
a specific test.

Let's prepare the fixtures:

.. code-block:: python

   @pytest.fixture
   async def catafact_service() -> AsyncIterator[MockService]:
       routes = [
           MockRoute("GET", "/fact", "random_catfact"),
       ]
       async with start_service(routes) as service:
           service.register(
               "random_catfact",
               JsonResponse({"fact": "test", "length": 4}),
           )
           yield service


   @pytest.fixture
   def catfact_url(catafact_service: MockService) -> URL:
       return catafact_service.url


   @pytest.fixture
   async def catfact_client(catfact_url: URL) -> AsyncIterator[CatfactClient]:
       async with ClientSession() as session:
           client = CatfactClient(
               client_name="catfact",
               session=session,
               url=catfact_url,
           )
           yield client

Now we can use them in tests. See full example in `examples/test_catfact_client.py`_

.. code-block:: python

    async def test_fetch_random_catfact(catfact_client: CatfactClient) -> None:
        # use default registered handler
        fact = await catfact_client.fetch_random_cat_fact()
        assert fact == CatfactSchema(fact="test", length=4)


    async def test_fetch_random_catfact_timeout(
        catfact_client: CatfactClient,
        catafact_service: MockService,
    ) -> None:
        # change default registered handler to time error handler
        catafact_service.register(
            "random_catfact",
            LatencyResponse(
                wrapped=JsonResponse({"fact": "test", "length": 4}),
                latency=1.5,
            ),
        )
        with pytest.raises(asyncio.TimeoutError):
            await catfact_client.fetch_random_cat_fact(timeout=1)


.. _PyPI: https://pypi.org/
.. _aiohttp: https://pypi.org/project/aiohttp/
.. _msgspec: https://github.com/jcrist/msgspec
.. _orjson: https://github.com/ijl/orjson
.. _pydantic: https://github.com/pydantic/pydantic

.. _examples/catfact_client.py: https://github.com/andy-takker/asyncly/blob/master/examples/catfact_client.py
.. _examples/test_catfact_client.py: https://github.com/andy-takker/asyncly/blob/master/examples/test_catfact_client.py

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/andy-takker/asyncly",
    "name": "asyncly",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": "aiohttp, http, client",
    "author": "Sergey Natalenko",
    "author_email": "sergey.natalenko@mail.ru",
    "download_url": "https://files.pythonhosted.org/packages/f9/78/f1a9dc19c6d2f24eca585c4f9ecc7aed916ac6f30ec01fc5ad0142101416/asyncly-0.3.2.tar.gz",
    "platform": null,
    "description": "Asyncly\n=======\n\n.. image:: https://img.shields.io/pypi/v/asyncly.svg\n   :target: https://pypi.python.org/pypi/asyncly/\n   :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/wheel/asyncly.svg\n   :target: https://pypi.python.org/pypi/asyncly/\n\n.. image:: https://img.shields.io/pypi/pyversions/asyncly.svg\n   :target: https://pypi.python.org/pypi/asyncly/\n\n.. image:: https://img.shields.io/pypi/l/asyncly.svg\n   :target: https://pypi.python.org/pypi/asyncly/\n\nSimple HTTP client and server for your integrations based on aiohttp_.\n\nInstallation\n------------\n\nInstallation is possible in standard ways, such as PyPI or\ninstallation from a git repository directly.\n\nInstalling from PyPI_:\n\n.. code-block:: bash\n\n   pip install asyncly\n\nInstalling from github.com:\n\n.. code-block:: bash\n\n   pip install git+https://github.com/andy-takker/asyncly\n\nThe package contains several extras and you can install additional dependencies\nif you specify them in this way.\n\nFor example, with msgspec_:\n\n.. code-block:: bash\n\n   pip install \"asyncly[msgspec]\"\n\nComplete table of extras below:\n\n+-------------------------------------+----------------------------------+\n| example                             | description                      |\n+=====================================+==================================+\n| ``pip install \"asyncly[msgspec]\"``  | For using msgspec_ structs       |\n+-------------------------------------+----------------------------------+\n| ``pip install \"asyncly[orjson]\"``   | For fast parsing json by orjson_ |\n+-------------------------------------+----------------------------------+\n| ``pip install \"asyncly[pydantic]\"`` | For using pydantic_ models       |\n+-------------------------------------+----------------------------------+\n\nQuick start guide\n-----------------\n\nHttpClient\n~~~~~~~~~~~~~~\n\nSimple HTTP Client for `https://catfact.ninja`. See full example in `examples/catfact_client.py`_\n\n.. code-block:: python\n\n   from asyncly import DEFAULT_TIMEOUT, BaseHttpClient, ResponseHandlersType\n   from asyncly.client.handlers.pydantic import parse_model\n   from asyncly.client.timeout import TimeoutType\n\n\n   class CatfactClient(BaseHttpClient):\n       RANDOM_CATFACT_HANDLERS: ResponseHandlersType = MappingProxyType(\n            {\n                 HTTPStatus.OK: parse_model(CatfactSchema),\n            }\n       )\n\n      async def fetch_random_cat_fact(\n          self,\n          timeout: TimeoutType = DEFAULT_TIMEOUT,\n      ) -> CatfactSchema:\n          return await self._make_req(\n              method=hdrs.METH_GET,\n              url=self._url / \"fact\",\n              handlers=self.RANDOM_CATFACT_HANDLERS,\n              timeout=timeout,\n          )\n\nTest Async Server for client\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFor the HTTP client, we create a server to which he will go and simulate real\nresponses. You can dynamically change the responses from the server in\na specific test.\n\nLet's prepare the fixtures:\n\n.. code-block:: python\n\n   @pytest.fixture\n   async def catafact_service() -> AsyncIterator[MockService]:\n       routes = [\n           MockRoute(\"GET\", \"/fact\", \"random_catfact\"),\n       ]\n       async with start_service(routes) as service:\n           service.register(\n               \"random_catfact\",\n               JsonResponse({\"fact\": \"test\", \"length\": 4}),\n           )\n           yield service\n\n\n   @pytest.fixture\n   def catfact_url(catafact_service: MockService) -> URL:\n       return catafact_service.url\n\n\n   @pytest.fixture\n   async def catfact_client(catfact_url: URL) -> AsyncIterator[CatfactClient]:\n       async with ClientSession() as session:\n           client = CatfactClient(\n               client_name=\"catfact\",\n               session=session,\n               url=catfact_url,\n           )\n           yield client\n\nNow we can use them in tests. See full example in `examples/test_catfact_client.py`_\n\n.. code-block:: python\n\n    async def test_fetch_random_catfact(catfact_client: CatfactClient) -> None:\n        # use default registered handler\n        fact = await catfact_client.fetch_random_cat_fact()\n        assert fact == CatfactSchema(fact=\"test\", length=4)\n\n\n    async def test_fetch_random_catfact_timeout(\n        catfact_client: CatfactClient,\n        catafact_service: MockService,\n    ) -> None:\n        # change default registered handler to time error handler\n        catafact_service.register(\n            \"random_catfact\",\n            LatencyResponse(\n                wrapped=JsonResponse({\"fact\": \"test\", \"length\": 4}),\n                latency=1.5,\n            ),\n        )\n        with pytest.raises(asyncio.TimeoutError):\n            await catfact_client.fetch_random_cat_fact(timeout=1)\n\n\n.. _PyPI: https://pypi.org/\n.. _aiohttp: https://pypi.org/project/aiohttp/\n.. _msgspec: https://github.com/jcrist/msgspec\n.. _orjson: https://github.com/ijl/orjson\n.. _pydantic: https://github.com/pydantic/pydantic\n\n.. _examples/catfact_client.py: https://github.com/andy-takker/asyncly/blob/master/examples/catfact_client.py\n.. _examples/test_catfact_client.py: https://github.com/andy-takker/asyncly/blob/master/examples/test_catfact_client.py\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Simple HTTP client and server for your integrations based on aiohttp",
    "version": "0.3.2",
    "project_urls": {
        "Bug Tracker": "https://github.com/andy-takker/v/issues",
        "Homepage": "https://github.com/andy-takker/asyncly",
        "Source": "https://github.com/andy-takker/asyncly"
    },
    "split_keywords": [
        "aiohttp",
        " http",
        " client"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "44a71f993e40191696e31979181a35ed73f087597a22b65e299a59377d455966",
                "md5": "55734f6961d084057fbb6321422bc52d",
                "sha256": "0fc6b218c133880fecc35264ac2bbb481a9fd7ffd4b376016156f3000cd72c30"
            },
            "downloads": -1,
            "filename": "asyncly-0.3.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "55734f6961d084057fbb6321422bc52d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 10238,
            "upload_time": "2024-11-03T21:14:49",
            "upload_time_iso_8601": "2024-11-03T21:14:49.720700Z",
            "url": "https://files.pythonhosted.org/packages/44/a7/1f993e40191696e31979181a35ed73f087597a22b65e299a59377d455966/asyncly-0.3.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f978f1a9dc19c6d2f24eca585c4f9ecc7aed916ac6f30ec01fc5ad0142101416",
                "md5": "8847710129a15dcbfd4df0a086d64b22",
                "sha256": "5c8dcf4e9f6a6abfe36d4737fcec2294a2dba04132e3694737aa6aeed69f28ed"
            },
            "downloads": -1,
            "filename": "asyncly-0.3.2.tar.gz",
            "has_sig": false,
            "md5_digest": "8847710129a15dcbfd4df0a086d64b22",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 8007,
            "upload_time": "2024-11-03T21:14:50",
            "upload_time_iso_8601": "2024-11-03T21:14:50.807306Z",
            "url": "https://files.pythonhosted.org/packages/f9/78/f1a9dc19c6d2f24eca585c4f9ecc7aed916ac6f30ec01fc5ad0142101416/asyncly-0.3.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-03 21:14:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "andy-takker",
    "github_project": "asyncly",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "asyncly"
}
        
Elapsed time: 0.69277s