Files
vmware-api-simulator/app/vsphere/rest/param_fields.py
T

88 lines
2.7 KiB
Python

"""Flatten nested body_example values into PARAM drawer fields."""
from __future__ import annotations
from typing import Any
def body_fields_from_example(body_example: dict[str, Any] | None) -> list[dict[str, Any]]:
"""PARAM inputs derived from body_example, including nested scalar paths.
Nested objects/arrays become dotted paths (``placement.host``, ``cpu.count``,
``disks.0.new_vmdk.name``) so the Params drawer can edit leaves while the
request body keeps the full nested JSON.
"""
if not isinstance(body_example, dict) or not body_example:
return []
fields: list[dict[str, Any]] = []
def _leaf_type(value: Any) -> str:
if isinstance(value, bool):
return "boolean"
if isinstance(value, int) and not isinstance(value, bool):
return "integer"
if isinstance(value, float):
return "number"
return "string"
def _walk(prefix: str, value: Any) -> None:
if isinstance(value, dict):
for key, child in value.items():
path = f"{prefix}.{key}" if prefix else str(key)
_walk(path, child)
return
if isinstance(value, list):
for index, child in enumerate(value):
path = f"{prefix}.{index}" if prefix else str(index)
_walk(path, child)
return
fields.append(
{
"name": prefix,
"type": _leaf_type(value),
"description": prefix,
"optional": True,
"enum": [],
"example": value,
}
)
_walk("", body_example)
return fields
def set_by_path(root: dict[str, Any], path: str, value: Any) -> None:
"""Assign ``value`` at a dotted path, creating intermediate dicts/lists."""
parts = [part for part in str(path).split(".") if part]
if not parts:
return
cur: Any = root
for index, part in enumerate(parts[:-1]):
nxt = parts[index + 1]
want_list = nxt.isdigit()
if isinstance(cur, list):
idx = int(part)
while len(cur) <= idx:
cur.append([] if want_list else {})
if cur[idx] is None or not isinstance(cur[idx], (dict, list)):
cur[idx] = [] if want_list else {}
cur = cur[idx]
continue
if part not in cur or not isinstance(cur[part], (dict, list)):
cur[part] = [] if want_list else {}
cur = cur[part]
last = parts[-1]
if isinstance(cur, list):
idx = int(last)
while len(cur) <= idx:
cur.append(None)
cur[idx] = value
else:
cur[last] = value
__all__ = ["body_fields_from_example", "set_by_path"]