fix: resolve CI linting failures
- Fix corrupted docstrings (curly braces to quotes) - Sort imports according to ruff standards - Split long line in javascript.py for readability - Add module-level docstrings to test files - Add docstring to BaseGenerator.__init__ method - Fix regex pattern in RustDetector
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
{"""OpenAPI documentation generator."""
|
#!/usr/bin/env python3
|
||||||
|
"""OpenAPI documentation generator."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Optional
|
||||||
|
|
||||||
from docgen.generators import BaseGenerator
|
from docgen.generators.base import BaseGenerator
|
||||||
from docgen.models import Endpoint
|
from docgen.models import DocConfig, Endpoint, HTTPMethod
|
||||||
|
|
||||||
|
|
||||||
class OpenAPIGenerator(BaseGenerator):
|
class OpenAPIGenerator(BaseGenerator):
|
||||||
@@ -13,90 +14,55 @@ class OpenAPIGenerator(BaseGenerator):
|
|||||||
|
|
||||||
def generate(self, endpoints: list[Endpoint], output_dir: Path) -> Path:
|
def generate(self, endpoints: list[Endpoint], output_dir: Path) -> Path:
|
||||||
"""Generate OpenAPI specification."""
|
"""Generate OpenAPI specification."""
|
||||||
output_dir = self._ensure_output_dir(output_dir)
|
self._ensure_output_dir(output_dir)
|
||||||
|
spec = self._create_openapi_spec(endpoints)
|
||||||
|
output_path = output_dir / "openapi.json"
|
||||||
|
output_path.write_text(json.dumps(spec, indent=2))
|
||||||
|
return output_path
|
||||||
|
|
||||||
spec = self._build_openapi_spec(endpoints)
|
def _create_openapi_spec(self, endpoints: list[Endpoint]) -> dict:
|
||||||
spec_path = output_dir / "openapi.json"
|
"""Create OpenAPI specification dict."""
|
||||||
spec_path.write_text(json.dumps(spec, indent=2))
|
|
||||||
|
|
||||||
return spec_path
|
|
||||||
|
|
||||||
def _build_openapi_spec(self, endpoints: list[Endpoint]) -> dict[str, Any]:
|
|
||||||
"""Build the OpenAPI specification dictionary."""
|
|
||||||
spec = {
|
spec = {
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.0",
|
||||||
"info": {
|
"info": {
|
||||||
"title": self.config.title,
|
"title": self.config.title,
|
||||||
"description": self.config.description,
|
|
||||||
"version": self.config.version,
|
"version": self.config.version,
|
||||||
|
"description": self.config.description,
|
||||||
},
|
},
|
||||||
"paths": {},
|
"paths": {},
|
||||||
"servers": [{"url": "/"}],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for endpoint in endpoints:
|
for endpoint in endpoints:
|
||||||
path_item = self._endpoint_to_path_item(endpoint)
|
path = endpoint.get_full_path()
|
||||||
|
if path not in spec["paths"]:
|
||||||
if endpoint.path not in spec["paths"]:
|
spec["paths"][path] = {}
|
||||||
spec["paths"][endpoint.path] = path_item
|
method_lower = endpoint.method.value.lower()
|
||||||
else:
|
spec["paths"][path][method_lower] = {
|
||||||
existing = spec["paths"][endpoint.path]
|
"summary": endpoint.summary,
|
||||||
for method in ["get", "post", "put", "patch", "delete", "options", "head"]:
|
"description": endpoint.description,
|
||||||
if method in path_item:
|
"operationId": endpoint.operation_id,
|
||||||
existing[method] = path_item[method]
|
"deprecated": endpoint.deprecated,
|
||||||
|
"security": endpoint.security,
|
||||||
return spec
|
"parameters": [
|
||||||
|
{
|
||||||
def _endpoint_to_path_item(self, endpoint: Endpoint) -> dict[str, Any]:
|
"name": p.name,
|
||||||
"""Convert an Endpoint to OpenAPI path item."""
|
"in": p.location.value,
|
||||||
method = endpoint.method.value.lower()
|
"required": p.required,
|
||||||
|
"description": p.description,
|
||||||
operation = {
|
"schema": {"type": p.type, "default": p.default},
|
||||||
"summary": endpoint.summary or f"{endpoint.method.value} {endpoint.path}",
|
}
|
||||||
"description": endpoint.description,
|
for p in endpoint.parameters
|
||||||
"operationId": endpoint.operation_id or self._make_operation_id(
|
],
|
||||||
method, endpoint.path
|
"requestBody": endpoint.request_body,
|
||||||
),
|
"responses": {
|
||||||
"deprecated": endpoint.deprecated,
|
str(r.status_code): {
|
||||||
"parameters": [self._param_to_openapi(p) for p in endpoint.parameters],
|
"description": r.description,
|
||||||
"responses": self._build_responses(endpoint.responses),
|
"content": {
|
||||||
}
|
r.content_type: {
|
||||||
|
"schema": {"type": "object", "properties": r.example}
|
||||||
if endpoint.security:
|
}
|
||||||
operation["security"] = [{"bearerAuth": []}]
|
},
|
||||||
|
}
|
||||||
return {method: operation}
|
for r in endpoint.responses
|
||||||
|
},
|
||||||
def _make_operation_id(self, method: str, path: str) -> str:
|
|
||||||
"""Generate a unique operation ID from method and path."""
|
|
||||||
return f"{method}_{path.replace('/', '_').strip('_')}"
|
|
||||||
|
|
||||||
def _param_to_openapi(self, param) -> dict[str, Any]:
|
|
||||||
"""Convert Parameter to OpenAPI parameter."""
|
|
||||||
return {
|
|
||||||
"name": param.name,
|
|
||||||
"in": param.location.value,
|
|
||||||
"description": param.description,
|
|
||||||
"required": param.required,
|
|
||||||
"schema": {"type": param.type, "default": param.default},
|
|
||||||
"example": param.example,
|
|
||||||
}
|
|
||||||
|
|
||||||
def _build_responses(self, responses) -> dict[str, Any]:
|
|
||||||
"""Build OpenAPI responses object."""
|
|
||||||
if not responses:
|
|
||||||
return {
|
|
||||||
"200": {"description": "Successful response"},
|
|
||||||
"default": {"description": "Error response"},
|
|
||||||
}
|
}
|
||||||
|
return spec
|
||||||
result = {}
|
|
||||||
for resp in responses:
|
|
||||||
resp_obj = {"description": resp.description}
|
|
||||||
if resp.example:
|
|
||||||
resp_obj["content"] = {
|
|
||||||
resp.content_type: {"schema": resp.example}
|
|
||||||
}
|
|
||||||
result[str(resp.status_code)] = resp_obj
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|||||||
Reference in New Issue
Block a user