Name | meatie JSON |
Version |
0.1.20
JSON |
| download |
home_page | https://github.com/pmateusz/meatie |
Summary | Meatie is a Python typed REST client library that eliminates the need for boilerplate code when integrating with external APIs. The library generates code for calling a REST API based on method signatures annotated with type hints. Meatie abstracts away mechanics related to HTTP communication, such as building URLs, encoding query parameters, parsing, and dumping Pydantic models. With some modest additional configuration effort, generated HTTP clients offer rate limiting, retries, and caching. |
upload_time | 2025-02-04 07:39:09 |
maintainer | None |
docs_url | None |
author | pmateusz |
requires_python | >=3.9 |
license | BSD-3-Clause |
keywords |
http-client
api-client
rest
http
api
requests
httpx
aiohttp
pydantic
asyncio
type-hints
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
<img src="https://repository-images.githubusercontent.com/735134836/df6752b8-38fa-4550-968e-cd2eda4adb37" alt="meatie">
[![GitHub Test Badge][1]][2] [![codecov.io][3]][4] [![pypi.org][5]][6] [![versions][7]][8]
[![downloads][9]][10] [![License][11]][12]
[1]: https://github.com/pmateusz/meatie/actions/workflows/ci.yaml/badge.svg "GitHub CI Badge"
[2]: https://github.com/pmateusz/meatie/actions/workflows/ci.yaml "GitHub Actions Page"
[3]: https://codecov.io/gh/pmateusz/meatie/branch/master/graph/badge.svg?branch=master "Coverage Badge"
[4]: https://codecov.io/gh/pmateusz/meatie?branch=master "Codecov site"
[5]: https://img.shields.io/pypi/v/meatie.svg "Pypi Latest Version Badge"
[6]: https://pypi.python.org/pypi/meatie "Pypi site"
[7]:https://img.shields.io/pypi/pyversions/meatie.svg
[8]: https://github.com/pmateusz/meatie
[9]: https://static.pepy.tech/badge/meatie
[10]: https://pepy.tech/project/meatie
[11]: https://img.shields.io/github/license/pmateusz/meatie "License Badge"
[12]: https://opensource.org/license/bsd-3-clause "License"
Meatie is a Python library that simplifies the implementation of REST API clients. The library generates code for
calling REST endpoints based on method signatures annotated with type hints. Meatie takes care of mechanics related to
HTTP communication, such as building URLs, encoding query parameters, and serializing the body in the HTTP requests and
responses. Rate limiting, retries, and caching are available with some modest extra setup.
Meatie works with all major HTTP client libraries (request, httpx, aiohttp) and offers seamless integration with
Pydantic (v1 and v2). The minimum officially supported version is Python 3.9.
## TL;DR
Generate HTTP clients using type annotations.
```python
from typing import Annotated
from aiohttp import ClientSession
from meatie import api_ref, endpoint
from meatie_aiohttp import Client
from pydantic import BaseModel, Field
class Todo(BaseModel):
user_id: int = Field(alias="userId")
id: int
title: str
completed: bool
class JsonPlaceholderClient(Client):
def __init__(self) -> None:
super().__init__(ClientSession(base_url="https://jsonplaceholder.typicode.com"))
@endpoint("/todos")
async def get_todos(self, user_id: Annotated[int, api_ref("userId")] = None) -> list[Todo]: ...
@endpoint("/users/{user_id}/todos")
async def get_todos_by_user(self, user_id: int) -> list[Todo]: ...
@endpoint("/todos")
async def post_todo(self, todo: Annotated[Todo, api_ref("body")]) -> Todo: ...
```
Do you use a different HTTP client library in your project? See the example adapted for [
`requests`](./tests/examples/requests/tutorial/test_basics.py) and [
`httpx`](./tests/examples/httpx/tutorial/test_basics.py).
### Caching
Cache result for a given TTL.
```python
from typing import Annotated
from meatie import MINUTE, api_ref, cache, endpoint, Cache
from meatie_aiohttp import Client
from pydantic import BaseModel
class Todo(BaseModel):
...
class JsonPlaceholderClient(Client):
def __init__(self) -> None:
super().__init__(
ClientSession(base_url="https://jsonplaceholder.typicode.com"),
local_cache=Cache(max_size=100),
)
@endpoint("/todos", cache(ttl=MINUTE, shared=False))
async def get_todos(self, user_id: Annotated[int, api_ref("userId")] = None) -> list[Todo]:
...
```
A cache key is built based on the URL path and query parameters. It does not include the scheme or the network location.
By default, every HTTP client instance has an independent cache. The behavior can be changed in the endpoint definition
to share cached results across all HTTP client class instances.
You can pass your custom cache to the local_cache parameter. The built-in cache provides a max_size parameter to limit
its size.
### Rate Limiting
Meatie can delay HTTP requests that exceed the predefined rate limit.
```python
from typing import Annotated
from aiohttp import ClientSession
from meatie import Limiter, Rate, api_ref, endpoint, limit
from meatie_aiohttp import Client
from pydantic import BaseModel
class Todo(BaseModel):
...
class JsonPlaceholderClient(Client):
def __init__(self) -> None:
super().__init__(
ClientSession(base_url="https://jsonplaceholder.typicode.com"),
limiter=Limiter(Rate(tokens_per_sec=10), capacity=10),
)
@endpoint("/todos", limit(tokens=2))
async def get_todos(self, user_id: Annotated[int, api_ref("userId")] = None) -> list[Todo]:
...
```
### Retries
Meatie can retry failed HTTP requests following the strategy set in the endpoint definition. The retry strategy is
controlled using third-party functions that specify when a retry should be attempted, how long to wait between
consecutive attempts to call the endpoint, and whether to abort further retries.
```python
from typing import Annotated
from aiohttp import ClientSession
from meatie import (
HttpStatusError,
RetryContext,
after_attempt,
api_ref,
endpoint,
fixed,
jit,
retry,
)
from meatie_aiohttp import Client
from pydantic import BaseModel
class Todo(BaseModel):
...
def should_retry(ctx: RetryContext) -> bool:
if isinstance(ctx.error, HttpStatusError):
return ctx.error.response.status >= 500
return False
class JsonPlaceholderClient(Client):
def __init__(self) -> None:
super().__init__(
ClientSession(base_url="https://jsonplaceholder.typicode.com", raise_for_status=True)
)
@endpoint("/todos", retry(on=should_retry, stop=after_attempt(3), wait=fixed(5) + jit(2)))
async def get_todos(self, user_id: Annotated[int, api_ref("userId")] = None) -> list[Todo]:
...
```
Meatie comes with a built-in set of predefined functions for building retry strategies. See
the [meatie.retry](./src/meatie/option/retry_option.py) option for more details.
### Calling Private Endpoints
Meatie can inject additional information into the HTTP request. A typical example is adding the `Authorization` header
with a token or signing the request using API keys.
```python
from typing import Annotated, override
from aiohttp import ClientSession
from meatie import Request, api_ref, endpoint, private
from meatie_aiohttp import Client
from pydantic import BaseModel
class Todo(BaseModel):
...
class JsonPlaceholderClient(Client):
def __init__(self) -> None:
super().__init__(ClientSession(base_url="https://jsonplaceholder.typicode.com"))
@endpoint("/todos", private)
async def get_todos(self, user_id: Annotated[int, api_ref("userId")] = None) -> list[Todo]:
...
@override
async def authenticate(self, request: Request) -> None:
request.headers["Authorization"] = "Bearer bWVhdGll"
```
## More Examples
Need more control over processing the HTTP requests or responses? See the [Meatie Cookbook](./docs/cookbook.md) with
solutions to the most frequently asked questions by the community.
Raw data
{
"_id": null,
"home_page": "https://github.com/pmateusz/meatie",
"name": "meatie",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "http-client, api-client, REST, HTTP, API, requests, httpx, aiohttp, pydantic, asyncio, type-hints",
"author": "pmateusz",
"author_email": "pmateusz@users.noreply.github.com",
"download_url": "https://files.pythonhosted.org/packages/5c/9a/f8c117466d6a40f1f75cafb1d7427fe5ac8178715703342887929d284120/meatie-0.1.20.tar.gz",
"platform": null,
"description": "<img src=\"https://repository-images.githubusercontent.com/735134836/df6752b8-38fa-4550-968e-cd2eda4adb37\" alt=\"meatie\">\n\n[![GitHub Test Badge][1]][2] [![codecov.io][3]][4] [![pypi.org][5]][6] [![versions][7]][8]\n[![downloads][9]][10] [![License][11]][12]\n\n[1]: https://github.com/pmateusz/meatie/actions/workflows/ci.yaml/badge.svg \"GitHub CI Badge\"\n\n[2]: https://github.com/pmateusz/meatie/actions/workflows/ci.yaml \"GitHub Actions Page\"\n\n[3]: https://codecov.io/gh/pmateusz/meatie/branch/master/graph/badge.svg?branch=master \"Coverage Badge\"\n\n[4]: https://codecov.io/gh/pmateusz/meatie?branch=master \"Codecov site\"\n\n[5]: https://img.shields.io/pypi/v/meatie.svg \"Pypi Latest Version Badge\"\n\n[6]: https://pypi.python.org/pypi/meatie \"Pypi site\"\n\n[7]:https://img.shields.io/pypi/pyversions/meatie.svg\n\n[8]: https://github.com/pmateusz/meatie\n\n[9]: https://static.pepy.tech/badge/meatie\n\n[10]: https://pepy.tech/project/meatie\n\n[11]: https://img.shields.io/github/license/pmateusz/meatie \"License Badge\"\n\n[12]: https://opensource.org/license/bsd-3-clause \"License\"\n\nMeatie is a Python library that simplifies the implementation of REST API clients. The library generates code for\ncalling REST endpoints based on method signatures annotated with type hints. Meatie takes care of mechanics related to\nHTTP communication, such as building URLs, encoding query parameters, and serializing the body in the HTTP requests and\nresponses. Rate limiting, retries, and caching are available with some modest extra setup.\n\nMeatie works with all major HTTP client libraries (request, httpx, aiohttp) and offers seamless integration with\nPydantic (v1 and v2). The minimum officially supported version is Python 3.9.\n\n## TL;DR\n\nGenerate HTTP clients using type annotations.\n\n```python\nfrom typing import Annotated\n\nfrom aiohttp import ClientSession\nfrom meatie import api_ref, endpoint\nfrom meatie_aiohttp import Client\nfrom pydantic import BaseModel, Field\n\n\nclass Todo(BaseModel):\n user_id: int = Field(alias=\"userId\")\n id: int\n title: str\n completed: bool\n\n\nclass JsonPlaceholderClient(Client):\n def __init__(self) -> None:\n super().__init__(ClientSession(base_url=\"https://jsonplaceholder.typicode.com\"))\n\n @endpoint(\"/todos\")\n async def get_todos(self, user_id: Annotated[int, api_ref(\"userId\")] = None) -> list[Todo]: ...\n\n @endpoint(\"/users/{user_id}/todos\")\n async def get_todos_by_user(self, user_id: int) -> list[Todo]: ...\n\n @endpoint(\"/todos\")\n async def post_todo(self, todo: Annotated[Todo, api_ref(\"body\")]) -> Todo: ...\n```\n\nDo you use a different HTTP client library in your project? See the example adapted for [\n`requests`](./tests/examples/requests/tutorial/test_basics.py) and [\n`httpx`](./tests/examples/httpx/tutorial/test_basics.py).\n\n### Caching\n\nCache result for a given TTL.\n\n```python\nfrom typing import Annotated\n\nfrom meatie import MINUTE, api_ref, cache, endpoint, Cache\nfrom meatie_aiohttp import Client\nfrom pydantic import BaseModel\n\n\nclass Todo(BaseModel):\n ...\n\n\nclass JsonPlaceholderClient(Client):\n def __init__(self) -> None:\n super().__init__(\n ClientSession(base_url=\"https://jsonplaceholder.typicode.com\"),\n local_cache=Cache(max_size=100),\n )\n\n @endpoint(\"/todos\", cache(ttl=MINUTE, shared=False))\n async def get_todos(self, user_id: Annotated[int, api_ref(\"userId\")] = None) -> list[Todo]:\n ...\n```\n\nA cache key is built based on the URL path and query parameters. It does not include the scheme or the network location.\nBy default, every HTTP client instance has an independent cache. The behavior can be changed in the endpoint definition\nto share cached results across all HTTP client class instances.\n\nYou can pass your custom cache to the local_cache parameter. The built-in cache provides a max_size parameter to limit\nits size.\n\n### Rate Limiting\n\nMeatie can delay HTTP requests that exceed the predefined rate limit.\n\n```python\nfrom typing import Annotated\n\nfrom aiohttp import ClientSession\nfrom meatie import Limiter, Rate, api_ref, endpoint, limit\nfrom meatie_aiohttp import Client\nfrom pydantic import BaseModel\n\n\nclass Todo(BaseModel):\n ...\n\n\nclass JsonPlaceholderClient(Client):\n def __init__(self) -> None:\n super().__init__(\n ClientSession(base_url=\"https://jsonplaceholder.typicode.com\"),\n limiter=Limiter(Rate(tokens_per_sec=10), capacity=10),\n )\n\n @endpoint(\"/todos\", limit(tokens=2))\n async def get_todos(self, user_id: Annotated[int, api_ref(\"userId\")] = None) -> list[Todo]:\n ...\n```\n\n### Retries\n\nMeatie can retry failed HTTP requests following the strategy set in the endpoint definition. The retry strategy is\ncontrolled using third-party functions that specify when a retry should be attempted, how long to wait between\nconsecutive attempts to call the endpoint, and whether to abort further retries.\n\n```python\nfrom typing import Annotated\n\nfrom aiohttp import ClientSession\nfrom meatie import (\n HttpStatusError,\n RetryContext,\n after_attempt,\n api_ref,\n endpoint,\n fixed,\n jit,\n retry,\n)\nfrom meatie_aiohttp import Client\nfrom pydantic import BaseModel\n\n\nclass Todo(BaseModel):\n ...\n\n\ndef should_retry(ctx: RetryContext) -> bool:\n if isinstance(ctx.error, HttpStatusError):\n return ctx.error.response.status >= 500\n return False\n\n\nclass JsonPlaceholderClient(Client):\n def __init__(self) -> None:\n super().__init__(\n ClientSession(base_url=\"https://jsonplaceholder.typicode.com\", raise_for_status=True)\n )\n\n @endpoint(\"/todos\", retry(on=should_retry, stop=after_attempt(3), wait=fixed(5) + jit(2)))\n async def get_todos(self, user_id: Annotated[int, api_ref(\"userId\")] = None) -> list[Todo]:\n ...\n```\n\nMeatie comes with a built-in set of predefined functions for building retry strategies. See\nthe [meatie.retry](./src/meatie/option/retry_option.py) option for more details.\n\n### Calling Private Endpoints\n\nMeatie can inject additional information into the HTTP request. A typical example is adding the `Authorization` header\nwith a token or signing the request using API keys.\n\n```python\nfrom typing import Annotated, override\n\nfrom aiohttp import ClientSession\nfrom meatie import Request, api_ref, endpoint, private\nfrom meatie_aiohttp import Client\nfrom pydantic import BaseModel\n\n\nclass Todo(BaseModel):\n ...\n\n\nclass JsonPlaceholderClient(Client):\n def __init__(self) -> None:\n super().__init__(ClientSession(base_url=\"https://jsonplaceholder.typicode.com\"))\n\n @endpoint(\"/todos\", private)\n async def get_todos(self, user_id: Annotated[int, api_ref(\"userId\")] = None) -> list[Todo]:\n ...\n\n @override\n async def authenticate(self, request: Request) -> None:\n request.headers[\"Authorization\"] = \"Bearer bWVhdGll\"\n```\n\n## More Examples\n\nNeed more control over processing the HTTP requests or responses? See the [Meatie Cookbook](./docs/cookbook.md) with\nsolutions to the most frequently asked questions by the community.\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Meatie is a Python typed REST client library that eliminates the need for boilerplate code when integrating with external APIs. The library generates code for calling a REST API based on method signatures annotated with type hints. Meatie abstracts away mechanics related to HTTP communication, such as building URLs, encoding query parameters, parsing, and dumping Pydantic models. With some modest additional configuration effort, generated HTTP clients offer rate limiting, retries, and caching.",
"version": "0.1.20",
"project_urls": {
"Homepage": "https://github.com/pmateusz/meatie",
"Repository": "https://github.com/pmateusz/meatie"
},
"split_keywords": [
"http-client",
" api-client",
" rest",
" http",
" api",
" requests",
" httpx",
" aiohttp",
" pydantic",
" asyncio",
" type-hints"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f35b4be7ab7b9fe30849f24153a9aef7ae2fd1229d2abad87f8c21d40ea830cb",
"md5": "2cb70fccd5562fe2e97e71f5231148d7",
"sha256": "7d4f28ba39a7b59683de954ac4ccc6a6c5ed58c2e84a2fe22195350ac9ee9ca9"
},
"downloads": -1,
"filename": "meatie-0.1.20-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2cb70fccd5562fe2e97e71f5231148d7",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 51252,
"upload_time": "2025-02-04T07:39:07",
"upload_time_iso_8601": "2025-02-04T07:39:07.562173Z",
"url": "https://files.pythonhosted.org/packages/f3/5b/4be7ab7b9fe30849f24153a9aef7ae2fd1229d2abad87f8c21d40ea830cb/meatie-0.1.20-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5c9af8c117466d6a40f1f75cafb1d7427fe5ac8178715703342887929d284120",
"md5": "8b71fdc587a3ac934104b47d5706c67c",
"sha256": "81213183dec8b87b14dd264d19d485dd754d8d70f9502593dcb3b8326a401c6e"
},
"downloads": -1,
"filename": "meatie-0.1.20.tar.gz",
"has_sig": false,
"md5_digest": "8b71fdc587a3ac934104b47d5706c67c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 26769,
"upload_time": "2025-02-04T07:39:09",
"upload_time_iso_8601": "2025-02-04T07:39:09.343829Z",
"url": "https://files.pythonhosted.org/packages/5c/9a/f8c117466d6a40f1f75cafb1d7427fe5ac8178715703342887929d284120/meatie-0.1.20.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-04 07:39:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "pmateusz",
"github_project": "meatie",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "meatie"
}