Skip to content

nanosdk.codegen

Generate a typed nanosdk client package from an OpenAPI 3.x document.

nanosdk generate openapi.yml -o src/my_sdk/_generated --name MyApi

writes a package with two modules:

  • models.py: pydantic models for the spec's schemas, by datamodel-codegen;
  • client.py: a parameter model per operation, a nanosdk.Routes group per tag, and MyApi / AsyncMyApi clients whose base_url defaults to the spec's first server.

Treat the package as build output: regenerate rather than edit it, and customise by subclassing the clients in your own module. Needs the nanosdk[codegen] extra.

Classes:

Name Description
SpecError

The OpenAPI document can't be turned into a client.

Functions:

Name Description
generate

Generate (or regenerate) a client package.

check

Report generated files that are missing or differ from a fresh generation.

load_spec

Read an OpenAPI document from a YAML or JSON file.

Attributes:

Name Type Description
Transform

A function that fixes up a spec dict before generation.

Transform module-attribute

Transform = Callable[[dict[str, Any]], dict[str, Any]]

A function that fixes up a spec dict before generation.

SpecError

Bases: ValueError

The OpenAPI document can't be turned into a client.

generate

generate(
    spec: str | Path,
    output: str | Path,
    *,
    name: str | None = None,
    base_url: str | None = None,
    rename: Mapping[str, str] | None = None,
    skip: Iterable[str] = (),
    include_deprecated: bool = False,
    lenient: bool = False,
    transform: Transform | None = None
) -> list[Path]

Generate (or regenerate) a client package.

Parameters:

Name Type Description Default
spec str | Path

Path to the OpenAPI document (YAML or JSON).

required
output str | Path

The package directory to write, such as src/my_sdk/_generated.

required
name str | None

Class name of the sync client (the async one is Async<name>); defaults to one derived from the spec's title.

None
base_url str | None

Default base URL, overriding the spec's first server (needed when the spec only has a relative server URL).

None
rename Mapping[str, str] | None

Route names to override, keyed by operationId or "METHOD /path".

None
skip Iterable[str]

Operations whose route and parameter model you write by hand (operationIds or "METHOD /path"). Their request and response models are still generated, named after the (renamed) route.

()
include_deprecated bool

Also generate deprecated operations.

False
lenient bool

Make every model field optional (X | None = None), for APIs whose responses leave out or null fields their spec says are required.

False
transform Transform | None

Fixes up the spec dict before generation (for broken specs).

None

Returns:

Type Description
list[Path]

The files written.

Raises:

Type Description
SpecError

If the spec can't be turned into a client.

check

check(
    spec: str | Path,
    output: str | Path,
    *,
    name: str | None = None,
    base_url: str | None = None,
    rename: Mapping[str, str] | None = None,
    skip: Iterable[str] = (),
    include_deprecated: bool = False,
    lenient: bool = False,
    transform: Transform | None = None
) -> list[Path]

Report generated files that are missing or differ from a fresh generation.

Takes the same arguments as generate; writes nothing.

Returns:

Type Description
list[Path]

The stale files; empty when the package is up to date.

load_spec

load_spec(path: str | Path) -> dict[str, Any]

Read an OpenAPI document from a YAML or JSON file.

Parameters:

Name Type Description Default
path str | Path

The spec file.

required

Returns:

Type Description
dict[str, Any]

The spec as a dict.

nanosdk.codegen.cli

nanosdk generate: the command-line front end of nanosdk.codegen.

Settings come from the command line, falling back to [tool.nanosdk.codegen] in the pyproject.toml of the current directory:

[tool.nanosdk.codegen]
spec = "spec/openapi.yml"
output = "src/my_sdk/_generated"
name = "MyApi"
base-url = "https://api.example.com/v1"
include-deprecated = false
lenient = false                       # true: every model field optional
transform = "scripts/fix_spec.py:fix"   # or "my_package.module:function"
rename = { getPetById = "get_pet", "GET /store/inventory" = "inventory" }
skip = ["updatePetWithForm"]          # operations you implement by hand