1- import io
2- import os
1+ import time
32import requests
43import warnings
54
6- import arff
75import xmltodict
86
97from . import config
108from .exceptions import (OpenMLServerError , OpenMLServerException ,
119 OpenMLServerNoResult )
1210
1311
14- def _perform_api_call (call , data = None , file_elements = None ,
15- add_authentication = True ):
12+ def _perform_api_call (call , data = None , file_elements = None ):
1613 """
1714 Perform an API call at the OpenML server.
18- return self._read_url(url, data=data, filePath=filePath,
19- def _read_url(self, url, add_authentication=False, data=None, filePath=None):
2015
2116 Parameters
2217 ----------
@@ -27,8 +22,6 @@ def _read_url(self, url, add_authentication=False, data=None, filePath=None):
2722 file_elements : dict
2823 Mapping of {filename: str} of strings which should be uploaded as
2924 files to the server.
30- add_authentication : bool
31- Whether to add authentication (api key) to the request.
3225
3326 Returns
3427 -------
@@ -50,12 +43,12 @@ def _read_url(self, url, add_authentication=False, data=None, filePath=None):
5043
5144
5245def _file_id_to_url (file_id , filename = None ):
53- '''
46+ """
5447 Presents the URL how to download a given file id
5548 filename is optional
56- '''
49+ """
5750 openml_url = config .server .split ('/api/' )
58- url = openml_url [0 ] + '/data/download/%s' % file_id
51+ url = openml_url [0 ] + '/data/download/%s' % file_id
5952 if filename is not None :
6053 url += '/' + filename
6154 return url
@@ -71,7 +64,12 @@ def _read_url_files(url, data=None, file_elements=None):
7164 file_elements = {}
7265 # Using requests.post sets header 'Accept-encoding' automatically to
7366 # 'gzip,deflate'
74- response = requests .post (url , data = data , files = file_elements )
67+ response = send_request (
68+ request_method = 'post' ,
69+ url = url ,
70+ data = data ,
71+ files = file_elements ,
72+ )
7573 if response .status_code != 200 :
7674 raise _parse_server_exception (response , url = url )
7775 if 'Content-Encoding' not in response .headers or \
@@ -87,12 +85,16 @@ def _read_url(url, data=None):
8785 data ['api_key' ] = config .apikey
8886
8987 if len (data ) == 0 or (len (data ) == 1 and 'api_key' in data ):
90- # do a GET
91- response = requests .get (url , params = data )
92- else : # an actual post request
88+ response = send_request (
89+ request_method = 'get' , url = url , data = data ,
90+ )
91+
92+ else :
9393 # Using requests.post sets header 'Accept-encoding' automatically to
9494 # 'gzip,deflate'
95- response = requests .post (url , data = data )
95+ response = send_request (
96+ request_method = 'post' , url = url , data = data ,
97+ )
9698
9799 if response .status_code != 200 :
98100 raise _parse_server_exception (response , url = url )
@@ -102,12 +104,44 @@ def _read_url(url, data=None):
102104 return response .text
103105
104106
107+ def send_request (
108+ request_method ,
109+ url ,
110+ data ,
111+ files = None ,
112+ ):
113+ n_retries = config .connection_n_retries
114+ response = None
115+ with requests .Session () as session :
116+ # Start at one to have a non-zero multiplier for the sleep
117+ for i in range (1 , n_retries + 1 ):
118+ try :
119+ if request_method == 'get' :
120+ response = session .get (url , params = data )
121+ elif request_method == 'post' :
122+ response = session .post (url , data = data , files = files )
123+ else :
124+ raise NotImplementedError ()
125+ break
126+ except (
127+ requests .exceptions .ConnectionError ,
128+ requests .exceptions .SSLError ,
129+ ) as e :
130+ if i == n_retries :
131+ raise e
132+ else :
133+ time .sleep (0.1 * i )
134+ if response is None :
135+ raise ValueError ('This should never happen!' )
136+ return response
137+
138+
105139def _parse_server_exception (response , url = None ):
106140 # OpenML has a sopisticated error system
107141 # where information about failures is provided. try to parse this
108142 try :
109143 server_exception = xmltodict .parse (response .text )
110- except :
144+ except Exception :
111145 raise OpenMLServerError (('Unexpected server error. Please '
112146 'contact the developers!\n Status code: '
113147 '%d\n ' % response .status_code ) + response .text )
@@ -117,7 +151,7 @@ def _parse_server_exception(response, url=None):
117151 additional = None
118152 if 'oml:additional_information' in server_exception ['oml:error' ]:
119153 additional = server_exception ['oml:error' ]['oml:additional_information' ]
120- if code in [372 , 512 , 500 , 482 , 542 , 674 ]: # datasets,
154+ if code in [372 , 512 , 500 , 482 , 542 , 674 ]:
121155 # 512 for runs, 372 for datasets, 500 for flows
122156 # 482 for tasks, 542 for evaluations, 674 for setups
123157 return OpenMLServerNoResult (code , message , additional )
0 commit comments