Octri

Python

The Python SDK publishes to PyPI with two clients over one surface: Acme, whose methods block, and AsyncAcme, whose methods are coroutines. It needs Python 3.10 or later and uses httpx for both.

Install

bash
pip install your-org-api-client

Options

Set these for Python in SDK Studio. Each one names its key for octri sdk settings set. Every option, for every language, is in the settings reference.

Data Model Frameworkchoicedefault: pydantic

pydantic, dataclass or typeddict. See data model.

style.python

Synchronous companionschoicedefault: include

include adds a blocking client beside the async one. See sync methods.

syncMethods

Client stylechoicedefault: class

class gives callers a client to create. functions gives free functions to import. See client style.

clientStyleByLang.python

Namespacechoicedefault: tags

Groups operations by tags, by URL path, or not at all with none.

namespaceByLang.python

Method namingchoicedefault: short

short drops the group's word from the method name, and full keeps the operation ID. Set for every language at once.

methodNaming

Argument stylechoicedefault: positional

object takes one parameters object, and positional takes arguments in order. See argument style.

outputByLang.python.argumentStyle

Doc commentschoicedefault: full

full or minimal.

outputByLang.python.docComments

Usage examplechoicedefault: full

full or concise.

outputByLang.python.usageExample

File headerchoicedefault: include

include or omit. Omitting it needs the Enterprise plan. Set for every language at once.

fileHeader

Data model

How response models are represented. This is the choice your users feel most.

python
@dataclass
class User:
    id: str

Standard library, no dependencies, no runtime validation.

pydantic is the default, and it is a dependency

Runtime validation catches spec drift at the boundary, where the error names the field that broke, which is why it's the default. But it's a dependency and a performance cost your users didn't choose. If your consumers are FastAPI shops, that cost is already paid. If you're shipping to people who keep their dependency trees short, switch to dataclass before the first release.

Sync methods

include, the default, gives every operation a blocking twin and exports both clients. Scripts, notebooks and Django views use Acme; asyncio code uses AsyncAcme. The namespaces and method names are the same on both.

python
acme = Acme(config)
users = acme.users.list(limit=10)

async_acme = AsyncAcme(config)
users = await async_acme.users.list(limit=10)

omit ships AsyncAcme alone, for a package that is asyncio-only. With the functions client style, the coroutine keeps the plain name (list_users) and the blocking twin carries a _sync suffix (list_users_sync).

Package name

PyPI names are global and normalised: underscores and hyphens are treated the same, case is ignored. Acme_API and acme-api are the same project.

text
acme-api      distribution name (pip install acme-api)
acme_api      import name (import acme_api)
PyPI never lets you reuse a version

Deleting a release does not free its version number. 1.0.0 published once is 1.0.0 forever. See Publishing.

What callers write

python
import os

from acme_api import Acme, AsyncAcme, ClientAuthConfig, ClientConfig

config = ClientConfig(
    base_url="https://api.acme.com/v1",
    auth=ClientAuthConfig(bearer=os.environ["ACME_TOKEN"]),
)

# Blocking: list_paginated is an iterator that fetches pages as you loop.
acme = Acme(config)
for user in acme.users.list_paginated(limit=100):
    print(user.id)

# asyncio: the same call is an async iterator.
async_acme = AsyncAcme(config)
async for user in async_acme.users.list_paginated(limit=100):
    print(user.id)

Failures raise a subclass of SdkHttpError per common status (SdkNotFoundError, SdkRateLimitError and so on, importable from acme_api.errors), each carrying status_code and request_id.

Runtime

RequiresPython 3.10 or newer
HTTPhttpx
Timeout30 seconds per attempt
RetriesUp to 3 attempts, with backoff from 500 ms to 8 seconds
Idempotency keysPOST and PATCH

Those are the defaults. See every setting and retries and timeouts to change them.

Streaming

For an operation that streams:

python
for event in client.events.stream():
    print(event.id)

On AsyncAcme, write async for. Stop iterating as soon as you're done, so the connection can close. See streaming.

Handling errors

python
from acme_api.errors import SdkHttpError, SdkNotFoundError

try:
    client.users.get(id="usr_1")
except SdkNotFoundError:
    return None
except SdkHttpError as error:
    print(error.status_code, error.request_id)
    raise

Each common status has its own subclass of SdkHttpError. error.data holds the decoded model, which you can narrow with isinstance. See what's in the package.