A utility to generate Clio API models from OpenAPI specifications for use with our Clio API Python Client.
Project description
Usage
Installation
pip install clio-api-model-generator
Generating Models
To execute the generator and produce dataclass models, run:
from clio_api_model_generator import clio_manage as manage_model_generator
manage_model_generator.generate_models(output_dir=models_dir, overwrite=False)
This script will initialize the models directory, download the OpenAPI spec, and generate all necessary dataclasses.
Model Generator Generation Flow
This document explains the setup process for handling the models directory, running generator scripts, and ensuring the correct paths are set dynamically.
Overview
The project handles the models directory in the following way:
- Checks for the existence of the
modelsfolder in the parent directory first (preferred). - If not found in the parent, it checks the project root directory.
- If the folder exists and is not empty, it is backed up with a unique name (e.g.,
models.backup,models.backup1, etc.). - If no models folder is found, a new one is created in the preferred location (parent or project root).
- Static files from the
static/directory are copied into the models folder. - Environment variables are set to ensure the generator scripts use the correct folder paths.
- Generator scripts are imported after paths are set.
Setup Process
Execution Flow Summary
- Check parent directory for
modelsfolder first. - Backup existing folder if not empty and create a new one.
- Copy static files into the models folder.
- Set environment variables with the correct paths.
- Import generator scripts that rely on the updated paths.
Expected Outputs
Case 1: Models folder found in the parent directory and backed up
Existing non-empty models directory found at: /home/user/models
Renamed "/home/user/models" to "/home/user/models.backup"
Created new "/home/user/models" directory.
Copied all files from "static/" to "/home/user/models".
Set environment variables for model paths: /home/user/models
Case 2: No models folder found, creating a new one
No existing "models" directory found in parent or current directory.
Created new "/home/user/project/models" directory.
Copied all files from "static/" to "/home/user/project/models".
Set environment variables for model paths: /home/user/project/models
Notes
- Ensure the
static/directory exists and contains the required files before running the script. - The parent directory is prioritized when determining the location of the
modelsfolder. - Environment variables are crucial to dynamically set paths without modifying scripts manually.
Dataclass Generator Scripts
This document provides an overview of the dataclass generator scripts, explaining their order of execution, flow, and parsing/extraction logic for each generator.
Overview
The scripts process an OpenAPI specification to generate Python dataclasses for:
- Schemas – Representing API response objects.
- Fields – Handling OpenAPI field mappings.
- Query Parameters – Handling API query parameters.
- Request Bodies – Handling request payloads.
- Endpoints – Registering API endpoints with generated models.
Order of Execution
The generation process is orchestrated by generate_models.py, which follows this sequence:
-
Initialization (folder setup and OpenAPI spec download)
- Ensures the
modelsdirectory is ready. - Downloads the OpenAPI spec if not present.
- Ensures the
-
Schema Generation (
components.py)- Generates dataclasses from OpenAPI schemas.
-
Field Extraction (
fields.py)- Extracts field definitions for models based on schema dependencies.
-
Query Parameter Handling (
query.py)- Creates query dataclasses based on API query parameters.
-
Request Body Handling (
request_body.py)- Processes and generates dataclasses for API request bodies.
-
Endpoint Registry Creation (
endpoints.py)- Registers generated models to the API endpoint paths.
Parsing and Extraction Logic
1. Schema Generator (components.py)
Purpose:
Processes OpenAPI components.schemas to generate Python dataclasses.
Key Logic:
- Reads the OpenAPI spec from
SPEC_FILE_PATH. - Iterates over schemas containing
_basein the name. - Recursively processes properties:
- Required fields are listed first.
- Optional fields are annotated with
Optional.
- Handles nested objects by generating sub-dataclasses.
Example Output:
@dataclass
class UserBase:
id: int
name: str
email: Optional[str] = None
Fields Generation (fields.py)
Purpose
The fields.py script generates dataclasses that represent OpenAPI schema field definitions, including handling dependencies and nested resources.
Key Steps in Fields Generation
-
Reading OpenAPI Spec:
- Reads schema definitions from
SPEC_FILE_PATH. - Focuses on schemas without underscores (filters
_baseschemas).
- Reads schema definitions from
-
Processing Base Fields:
- Base schema references are extracted from
allOfdefinitions. - Fields are copied from the base schema into the generated dataclass.
- Field names are sanitized to be valid Python identifiers.
- Base schema references are extracted from
-
Handling Nested Resources:
- Nested resources are identified within the schema.
- If a nested reference is found, the corresponding nested resource dataclass is created and included in the parent class.
- Nested fields are marked as
Optionaland are postponed if dependencies exist.
-
Topological Sorting:
- Ensures that dataclasses are generated in the correct dependency order.
- Handles cyclic dependencies by raising errors.
-
Mapping to Endpoints:
- Generates a mapping of fields to API responses using list and show schemas.
- Outputs a
endpoint_field_mapping.jsonfile for later use in endpoint definitions.
Example Workflow in fields.py
Input OpenAPI Schema Example
"Account": {
"allOf": [
{ "$ref": "#/components/schemas/BaseEntity" },
{
"properties": {
"name": { "type": "string" },
"contacts": {
"$ref": "#/components/schemas/Contact"
}
}
}
]
},
"Contact": {
"properties": {
"email": { "type": "string" },
"phone": { "type": "string" }
}
}
Output Generated Dataclass
from dataclasses import dataclass
from typing import Optional
from models.schemas import *
@dataclass
class Account_Fields:
id: Optional[int] = None
created_at: Optional[str] = None
name: Optional[str] = None
contacts: Optional[Contact_Fields] = None
Handling Base Fields
-
Base Schema Reference Processing:
- Extracted from the first
allOfitem. - Fields from the referenced schema (e.g.,
BaseEntity) are added.
- Extracted from the first
-
Base Fields Example:
@dataclass class BaseEntity: id: Optional[int] = None created_at: Optional[str] = None
Handling Nested Resources
-
Detecting Nested Fields:
- Any field containing a reference (
$ref) to another schema is treated as a nested resource. - These are appended with
_Fieldsand added to the parent dataclass.
- Any field containing a reference (
-
Nested Field Example:
@dataclass class Contact_Fields: email: Optional[str] = None phone: Optional[str] = None
-
Embedding in Parent:
@dataclass class Account_Fields: name: Optional[str] = None contacts: Optional[Contact_Fields] = None
Mapping to Endpoints
The generator script processes schemas with _list and _show suffixes to establish relationships between fields and endpoint responses.
Example Mapping in endpoint_field_mapping.json:
{
"Account_list": "Account_Fields",
"User_show": "User_Fields"
}
Logic:
- The mapping associates the API response schemas to the generated field dataclasses.
- Helps the endpoint generator (
endpoints.py) link responses to correct models.
3. Query Generator (query.py)
Purpose:
Generates dataclasses for API query parameters.
Key Logic:
- Reads query parameters from API operations.
- Transforms query parameter names to valid Python identifiers.
- Maps OpenAPI types to Python types.
- Writes required and optional fields separately.
Example Output:
@dataclass
class AccountQuery:
account_id: int
status: Optional[str] = None
4. Request Body Generator (request_body.py)
Purpose:
Processes request body parameters for API operations.
Key Logic:
- Extracts the request body schema from
application/jsoncontent. - Handles nested object properties.
- Generates dataclasses with required and optional fields.
Example Output:
@dataclass
class CreateAccountRequestBody:
name: str
email: str
age: Optional[int] = None
5. Endpoints Generator (endpoints.py)
Purpose:
Creates an Endpoints registry to store endpoint mappings.
Key Logic:
- Iterates through API paths and methods.
- Stores metadata such as path, method, query, and request body models.
- Handles special download cases based on HTTP 303 responses.
Example Output:
class Endpoints:
registry = {
'get_user': {
'path': '/users/{user_id}',
'method': 'GET',
'query_model': UserQuery,
'request_body_model': None
}
}
Directory Structure
project-root/
│-- models/
│ ├── query.py
│ ├── request_body.py
│ ├── endpoints.py
│ ├── fields.py
│ ├── schemas.py
│-- static/
│ ├── __init__.py
│ ├── models_registry.py
│-- generate_models.py
│-- openapi.json
Static files get copied to models directory automatically before generating the model dataclasses
Conclusion
This setup automates the creation of Python dataclasses from an OpenAPI spec, providing a structured way to handle API interactions and ensuring maintainability through a clear generation flow.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clio_api_model_generator-0.2.4.tar.gz.
File metadata
- Download URL: clio_api_model_generator-0.2.4.tar.gz
- Upload date:
- Size: 21.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8328621eed7f293f576f05960b01449edc080755f65627164d17358dc3cb0bfe
|
|
| MD5 |
d379cb2f0fb286cfd32ea0d0cc57b893
|
|
| BLAKE2b-256 |
6a7773bd3b47670922afb1880bb4303a967d514ebf94c5ff4d7178f23b0e8bd8
|
File details
Details for the file clio_api_model_generator-0.2.4-py3-none-any.whl.
File metadata
- Download URL: clio_api_model_generator-0.2.4-py3-none-any.whl
- Upload date:
- Size: 23.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94754257bf49944ea8693d75556c5134ec0db36d90997561fc676736fae38d63
|
|
| MD5 |
f064ed72413c1f930ef6d619ae8504f2
|
|
| BLAKE2b-256 |
623ad0ce5d00e934cfd4a0bfb876a0a6adbd61c805dc5def7b0c1ee99f7873a9
|