standardize packaging, tooling, docs, CI, and licensing

This commit is contained in:
2026-09-10 18:49:04 +05:30
parent c95de5a6e9
commit 0efe68b052
25 changed files with 667 additions and 74 deletions

View File

@@ -66,7 +66,7 @@ def generate_routes(
output_dir.mkdir(parents=True, exist_ok=True)
# Group paths by resource (first non-param path segment)
resources: dict[str, list[tuple[str, str, dict]]] = {}
resources_map: dict[str, list[tuple[str, str, dict[str, Any]]]] = {}
paths = spec.get("paths", {})
for path, methods in paths.items():
@@ -74,18 +74,18 @@ def generate_routes(
if not segments:
continue
resource = segments[0]
if resource not in resources:
resources[resource] = []
if resource not in resources_map:
resources_map[resource] = []
for http_method, operation in methods.items():
if http_method.startswith("x-"):
continue
resources[resource].append((path, http_method, operation))
resources_map[resource].append((path, http_method, operation))
generated_files: list[Path] = []
for resource in sorted(resources):
operations = resources[resource]
for resource in sorted(resources_map):
operations = resources_map[resource]
_validate_operations(resource, operations)
file_path = output_dir / f"{resource}.py"
@@ -116,7 +116,9 @@ _TYPE_MAP: dict[str, str] = {
}
def _validate_operations(resource: str, operations: list[tuple[str, str, dict]]) -> None:
def _validate_operations(
resource: str, operations: list[tuple[str, str, dict[str, Any]]]
) -> None:
"""Ensure every operation has an operationId."""
for path, http_method, operation in operations:
if not operation.get("operationId"):
@@ -144,7 +146,7 @@ def _get_request_body_schema(operation: dict[str, Any]) -> str | None:
schema = media_info.get("schema", {})
ref = schema.get("$ref", "")
if ref:
return ref.rsplit("/", 1)[-1]
return str(ref.rsplit("/", 1)[-1])
return None
@@ -159,7 +161,7 @@ def _get_success_status(operation: dict[str, Any]) -> str:
return "200"
def _needs_any(operations: list[tuple[str, str, dict]]) -> bool:
def _needs_any(operations: list[tuple[str, str, dict[str, Any]]]) -> bool:
"""Check if any operation uses a type that requires `from typing import Any`."""
for _, _, op in operations:
for param in op.get("parameters", []):
@@ -176,7 +178,7 @@ def _needs_any(operations: list[tuple[str, str, dict]]) -> bool:
def _generate_resource_file(
resource: str,
operations: list[tuple[str, str, dict]],
operations: list[tuple[str, str, dict[str, Any]]],
spec_path: str,
use_models: bool,
models_module: str,
@@ -205,7 +207,9 @@ def _generate_resource_file(
if schema:
schemas_needed.add(schema)
if schemas_needed:
lines.append(f"from {models_module} import {', '.join(sorted(schemas_needed))}")
lines.append(
f"from {models_module} import {', '.join(sorted(schemas_needed))}"
)
lines.append("")
@@ -237,7 +241,6 @@ def _generate_handler(
schema: dict[str, Any] = param.get("schema", {})
param_type: str = _resolve_type(schema)
required: bool = param.get("required", False)
description: str = schema.get("description", schema.get("x-description", ""))
default_raw = schema.get("default")
if param_in == "path":
@@ -277,13 +280,15 @@ def _generate_handler(
# Document parameters
doc_params: list[tuple[str, str, str]] = []
for param in operation.get("parameters", []):
name: str = param.get("name", "")
param_in: str = param.get("in", "")
schema: dict[str, Any] = param.get("schema", {})
param_type: str = _resolve_type(schema)
description: str = param.get("description", schema.get("x-description", ""))
if param_in in ("path", "query"):
doc_params.append((name, param_type, description))
doc_name: str = param.get("name", "")
doc_in: str = param.get("in", "")
doc_schema: dict[str, Any] = param.get("schema", {})
doc_type: str = _resolve_type(doc_schema)
doc_description: str = param.get(
"description", doc_schema.get("x-description", "")
)
if doc_in in ("path", "query"):
doc_params.append((doc_name, doc_type, doc_description))
if doc_params:
lines.append("")