"""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"]