generate-python
Python Code Generation from OpenAPI
Generate Python (Pydantic models + sync API functions + tools.json) from OpenAPI via aptx-ft CLI.
Contents
- Prerequisites
- Command Overview
- Parameter Reference
- Discovery Phase
- Workflow
- Manifest Tracking
- Output Structure
- Naming Conventions
- Type Mapping
- Runtime Dependencies
- Boundaries
Prerequisites
# CLI tool (monorepo)
pnpm add -D @aptx/frontend-tk-cli
# Python runtime dependencies (install in the Python project)
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 functionsgenerates spec files that reference models. Runpython modelfirst 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
# 1. Locate OpenAPI spec
ls ./openapi.json ./swagger.json ./docs/openapi.yaml 2>/dev/null
# 2. Check Python project structure
ls pyproject.toml setup.py setup.cfg 2>/dev/null
# 3. Identify output directories
ls -d src/*/ 2>/dev/null
# 4. Check existing generated code
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
# Step 1: Generate models first
pnpm exec aptx-ft python model -i ./openapi.json -o ./src/api
# Step 2: Generate functions (references models)
pnpm exec aptx-ft python functions -i ./openapi.json -o ./src/api \
--model-mode relative --model-path ./models
# Step 3: Generate tools.json (optional, for OpenAI function-calling)
pnpm exec aptx-ft python tools -i ./openapi.json -o ./src/api
Monorepo Example
# Models into shared package
pnpm exec aptx-ft python model -i ./openapi.json -o ./packages/api-core-python/src/aptx_api_models
# Functions with package import
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/Middlewaretypes - 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-artifactsorgenerate-models - Does NOT validate OpenAPI specification correctness
- Does NOT handle authenticated URL downloads → use
download-openapifirst - 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
More from haibaraaiaptx/frontend-openapi-skills
download-openapi
Download remote OpenAPI/Swagger JSON specification from a URL to local file using aptx-ft CLI. TRIGGER when user mentions: (1) fetch/pull/download swagger or openapi from URL, (2) save API spec to openapi.json locally, (3) get API documentation from server, or (4) prepare local input for code generation. DO NOT TRIGGER when: generating code/types from local file, reading existing openapi.json, downloading non-OpenAPI files, or authentication is required.
25generate-artifacts
Generate frontend artifacts from OpenAPI via aptx-ft, including models and request clients. Use when user wants: (1) to generate API code from OpenAPI/Swagger, (2) React Query hooks from API spec, (3) Vue Query composables from API spec, (4) function-based API clients, (5) a standard flow for frontend projects without framework-specific business adaptation, (6) track generated files with manifest, (7) preview changes before generation, or (8) update barrel files automatically.
24generate-models
Generate TypeScript interfaces and enums from OpenAPI schemas using aptx-ft CLI. Use when user asks to: (1) generate types/models from OpenAPI/Swagger, (2) create TypeScript interfaces from API schema, (3) extract type definitions from openapi.json, (4) generate selective models with --name filter, (5) preserve translated enum values, (6) track generated files with manifest, (7) preview changes before generation, or (8) update barrel files automatically. Do NOT use for full artifact generation with request layer or Material UI enum adaptation.
23adapt-materal-enums
Materal-specific enum adaptation workflow: fetch enum values from provider API, let LLM fill suggested_name, then apply patch with aptx-ft. Use ONLY when: (1) user mentions Materal framework, (2) Materal naming rules are required, or (3) adapting Materal enum semantics. Do NOT use for generic OpenAPI projects.
23generate-barrels
Generate barrel index.ts files for TypeScript projects. Use when user mentions: (1) barrel files, (2) index.ts exports, (3) re-export files, (4) simplify import paths, (5) create index files for directory, or (6) generate export aggregators.
18download-swagger-file
从 URL 下载 OpenAPI 3.x JSON 规范文件。用于:(1)从远程服务器获取 API 规范,(2)将 OpenAPI JSON 保存到本地,(3)为 TypeScript 模型生成准备规范。
6