nanosdk.client
¶
The clients, and the bound routes you get when you access a route on one.
class GitHub(nanosdk.Client):
get_user = nanosdk.get("/users/{username}", request=GetUser, response=User)
with GitHub("https://api.github.com") as gh:
user = gh.get_user(username="octocat") # gh.get_user is a BoundRoute
A client's public attributes are your routes plus with_options, close / aclose
and the context-manager protocol. Everything else is underscored, including the hooks
you override (_prepare_request, _process_response, _raise_for_status,
_retry_policy), so routes can be named anything except those few public names.
Client
¶
Client(
base_url: str | URL = "",
*,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes = DEFAULT_TIMEOUT,
auth: Auth | tuple[str, str] | None = None,
error_model: type[Any] | None = None,
retry: Retry | None = None,
logger: Logger | None = None,
http_client: Client | None = None,
**httpx_kwargs: Any
)
Synchronous API client, built on httpx.Client.
Subclass it and declare routes as class attributes; on an instance each route
becomes a BoundRoute method:
class GitHub(nanosdk.Client):
get_user = nanosdk.get("/users/{username}", request=GetUser, response=User)
with GitHub("https://api.github.com") as gh:
user = gh.get_user(username="octocat") # -> User
Apart from your routes, an instance only exposes
with_options and close (or
use it as a context manager). Customise behaviour by overriding the underscored
hooks _prepare_request,
_process_response,
_raise_for_status and
_retry_policy. A route named like one of the
client's own attributes (close, with_options, a hook, ...) raises TypeError
when the class is defined.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str | URL
|
Prefix for every route path, such as |
''
|
headers
|
Mapping[str, str] | None
|
Headers sent with every request. |
None
|
timeout
|
TimeoutTypes
|
Seconds, an |
DEFAULT_TIMEOUT
|
auth
|
Auth | tuple[str, str] | None
|
Any |
None
|
error_model
|
type[Any] | None
|
A type to parse 4xx/5xx bodies into, exposed as
|
None
|
retry
|
Retry | None
|
Retry policy for transient failures; |
None
|
logger
|
Logger | None
|
Where to log requests, responses and retries; defaults to the |
None
|
http_client
|
Client | None
|
Use this |
None
|
**httpx_kwargs
|
Any
|
Any other |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Methods:
| Name | Description |
|---|---|
with_options |
Return a copy of the client with extra headers or a different timeout/retry. |
close |
Close the connection pool, unless it came from |
_prepare_request |
Hook called on every outgoing request, including each retry. Override it. |
_process_response |
Hook called on every final response, before the status check and decoding. |
_raise_for_status |
Hook: raise if |
_retry_policy |
Hook: choose the retry policy for a route. Override to vary it per route. |
with_options
¶
with_options(
*,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes | _NotGiven = NOT_GIVEN,
retry: Retry | _NotGiven | None = NOT_GIVEN
) -> Self
Return a copy of the client with extra headers or a different timeout/retry.
The copy is the same class, so all routes are available on it, and it shares the original's connection pool. It never closes the pool: close the original.
Example
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
headers
|
Mapping[str, str] | None
|
Headers added to every request, on top of existing ones. |
None
|
timeout
|
TimeoutTypes | _NotGiven
|
Replaces the timeout; |
NOT_GIVEN
|
retry
|
Retry | _NotGiven | None
|
Replaces the retry policy; |
NOT_GIVEN
|
Returns:
| Type | Description |
|---|---|
Self
|
The configured copy. |
_prepare_request
¶
Hook called on every outgoing request, including each retry. Override it.
Use it to sign requests, add per-request headers or log. Auth from auth= is
applied after this hook.
Example
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
Request
|
The request about to be sent. |
required |
route
|
Route[Any, Any, Any]
|
The route being called; read |
required |
Returns:
| Type | Description |
|---|---|
Request
|
The request to send: |
_process_response
¶
Hook called on every final response, before the status check and decoding.
Override it to unwrap response envelopes, record rate limits or log. Responses that are retried don't reach it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
The response. |
required |
route
|
Route[Any, Any, Any]
|
The route that was called. |
required |
Returns:
| Type | Description |
|---|---|
Response
|
The response to check and decode: |
Response
|
|
_raise_for_status
¶
Hook: raise if response is an error. Override to map errors your own way.
Called after _process_response and before decoding, for every call except
.raw(). The default raises
APIStatusError on a 4xx or 5xx status, with the body
parsed by the client's error_model when one is set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
The final response for a call. |
required |
Raises:
| Type | Description |
|---|---|
APIStatusError
|
If the status is 4xx or 5xx. |
_retry_policy
¶
Hook: choose the retry policy for a route. Override to vary it per route.
Example
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
route
|
Route[Any, Any, Any]
|
The route about to be sent. |
required |
Returns:
| Type | Description |
|---|---|
Retry | None
|
The policy to use, or |
Retry | None
|
|
AsyncClient
¶
AsyncClient(
base_url: str | URL = "",
*,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes = DEFAULT_TIMEOUT,
auth: Auth | tuple[str, str] | None = None,
error_model: type[Any] | None = None,
retry: Retry | None = None,
logger: Logger | None = None,
http_client: AsyncClient | None = None,
**httpx_kwargs: Any
)
Asynchronous API client, built on httpx.AsyncClient.
The async twin of Client, with the same constructor arguments
(http_client takes an httpx.AsyncClient). Route calls return awaitables,
paginated routes give async iterators, the _prepare_request /
_process_response hooks are async def, and aclose replaces close.
class AsyncGitHub(Users, Repos, nanosdk.AsyncClient): ...
async with AsyncGitHub("https://api.github.com") as gh:
user = await gh.get_user(username="octocat")
async for repo in gh.list_repos.iter(username="octocat"): ...
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str | URL
|
Prefix for every route path. |
''
|
headers
|
Mapping[str, str] | None
|
Headers sent with every request. |
None
|
timeout
|
TimeoutTypes
|
Seconds, an |
DEFAULT_TIMEOUT
|
auth
|
Auth | tuple[str, str] | None
|
Any |
None
|
error_model
|
type[Any] | None
|
A type to parse 4xx/5xx bodies into. |
None
|
retry
|
Retry | None
|
Retry policy for transient failures; |
None
|
logger
|
Logger | None
|
Where to log; defaults to the |
None
|
http_client
|
AsyncClient | None
|
Use this |
None
|
**httpx_kwargs
|
Any
|
Any other |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Methods:
| Name | Description |
|---|---|
with_options |
Return a copy of the client with extra headers or a different timeout/retry. |
aclose |
Close the connection pool, unless it came from |
_prepare_request |
Hook called on every outgoing request, including each retry. |
_process_response |
Hook called on every final response, before the status check and decoding. |
_raise_for_status |
Hook: raise if |
_retry_policy |
Hook: choose the retry policy for a route. Override to vary it per route. |
with_options
¶
with_options(
*,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes | _NotGiven = NOT_GIVEN,
retry: Retry | _NotGiven | None = NOT_GIVEN
) -> Self
Return a copy of the client with extra headers or a different timeout/retry.
The copy is the same class, so all routes are available on it, and it shares the original's connection pool. It never closes the pool: close the original.
Example
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
headers
|
Mapping[str, str] | None
|
Headers added to every request, on top of existing ones. |
None
|
timeout
|
TimeoutTypes | _NotGiven
|
Replaces the timeout; |
NOT_GIVEN
|
retry
|
Retry | _NotGiven | None
|
Replaces the retry policy; |
NOT_GIVEN
|
Returns:
| Type | Description |
|---|---|
Self
|
The configured copy. |
_prepare_request
async
¶
Hook called on every outgoing request, including each retry.
The async version of Client._prepare_request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
Request
|
The request about to be sent. |
required |
route
|
Route[Any, Any, Any]
|
The route being called. |
required |
Returns:
| Type | Description |
|---|---|
Request
|
The request to send. |
_process_response
async
¶
Hook called on every final response, before the status check and decoding.
The async version of Client._process_response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
The response. |
required |
route
|
Route[Any, Any, Any]
|
The route that was called. |
required |
Returns:
| Type | Description |
|---|---|
Response
|
The response to check and decode. |
_raise_for_status
¶
Hook: raise if response is an error. Override to map errors your own way.
Called after _process_response and before decoding, for every call except
.raw(). The default raises
APIStatusError on a 4xx or 5xx status, with the body
parsed by the client's error_model when one is set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
The final response for a call. |
required |
Raises:
| Type | Description |
|---|---|
APIStatusError
|
If the status is 4xx or 5xx. |
_retry_policy
¶
Hook: choose the retry policy for a route. Override to vary it per route.
Example
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
route
|
Route[Any, Any, Any]
|
The route about to be sent. |
required |
Returns:
| Type | Description |
|---|---|
Retry | None
|
The policy to use, or |
Retry | None
|
|
http_client
¶
http_client(client: Client) -> Client
http_client(client: AsyncClient) -> AsyncClient
http_client(
client: Client | AsyncClient,
) -> Client | AsyncClient
The httpx client underneath a nanosdk client, for anything nanosdk doesn't wrap.
A function rather than an attribute, so it can't collide with a route name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Client | AsyncClient
|
A nanosdk client. |
required |
Returns:
| Type | Description |
|---|---|
Client | AsyncClient
|
Its |
Bound routes¶
What you get when you access a route on a client instance (api.get_user).
BoundRoute
¶
A route attached to a Client; what api.some_route gives you.
Call it with the request model's arguments to send the request and get the decoded response. The other methods are variations for when you need more control.
api.get_user(user_id=1) # -> User
api.get_user.send(GetUser(user_id=1)) # already-built model
api.get_user.raw(user_id=1) # httpx.Response, no status check / decoding
api.get_user.build_request(user_id=1) # httpx.Request, not sent
Attributes:
| Name | Type | Description |
|---|---|---|
route |
Route[P, ReqT, RespT]
|
The underlying |
client |
Client
|
The client it's bound to. |
Methods:
| Name | Description |
|---|---|
__call__ |
Build the request model from the arguments, send it, and decode the response. |
send |
Send an already-built request model and decode the response. |
raw |
Like calling the route, but return the |
build_request |
Build the request that calling the route would send, without sending it. |
__call__
¶
Build the request model from the arguments, send it, and decode the response.
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the arguments are invalid; nothing is sent. |
APIStatusError
|
On a 4xx/5xx response. |
APIConnectionError
|
If no response arrived, after any retries. |
ResponseValidationError
|
If the body doesn't match the response type. |
send
¶
Send an already-built request model and decode the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ReqT
|
An instance of the route's request model. |
required |
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
raw
¶
Like calling the route, but return the httpx.Response as-is.
Hooks and retries apply; there's no status check and no decoding.
Returns:
| Type | Description |
|---|---|
Response
|
The response, whatever its status. |
build_request
¶
Build the request that calling the route would send, without sending it.
Auth and the _prepare_request hook aren't applied; they run at send time.
Returns:
| Type | Description |
|---|---|
Request
|
The unsent request. |
BoundPaginatedRoute
¶
BoundPaginatedRoute(
paginated: PaginatedRoute[P, ReqT, RespT, ItemT],
client: Client,
)
Bases: BoundRoute[P, ReqT, RespT]
A paginated route attached to a Client.
Calling it fetches just the first page, like any BoundRoute;
iter and pages walk all of them.
first = api.list_posts(limit=50) # the first page's response
for post in api.list_posts.iter(limit=50): # every post, page by page
...
Attributes:
| Name | Type | Description |
|---|---|---|
paginated |
PaginatedRoute[P, ReqT, RespT, ItemT]
|
The underlying |
Methods:
| Name | Description |
|---|---|
__call__ |
Build the request model from the arguments, send it, and decode the response. |
send |
Send an already-built request model and decode the response. |
raw |
Like calling the route, but return the |
build_request |
Build the request that calling the route would send, without sending it. |
iter |
Iterate over every item on every page. |
pages |
Iterate over every page, with each page's request, data, items and response. |
__call__
¶
Build the request model from the arguments, send it, and decode the response.
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the arguments are invalid; nothing is sent. |
APIStatusError
|
On a 4xx/5xx response. |
APIConnectionError
|
If no response arrived, after any retries. |
ResponseValidationError
|
If the body doesn't match the response type. |
send
¶
Send an already-built request model and decode the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ReqT
|
An instance of the route's request model. |
required |
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
raw
¶
Like calling the route, but return the httpx.Response as-is.
Hooks and retries apply; there's no status check and no decoding.
Returns:
| Type | Description |
|---|---|
Response
|
The response, whatever its status. |
build_request
¶
Build the request that calling the route would send, without sending it.
Auth and the _prepare_request hook aren't applied; they run at send time.
Returns:
| Type | Description |
|---|---|
Request
|
The unsent request. |
iter
¶
iter(
*args: P.args, **kwargs: P.kwargs
) -> Iterator[ItemT]
Iterate over every item on every page.
Arguments are validated immediately; pages are fetched as you iterate, so
itertools.islice or break stops further requests.
Returns:
| Type | Description |
|---|---|
Iterator[ItemT]
|
A lazy iterator over the items. |
pages
¶
AsyncBoundRoute
¶
AsyncBoundRoute(
route: Route[P, ReqT, RespT], client: AsyncClient
)
A route attached to an AsyncClient.
The async twin of BoundRoute: calling it, send and raw
return awaitables.
Attributes:
| Name | Type | Description |
|---|---|---|
route |
Route[P, ReqT, RespT]
|
The underlying |
client |
AsyncClient
|
The client it's bound to. |
Methods:
| Name | Description |
|---|---|
__call__ |
Build the request model, send it, and decode the response. |
send |
Send an already-built request model and decode the response. |
raw |
Like calling the route, but return the |
build_request |
Build the request that calling the route would send, without sending it. |
__call__
async
¶
Build the request model, send it, and decode the response.
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
send
async
¶
Send an already-built request model and decode the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ReqT
|
An instance of the route's request model. |
required |
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
raw
async
¶
Like calling the route, but return the httpx.Response as-is.
Returns:
| Type | Description |
|---|---|
Response
|
The response, whatever its status. |
build_request
¶
Build the request that calling the route would send, without sending it.
Returns:
| Type | Description |
|---|---|
Request
|
The unsent request. |
AsyncBoundPaginatedRoute
¶
AsyncBoundPaginatedRoute(
paginated: PaginatedRoute[P, ReqT, RespT, ItemT],
client: AsyncClient,
)
Bases: AsyncBoundRoute[P, ReqT, RespT]
A paginated route attached to an AsyncClient.
Attributes:
| Name | Type | Description |
|---|---|---|
paginated |
PaginatedRoute[P, ReqT, RespT, ItemT]
|
The underlying |
Methods:
| Name | Description |
|---|---|
__call__ |
Build the request model, send it, and decode the response. |
send |
Send an already-built request model and decode the response. |
raw |
Like calling the route, but return the |
build_request |
Build the request that calling the route would send, without sending it. |
iter |
Iterate over every item on every page with |
pages |
Iterate over every page with |
__call__
async
¶
Build the request model, send it, and decode the response.
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
send
async
¶
Send an already-built request model and decode the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ReqT
|
An instance of the route's request model. |
required |
Returns:
| Type | Description |
|---|---|
RespT
|
The decoded response. |
raw
async
¶
Like calling the route, but return the httpx.Response as-is.
Returns:
| Type | Description |
|---|---|
Response
|
The response, whatever its status. |
build_request
¶
Build the request that calling the route would send, without sending it.
Returns:
| Type | Description |
|---|---|
Request
|
The unsent request. |
iter
¶
iter(
*args: P.args, **kwargs: P.kwargs
) -> AsyncIterator[ItemT]
Iterate over every item on every page with async for.
Returns:
| Type | Description |
|---|---|
AsyncIterator[ItemT]
|
A lazy async iterator over the items. |
pages
¶
pages(
*args: P.args, **kwargs: P.kwargs
) -> AsyncIterator[Page[ReqT, RespT, ItemT]]
Iterate over every page with async for.
Returns:
| Type | Description |
|---|---|
AsyncIterator[Page[ReqT, RespT, ItemT]]
|
A lazy async iterator over |