1"""
2This module defines a Connexion specific options class to pass to the Connexion App or API.
3"""
4import dataclasses
5import logging
6import typing as t
7
8try:
9 from swagger_ui_bundle import swagger_ui_path as default_template_dir
10except ImportError:
11 default_template_dir = None
12
13NO_UI_MSG = """The swagger_ui directory could not be found.
14 Please install connexion with extra install: pip install connexion[swagger-ui]
15 or provide the path to your local installation by passing swagger_path=<your path>
16"""
17
18logger = logging.getLogger("connexion.options")
19
20
21@dataclasses.dataclass
22class SwaggerUIOptions:
23 """Options to configure the Swagger UI.
24
25 :param serve_spec: Whether to serve the Swagger / OpenAPI Specification
26 :param spec_path: Where to serve the Swagger / OpenAPI Specification
27
28 :param swagger_ui: Whether to serve the Swagger UI
29 :param swagger_ui_path: Where to serve the Swagger UI
30 :param swagger_ui_config: Options to configure the Swagger UI. See
31 https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration
32 for an overview of the available options.
33 :param swagger_ui_template_dir: Directory with static files to use to serve Swagger UI
34 :param swagger_ui_template_arguments: Arguments passed to the Swagger UI template. Useful
35 when providing your own template dir with additional template arguments.
36 """
37
38 serve_spec: bool = True
39 spec_path: t.Optional[str] = None
40
41 swagger_ui: bool = True
42 swagger_ui_config: dict = dataclasses.field(default_factory=dict)
43 swagger_ui_path: str = "/ui"
44 swagger_ui_template_dir: t.Optional[str] = None
45 swagger_ui_template_arguments: dict = dataclasses.field(default_factory=dict)
46
47
48class SwaggerUIConfig:
49 """Class holding swagger UI specific options."""
50
51 def __init__(
52 self,
53 options: t.Optional[SwaggerUIOptions] = None,
54 oas_version: t.Tuple[int, ...] = (2,),
55 ):
56 if oas_version >= (3, 0, 0):
57 self.spec_path = "/openapi.json"
58 else:
59 self.spec_path = "/swagger.json"
60
61 if options is not None and not isinstance(options, SwaggerUIOptions):
62 raise ValueError(
63 f"`swaggger_ui_options` should be of type `SwaggerUIOptions`, "
64 f"but received {type(options)} instead."
65 )
66
67 self._options = options or SwaggerUIOptions()
68
69 @property
70 def openapi_spec_available(self) -> bool:
71 """Whether to make the OpenAPI Specification available."""
72 return self._options.serve_spec
73
74 @property
75 def openapi_spec_path(self) -> str:
76 """Path to host the Swagger UI."""
77 return self._options.spec_path or self.spec_path
78
79 @property
80 def swagger_ui_available(self) -> bool:
81 """Whether to make the Swagger UI available."""
82 if self._options.swagger_ui and self.swagger_ui_template_dir is None:
83 logger.warning(NO_UI_MSG)
84 return False
85 return self._options.swagger_ui
86
87 @property
88 def swagger_ui_path(self) -> str:
89 """Path to mount the Swagger UI and make it accessible via a browser."""
90 return self._options.swagger_ui_path
91
92 @property
93 def swagger_ui_template_dir(self) -> str:
94 """Directory with static files to use to serve Swagger UI."""
95 return self._options.swagger_ui_template_dir or default_template_dir
96
97 @property
98 def swagger_ui_config(self) -> dict:
99 """Options to configure the Swagger UI."""
100 return self._options.swagger_ui_config
101
102 @property
103 def swagger_ui_template_arguments(self) -> dict:
104 """Arguments passed to the Swagger UI template."""
105 return self._options.swagger_ui_template_arguments