Introduce Python code generator for OpenAPI spec to dataclasses

Add a [Python code generator][1] that takes an OpenAPI definition and
outputs the corresponding data model as [dataclasses][2]

This is intended to be used in the Remote Asset Library project, to
create, download, parse, and validate information of a remote asset
library.

[1]: https://koxudaxi.github.io/datamodel-code-generator/
[2]: https://docs.python.org/3/library/dataclasses.html

## Running the Generator

The generator is a Python script, which creates its own Python
virtualenv, installs the dependencies it needs, and then runs the
generator within that virtualenv.

The script is intended to run via the `generate_datamodels` CMake
target. For example, `ninja generate_datamodels` in the build
directory.

## Details

The virtualenv is created in Blender's build directory, and is not
cleaned up after running. This means that subsequent runs will just
use it directly, instead of reinstalling dependencies on every run.

## Generated Code & Interaction with Build System

It is my intention that the code generation _only_ happens when the
OpenAPI specification changes. This means that the generated code will
be committed to Git like any hand-written code. Building Blender will
therefore _not_ require the code generator to run. Only people working
on the area that uses the generated code will have to deal with this.

Pull Request: https://projects.blender.org/blender/blender/pulls/139495
This commit is contained in:
Sybren A. Stüvel
2025-08-01 16:33:56 +02:00
parent 24a7c42766
commit 3ca28acbb3
8 changed files with 462 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# SPDX-FileCopyrightText: 2025 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later

View File

@@ -0,0 +1,3 @@
# SPDX-FileCopyrightText: 2025 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later

View File

@@ -0,0 +1,98 @@
# SPDX-FileCopyrightText: 2025 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Generated by datamodel-codegen:
# source filename: blender_asset_library_openapi.yaml
from __future__ import annotations
from dataclasses import dataclass
from typing import Optional
@dataclass
class Contact:
name: str
url: Optional[str] = None
email: Optional[str] = None
@dataclass
class AssetLibraryMeta:
api_versions: dict[str, str]
name: str
contact: Contact
# This OpenAPI specification was used to generate the above code.
# It is here so that Blender does not have to parse the YAML file.
OPENAPI_SPEC = {
'openapi': '3.0.0',
'info': {
'version': '1.0.0',
'title': 'Blender Asset Library API',
'description': "Blender's API for describing and fetching assets from online libraries.",
'contact': {
'name': 'Blender',
'url': 'https://www.blender.org/'},
'license': {
'name': 'GPLv3',
'url': 'https://www.gnu.org/licenses/gpl-3.0.en.html'}},
'servers': [
{
'url': '/'}],
'paths': {
'/_asset-library-meta.json': {
'summary': 'Meta-information about this asset library.',
'get': {
'summary': 'Retrieve the asset library meta info.',
'operationId': 'getLibraryMeta',
'responses': {
'200': {
'description': 'normal response',
'content': {
'application/json': {
'schema': {
'$ref': '#/components/schemas/AssetLibraryMeta'}}}}}}}},
'components': {
'schemas': {
'AssetLibraryMeta': {
'type': 'object',
'description': 'Meta-data of this asset library.',
'properties': {
'api_versions': {
'type': 'object',
'description': 'API versions of this asset library. This is reflected in the URLs of all OpenAPI operations except the one to get this metadata.\nA single asset library can expose multiple versions, in order to be backward-compatible with older versions of Blender.\nProperties should be "v1", "v2", etc. and their values should point to their respective index files.\n',
'additionalProperties': {
'type': 'string'},
'patternProperties': {
'^v[0-9]+$': {
'type': 'string'}}},
'name': {
'type': 'string',
'description': 'Name of this asset library.'},
'contact': {
'$ref': '#/components/schemas/Contact'}},
'required': [
'api_versions',
'name',
'contact'],
'example': {
'api_versions': {
'v1': '_v1/asset-index.json'},
'name': 'Blender Essentials',
'contact': {
'name': 'Blender',
'url': 'https://www.blender.org/'}}},
'Contact': {
'type': 'object',
'description': 'Owner / publisher of this asset library.',
'properties': {
'name': {
'type': 'string'},
'url': {
'type': 'string'},
'email': {
'type': 'string'}},
'required': ['name']}}}}

View File

@@ -0,0 +1,83 @@
# SPDX-FileCopyrightText: 2025 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
# This is the OpenAPI specification for Blender's Remote Assets system.
#
# It has been intentionally trimmed down to the bare minimum for a review of the
# code generator in general, and how it integrates into Blender's build system.
#
# The `paths` section is not used by the Blender code, and is here just for
# referencing by humans. The Python code generator just uses the data structures
# specified by the `components` section.
openapi: 3.0.0
info:
version: 1.0.0
title: Blender Asset Library API
description: Blender's API for describing and fetching assets from online libraries.
contact:
name: Blender
url: https://www.blender.org/
license:
name: GPLv3
url: https://www.gnu.org/licenses/gpl-3.0.en.html
servers:
- url: /
paths:
/_asset-library-meta.json:
summary: Meta-information about this asset library.
get:
summary: Retrieve the asset library meta info.
operationId: getLibraryMeta
responses:
"200":
description: normal response
content:
application/json:
schema:
$ref: "#/components/schemas/AssetLibraryMeta"
components:
schemas:
AssetLibraryMeta:
type: object
description: "Meta-data of this asset library."
properties:
"api_versions":
type: object
description: >
API versions of this asset library. This is reflected in the URLs of
all OpenAPI operations except the one to get this metadata.
A single asset library can expose multiple versions, in order to be
backward-compatible with older versions of Blender.
Properties should be "v1", "v2", etc. and their values should point
to their respective index files.
additionalProperties:
type: string
patternProperties:
"^v[0-9]+$":
type: string
"name":
type: string
description: Name of this asset library.
"contact": { $ref: "#/components/schemas/Contact" }
required: [api_versions, name, contact]
example:
api_versions:
v1: _v1/asset-index.json
name: Blender Essentials
contact:
name: Blender
url: https://www.blender.org/
Contact:
type: object
description: Owner / publisher of this asset library.
properties:
"name": { type: string }
"url": { type: string }
"email": { type: string }
required: [name]