Skip to content

Commit 827a1ba

Browse files
committed
Use static types for LIBRARY_ERRORS
1 parent 9ceaf22 commit 827a1ba

3 files changed

Lines changed: 62 additions & 43 deletions

File tree

exasol/error/_error.py

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@
33
from inspect import cleandoc
44
from pathlib import Path
55
from typing import (
6+
Any,
67
Dict,
78
Iterable,
89
List,
910
Mapping,
11+
Optional,
1012
Union,
1113
)
1214

1315
with warnings.catch_warnings():
1416
warnings.simplefilter("ignore")
1517
from exasol_error_reporting_python import exa_error
16-
from exasol_error_reporting_python.error_message_builder import InvalidErrorCode
18+
from exasol_error_reporting_python.error_message_builder import (
19+
ErrorMessageBuilder,
20+
InvalidErrorCode,
21+
)
1722

1823

1924
@dataclass(frozen=True)
@@ -29,17 +34,19 @@ def __init__(
2934
message: str,
3035
mitigations: Union[str, Iterable[str]],
3136
parameters: Dict[str, Union[str, Parameter]],
32-
):
37+
) -> None:
3338
# This function maybe flattened into or moved out of the constructor in the future.
34-
def build_error(code, msg, mitigations, params):
39+
def build_error(code, msg, mitigations, params) -> ErrorMessageBuilder:
3540
builder = exa_error.ExaError.message_builder(code)
3641
builder.message(msg)
3742

3843
for mitigation in mitigations:
3944
builder.mitigation(mitigation)
4045

4146
for k, v in params.items():
42-
name, value, description = k, v, ""
47+
name = k
48+
value = v
49+
description: Optional[str] = ""
4350
if isinstance(v, Parameter):
4451
value = v.value
4552
description = v.description
@@ -93,35 +100,58 @@ def _long(error: Error):
93100
return output[:-1]
94101

95102

103+
@dataclass(frozen=True)
104+
class StaticError:
105+
identifier: str
106+
message: str
107+
messagePlaceholders: List[Dict[str, str]]
108+
description: Optional[str]
109+
mitigations: List[str]
110+
sourceFile: str
111+
112+
def to_dict(self) -> Dict[str, Any]:
113+
ret_val = {
114+
"identifier": self.identifier,
115+
"message": self.message,
116+
"messagePlaceholders": self.messagePlaceholders,
117+
"mitigations": self.mitigations,
118+
"sourceFile": self.sourceFile,
119+
}
120+
if self.description is not None:
121+
ret_val["description"] = self.description
122+
return ret_val
123+
124+
96125
# ATTENTION: In the event of an exception while creating an error, we encounter a chicken-and-egg problem regarding error definitions.
97126
# Therefore, errors created by this library must be defined "statically" within this file.
98127
# Details should then be used to create a low-level error. The information should also be used to create/update the error-codes.json
99128
# as part of the release preparation. This is only necessary for this library, as it is the root, other libraries should use
100129
# the `ec` command-line tool to update and create their project specifc error-codes.json file.
101130
LIBRARY_ERRORS = {
102-
"E-ERP-1": {
103-
"identifier": "E-ERP-1",
104-
"message": "Invalid error code {{code}}.",
105-
"messagePlaceholders": [
131+
"E-ERP-1": StaticError(
132+
identifier="E-ERP-1",
133+
message="Invalid error code {{code}}.",
134+
messagePlaceholders=[
106135
{
107136
"placeholder": "code",
108137
"description": "Error code which was causing the error.",
109138
}
110139
],
111-
"mitigations": ["Ensure you follow the standard error code format."],
112-
"sourceFile": Path(__file__).name,
113-
},
114-
"E-ERP-2": {
115-
"identifier": "E-ERP-2",
116-
"message": "Unknown error/exception occurred.",
117-
"messagePlaceholders": [
140+
description=None,
141+
mitigations=["Ensure you follow the standard error code format."],
142+
sourceFile=Path(__file__).name,
143+
),
144+
"E-ERP-2": StaticError(
145+
identifier="E-ERP-2",
146+
message="Unknown error/exception occurred.",
147+
messagePlaceholders=[
118148
{
119149
"placeholder": "traceback",
120150
"description": "Exception traceback which lead to the generation of this error.",
121151
}
122152
],
123-
"description": "An unexpected error occurred during the creation of the error",
124-
"mitigations": [
153+
description="An unexpected error occurred during the creation of the error",
154+
mitigations=[
125155
cleandoc(
126156
"""
127157
A good starting point would be to investigate the cause of the attached exception.
@@ -131,8 +161,8 @@ def _long(error: Error):
131161
"""
132162
)
133163
],
134-
"sourceFile": Path(__file__).name,
135-
},
164+
sourceFile=Path(__file__).name,
165+
),
136166
}
137167

138168

@@ -161,16 +191,10 @@ def ExaError(
161191
except InvalidErrorCode:
162192
error_code = "E-ERP-1"
163193
error_details = LIBRARY_ERRORS[error_code]
164-
identifier = error_details["identifier"]
165-
assert isinstance(identifier, str)
166-
_message = error_details["message"]
167-
assert isinstance(_message, str)
168-
_mitigations = error_details["mitigations"]
169-
assert isinstance(_mitigations, list)
170194
return Error(
171-
code=identifier,
172-
message=_message,
173-
mitigations=_mitigations,
195+
code=error_details.identifier,
196+
message=error_details.message,
197+
mitigations=error_details.mitigations,
174198
parameters={"code": code},
175199
)
176200
except Exception as ex:
@@ -180,29 +204,23 @@ def ExaError(
180204
parameters = {"traceback": tb}
181205
error_code = "E-ERP-2"
182206
error_details = LIBRARY_ERRORS[error_code]
183-
identifier = error_details["identifier"]
184-
assert isinstance(identifier, str)
185-
_message = error_details["message"]
186-
assert isinstance(_message, str)
187-
_mitigations = error_details["mitigations"]
188-
assert isinstance(_mitigations, list)
189207
return Error(
190-
code=identifier,
191-
message=_message,
192-
mitigations=_mitigations,
208+
code=error_details.identifier,
209+
message=error_details.message,
210+
mitigations=error_details.mitigations,
193211
parameters=parameters,
194212
)
195213

196214

197-
def _create_error_code_definitions(version=None):
215+
def _create_error_code_definitions(version=None) -> Dict[str, Any]:
198216
from exasol.error.version import VERSION
199217

200218
version = version or VERSION
201219
return {
202220
"$schema": "https://schemas.exasol.com/error_code_report-1.0.0.json",
203221
"projectName": "exasol-error-reporting",
204222
"projectVersion": version,
205-
"errorCodes": [code for code in LIBRARY_ERRORS.values()],
223+
"errorCodes": [code.to_dict() for code in LIBRARY_ERRORS.values()],
206224
}
207225

208226

exasol_error_reporting_python/error_message_builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, error_code: str) -> None:
3030
self._error_code = error_code
3131
self._message_builder: List[str] = []
3232
self._mitigations: List[str] = []
33-
self._parameter_dict: Dict[str, str] = {}
33+
self._parameter_dict: Dict[str, Optional[str]] = {}
3434

3535
def message(self, message: str, *arguments) -> "ErrorMessageBuilder":
3636
"""

exasol_error_reporting_python/parameters_mapper.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ def __init__(self, text: str, arguments: List[str]) -> None:
1818
self._text = text
1919
self._parameters = arguments
2020
self._parameter_idx = 0
21-
self._parameter_dict: Dict[str, str] = {}
21+
self._parameter_dict: Dict[str, Optional[str]] = {}
2222

2323
@classmethod
24-
def get_params_dict(cls, text: str, arguments: List[str]) -> Dict[str, str]:
24+
def get_params_dict(
25+
cls, text: str, arguments: List[str]
26+
) -> Dict[str, Optional[str]]:
2527
"""
2628
Create ParametersMapper object and return the generated dictionary
2729
that maps the placeholders and parameters.
@@ -45,7 +47,6 @@ def _map_parameters(self) -> None:
4547
for placeholder in PlaceholderHandler.get_placeholders(self._text):
4648
if self._is_parameter_present():
4749
current_parameter = self._get_current_parameter()
48-
assert current_parameter is not None
4950
self._parameter_dict[placeholder.name] = current_parameter
5051
self._next_parameters()
5152

0 commit comments

Comments
 (0)