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"
}