Checkpoint web parity through Chromium input tasks
This commit is contained in:
128
tools/web/generate-io-format-runtime-inventory.py
Normal file
128
tools/web/generate-io-format-runtime-inventory.py
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate the format capability inventory from one pinned Blender runtime."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def decode(value):
|
||||
if isinstance(value, bytes):
|
||||
return value.decode("utf-8", errors="replace")
|
||||
return str(value)
|
||||
|
||||
|
||||
def binary_sha256(path):
|
||||
digest = hashlib.sha256()
|
||||
with open(path, "rb") as handle:
|
||||
for block in iter(lambda: handle.read(1024 * 1024), b""):
|
||||
digest.update(block)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def property_info(prop):
|
||||
result = {"identifier": prop.identifier, "type": prop.type}
|
||||
if hasattr(prop, "array_length"):
|
||||
result["arrayLength"] = prop.array_length
|
||||
if prop.type == "ENUM":
|
||||
try:
|
||||
result["enumItems"] = [item.identifier for item in prop.enum_items]
|
||||
except (AttributeError, RuntimeError):
|
||||
result["enumItems"] = []
|
||||
return result
|
||||
|
||||
|
||||
def operator_info(operator_path, build_option):
|
||||
module_name, operator_name = operator_path.split(".", 1)
|
||||
try:
|
||||
operator = getattr(getattr(bpy.ops, module_name), operator_name)
|
||||
rna = operator.get_rna_type()
|
||||
properties = [property_info(prop) for prop in rna.properties if prop.identifier != "rna_type"]
|
||||
properties.sort(key=lambda prop: prop["identifier"])
|
||||
enabled = True if build_option is None else bool(getattr(bpy.app.build_options, build_option))
|
||||
return {
|
||||
"operator": operator_path,
|
||||
"registered": True,
|
||||
"rnaIdentifier": rna.identifier,
|
||||
"buildOption": build_option,
|
||||
"buildOptionEnabled": enabled,
|
||||
"runtimeStatus": "AVAILABLE" if enabled else "BUILD_OPTION_DISABLED",
|
||||
"properties": properties,
|
||||
}
|
||||
except (AttributeError, KeyError, RuntimeError) as error:
|
||||
return {
|
||||
"operator": operator_path,
|
||||
"registered": False,
|
||||
"rnaIdentifier": None,
|
||||
"buildOption": build_option,
|
||||
"buildOptionEnabled": None,
|
||||
"runtimeStatus": "OPERATOR_UNREGISTERED",
|
||||
"properties": [],
|
||||
"error": type(error).__name__,
|
||||
}
|
||||
|
||||
|
||||
def format_entry(format_id, family, extensions, import_operator, export_operator, build_option, variants):
|
||||
return {
|
||||
"format": format_id,
|
||||
"family": family,
|
||||
"extensions": extensions,
|
||||
"variants": variants,
|
||||
"import": operator_info(import_operator, build_option),
|
||||
"export": operator_info(export_operator, build_option),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
if "--" not in sys.argv or len(sys.argv[sys.argv.index("--") + 1:]) != 1:
|
||||
raise SystemExit("usage: generate-io-format-runtime-inventory.py OUTPUT.json")
|
||||
output = pathlib.Path(sys.argv[sys.argv.index("--") + 1]).resolve()
|
||||
version = tuple(int(value) for value in bpy.app.version)
|
||||
if version != (5, 2, 0):
|
||||
raise RuntimeError(f"expected Blender 5.2.0, got {version}")
|
||||
binary_path = pathlib.Path(bpy.app.binary_path).resolve()
|
||||
options = {
|
||||
"alembic": bool(bpy.app.build_options.alembic),
|
||||
"usd": bool(bpy.app.build_options.usd),
|
||||
"io_ply": bool(bpy.app.build_options.io_ply),
|
||||
"io_stl": bool(bpy.app.build_options.io_stl),
|
||||
"io_wavefront_obj": bool(bpy.app.build_options.io_wavefront_obj),
|
||||
}
|
||||
formats = [
|
||||
format_entry("GLTF", "GLTF", [".gltf"], "import_scene.gltf", "export_scene.gltf", None, ["GLTF_SEPARATE"]),
|
||||
format_entry("GLB", "GLTF", [".glb"], "import_scene.gltf", "export_scene.gltf", None, ["GLB"]),
|
||||
format_entry("OBJ", "OBJ", [".obj"], "wm.obj_import", "wm.obj_export", "io_wavefront_obj", ["OBJ"]),
|
||||
format_entry("STL", "STL", [".stl"], "wm.stl_import", "wm.stl_export", "io_stl", ["STL_BINARY", "STL_ASCII"]),
|
||||
format_entry("PLY", "PLY", [".ply"], "wm.ply_import", "wm.ply_export", "io_ply", ["PLY"]),
|
||||
format_entry("USD", "USD", [".usd", ".usda", ".usdc", ".usdz"], "wm.usd_import", "wm.usd_export", "usd", ["USD", "USDA", "USDC", "USDZ"]),
|
||||
format_entry("ALEMBIC", "ALEMBIC", [".abc"], "wm.alembic_import", "wm.alembic_export", "alembic", ["ALEMBIC"]),
|
||||
]
|
||||
inventory = {
|
||||
"schemaVersion": 1,
|
||||
"task": "M12-05A",
|
||||
"runtime": {
|
||||
"blenderVersion": bpy.app.version_string,
|
||||
"versionTuple": list(version),
|
||||
"buildHash": decode(bpy.app.build_hash),
|
||||
"buildBranch": decode(bpy.app.build_branch),
|
||||
"buildPlatform": decode(bpy.app.build_platform),
|
||||
"buildType": decode(bpy.app.build_type),
|
||||
"buildDate": decode(bpy.app.build_date),
|
||||
"buildTime": decode(bpy.app.build_time),
|
||||
"buildCommitTimestamp": int(bpy.app.build_commit_timestamp),
|
||||
"binarySha256": binary_sha256(binary_path),
|
||||
"buildOptions": options,
|
||||
},
|
||||
"formats": formats,
|
||||
}
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text(json.dumps(inventory, sort_keys=True, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"io-format-runtime-inventory-generated formats={len(formats)} blender={bpy.app.version_string} output={output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user