-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate.py
More file actions
111 lines (85 loc) · 3.37 KB
/
generate.py
File metadata and controls
111 lines (85 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python3
"""
Fetch the latest OpenAPI spec from RoxyAPI, run openapi-python-client to generate
typed client code, then run codegen to produce the factory.py wrapper.
Run with: python generate.py
"""
import json
import shutil
import subprocess
import sys
from pathlib import Path
SPEC_URL = "https://roxyapi.com/api/v2/openapi.json"
SPEC_PATH = Path("specs/openapi.json")
GENERATED_DIR = Path("src/roxy_sdk/_generated")
def fetch_spec() -> dict:
import urllib.request
print(f"Fetching OpenAPI spec from {SPEC_URL}")
with urllib.request.urlopen(SPEC_URL) as resp:
spec = json.loads(resp.read())
# Patch server URL to absolute prod URL
if spec.get("servers") and spec["servers"][0].get("url") == "/api/v2":
spec["servers"][0]["url"] = "https://roxyapi.com/api/v2"
print("Patched server URL to https://roxyapi.com/api/v2")
SPEC_PATH.parent.mkdir(exist_ok=True)
SPEC_PATH.write_text(json.dumps(spec, indent=2))
print(f"Spec saved to {SPEC_PATH}")
# Count endpoints for verification
paths = spec.get("paths", {})
endpoint_count = sum(len(methods) for methods in paths.values())
print(f"Spec contains {len(paths)} paths, {endpoint_count} endpoints")
return spec
def run_openapi_python_client() -> None:
"""Run openapi-python-client to generate typed client code into _generated/."""
# Clean existing generated directory
if GENERATED_DIR.exists():
shutil.rmtree(GENERATED_DIR)
print(f"Cleaned {GENERATED_DIR}")
# Find the openapi-python-client binary
# Try .venv first, then system PATH
venv_bin = Path(".venv/bin/openapi-python-client")
if venv_bin.exists():
opc_cmd = str(venv_bin)
else:
opc_cmd = "openapi-python-client"
cmd = [
opc_cmd,
"generate",
"--path", str(SPEC_PATH),
"--meta", "none",
"--output-path", str(GENERATED_DIR),
]
# Note: openapi-python-client.toml is not used with --meta none
print(f"\nRunning: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout, end="")
if result.returncode != 0:
print(result.stderr, end="", file=sys.stderr)
sys.exit(result.returncode)
# Count generated files
api_files = list((GENERATED_DIR / "api").rglob("*.py")) if (GENERATED_DIR / "api").exists() else []
model_files = list((GENERATED_DIR / "models").rglob("*.py")) if (GENERATED_DIR / "models").exists() else []
print(f"Generated {len(api_files)} API files, {len(model_files)} model files")
def run_codegen() -> None:
"""Run codegen.py to produce the factory.py wrapper."""
print("\nRunning codegen...")
result = subprocess.run(
[sys.executable, "codegen.py"],
capture_output=True,
text=True,
)
print(result.stdout, end="")
if result.returncode != 0:
print(result.stderr, end="", file=sys.stderr)
sys.exit(result.returncode)
def main() -> None:
# 1. Fetch spec from production API
fetch_spec()
# 2. Generate factory.py from spec (domain classes, methods, Roxy aggregate)
run_codegen()
# Optional: run openapi-python-client for typed models (not used by factory.py yet)
# Uncomment when wiring typed return types:
# run_openapi_python_client()
print("\nDone. All generated code is up to date.")
if __name__ == "__main__":
main()