| 253 | |
| 254 | |
| 255 | class ClientErrorHandler(FilteredExceptionHandler): |
| 256 | EXCEPTIONS_TO_HANDLE = ClientError |
| 257 | RC = CLIENT_ERROR_RC |
| 258 | |
| 259 | def _do_handle_exception(self, exception, stdout, stderr, **kwargs): |
| 260 | parsed_globals = kwargs.get('parsed_globals') |
| 261 | error_info = self._extract_error_info(exception) |
| 262 | |
| 263 | if error_info: |
| 264 | formatted_message = self._get_formatted_message( |
| 265 | error_info, exception |
| 266 | ) |
| 267 | displayed_structured = self._display_structured_error( |
| 268 | error_info, formatted_message, stderr, parsed_globals |
| 269 | ) |
| 270 | if displayed_structured: |
| 271 | return self.RC |
| 272 | |
| 273 | write_error(stderr, str(exception)) |
| 274 | return self.RC |
| 275 | |
| 276 | def _get_formatted_message(self, error_info, exception): |
| 277 | return str(exception) |
| 278 | |
| 279 | def _extract_error_info(self, exception): |
| 280 | error_response = self._extract_error_response(exception) |
| 281 | if error_response and 'Error' in error_response: |
| 282 | return error_response['Error'] |
| 283 | return None |
| 284 | |
| 285 | @staticmethod |
| 286 | def _extract_error_response(exception): |
| 287 | if not isinstance(exception, ClientError): |
| 288 | return None |
| 289 | |
| 290 | if hasattr(exception, 'response') and 'Error' in exception.response: |
| 291 | error_dict = dict(exception.response['Error']) |
| 292 | |
| 293 | modeled_fields = exception.modeled_fields |
| 294 | if modeled_fields is not None: |
| 295 | modeled_lower = {f.lower() for f in modeled_fields} |
| 296 | else: |
| 297 | modeled_lower = {'code', 'message'} |
| 298 | |
| 299 | # Only include fields present in the error shape model. |
| 300 | excluded_keys = {'Error', 'ResponseMetadata', 'Code', 'Message'} |
| 301 | for key, value in exception.response.items(): |
| 302 | if key not in excluded_keys and key not in error_dict: |
| 303 | if key.lower() in modeled_lower: |
| 304 | error_dict[key] = value |
| 305 | |
| 306 | # Unmodeled fields can contain data that shouldn't be displayed. |
| 307 | for key in list(error_dict.keys()): |
| 308 | if key.lower() not in modeled_lower: |
| 309 | del error_dict[key] |
| 310 | |
| 311 | return {'Error': error_dict} |
| 312 |
no outgoing calls