[docs]classTimersAPIError(GlobusAPIError):""" Error class to represent error responses from Timers. Has no particular additions to the base ``GlobusAPIError``, but implements a different method for parsing error responses from Timers due to the differences between various error formats used. """def_parse_undefined_error_format(self)->bool:""" Treat any top-level "error" key as an "array of size 1". Meaning that we'll see a single subdocument for data shaped like { "error": { "foo": "bar" } } Error shapes also include validation errors in a 'details' array: { "detail": [ { "loc": ["body", "start"], "msg": "field required", "type": "value_error.missing" }, { "loc": ["body", "callback_url"], "msg": "field required", "type": "value_error.missing" } ] } """# if there is not a top-level 'error' key and no top-level# 'detail' key, no special behavior is defined# fall-back to the base class implementation# but before that fallback, try the two relevant branches# if 'error' is present, use it to populate the errors array# extract 'code' from it# and extract 'messages' from itifisinstance(self._dict_data.get("error"),dict):self.errors=[ErrorSubdocument(self._dict_data["error"])]self.code=self._extract_code_from_error_array(self.errors)self.messages=self._extract_messages_from_error_array(self.errors)returnTrueelif_guards.is_list_of(self._dict_data.get("detail"),dict):# FIXME:# the 'code' is currently being set explicitly by the# SDK in this case even though none was provided by# the service# in a future version of the SDK, the code should be `None`self.code="Validation Error"# collect the errors array from detailsself.errors=[ErrorSubdocument(d)fordinself._dict_data["detail"]]# drop error objects which don't have the relevant fields# and then build custom 'messages' for Globus Timers errorsdetails=list(_details_from_errors(self.errors))self.messages=[f"{e['msg']}: {'.'.join(kforkine['loc'])}"foreindetails]returnTrueelse:returnsuper()._parse_undefined_error_format()