inference-model 2.0.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inference_model/__init__.py +0 -0
- inference_model/utils/__init__.py +0 -0
- inference_model/utils/documentation_helper/__init__.py +0 -0
- inference_model/utils/documentation_helper/exporters/__init__.py +176 -0
- inference_model/utils/documentation_helper/exporters/collapsible_markdown_exporter.py +49 -0
- inference_model/utils/documentation_helper/exporters/markdown_exporter.py +77 -0
- inference_model/utils/documentation_helper/model.py +353 -0
- inference_model/v1/__init__.py +0 -0
- inference_model/v1/custom_redis.py +282 -0
- inference_model/v1/inference_job.py +105 -0
- inference_model/v1/inference_request.py +15 -0
- inference_model/v1/instance.py +23 -0
- inference_model/v1/worker_specification.py +43 -0
- inference_model-2.0.12.dist-info/LICENSE +287 -0
- inference_model-2.0.12.dist-info/METADATA +24 -0
- inference_model-2.0.12.dist-info/RECORD +17 -0
- inference_model-2.0.12.dist-info/WHEEL +4 -0
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Dict, List, Type
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
from pydantic_settings import BaseSettings
|
|
6
|
+
|
|
7
|
+
from inference_model.utils.documentation_helper.model import (
|
|
8
|
+
LeaveSetting,
|
|
9
|
+
NestingSetting,
|
|
10
|
+
RootSetting,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ExporterBase(BaseModel, ABC):
|
|
15
|
+
"""
|
|
16
|
+
A Base class to create setting exporters for different formats from.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
root_setting: RootSetting
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
setting_cls: Type[BaseSettings],
|
|
24
|
+
cls: Type[RootSetting] = RootSetting,
|
|
25
|
+
**kwargs
|
|
26
|
+
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Initialize the object.
|
|
29
|
+
|
|
30
|
+
:param setting_cls: Each setting exporter requires a setting class to export from.
|
|
31
|
+
:param cls:
|
|
32
|
+
In case we would want to use a custom cls, we can pass it here.
|
|
33
|
+
RootSetting should be fine in most cases though.
|
|
34
|
+
"""
|
|
35
|
+
super().__init__(root_setting=cls(setting_cls=setting_cls), **kwargs)
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def _header_translation_dict() -> Dict[str, str]:
|
|
39
|
+
"""
|
|
40
|
+
Return a dictionary to translate the pydantic-parameters to the values that should be used in the export.
|
|
41
|
+
|
|
42
|
+
This method may be overridden to create custom naming.
|
|
43
|
+
It is provided, however, to allow different formats to be similar in naming,
|
|
44
|
+
thus, providing a naming-convention.
|
|
45
|
+
:return:
|
|
46
|
+
A Dictionary with the translation.
|
|
47
|
+
The key is the pydantic-parameter, the value is the export-parameter.
|
|
48
|
+
"""
|
|
49
|
+
return {
|
|
50
|
+
"full_env_name": "Environment Variable",
|
|
51
|
+
"description": "Description",
|
|
52
|
+
"default": "Default Value",
|
|
53
|
+
"annotation_string": "Type",
|
|
54
|
+
"required": "required",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def _max_leave_param_length(
|
|
58
|
+
self, leave_settings: List[LeaveSetting], include_header_length: bool
|
|
59
|
+
) -> Dict[str, int]:
|
|
60
|
+
"""
|
|
61
|
+
Calculate the maximum length of each parameter in the leave_settings.
|
|
62
|
+
|
|
63
|
+
Some exporters may want to have a fixed width for each column.
|
|
64
|
+
This is a helper-function to calculate the length of those columns.
|
|
65
|
+
:param leave_settings: A list of leave-settings to calculate the maximum length of each parameter from.
|
|
66
|
+
:param include_header_length: Weather to include the header length in the calculation.
|
|
67
|
+
:return:
|
|
68
|
+
A dictionary with the maximum length of each parameter.
|
|
69
|
+
The key is the pydantic-parameter, the value is the maximum length.
|
|
70
|
+
"""
|
|
71
|
+
if not include_header_length:
|
|
72
|
+
max_lengths: Dict[str, int] = {
|
|
73
|
+
"full_env_name": 0,
|
|
74
|
+
"description": 0,
|
|
75
|
+
"default": 0,
|
|
76
|
+
"annotation_string": 0,
|
|
77
|
+
"required": 0,
|
|
78
|
+
}
|
|
79
|
+
else:
|
|
80
|
+
max_lengths: Dict[str, int] = {
|
|
81
|
+
param: len(header)
|
|
82
|
+
for param, header in self._header_translation_dict().items()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for leave_setting in leave_settings:
|
|
86
|
+
for parameter, max_length in max_lengths.items():
|
|
87
|
+
length: int = len(str(getattr(leave_setting, parameter)))
|
|
88
|
+
if length > max_length:
|
|
89
|
+
max_lengths[parameter] = length
|
|
90
|
+
|
|
91
|
+
return max_lengths
|
|
92
|
+
|
|
93
|
+
@abstractmethod
|
|
94
|
+
def _export_leaves_to_string(self, leave_settings: List[LeaveSetting]) -> str:
|
|
95
|
+
"""
|
|
96
|
+
Export the leave-settings to a string.
|
|
97
|
+
|
|
98
|
+
This method should be implemented by the child-class, since it is format-specific.
|
|
99
|
+
:param leave_settings: A list of leave-settings to export.
|
|
100
|
+
:return: The exported string.
|
|
101
|
+
"""
|
|
102
|
+
raise NotImplementedError()
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def _export_nesting_header_to_string(self, nesting_setting: NestingSetting) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Export the flat nesting-settings to a string.
|
|
108
|
+
|
|
109
|
+
This method will only export the header, description, etc., but NOT sub-settings!
|
|
110
|
+
This method should be implemented by the child-class, since it is format-specific.
|
|
111
|
+
:param nesting_setting: The nesting-setting to export.
|
|
112
|
+
:return: The exported string.
|
|
113
|
+
"""
|
|
114
|
+
raise NotImplementedError()
|
|
115
|
+
|
|
116
|
+
def _export_full_nesting_to_string(self, nesting_setting: NestingSetting) -> str:
|
|
117
|
+
"""
|
|
118
|
+
Export the full nesting-settings to a string.
|
|
119
|
+
|
|
120
|
+
This method will only export the header, description, etc., AND sub-settings!
|
|
121
|
+
|
|
122
|
+
This method may be overridden to create custom naming.
|
|
123
|
+
It is provided, however, to allow different formats to be similar in naming,
|
|
124
|
+
thus, providing a naming-convention.
|
|
125
|
+
|
|
126
|
+
Generally, A nested setting is exported by exporting:
|
|
127
|
+
- Header, description, etc. by calling _export_nesting_header_to_string.
|
|
128
|
+
- Leaves-settings by calling _export_leaves_to_string.
|
|
129
|
+
- Nesting-settings by calling _export_full_nesting_to_string.
|
|
130
|
+
|
|
131
|
+
:param nesting_setting: The nesting-setting to export.
|
|
132
|
+
:return: The exported string.
|
|
133
|
+
"""
|
|
134
|
+
string: str = self._export_nesting_header_to_string(
|
|
135
|
+
nesting_setting=nesting_setting
|
|
136
|
+
)
|
|
137
|
+
string += self._export_leaves_to_string(
|
|
138
|
+
leave_settings=list(nesting_setting.sub_leave_settings)
|
|
139
|
+
)
|
|
140
|
+
for sub_nesting_setting in nesting_setting.sub_nesting_settings:
|
|
141
|
+
string += self._export_full_nesting_to_string(
|
|
142
|
+
nesting_setting=sub_nesting_setting
|
|
143
|
+
)
|
|
144
|
+
return string
|
|
145
|
+
|
|
146
|
+
def export(self) -> str:
|
|
147
|
+
"""
|
|
148
|
+
Export the settings to a string.
|
|
149
|
+
|
|
150
|
+
:return: The exported string.
|
|
151
|
+
"""
|
|
152
|
+
export: str = (
|
|
153
|
+
self._export_full_nesting_to_string(
|
|
154
|
+
nesting_setting=self.root_setting
|
|
155
|
+
).strip()
|
|
156
|
+
+ "\n"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return "\n".join([line.rstrip() for line in export.split("\n")])
|
|
160
|
+
|
|
161
|
+
def __str__(self) -> str:
|
|
162
|
+
"""
|
|
163
|
+
Return the exported string.
|
|
164
|
+
|
|
165
|
+
:return: The exported string.
|
|
166
|
+
"""
|
|
167
|
+
return self.export()
|
|
168
|
+
|
|
169
|
+
def save(self, filename: str) -> None:
|
|
170
|
+
"""
|
|
171
|
+
Save the exported string to a file.
|
|
172
|
+
|
|
173
|
+
:param filename: The filename to save the exported string to.
|
|
174
|
+
"""
|
|
175
|
+
with open(filename, "w") as f:
|
|
176
|
+
f.write(str(self))
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from inference_model.utils.documentation_helper.exporters.markdown_exporter import (
|
|
4
|
+
MarkdownExporter,
|
|
5
|
+
)
|
|
6
|
+
from inference_model.utils.documentation_helper.model import LeaveSetting
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CollapsibleMarkdownExporter(MarkdownExporter):
|
|
10
|
+
"""
|
|
11
|
+
Another Markdown format.
|
|
12
|
+
|
|
13
|
+
Leaves are collapsible Headers to make documentations with long descriptions more readable.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def _export_leaves_to_string(self, leave_settings: List[LeaveSetting]) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Overwrite the method to export the leaves in a collapsible format.
|
|
19
|
+
|
|
20
|
+
:param leave_settings: The list of leave-settings to export.
|
|
21
|
+
:return: The string representation of the leave-settings.
|
|
22
|
+
"""
|
|
23
|
+
export_strings: List[str] = []
|
|
24
|
+
for leave_setting in leave_settings:
|
|
25
|
+
export_string: str = "<details>\n"
|
|
26
|
+
export_string += f" <summary>{leave_setting.full_env_name}</summary>\n"
|
|
27
|
+
export_string += " <table>\n"
|
|
28
|
+
|
|
29
|
+
for param, header in self._header_translation_dict().items():
|
|
30
|
+
if param == "description" or param == "full_env_name":
|
|
31
|
+
# Skipping those, since they are already contained elsewhere.
|
|
32
|
+
continue
|
|
33
|
+
|
|
34
|
+
export_string += " <tr>\n"
|
|
35
|
+
export_string += f" <td>{header}</td>\n"
|
|
36
|
+
export_string += (
|
|
37
|
+
f" <td>{getattr(leave_setting, param)}</td>\n"
|
|
38
|
+
)
|
|
39
|
+
export_string += " </tr>\n"
|
|
40
|
+
|
|
41
|
+
export_string += " </table>\n"
|
|
42
|
+
if leave_setting.description:
|
|
43
|
+
export_string += f" {leave_setting.description}\n"
|
|
44
|
+
export_string += "</details>"
|
|
45
|
+
export_string += "\n\n"
|
|
46
|
+
|
|
47
|
+
export_strings.append(export_string)
|
|
48
|
+
|
|
49
|
+
return "".join(export_strings)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from typing import Dict, List
|
|
2
|
+
|
|
3
|
+
from inference_model.utils.documentation_helper.exporters import ExporterBase
|
|
4
|
+
from inference_model.utils.documentation_helper.model import (
|
|
5
|
+
LeaveSetting,
|
|
6
|
+
NestingSetting,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MarkdownExporter(ExporterBase):
|
|
11
|
+
"""
|
|
12
|
+
A class to export the settings to a Markdown format.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def _export_leaves_to_string(self, leave_settings: List[LeaveSetting]) -> str:
|
|
16
|
+
"""
|
|
17
|
+
Export the leave-settings to a string as a Markdown table.
|
|
18
|
+
|
|
19
|
+
:param leave_settings: A list of leave-settings to export.
|
|
20
|
+
:return: The exported string
|
|
21
|
+
"""
|
|
22
|
+
# We want the table to be formatted properly. This includes that the columns have a fixed width.
|
|
23
|
+
# Each column may have a different width, but the width of each column should be the same for each row.
|
|
24
|
+
# We calculate the maximum length of each column and use this to format the table.
|
|
25
|
+
max_param_lengths: Dict[str, int] = self._max_leave_param_length(
|
|
26
|
+
leave_settings=leave_settings, include_header_length=True
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# We are building the header of the table.
|
|
30
|
+
header: str = " | ".join(
|
|
31
|
+
[
|
|
32
|
+
self._header_translation_dict().get(param).ljust(length)
|
|
33
|
+
for param, length in max_param_lengths.items()
|
|
34
|
+
]
|
|
35
|
+
)
|
|
36
|
+
header = f"| {header} |"
|
|
37
|
+
|
|
38
|
+
# The header is separated from the rows by a seperator.
|
|
39
|
+
seperator: str = "|".join(
|
|
40
|
+
"-" * (length + 2) for length in max_param_lengths.values()
|
|
41
|
+
)
|
|
42
|
+
seperator = f"|{seperator}|"
|
|
43
|
+
|
|
44
|
+
# We are building the rows of the table.
|
|
45
|
+
rows: List[str] = [
|
|
46
|
+
" | ".join(
|
|
47
|
+
[
|
|
48
|
+
str(getattr(leave_setting, param)).ljust(length)
|
|
49
|
+
for param, length in max_param_lengths.items()
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
for leave_setting in leave_settings
|
|
53
|
+
]
|
|
54
|
+
rows = [f"| {row} |" for row in rows]
|
|
55
|
+
|
|
56
|
+
# finally we join the header, seperator and rows to a single string
|
|
57
|
+
return "\n".join([header, seperator] + rows) + "\n\n"
|
|
58
|
+
|
|
59
|
+
def _export_nesting_header_to_string(self, nesting_setting: NestingSetting) -> str:
|
|
60
|
+
"""
|
|
61
|
+
Export the flat nesting-settings to a string (as a markdown header with some text).
|
|
62
|
+
|
|
63
|
+
This method will only export the header, description, etc., but NOT sub-settings!
|
|
64
|
+
:param nesting_setting: The nesting-setting to export.
|
|
65
|
+
:return: The exported string.
|
|
66
|
+
"""
|
|
67
|
+
# Create a new Markdown header.
|
|
68
|
+
expected_string: str = (
|
|
69
|
+
"#" * (nesting_setting.nesting_count + 1)
|
|
70
|
+
+ f" {nesting_setting.full_env_name}\n\n"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Optionally add the description if given.
|
|
74
|
+
if nesting_setting.description:
|
|
75
|
+
expected_string += f"{nesting_setting.description}\n\n"
|
|
76
|
+
|
|
77
|
+
return expected_string
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict, Iterator, Optional, Type
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
from pydantic.fields import FieldInfo
|
|
6
|
+
from pydantic_core import PydanticUndefined
|
|
7
|
+
from pydantic_settings import BaseSettings
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Setting(BaseModel, ABC):
|
|
11
|
+
"""
|
|
12
|
+
All information regarding a settings-parameter.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
prefix_: Optional[str]
|
|
16
|
+
setting_name: str
|
|
17
|
+
root_model_config: Dict[str, Any]
|
|
18
|
+
nesting_count: int
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
prefix: Optional[str],
|
|
23
|
+
setting_name: str,
|
|
24
|
+
root_model_config: Dict[str, Any],
|
|
25
|
+
nesting_count: int,
|
|
26
|
+
**kwargs,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Initialize the setting.
|
|
30
|
+
|
|
31
|
+
:param prefix: The prefix of the setting including suffixed nested-delimiter.
|
|
32
|
+
:param setting_name: The name of the setting excluding the prefix or nested-delimiter.
|
|
33
|
+
:param root_model_config:
|
|
34
|
+
The model config as defined in RootSetting, since model_config gets passed down the tree.
|
|
35
|
+
:param nesting_count: The nesting count of the setting. Root=0, Nesting=1, ..., Leave=n.
|
|
36
|
+
"""
|
|
37
|
+
if prefix is None and nesting_count != 0:
|
|
38
|
+
raise ValueError("prefix is None but nesting_count is not 0")
|
|
39
|
+
if root_model_config.get("env_nested_delimiter") is None:
|
|
40
|
+
raise ValueError("env_nested_delimiter is not set in model_config")
|
|
41
|
+
if setting_name is None:
|
|
42
|
+
raise ValueError("setting_name is empty")
|
|
43
|
+
|
|
44
|
+
super().__init__(
|
|
45
|
+
prefix_=prefix,
|
|
46
|
+
setting_name=setting_name,
|
|
47
|
+
root_model_config=root_model_config,
|
|
48
|
+
nesting_count=nesting_count,
|
|
49
|
+
**kwargs,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def env_nested_delimiter(self) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Return the env_nested_delimiter of the current setting.
|
|
56
|
+
|
|
57
|
+
When configuring the settings using environment-variable, we need to know the delimiter.
|
|
58
|
+
:return: The env_nested_delimiter of the current setting.
|
|
59
|
+
"""
|
|
60
|
+
return self.root_model_config.get("env_nested_delimiter")
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def prefix(self) -> str:
|
|
64
|
+
"""
|
|
65
|
+
Return the full prefix of the current setting.
|
|
66
|
+
|
|
67
|
+
The prefix is the full path to the current setting, including all parent settings.
|
|
68
|
+
The prefix will be upper-cased, when it is not case-sensitive.
|
|
69
|
+
:return: The full prefix of the current setting.
|
|
70
|
+
"""
|
|
71
|
+
if self.prefix_ is None:
|
|
72
|
+
return ""
|
|
73
|
+
|
|
74
|
+
# At the root level, the env-prefix, will not be suffixed with the nested-delimiter.
|
|
75
|
+
# Since the env-prefix will be the setting-name at nesting_count 0,
|
|
76
|
+
# and the prefix_ at nesting_count 1, we need to skip adding nested-delimiter at nesting_count 0 and 1.
|
|
77
|
+
if self.nesting_count > 1:
|
|
78
|
+
prefix: str = f"{self.prefix_}{self.env_nested_delimiter}"
|
|
79
|
+
else:
|
|
80
|
+
prefix: str = self.prefix_
|
|
81
|
+
|
|
82
|
+
if self.root_model_config.get("case_sensitive"):
|
|
83
|
+
return prefix
|
|
84
|
+
else:
|
|
85
|
+
return prefix.upper()
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def full_env_name(self) -> str:
|
|
89
|
+
"""
|
|
90
|
+
Return the full_env_name of the current setting including all parent prefixes, delimiter and setting_name.
|
|
91
|
+
|
|
92
|
+
The full_env_name will be upper-cased, when it is not case-sensitive.
|
|
93
|
+
:return: The full_env_name of the current setting.
|
|
94
|
+
"""
|
|
95
|
+
full_env_name: str = f"{self.prefix}{self.setting_name}"
|
|
96
|
+
if self.root_model_config.get("case_sensitive"):
|
|
97
|
+
return full_env_name
|
|
98
|
+
else:
|
|
99
|
+
return full_env_name.upper()
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def description(self) -> str:
|
|
104
|
+
"""
|
|
105
|
+
Return the description of the current setting.
|
|
106
|
+
|
|
107
|
+
The description is the description of the current setting.
|
|
108
|
+
:return: The description of the current setting.
|
|
109
|
+
"""
|
|
110
|
+
raise NotImplementedError()
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def is_nesting(cls) -> bool:
|
|
114
|
+
"""
|
|
115
|
+
Determine if this setting could contain sub-settings.
|
|
116
|
+
|
|
117
|
+
Note: An empty BaseSetting will not contain any sub-settings, yet it will be considered nesting.
|
|
118
|
+
This is intentional.
|
|
119
|
+
:return: True if there could be a sub-settings, False otherwise.
|
|
120
|
+
"""
|
|
121
|
+
return issubclass(cls, NestingSetting)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class LeaveSetting(Setting):
|
|
125
|
+
"""
|
|
126
|
+
A LeaveSetting, which is a setting that does not contain other settings (is a leave).
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
130
|
+
|
|
131
|
+
field_info: FieldInfo
|
|
132
|
+
|
|
133
|
+
def __init__(
|
|
134
|
+
self,
|
|
135
|
+
prefix: Optional[str],
|
|
136
|
+
setting_name: str,
|
|
137
|
+
root_model_config: Dict[str, Any],
|
|
138
|
+
nesting_count: int,
|
|
139
|
+
field_info: FieldInfo,
|
|
140
|
+
**kwargs,
|
|
141
|
+
) -> None:
|
|
142
|
+
"""
|
|
143
|
+
Initialize the leave-setting.
|
|
144
|
+
|
|
145
|
+
:param prefix: The prefix of the setting including suffixed nested-delimiter.
|
|
146
|
+
:param setting_name: The name of the setting excluding the prefix or nested-delimiter.
|
|
147
|
+
:param root_model_config:
|
|
148
|
+
The model config as defined in RootSetting, since model_config gets passed down the tree.
|
|
149
|
+
:param nesting_count: The nesting count of the setting. Root=0, Nesting=1, ..., Leave=n.
|
|
150
|
+
:param field_info: The field-info-object from pydantic containing further information of the setting.
|
|
151
|
+
"""
|
|
152
|
+
super().__init__(
|
|
153
|
+
prefix=prefix,
|
|
154
|
+
root_model_config=root_model_config,
|
|
155
|
+
setting_name=setting_name,
|
|
156
|
+
nesting_count=nesting_count,
|
|
157
|
+
field_info=field_info,
|
|
158
|
+
**kwargs,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def description(self) -> str:
|
|
163
|
+
"""
|
|
164
|
+
Return the description of the current setting.
|
|
165
|
+
|
|
166
|
+
The description is the description of the current setting.
|
|
167
|
+
:return: The description of the current setting.
|
|
168
|
+
"""
|
|
169
|
+
return (self.field_info.description or "").strip()
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def annotation(self) -> Type[Any]:
|
|
173
|
+
"""
|
|
174
|
+
Return the annotation of the current setting.
|
|
175
|
+
|
|
176
|
+
The annotation is the type of the current setting.
|
|
177
|
+
:return: The annotation of the current setting.
|
|
178
|
+
"""
|
|
179
|
+
return self.field_info.annotation
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def annotation_string(self) -> str:
|
|
183
|
+
"""
|
|
184
|
+
Return a string-representation fo the annotation.
|
|
185
|
+
|
|
186
|
+
:return: The string-representation of the annotation.
|
|
187
|
+
"""
|
|
188
|
+
return (
|
|
189
|
+
str(self.annotation)
|
|
190
|
+
.replace("typing.", "")
|
|
191
|
+
.replace("class ", "")
|
|
192
|
+
.replace("'", "")
|
|
193
|
+
.replace("<", "")
|
|
194
|
+
.replace(">", "")
|
|
195
|
+
).strip()
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def required(self) -> bool:
|
|
199
|
+
"""
|
|
200
|
+
Return if the setting is required.
|
|
201
|
+
|
|
202
|
+
:return: True if the setting is required, False otherwise
|
|
203
|
+
"""
|
|
204
|
+
return self.field_info.is_required()
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def default(self) -> str:
|
|
208
|
+
"""
|
|
209
|
+
Return the default value of the setting.
|
|
210
|
+
|
|
211
|
+
:return: The default value of the setting.
|
|
212
|
+
"""
|
|
213
|
+
if self.field_info.default != PydanticUndefined:
|
|
214
|
+
return str(self.field_info.default)
|
|
215
|
+
elif self.field_info.default_factory:
|
|
216
|
+
return "Created by a default-factory."
|
|
217
|
+
else:
|
|
218
|
+
return "---"
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class NestingSetting(Setting):
|
|
222
|
+
"""
|
|
223
|
+
ANestingSetting, which is a setting that contains other settings (is nesting).
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
227
|
+
|
|
228
|
+
field_infos: Dict[str, FieldInfo]
|
|
229
|
+
description_: str
|
|
230
|
+
|
|
231
|
+
def __init__(
|
|
232
|
+
self,
|
|
233
|
+
prefix: Optional[str],
|
|
234
|
+
setting_name: str,
|
|
235
|
+
root_model_config: Dict[str, Any],
|
|
236
|
+
nesting_count: int,
|
|
237
|
+
field_infos: Dict[str, FieldInfo],
|
|
238
|
+
description: str,
|
|
239
|
+
**kwargs,
|
|
240
|
+
) -> None:
|
|
241
|
+
"""
|
|
242
|
+
Initialize the nesting-setting.
|
|
243
|
+
|
|
244
|
+
:param prefix: The prefix of the setting including suffixed nested-delimiter.
|
|
245
|
+
:param setting_name: The name of the setting excluding the prefix or nested-delimiter.
|
|
246
|
+
:param root_model_config:
|
|
247
|
+
The model config as defined in RootSetting, since model_config gets passed down the tree.
|
|
248
|
+
:param nesting_count: The nesting count of the setting. Root=0, Nesting=1, ..., Leave=n.
|
|
249
|
+
:param field_infos: The field-infos of the sub-settings.
|
|
250
|
+
:param description: The description of the nesting-setting.
|
|
251
|
+
"""
|
|
252
|
+
super().__init__(
|
|
253
|
+
prefix=prefix,
|
|
254
|
+
setting_name=setting_name,
|
|
255
|
+
root_model_config=root_model_config,
|
|
256
|
+
nesting_count=nesting_count,
|
|
257
|
+
field_infos=field_infos,
|
|
258
|
+
description_=description,
|
|
259
|
+
**kwargs,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def description(self) -> str:
|
|
264
|
+
"""
|
|
265
|
+
Return the description of the current setting.
|
|
266
|
+
|
|
267
|
+
:return: The description of the current setting.
|
|
268
|
+
"""
|
|
269
|
+
return self.description_.strip()
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def sub_leave_settings(self) -> Iterator[LeaveSetting]:
|
|
273
|
+
"""
|
|
274
|
+
Return the sub-settings of the current setting (only leave settings).
|
|
275
|
+
|
|
276
|
+
This is a generator. When you want to make length-checks or reuse the iterator,
|
|
277
|
+
use list(setting.nested_settings) to make it a list.
|
|
278
|
+
:return: The sub-settings of the current setting (only leave settings).
|
|
279
|
+
"""
|
|
280
|
+
for field_name, field in self.field_infos.items():
|
|
281
|
+
if issubclass(type(field.annotation), type) and issubclass(
|
|
282
|
+
field.annotation, BaseSettings
|
|
283
|
+
):
|
|
284
|
+
continue
|
|
285
|
+
yield LeaveSetting(
|
|
286
|
+
prefix=self.full_env_name,
|
|
287
|
+
root_model_config=self.root_model_config,
|
|
288
|
+
field_info=field,
|
|
289
|
+
setting_name=field_name,
|
|
290
|
+
nesting_count=self.nesting_count + 1,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def sub_nesting_settings(self) -> Iterator["NestingSetting"]:
|
|
295
|
+
"""
|
|
296
|
+
Return the sub-settings of the current setting (only nesting settings).
|
|
297
|
+
|
|
298
|
+
This is a generator. When you want to make length-checks or reuse the iterator,
|
|
299
|
+
use list(setting.nested_settings) to make it a list.
|
|
300
|
+
:return: The sub-settings of the current setting (only nesting settings).
|
|
301
|
+
"""
|
|
302
|
+
for field_name, field in self.field_infos.items():
|
|
303
|
+
if not (
|
|
304
|
+
issubclass(type(field.annotation), type)
|
|
305
|
+
and issubclass(field.annotation, BaseSettings)
|
|
306
|
+
):
|
|
307
|
+
continue
|
|
308
|
+
yield NestingSetting(
|
|
309
|
+
prefix=self.full_env_name,
|
|
310
|
+
root_model_config=self.root_model_config,
|
|
311
|
+
field_infos=field.annotation.model_fields,
|
|
312
|
+
setting_name=field_name,
|
|
313
|
+
nesting_count=self.nesting_count + 1,
|
|
314
|
+
# A nested-setting may get a description by the class-docstring, or by the field-description.
|
|
315
|
+
# We will combine both, if they are not empty.
|
|
316
|
+
description=f"{(field.description or '').strip()}\n\n"
|
|
317
|
+
f"{(field.annotation.__doc__ or '').strip()}".strip(),
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
@property
|
|
321
|
+
def sub_settings(self) -> Iterator[Setting]:
|
|
322
|
+
"""
|
|
323
|
+
Return the sub-settings of the current setting (all settings).
|
|
324
|
+
|
|
325
|
+
This is a generator. When you want to make length-checks or reuse the iterator,
|
|
326
|
+
use list(setting.nested_settings) to make it a list.
|
|
327
|
+
:return: The sub-settings of the current setting (all settings).
|
|
328
|
+
"""
|
|
329
|
+
for sub_setting in self.sub_leave_settings:
|
|
330
|
+
yield sub_setting
|
|
331
|
+
for sub_setting in self.sub_nesting_settings:
|
|
332
|
+
yield sub_setting
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
class RootSetting(NestingSetting):
|
|
336
|
+
"""
|
|
337
|
+
The root-setting, which is the entry-point for the settings-configuration.
|
|
338
|
+
"""
|
|
339
|
+
|
|
340
|
+
def __init__(self, setting_cls: Type[BaseSettings]) -> None:
|
|
341
|
+
"""
|
|
342
|
+
Initialize the root-setting.
|
|
343
|
+
|
|
344
|
+
:param setting_cls: The class of the root-setting. Must be a child of BaseSetting.
|
|
345
|
+
"""
|
|
346
|
+
super().__init__(
|
|
347
|
+
prefix=None,
|
|
348
|
+
setting_name=setting_cls.model_config.get("env_prefix"),
|
|
349
|
+
root_model_config=setting_cls.model_config,
|
|
350
|
+
nesting_count=0,
|
|
351
|
+
field_infos=setting_cls.model_fields,
|
|
352
|
+
description=setting_cls.__doc__ or "",
|
|
353
|
+
)
|
|
File without changes
|