Fixes/upgrades
This commit is contained in:
91
protocol/mizan-codegen/scripts/run_pydantic_to_rust.py
Normal file
91
protocol/mizan-codegen/scripts/run_pydantic_to_rust.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Report a Pydantic module's declarations as JSON on stdout.
|
||||
|
||||
Takes one argv JSON object of `module` and `derives`; returns `enums` as
|
||||
name plus variant identifiers, and `structs` as rendered Rust source.
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import inspect
|
||||
import json
|
||||
import sys
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from pydantic_to_rust import (
|
||||
emit_rust_struct,
|
||||
to_rust_variant_ident,
|
||||
walk_pydantic_model,
|
||||
)
|
||||
|
||||
|
||||
def _declared_in(module, obj) -> bool:
|
||||
return getattr(obj, "__module__", None) == module.__name__
|
||||
|
||||
|
||||
def discover_models(module) -> list[type[BaseModel]]:
|
||||
"""BaseModel subclasses declared here. An imported one is another
|
||||
module's to emit."""
|
||||
return [
|
||||
obj
|
||||
for _, obj in inspect.getmembers(module, inspect.isclass)
|
||||
if issubclass(obj, BaseModel)
|
||||
and obj is not BaseModel
|
||||
and _declared_in(module, obj)
|
||||
]
|
||||
|
||||
|
||||
def discover_enums(module) -> list[type[Enum]]:
|
||||
"""Enum subclasses declared here. Only variant identifiers are reported;
|
||||
the caller renders the enum body."""
|
||||
return [
|
||||
obj
|
||||
for _, obj in inspect.getmembers(module, inspect.isclass)
|
||||
if issubclass(obj, Enum) and obj is not Enum and _declared_in(module, obj)
|
||||
]
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) < 2:
|
||||
sys.stderr.write("run_pydantic_to_rust.py: missing JSON payload argument\n")
|
||||
return 2
|
||||
|
||||
payload = json.loads(sys.argv[1])
|
||||
module_name: str = payload["module"]
|
||||
derives = tuple(payload["derives"])
|
||||
|
||||
sys.path.insert(0, str(Path.cwd()))
|
||||
|
||||
module = importlib.import_module(module_name)
|
||||
enums = discover_enums(module)
|
||||
models = discover_models(module)
|
||||
if not enums and not models:
|
||||
sys.stderr.write(
|
||||
f"run_pydantic_to_rust.py: no Enum or BaseModel subclasses "
|
||||
f"declared in {module_name!r}\n"
|
||||
)
|
||||
return 3
|
||||
|
||||
json.dump(
|
||||
{
|
||||
"enums": [
|
||||
{
|
||||
"name": enum_class.__name__,
|
||||
"variants": [to_rust_variant_ident(m.name) for m in enum_class],
|
||||
}
|
||||
for enum_class in enums
|
||||
],
|
||||
"structs": [
|
||||
emit_rust_struct(walk_pydantic_model(model), derives=derives)
|
||||
for model in models
|
||||
],
|
||||
},
|
||||
sys.stdout,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user