| name | generate-python |
| description | Generate Python code from OpenAPI via aptx-ft, including Pydantic models, sync API functions, and OpenAI function-calling tools.json. Use when user wants: (1) to generate Python client code from OpenAPI/Swagger, (2) Pydantic v2 data models from API schemas, (3) sync API function wrappers with RequestSpec, (4) OpenAI function-calling tools.json, (5) Python code generation targeting aptx-api-core runtime, (6) track generated files with manifest, (7) preview changes before generation. Do NOT use for TypeScript code generation โ use generate-artifacts or generate-models instead. |
Python Code Generation from OpenAPI
Generate Python (Pydantic models + sync API functions + tools.json) from OpenAPI via aptx-ft CLI.
Contents
Prerequisites
pnpm add -D @aptx/frontend-tk-cli
pip install aptx-api-core pydantic
The Python codegen plugin (@aptx/frontend-tk-plugin-python) must be loaded. In a monorepo where the plugin is a workspace dependency of the CLI, it is auto-discovered.
Command Overview
| Command | Purpose | Output |
|---|
python model | Generate Pydantic v2 model classes | models/*.py |
python functions | Generate spec + sync function wrappers | spec/**/*.py + functions/**/*.py |
python tools | Generate OpenAI function-calling JSON | tools.json |
Dependency: python functions generates spec files that reference models. Run python model first if you need model imports.
Parameter Reference
All paths are relative to working directory (project root).
Common Options (all three commands)
| Parameter | Required | Description |
|---|
-i, --input | Yes | OpenAPI file path (e.g., ./openapi.json) |
-o, --output | Yes | Output directory (e.g., ./src/api) |
--no-manifest | No | Disable manifest tracking (default: false) |
--manifest-dir | No | Custom manifest directory (default: .generated) |
--dry-run | No | Preview mode without updating manifest (default: false) |
Additional Options for python functions
| Parameter | Required | Description |
|---|
--model-mode | No | relative (same project) or package (monorepo) |
--model-path | No | Path or package name for model imports |
Note: relative ไผๆโๅฝๅ็ๆๆไปถ -> ๆจกๅ็ฎๅฝโ่ฎก็ฎ Python ๅ
็ธๅฏนๅฏผๅ
ฅ๏ผpackage ไผ็ดๆฅไฝฟ็จไผ ๅ
ฅ็ Python ๅ
่ทฏๅพใ
Model Source Decision
Status: Implemented. ๅๅ
ๅบๆฏไผ็ๆๆพๅผๅ
็ธๅฏนๅฏผๅ
ฅ๏ผๅฆ from ...models.UserDto import UserDto๏ผ๏ผ่ทจๅ
ๅบๆฏๅฏ็จ --model-mode package --model-path my_package.modelsใ
Is the models directory inside the same Python package where functions are generated?
โโโ YES โ --model-mode relative --model-path ./models (planned)
โโโ NO โ --model-mode package --model-path my_package.models (planned)
Discovery Phase โ MANDATORY FIRST STEP
Before executing any generation command, discover the actual project configuration.
Checklist
ls ./openapi.json ./swagger.json ./docs/openapi.yaml 2>/dev/null
ls pyproject.toml setup.py setup.cfg 2>/dev/null
ls -d src/*/ 2>/dev/null
ls ./src/api/models/*.py 2>/dev/null || echo "no models yet"
ls ./src/api/spec/*.py 2>/dev/null || echo "no specs yet"
Critical Rules
| Never | Always |
|---|
| Guess package name from directory | Read pyproject.toml to get actual package name |
| Assume model import paths | Verify the Python module path is importable |
| Skip checking existing files | Check if output directory already has content |
Workflow
- Discovery โ Read project files, find OpenAPI spec, identify output paths
- Check output directory โ determine if regeneration is needed
- Confirm with user โ output dir, model-mode/model-path settings
- Execute โ Show command, get approval, run
Execution Order
pnpm exec aptx-ft python model -i ./openapi.json -o ./src/api
pnpm exec aptx-ft python functions -i ./openapi.json -o ./src/api \
--model-mode relative --model-path ./models
pnpm exec aptx-ft python tools -i ./openapi.json -o ./src/api
Monorepo Example
pnpm exec aptx-ft python model -i ./openapi.json -o ./packages/api-core-python/src/aptx_api_models
pnpm exec aptx-ft python functions -i ./openapi.json -o ./services/web/api \
--model-mode package --model-path aptx_api_models
Manifest Tracking
The CLI tracks generated files and detects changes between generations.
Generated Manifest Files
<output>/
โโโ .generated/
โ โโโ manifest.json # Tracks all generated files
โ โโโ deletion-report.json # Machine-readable change report
โ โโโ deletion-report.md # Human-readable change report with LLM suggestions
โโโ generated files...
When to Use Manifest Options
| Scenario | Command |
|---|
| Normal generation | Omit manifest options (default) |
| CI/CD without tracking | Add --no-manifest |
| Preview changes before applying | Add --dry-run |
| Custom manifest location | Add --manifest-dir ./meta |
Output Structure
src/api/
โโโ .generated/ # Manifest tracking files
โโโ models/ # From python:model
โ โโโ __init__.py # Auto-generated barrel
โ โโโ UserDto.py # Pydantic BaseModel
โ โโโ Status.py # Enum class
โ โโโ CreateRequest.py # BaseModel with Field aliases
โโโ spec/ # From python:functions
โ โโโ __init__.py
โ โโโ user/
โ โโโ __init__.py
โ โโโ get_info_spec.py # RequestSpec builder
โโโ functions/ # From python:functions
โ โโโ __init__.py
โ โโโ user/
โ โโโ __init__.py
โ โโโ get_info.py # def wrapper
โโโ tools.json # From python:tools (OpenAI function-calling)
Naming Conventions
Model Naming
| OpenAPI Schema | Python Output |
|---|
UserDto | class UserDto(BaseModel) โ name unchanged |
AddAssignmentRequest | class AddAssignmentRequest(BaseModel) |
Property Naming
Properties are converted to snake_case with Field(alias=...) preserving the original name:
class UserDto(BaseModel):
model_config = ConfigDict(populate_by_name=True)
user_name: str = Field(alias="userName")
created_at: str = Field(alias="createdAt")
Function Naming
Function names are derived from operationId through a normalization pipeline:
operation_name: "getMainAPIUserGetInfo"
โ strip HTTP method prefix: "MainAPIUserGetInfo"
โ strip service prefix: "UserGetInfo"
โ strip namespace prefix: "GetInfo"
โ snake_case: "get_info"
Output:
spec file: spec/user/get_info_spec.py โ build_get_info_spec()
function file: functions/user/get_info.py โ def get_info()
Python reserved words get a trailing underscore: class โ class_.
Type Mapping
OpenAPI types are mapped to Python types as follows:
| OpenAPI / IR Type | Python Type |
|---|
string | str |
number | float |
boolean | bool |
object | dict[str, Any] |
array<T> | list[T] |
$ref to schema | Schema class name directly |
| union types | A | B |
| nullable | T | None |
| enum values | Literal["value"] |
Generated Code Examples
Model File (models/UserDto.py)
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field
class UserDto(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str = Field(alias="id")
user_name: str = Field(alias="userName")
status: Status | None = Field(default=None, alias="status")
Spec File (spec/user/get_info_spec.py)
from __future__ import annotations
from ...models.get_info_input import GetInfoInput
from aptx_api_core import RequestSpec
def build_get_info_spec(input: GetInfoInput) -> RequestSpec:
return RequestSpec(
method="GET",
path="/MainAPI/User/GetInfo",
input=input,
)
Function File (functions/user/get_info.py)
from __future__ import annotations
from ...models.get_info_input import GetInfoInput
from ...models.user_dto import UserDto
from aptx_api_core import get_api_client
from ...spec.user.get_info_spec import build_get_info_spec
def get_info(input: GetInfoInput) -> UserDto:
return get_api_client().execute(
build_get_info_spec(input),
response_type=UserDto,
)
Tools JSON (tools.json)
[
{
"type": "function",
"function": {
"name": "userGetInfo",
"description": "Get user information",
"parameters": {
"type": "object",
"properties": {
"id": { "type": "string" }
}
}
}
}
]
Runtime Dependencies
Generated Python code requires at runtime:
# pyproject.toml
[project]
dependencies = [
"aptx-api-core>=0.1.0",
"pydantic>=2.0",
]
- aptx-api-core โ sync/async HTTP client runtime with middleware pipeline, error handling, and
RequestSpec / ApiClient / Middleware types
- pydantic v2 โ data model base classes (
BaseModel, Enum) with validation
Boundaries
This skill handles OpenAPI โ Python generation only:
- Does NOT generate TypeScript code โ use
generate-artifacts or generate-models
- Does NOT validate OpenAPI specification correctness
- Does NOT handle authenticated URL downloads โ use
download-openapi first
- Does NOT modify the Python runtime library (
aptx-api-core) itself
- Does NOT create or modify the plugin code (
@aptx/frontend-tk-plugin-python)
Related Skills
- generate-artifacts: TypeScript artifact generation (models + React Query / Vue Query)
- generate-models: TypeScript model-only generation
- download-openapi: Fetch OpenAPI spec from URL
- write-plugin: Write custom CLI plugins