forked from openml/openml-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_api_calls.py
More file actions
151 lines (127 loc) · 5.17 KB
/
Copy path_api_calls.py
File metadata and controls
151 lines (127 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import io
import os
import requests
import warnings
import arff
import xmltodict
from . import config
from .exceptions import (OpenMLServerError, OpenMLServerException,
OpenMLServerNoResult)
def _perform_api_call(call, data=None, file_dictionary=None,
file_elements=None, add_authentication=True):
"""
Perform an API call at the OpenML server.
return self._read_url(url, data=data, filePath=filePath,
def _read_url(self, url, add_authentication=False, data=None, filePath=None):
Parameters
----------
call : str
The API call. For example data/list
data : dict
Dictionary with post-request payload.
file_dictionary : dict
Mapping of {filename: path} of files which should be uploaded to the
server.
file_elements : dict
Mapping of {filename: str} of strings which should be uploaded as
files to the server.
add_authentication : bool
Whether to add authentication (api key) to the request.
Returns
-------
return_code : int
HTTP return code
return_value : str
Return value of the OpenML server
"""
url = config.server
if not url.endswith("/"):
url += "/"
url += call
url = url.replace('=', '%3d')
if file_dictionary is not None or file_elements is not None:
return _read_url_files(url, data=data, file_dictionary=file_dictionary,
file_elements=file_elements)
return _read_url(url, data)
def _file_id_to_url(file_id, filename=None):
'''
Presents the URL how to download a given file id
filename is optional
'''
openml_url = config.server.split('/api/')
url = openml_url[0] + '/data/download/%s' %file_id
if filename is not None:
url += '/' + filename
return url
def _read_url_files(url, data=None, file_dictionary=None, file_elements=None):
"""do a post request to url with data, file content of
file_dictionary and sending file_elements as files"""
data = {} if data is None else data
data['api_key'] = config.apikey
if file_elements is None:
file_elements = {}
if file_dictionary is not None:
for key, path in file_dictionary.items():
path = os.path.abspath(path)
if os.path.exists(path):
try:
if key is 'dataset':
# check if arff is valid?
decoder = arff.ArffDecoder()
with io.open(path, encoding='utf8') as fh:
decoder.decode(fh, encode_nominal=True)
except:
raise ValueError("The file you have provided is not a valid arff file")
file_elements[key] = open(path, 'rb')
else:
raise ValueError("File doesn't exist")
# Using requests.post sets header 'Accept-encoding' automatically to
# 'gzip,deflate'
response = requests.post(url, data=data, files=file_elements)
if response.status_code != 200:
raise _parse_server_exception(response, url=url)
if 'Content-Encoding' not in response.headers or \
response.headers['Content-Encoding'] != 'gzip':
warnings.warn('Received uncompressed content from OpenML for %s.' % url)
return response.text
def _read_url(url, data=None):
data = {} if data is None else data
if config.apikey is not None:
data['api_key'] = config.apikey
if len(data) == 0 or (len(data) == 1 and 'api_key' in data):
# do a GET
response = requests.get(url, params=data)
else: # an actual post request
# Using requests.post sets header 'Accept-encoding' automatically to
# 'gzip,deflate'
response = requests.post(url, data=data)
if response.status_code != 200:
raise _parse_server_exception(response, url=url)
if 'Content-Encoding' not in response.headers or \
response.headers['Content-Encoding'] != 'gzip':
warnings.warn('Received uncompressed content from OpenML for %s.' % url)
return response.text
def _parse_server_exception(response, url=None):
# OpenML has a sopisticated error system
# where information about failures is provided. try to parse this
try:
server_exception = xmltodict.parse(response.text)
except:
raise OpenMLServerError(('Unexpected server error. Please '
'contact the developers!\nStatus code: '
'%d\n' % response.status_code) + response.text)
code = int(server_exception['oml:error']['oml:code'])
message = server_exception['oml:error']['oml:message']
additional = None
if 'oml:additional_information' in server_exception['oml:error']:
additional = server_exception['oml:error']['oml:additional_information']
if code in [372, 512, 500, 482, 542, 674]: # datasets,
# 512 for runs, 372 for datasets, 500 for flows
# 482 for tasks, 542 for evaluations, 674 for setups
return OpenMLServerNoResult(code, message, additional)
return OpenMLServerException(
code=code,
message=message,
additional=additional,
url=url
)