Coverage for fastapi_docx/openapi.py: 96%
23 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-24 20:22 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-24 20:22 +0000
1from collections.abc import Callable
2from typing import Any
4from fastapi import FastAPI
5from fastapi.openapi.utils import get_openapi
7from fastapi_docx.exception_finder import ErrType, RouteExcFinder
8from fastapi_docx.response_generator import (
9 ErrSchema,
10 HTTPExceptionSchema,
11 add_model_to_openapi,
12 write_response,
13)
16def custom_openapi(
17 app: FastAPI,
18 customError: type[ErrType] | None = None,
19 customErrSchema: type[ErrSchema] | None = None,
20 HTTPExcSchema: type[ErrSchema] = HTTPExceptionSchema,
21 dependencyClasses: tuple[type] | None = None,
22 serviceClasses: tuple[type] | None = None,
23) -> Callable:
24 """Modify the OpenAPI specification for a FastAPI app to include any `HTTPException` raised in service classes and/or dependency classes.
26 Optionally include custom exceptions and their schemas in the OpenAPI specification.
28 Optionally include service classes and/or dependency classes.
29 Specified service and dependency classes will be scanned for both HTTPExceptions and custom exceptions.
31 Parameters:
32 `app`: The FastAPI app for which to generate the OpenAPI specification.
33 `customError`: A custom exception class that should be included in the OpenAPI specification.
34 All subclasses of the `customError` will be found and added to the spec.
35 Note: any custom error should be able to be instantiated without required arguments.
36 If paramaterizing your custom exceptions, ensure they use default kwargs.
37 `customErrSchema`: The schema for the `customError` exception class.
38 `HTTPExcSchema`: The schema for fastAPI/starlette HTTPExceptions raised by the app.
39 Defaults to one field: `detail: Optional[str]`
40 `dependencyClasses`: A tuple of classes that represent dependencies for the app's routes.
41 You can subclass all dependencies and pass only the base e.g. `dependencyClasses=(BaseDependency,)`
42 `serviceClasses`: A tuple of classes that represent service classes for the app's routes.
43 You can subclass all services and pass only the base e.g. `serviceClasses=(BaseService,)`
44 Returns:
45 A callable that returns the modified OpenAPI specification as a dictionary or else None.
46 """
48 def _custom_openapi() -> Any:
49 if app.openapi_schema:
50 return app.openapi_schema
51 openapi_schema = get_openapi(
52 title=app.title,
53 version=app.version,
54 description=app.description,
55 routes=app.routes,
56 )
57 add_model_to_openapi(openapi_schema, HTTPExcSchema)
58 if customErrSchema:
59 add_model_to_openapi(openapi_schema, customErrSchema)
60 finder = RouteExcFinder(customError, dependencyClasses, serviceClasses)
61 for route in app.routes:
62 if getattr(route, "include_in_schema", None):
63 for exception in finder.extract_exceptions(route):
64 write_response(
65 openapi_schema,
66 route,
67 exception,
68 customError,
69 customErrSchema,
70 )
71 finder.clear()
72 app.openapi_schema = openapi_schema
73 return app.openapi_schema
75 return _custom_openapi