pumpwood_communication.exceptions
Define PumpWood exceptions to be treated as API errors.
Define especific errors for PumpWood plataform. These errors will be treated and will not result in default 500 errors
1"""Define PumpWood exceptions to be treated as API errors. 2 3Define especific errors for PumpWood plataform. These errors will be treated 4and will not result in default 500 errors 5""" 6from typing import Any 7from loguru import logger 8 9 10class PumpWoodException(Exception): # NOQA 11 """Special exception used in Pumpowod Systems. 12 13 It permits treatment of raises on applications serializing response 14 using to_dict function and return status code as `status_code` 15 attribute value. 16 """ 17 18 status_code: int = 400 19 """PumpWoodException will return status 400 on Pumpwood backend.""" 20 21 message: str 22 """Message associated with raise.""" 23 24 payload: dict 25 """Dictionary payload that will be returned by to_dict funcion and format 26 message string.""" 27 28 translate: bool 29 """If message will be translated or not.""" 30 31 parallel: bool 32 """If error was raised on a parallel request.""" 33 34 def __repr__(self): 35 """@private.""" 36 message_fmt = self.format_message() 37 template = "{class_name}[status_code={status_code}]: " + \ 38 "{message_fmt}\nerror payload={payload}" 39 return template.format( 40 class_name=self.__class__.__name__, 41 status_code=self.status_code, 42 message_fmt=message_fmt, 43 payload=self.payload) 44 45 def __str__(self): 46 """@private.""" 47 message_fmt = self.format_message() 48 template = "{class_name}[status_code={status_code}]: " + \ 49 "{message_fmt}\nerror payload={payload}" 50 return template.format( 51 class_name=self.__class__.__name__, 52 status_code=self.status_code, 53 message_fmt=message_fmt, 54 payload=self.payload) 55 56 def __init__(self, message: str, payload: dict = None, 57 status_code: int = None, translate: bool = False, 58 parallel: bool = False): 59 """Initialize the PumpWood exception. 60 61 Args: 62 message (str): 63 Message that will be formated using payload 64 information using `{key}` to replace information. 65 payload (dict): 66 Payload data passed as a dictionary, it will be returned 67 in payload at `to_dict` funcion and used to format message. 68 Defaults to None. 69 status_code (int): 70 Change the default status code of the exception. 71 Defaults to None. 72 translate (bool): 73 Set if message should be translated or not. 74 Defaults to False. 75 parallel (bool): 76 Error on a parallel request. Defaults to False. 77 """ 78 Exception.__init__(self) 79 80 # Initialize payload to avoid mutable default issues 81 if payload is None: 82 payload = {} 83 84 self.message = message 85 if status_code is not None: 86 self.status_code = status_code 87 self.payload = payload 88 self.translate = translate 89 self.parallel = parallel 90 91 def format_message(self) -> str: 92 """Format exception message using payload data. 93 94 Substitute placeholders at exception message with payload. 95 96 Returns: 97 Return a string of message with placeholders substituted with 98 payload data. 99 """ 100 if self.translate: 101 try: 102 return self.message.format(**self.payload) 103 except Exception: 104 return self.message + "\n** format error **" 105 else: 106 try: 107 return self.message.format(**self.payload) 108 except Exception: 109 return self.message + "\n** format error **" 110 111 def to_dict(self) -> dict[str, Any]: 112 """Serialize Exception object to return as reponse. 113 114 Returns: 115 Return a dictionary with keys: 116 - **payload [dict]:** Payload associated with raise. 117 - **type [str]:** Return name of the class of the Exception. 118 - **message_not_fmt [str]:** Return msg without replacemnt of the 119 msg with payload information. 120 - **message [str]:** Return msg formated with payload information. 121 """ 122 message_fmt = self.format_message() 123 rv = { 124 "__error__": 'PumpWoodException', 125 "type": self.__class__.__name__, 126 "payload": self.payload, 127 "message_not_fmt": self.message, 128 "message": message_fmt, 129 "parallel": self.parallel} 130 return rv 131 132 133class PumpWoodDataLoadingException(PumpWoodException): 134 """Problem when loading data at dataloaders and to_load models.""" 135 136 pass 137 138 139class PumpWoodDatabaseError(PumpWoodException): 140 """Errors raised by Postgres and not treated by other handlers.""" 141 142 pass 143 144 145class PumpWoodUniqueDatabaseError(PumpWoodException): 146 """Unique errors raised by Postgres.""" 147 148 pass 149 150 151class PumpWoodDataTransformationException(PumpWoodException): 152 """Problem when transforming model data.""" 153 154 pass 155 156 157class PumpWoodWrongParameters(PumpWoodException): 158 """Raise for errors in object deserialization.""" 159 160 pass 161 162 163class PumpWoodObjectSavingException(PumpWoodException): 164 """Raise for errors in object deserialization.""" 165 166 pass 167 168 169class PumpWoodObjectDeleteException(PumpWoodException): 170 """Raise for errors in object deserialization.""" 171 172 pass 173 174 175class PumpWoodActionArgsException(PumpWoodException): 176 """Missing arguments to perform action.""" 177 178 pass 179 180 181class PumpWoodUnauthorized(PumpWoodException): 182 """User Unauthorized to perform action.""" 183 184 status_code = 401 185 186 187class PumpWoodForbidden(PumpWoodException): 188 """Action not permited.""" 189 190 status_code = 403 191 192 193class PumpWoodObjectDoesNotExist(PumpWoodException): 194 """Object not found in database.""" 195 196 status_code = 404 197 198 199class PumpWoodQueryException(PumpWoodException): 200 """Problem when querying data, like wrong fields or operators.""" 201 202 pass 203 204 205class PumpWoodIntegrityError(PumpWoodException): 206 """Problem when saving data due to IntegrityError.""" 207 208 pass 209 210 211class PumpWoodNotImplementedError(PumpWoodException): 212 """Problem when saving data due to NotImplementedError.""" 213 214 pass 215 216 217class PumpWoodMicroserviceUnavailableError(PumpWoodException): 218 """Problem when trying to use a microservice that was not deployied.""" 219 220 pass 221 222 223class PumpWoodMFAError(PumpWoodException): 224 """Problem when using MFA.""" 225 226 pass 227 228 229class PumpWoodJSONLoadError(PumpWoodException): 230 """Problem loading json data from request.""" 231 232 pass 233 234 235class PumpWoodCacheError(PumpWoodException): 236 """Problem using pumpwood cache.""" 237 238 pass 239 240 241class PumpWoodOtherException(PumpWoodException): 242 """Other untreated error on server.""" 243 244 status_code = 500 245 246 def __init__(self, message: str, payload: dict = None, 247 status_code: int = None, parallel: bool = False): 248 """Initialize the PumpWoodOtherException. 249 250 Args: 251 message (str): 252 Message that will be formated using payload 253 information using `{key}` to replace information. 254 payload (dict): 255 Payload data passed as a dictionary, it will be returned 256 in payload at `to_dict` funcion and used to format message. 257 Defaults to None. 258 status_code (int): 259 Change the default status code of the exception. 260 Defaults to None. 261 parallel (bool): 262 Error on a parallel request. Defaults to False. 263 """ 264 Exception.__init__(self) 265 266 # Initialize payload to avoid mutable default issues 267 if payload is None: 268 payload = {} 269 270 # Limit size of the error 271 self.message = message[:1000] 272 if status_code is not None: 273 self.status_code = status_code 274 self.payload = payload 275 self.translate = False 276 self.parallel = parallel 277 278 279class AirflowMicroServiceException(PumpWoodException): 280 """Raises from AirflowMicroService.""" 281 282 pass 283 284 285exceptions_dict = { 286 "PumpWoodException": PumpWoodException, 287 "PumpWoodDataLoadingException": PumpWoodDataLoadingException, 288 "PumpWoodDatabaseError": PumpWoodDatabaseError, 289 "PumpWoodDataTransformationException": PumpWoodDataTransformationException, 290 "PumpWoodWrongParameters": PumpWoodWrongParameters, 291 "PumpWoodObjectSavingException": PumpWoodObjectSavingException, 292 "PumpWoodObjectDeleteException": PumpWoodObjectDeleteException, 293 "PumpWoodActionArgsException": PumpWoodActionArgsException, 294 "PumpWoodUnauthorized": PumpWoodUnauthorized, 295 "PumpWoodForbidden": PumpWoodForbidden, 296 "PumpWoodObjectDoesNotExist": PumpWoodObjectDoesNotExist, 297 "PumpWoodQueryException": PumpWoodQueryException, 298 "PumpWoodIntegrityError": PumpWoodIntegrityError, 299 "PumpWoodNotImplementedError": PumpWoodNotImplementedError, 300 "PumpWoodMicroserviceUnavailableError": 301 PumpWoodMicroserviceUnavailableError, 302 "PumpWoodMFAError": PumpWoodMFAError, 303 "PumpWoodOtherException": PumpWoodOtherException, 304 "AirflowMicroServiceException": AirflowMicroServiceException, 305 "PumpWoodUniqueDatabaseError": PumpWoodUniqueDatabaseError 306} 307""" 308Dictionary used by backends/microservice to treat Pumpwood exceptions and 309re-raise them exception. 310""" 311 312 313def raise_pumpwood_exception(exception_name: str, message: str, 314 payload: dict = None, status_code: int = None, 315 translate: bool = False, parallel: bool = False): 316 """Raise a PumpWood exception based on its name. 317 318 Args: 319 exception_name (str): 320 Name of the exception to be retrieved and raised. 321 message (str): 322 The error message associated with the exception. 323 payload (dict): 324 A dictionary containing additional data for the exception. 325 Defaults to None. 326 status_code (int): 327 HTTP status code to be returned. Defaults to None. 328 translate (bool): 329 Whether the message should be translated. Defaults to False. 330 parallel (bool): 331 If the exception happened during parallel processing. 332 Defaults to False. 333 334 Returns: 335 None: This function does not return as it always raises an exception. 336 337 Raises: 338 PumpWoodOtherException: 339 If the specified exception_name is not found in the registry. 340 PumpWoodException: 341 The specific exception mapped to the exception_name. 342 """ 343 # Initialize payload to avoid mutable default issues 344 if payload is None: 345 payload = {} 346 347 pumpwood_exception = exceptions_dict.get(exception_name) 348 if pumpwood_exception is None: 349 msg = ( 350 "exception_name [{exception_name}] not found in PumpWood " 351 "Exceptions. Check implementation") 352 logger.error( 353 msg.format(exception_name=exception_name)) 354 raise PumpWoodOtherException( 355 msg.format(exception_name=exception_name), 356 payload=payload, status_code=status_code, 357 translate=translate, parallel=parallel) 358 else: 359 raise pumpwood_exception( 360 message=message, payload=payload, status_code=status_code, 361 translate=translate, parallel=parallel)
11class PumpWoodException(Exception): # NOQA 12 """Special exception used in Pumpowod Systems. 13 14 It permits treatment of raises on applications serializing response 15 using to_dict function and return status code as `status_code` 16 attribute value. 17 """ 18 19 status_code: int = 400 20 """PumpWoodException will return status 400 on Pumpwood backend.""" 21 22 message: str 23 """Message associated with raise.""" 24 25 payload: dict 26 """Dictionary payload that will be returned by to_dict funcion and format 27 message string.""" 28 29 translate: bool 30 """If message will be translated or not.""" 31 32 parallel: bool 33 """If error was raised on a parallel request.""" 34 35 def __repr__(self): 36 """@private.""" 37 message_fmt = self.format_message() 38 template = "{class_name}[status_code={status_code}]: " + \ 39 "{message_fmt}\nerror payload={payload}" 40 return template.format( 41 class_name=self.__class__.__name__, 42 status_code=self.status_code, 43 message_fmt=message_fmt, 44 payload=self.payload) 45 46 def __str__(self): 47 """@private.""" 48 message_fmt = self.format_message() 49 template = "{class_name}[status_code={status_code}]: " + \ 50 "{message_fmt}\nerror payload={payload}" 51 return template.format( 52 class_name=self.__class__.__name__, 53 status_code=self.status_code, 54 message_fmt=message_fmt, 55 payload=self.payload) 56 57 def __init__(self, message: str, payload: dict = None, 58 status_code: int = None, translate: bool = False, 59 parallel: bool = False): 60 """Initialize the PumpWood exception. 61 62 Args: 63 message (str): 64 Message that will be formated using payload 65 information using `{key}` to replace information. 66 payload (dict): 67 Payload data passed as a dictionary, it will be returned 68 in payload at `to_dict` funcion and used to format message. 69 Defaults to None. 70 status_code (int): 71 Change the default status code of the exception. 72 Defaults to None. 73 translate (bool): 74 Set if message should be translated or not. 75 Defaults to False. 76 parallel (bool): 77 Error on a parallel request. Defaults to False. 78 """ 79 Exception.__init__(self) 80 81 # Initialize payload to avoid mutable default issues 82 if payload is None: 83 payload = {} 84 85 self.message = message 86 if status_code is not None: 87 self.status_code = status_code 88 self.payload = payload 89 self.translate = translate 90 self.parallel = parallel 91 92 def format_message(self) -> str: 93 """Format exception message using payload data. 94 95 Substitute placeholders at exception message with payload. 96 97 Returns: 98 Return a string of message with placeholders substituted with 99 payload data. 100 """ 101 if self.translate: 102 try: 103 return self.message.format(**self.payload) 104 except Exception: 105 return self.message + "\n** format error **" 106 else: 107 try: 108 return self.message.format(**self.payload) 109 except Exception: 110 return self.message + "\n** format error **" 111 112 def to_dict(self) -> dict[str, Any]: 113 """Serialize Exception object to return as reponse. 114 115 Returns: 116 Return a dictionary with keys: 117 - **payload [dict]:** Payload associated with raise. 118 - **type [str]:** Return name of the class of the Exception. 119 - **message_not_fmt [str]:** Return msg without replacemnt of the 120 msg with payload information. 121 - **message [str]:** Return msg formated with payload information. 122 """ 123 message_fmt = self.format_message() 124 rv = { 125 "__error__": 'PumpWoodException', 126 "type": self.__class__.__name__, 127 "payload": self.payload, 128 "message_not_fmt": self.message, 129 "message": message_fmt, 130 "parallel": self.parallel} 131 return rv
Special exception used in Pumpowod Systems.
It permits treatment of raises on applications serializing response
using to_dict function and return status code as status_code
attribute value.
57 def __init__(self, message: str, payload: dict = None, 58 status_code: int = None, translate: bool = False, 59 parallel: bool = False): 60 """Initialize the PumpWood exception. 61 62 Args: 63 message (str): 64 Message that will be formated using payload 65 information using `{key}` to replace information. 66 payload (dict): 67 Payload data passed as a dictionary, it will be returned 68 in payload at `to_dict` funcion and used to format message. 69 Defaults to None. 70 status_code (int): 71 Change the default status code of the exception. 72 Defaults to None. 73 translate (bool): 74 Set if message should be translated or not. 75 Defaults to False. 76 parallel (bool): 77 Error on a parallel request. Defaults to False. 78 """ 79 Exception.__init__(self) 80 81 # Initialize payload to avoid mutable default issues 82 if payload is None: 83 payload = {} 84 85 self.message = message 86 if status_code is not None: 87 self.status_code = status_code 88 self.payload = payload 89 self.translate = translate 90 self.parallel = parallel
Initialize the PumpWood exception.
Arguments:
- message (str): Message that will be formated using payload
information using
{key}to replace information. - payload (dict): Payload data passed as a dictionary, it will be returned
in payload at
to_dictfuncion and used to format message. Defaults to None. - status_code (int): Change the default status code of the exception. Defaults to None.
- translate (bool): Set if message should be translated or not. Defaults to False.
- parallel (bool): Error on a parallel request. Defaults to False.
Dictionary payload that will be returned by to_dict funcion and format message string.
92 def format_message(self) -> str: 93 """Format exception message using payload data. 94 95 Substitute placeholders at exception message with payload. 96 97 Returns: 98 Return a string of message with placeholders substituted with 99 payload data. 100 """ 101 if self.translate: 102 try: 103 return self.message.format(**self.payload) 104 except Exception: 105 return self.message + "\n** format error **" 106 else: 107 try: 108 return self.message.format(**self.payload) 109 except Exception: 110 return self.message + "\n** format error **"
Format exception message using payload data.
Substitute placeholders at exception message with payload.
Returns:
Return a string of message with placeholders substituted with payload data.
112 def to_dict(self) -> dict[str, Any]: 113 """Serialize Exception object to return as reponse. 114 115 Returns: 116 Return a dictionary with keys: 117 - **payload [dict]:** Payload associated with raise. 118 - **type [str]:** Return name of the class of the Exception. 119 - **message_not_fmt [str]:** Return msg without replacemnt of the 120 msg with payload information. 121 - **message [str]:** Return msg formated with payload information. 122 """ 123 message_fmt = self.format_message() 124 rv = { 125 "__error__": 'PumpWoodException', 126 "type": self.__class__.__name__, 127 "payload": self.payload, 128 "message_not_fmt": self.message, 129 "message": message_fmt, 130 "parallel": self.parallel} 131 return rv
Serialize Exception object to return as reponse.
Returns:
Return a dictionary with keys:
- payload [dict]: Payload associated with raise.
- type [str]: Return name of the class of the Exception.
- message_not_fmt [str]: Return msg without replacemnt of the msg with payload information.
- message [str]: Return msg formated with payload information.
134class PumpWoodDataLoadingException(PumpWoodException): 135 """Problem when loading data at dataloaders and to_load models.""" 136 137 pass
Problem when loading data at dataloaders and to_load models.
Inherited Members
140class PumpWoodDatabaseError(PumpWoodException): 141 """Errors raised by Postgres and not treated by other handlers.""" 142 143 pass
Errors raised by Postgres and not treated by other handlers.
Inherited Members
146class PumpWoodUniqueDatabaseError(PumpWoodException): 147 """Unique errors raised by Postgres.""" 148 149 pass
Unique errors raised by Postgres.
Inherited Members
152class PumpWoodDataTransformationException(PumpWoodException): 153 """Problem when transforming model data.""" 154 155 pass
Problem when transforming model data.
Inherited Members
158class PumpWoodWrongParameters(PumpWoodException): 159 """Raise for errors in object deserialization.""" 160 161 pass
Raise for errors in object deserialization.
Inherited Members
164class PumpWoodObjectSavingException(PumpWoodException): 165 """Raise for errors in object deserialization.""" 166 167 pass
Raise for errors in object deserialization.
Inherited Members
170class PumpWoodObjectDeleteException(PumpWoodException): 171 """Raise for errors in object deserialization.""" 172 173 pass
Raise for errors in object deserialization.
Inherited Members
176class PumpWoodActionArgsException(PumpWoodException): 177 """Missing arguments to perform action.""" 178 179 pass
Missing arguments to perform action.
Inherited Members
188class PumpWoodForbidden(PumpWoodException): 189 """Action not permited.""" 190 191 status_code = 403
Action not permited.
Inherited Members
194class PumpWoodObjectDoesNotExist(PumpWoodException): 195 """Object not found in database.""" 196 197 status_code = 404
Object not found in database.
Inherited Members
200class PumpWoodQueryException(PumpWoodException): 201 """Problem when querying data, like wrong fields or operators.""" 202 203 pass
Problem when querying data, like wrong fields or operators.
Inherited Members
206class PumpWoodIntegrityError(PumpWoodException): 207 """Problem when saving data due to IntegrityError.""" 208 209 pass
Problem when saving data due to IntegrityError.
Inherited Members
212class PumpWoodNotImplementedError(PumpWoodException): 213 """Problem when saving data due to NotImplementedError.""" 214 215 pass
Problem when saving data due to NotImplementedError.
Inherited Members
Problem when using MFA.
Inherited Members
230class PumpWoodJSONLoadError(PumpWoodException): 231 """Problem loading json data from request.""" 232 233 pass
Problem loading json data from request.
Inherited Members
236class PumpWoodCacheError(PumpWoodException): 237 """Problem using pumpwood cache.""" 238 239 pass
Problem using pumpwood cache.
Inherited Members
242class PumpWoodOtherException(PumpWoodException): 243 """Other untreated error on server.""" 244 245 status_code = 500 246 247 def __init__(self, message: str, payload: dict = None, 248 status_code: int = None, parallel: bool = False): 249 """Initialize the PumpWoodOtherException. 250 251 Args: 252 message (str): 253 Message that will be formated using payload 254 information using `{key}` to replace information. 255 payload (dict): 256 Payload data passed as a dictionary, it will be returned 257 in payload at `to_dict` funcion and used to format message. 258 Defaults to None. 259 status_code (int): 260 Change the default status code of the exception. 261 Defaults to None. 262 parallel (bool): 263 Error on a parallel request. Defaults to False. 264 """ 265 Exception.__init__(self) 266 267 # Initialize payload to avoid mutable default issues 268 if payload is None: 269 payload = {} 270 271 # Limit size of the error 272 self.message = message[:1000] 273 if status_code is not None: 274 self.status_code = status_code 275 self.payload = payload 276 self.translate = False 277 self.parallel = parallel
Other untreated error on server.
247 def __init__(self, message: str, payload: dict = None, 248 status_code: int = None, parallel: bool = False): 249 """Initialize the PumpWoodOtherException. 250 251 Args: 252 message (str): 253 Message that will be formated using payload 254 information using `{key}` to replace information. 255 payload (dict): 256 Payload data passed as a dictionary, it will be returned 257 in payload at `to_dict` funcion and used to format message. 258 Defaults to None. 259 status_code (int): 260 Change the default status code of the exception. 261 Defaults to None. 262 parallel (bool): 263 Error on a parallel request. Defaults to False. 264 """ 265 Exception.__init__(self) 266 267 # Initialize payload to avoid mutable default issues 268 if payload is None: 269 payload = {} 270 271 # Limit size of the error 272 self.message = message[:1000] 273 if status_code is not None: 274 self.status_code = status_code 275 self.payload = payload 276 self.translate = False 277 self.parallel = parallel
Initialize the PumpWoodOtherException.
Arguments:
- message (str): Message that will be formated using payload
information using
{key}to replace information. - payload (dict): Payload data passed as a dictionary, it will be returned
in payload at
to_dictfuncion and used to format message. Defaults to None. - status_code (int): Change the default status code of the exception. Defaults to None.
- parallel (bool): Error on a parallel request. Defaults to False.
Inherited Members
280class AirflowMicroServiceException(PumpWoodException): 281 """Raises from AirflowMicroService.""" 282 283 pass
Raises from AirflowMicroService.
Inherited Members
Dictionary used by backends/microservice to treat Pumpwood exceptions and re-raise them exception.
314def raise_pumpwood_exception(exception_name: str, message: str, 315 payload: dict = None, status_code: int = None, 316 translate: bool = False, parallel: bool = False): 317 """Raise a PumpWood exception based on its name. 318 319 Args: 320 exception_name (str): 321 Name of the exception to be retrieved and raised. 322 message (str): 323 The error message associated with the exception. 324 payload (dict): 325 A dictionary containing additional data for the exception. 326 Defaults to None. 327 status_code (int): 328 HTTP status code to be returned. Defaults to None. 329 translate (bool): 330 Whether the message should be translated. Defaults to False. 331 parallel (bool): 332 If the exception happened during parallel processing. 333 Defaults to False. 334 335 Returns: 336 None: This function does not return as it always raises an exception. 337 338 Raises: 339 PumpWoodOtherException: 340 If the specified exception_name is not found in the registry. 341 PumpWoodException: 342 The specific exception mapped to the exception_name. 343 """ 344 # Initialize payload to avoid mutable default issues 345 if payload is None: 346 payload = {} 347 348 pumpwood_exception = exceptions_dict.get(exception_name) 349 if pumpwood_exception is None: 350 msg = ( 351 "exception_name [{exception_name}] not found in PumpWood " 352 "Exceptions. Check implementation") 353 logger.error( 354 msg.format(exception_name=exception_name)) 355 raise PumpWoodOtherException( 356 msg.format(exception_name=exception_name), 357 payload=payload, status_code=status_code, 358 translate=translate, parallel=parallel) 359 else: 360 raise pumpwood_exception( 361 message=message, payload=payload, status_code=status_code, 362 translate=translate, parallel=parallel)
Raise a PumpWood exception based on its name.
Arguments:
- exception_name (str): Name of the exception to be retrieved and raised.
- message (str): The error message associated with the exception.
- payload (dict): A dictionary containing additional data for the exception. Defaults to None.
- status_code (int): HTTP status code to be returned. Defaults to None.
- translate (bool): Whether the message should be translated. Defaults to False.
- parallel (bool): If the exception happened during parallel processing. Defaults to False.
Returns:
None: This function does not return as it always raises an exception.
Raises:
- PumpWoodOtherException: If the specified exception_name is not found in the registry.
- PumpWoodException: The specific exception mapped to the exception_name.