diff --git a/openml/_api_calls.py b/openml/_api_calls.py index f423b3e38..22223d587 100644 --- a/openml/_api_calls.py +++ b/openml/_api_calls.py @@ -1,4 +1,5 @@ import time +from typing import Dict import requests import warnings @@ -80,7 +81,7 @@ def _read_url_files(url, data=None, file_elements=None): files=file_elements, ) if response.status_code != 200: - raise _parse_server_exception(response, url) + raise _parse_server_exception(response, url, file_elements=file_elements) if 'Content-Encoding' not in response.headers or \ response.headers['Content-Encoding'] != 'gzip': warnings.warn('Received uncompressed content from OpenML for {}.' @@ -95,7 +96,7 @@ def _read_url(url, request_method, data=None): response = send_request(request_method=request_method, url=url, data=data) if response.status_code != 200: - raise _parse_server_exception(response, url) + raise _parse_server_exception(response, url, file_elements=None) if 'Content-Encoding' not in response.headers or \ response.headers['Content-Encoding'] != 'gzip': warnings.warn('Received uncompressed content from OpenML for {}.' @@ -137,7 +138,11 @@ def send_request( return response -def _parse_server_exception(response, url): +def _parse_server_exception( + response: requests.Response, + url: str, + file_elements: Dict, +) -> OpenMLServerError: # OpenML has a sophisticated error system # where information about failures is provided. try to parse this try: @@ -152,10 +157,27 @@ def _parse_server_exception(response, url): message = server_error['oml:message'] additional_information = server_error.get('oml:additional_information') if code in [372, 512, 500, 482, 542, 674]: + if additional_information: + full_message = '{} - {}'.format(message, additional_information) + else: + full_message = message + # 512 for runs, 372 for datasets, 500 for flows # 482 for tasks, 542 for evaluations, 674 for setups - return OpenMLServerNoResult(code, message, additional_information) - full_message = '{} - {}'.format(message, additional_information) + return OpenMLServerNoResult( + code=code, + message=full_message, + ) + # 163: failure to validate flow XML (https://www.openml.org/api_docs#!/flow/post_flow) + if code in [163] and file_elements is not None and 'description' in file_elements: + # file_elements['description'] is the XML file description of the flow + full_message = '\n{}\n{} - {}'.format( + file_elements['description'], + message, + additional_information, + ) + else: + full_message = '{} - {}'.format(message, additional_information) return OpenMLServerException( code=code, message=full_message, diff --git a/openml/exceptions.py b/openml/exceptions.py index 400d652d1..78accd671 100644 --- a/openml/exceptions.py +++ b/openml/exceptions.py @@ -18,7 +18,7 @@ class OpenMLServerException(OpenMLServerError): # Code needs to be optional to allow the exceptino to be picklable: # https://stackoverflow.com/questions/16244923/how-to-make-a-custom-exception-class-with-multiple-init-args-pickleable # noqa: E501 - def __init__(self, message: str, code: str = None, url: str = None): + def __init__(self, message: str, code: int = None, url: str = None): self.message = message self.code = code self.url = url