pyxetabase 3.1.1.dev1__py3-none-any.whl → 3.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyxetabase might be problematic. Click here for more details.
- {pyxetabase-3.1.1.dev1.dist-info → pyxetabase-3.1.2.dist-info}/METADATA +1 -1
- pyxetabase-3.1.2.dist-info/RECORD +35 -0
- pyopencga/__init__.py +0 -0
- pyopencga/commons.py +0 -347
- pyopencga/exceptions.py +0 -8
- pyopencga/opencga_client.py +0 -334
- pyopencga/opencga_config.py +0 -211
- pyopencga/rest_clients/__init__.py +0 -0
- pyopencga/rest_clients/_parent_rest_clients.py +0 -110
- pyopencga/rest_clients/admin_client.py +0 -172
- pyopencga/rest_clients/alignment_client.py +0 -373
- pyopencga/rest_clients/clinical_analysis_client.py +0 -1279
- pyopencga/rest_clients/cohort_client.py +0 -338
- pyopencga/rest_clients/disease_panel_client.py +0 -352
- pyopencga/rest_clients/family_client.py +0 -355
- pyopencga/rest_clients/file_client.py +0 -698
- pyopencga/rest_clients/ga4gh_client.py +0 -86
- pyopencga/rest_clients/individual_client.py +0 -435
- pyopencga/rest_clients/job_client.py +0 -415
- pyopencga/rest_clients/meta_client.py +0 -85
- pyopencga/rest_clients/organization_client.py +0 -216
- pyopencga/rest_clients/project_client.py +0 -128
- pyopencga/rest_clients/sample_client.py +0 -446
- pyopencga/rest_clients/study_client.py +0 -461
- pyopencga/rest_clients/user_client.py +0 -192
- pyopencga/rest_clients/variant_client.py +0 -1378
- pyopencga/rest_clients/variant_operation_client.py +0 -745
- pyopencga/rest_clients/workflow_client.py +0 -263
- pyopencga/rest_response.py +0 -220
- pyopencga/retry.py +0 -57
- pyxetabase-3.1.1.dev1.dist-info/RECORD +0 -63
- {pyxetabase-3.1.1.dev1.dist-info → pyxetabase-3.1.2.dist-info}/WHEEL +0 -0
- {pyxetabase-3.1.1.dev1.dist-info → pyxetabase-3.1.2.dist-info}/licenses/LICENSE +0 -0
- {pyxetabase-3.1.1.dev1.dist-info → pyxetabase-3.1.2.dist-info}/top_level.txt +0 -0
pyopencga/opencga_client.py
DELETED
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import getpass
|
|
2
|
-
import time
|
|
3
|
-
import sys
|
|
4
|
-
import re
|
|
5
|
-
if sys.version_info >= (3, 8):
|
|
6
|
-
from importlib.metadata import version
|
|
7
|
-
else:
|
|
8
|
-
from importlib_metadata import version
|
|
9
|
-
|
|
10
|
-
from pyopencga.opencga_config import ClientConfiguration
|
|
11
|
-
from pyopencga.rest_clients.admin_client import Admin
|
|
12
|
-
from pyopencga.rest_clients.alignment_client import Alignment
|
|
13
|
-
from pyopencga.rest_clients.clinical_analysis_client import ClinicalAnalysis
|
|
14
|
-
from pyopencga.rest_clients.cohort_client import Cohort
|
|
15
|
-
from pyopencga.rest_clients.family_client import Family
|
|
16
|
-
from pyopencga.rest_clients.file_client import File
|
|
17
|
-
from pyopencga.rest_clients.ga4gh_client import GA4GH
|
|
18
|
-
from pyopencga.rest_clients.individual_client import Individual
|
|
19
|
-
from pyopencga.rest_clients.job_client import Job
|
|
20
|
-
from pyopencga.rest_clients.meta_client import Meta
|
|
21
|
-
from pyopencga.rest_clients.disease_panel_client import DiseasePanel
|
|
22
|
-
from pyopencga.rest_clients.project_client import Project
|
|
23
|
-
from pyopencga.rest_clients.sample_client import Sample
|
|
24
|
-
from pyopencga.rest_clients.study_client import Study
|
|
25
|
-
from pyopencga.rest_clients.variant_operation_client import VariantOperation
|
|
26
|
-
from pyopencga.rest_clients.user_client import User
|
|
27
|
-
from pyopencga.rest_clients.variant_client import Variant
|
|
28
|
-
from pyopencga.rest_clients.organization_client import Organization
|
|
29
|
-
from pyopencga.rest_clients.workflow_client import Workflow
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class OpencgaClient(object):
|
|
33
|
-
def __init__(self, configuration, token=None, refresh_token=None, on_retry=None, auto_refresh=True):
|
|
34
|
-
"""
|
|
35
|
-
:param on_retry: callback to be called with client retries an operation.
|
|
36
|
-
It must accept parameters: client, exc_type, exc_val, exc_tb, call
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
if not isinstance(configuration, ClientConfiguration):
|
|
40
|
-
raise ValueError('Expected ClientConfiguration instance')
|
|
41
|
-
|
|
42
|
-
self.configuration = configuration
|
|
43
|
-
self.auto_refresh = auto_refresh
|
|
44
|
-
self.on_retry = on_retry
|
|
45
|
-
self.clients = []
|
|
46
|
-
self._login_handler = None
|
|
47
|
-
self.token = token
|
|
48
|
-
self.refresh_token = refresh_token
|
|
49
|
-
self._create_clients()
|
|
50
|
-
self._check_versions()
|
|
51
|
-
if self.configuration.sso_login:
|
|
52
|
-
self._sso_login()
|
|
53
|
-
|
|
54
|
-
def __enter__(self):
|
|
55
|
-
return self
|
|
56
|
-
|
|
57
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
58
|
-
self.logout()
|
|
59
|
-
|
|
60
|
-
def _check_versions(self):
|
|
61
|
-
# Getting client and server versions
|
|
62
|
-
client_version = version("pyopencga")
|
|
63
|
-
server_version = self.meta.about().get_result(0)['Version'].split('-')[0]
|
|
64
|
-
|
|
65
|
-
ansi_reset = "\033[0m"
|
|
66
|
-
ansi_red = "\033[31m"
|
|
67
|
-
ansi_yellow = "\033[33m"
|
|
68
|
-
if tuple(server_version.split('.')[:2]) < tuple(client_version.split('.')[:2]):
|
|
69
|
-
msg = '[WARNING]: Client version ({}) is higher than server version ({}).' \
|
|
70
|
-
' Some client features may not be implemented in the server.\n'.format(client_version, server_version)
|
|
71
|
-
sys.stdout.write('{}{}{}'.format(ansi_red, msg, ansi_reset))
|
|
72
|
-
elif tuple(server_version.split('.')[:2]) > tuple(client_version.split('.')[:2]):
|
|
73
|
-
msg = '[INFO]: Client version ({}) is lower than server version ({}).' \
|
|
74
|
-
' Some client features may not work as intended.\n'.format(client_version, server_version)
|
|
75
|
-
sys.stdout.write('{}{}{}'.format(ansi_yellow, msg, ansi_reset))
|
|
76
|
-
|
|
77
|
-
def _create_clients(self):
|
|
78
|
-
self.organizations = Organization(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
79
|
-
self.users = User(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
80
|
-
self.projects = Project(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
81
|
-
self.studies = Study(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
82
|
-
self.files = File(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
83
|
-
self.jobs = Job(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
84
|
-
self.samples = Sample(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
85
|
-
self.individuals = Individual(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
86
|
-
self.families = Family(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
87
|
-
self.cohorts = Cohort(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
88
|
-
self.disease_panels = DiseasePanel(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
89
|
-
self.alignments = Alignment(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
90
|
-
self.variants = Variant(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
91
|
-
self.clinical = ClinicalAnalysis(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
92
|
-
self.operations = VariantOperation(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
93
|
-
self.variant_operations = self.operations # DEPRECATED: use 'self.operations'
|
|
94
|
-
self.meta = Meta(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
95
|
-
self.ga4gh = GA4GH(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
96
|
-
self.admin = Admin(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
97
|
-
self.workflows = Workflow(self.configuration, self.token, self._login_handler, auto_refresh=self.auto_refresh)
|
|
98
|
-
|
|
99
|
-
self.clients = [
|
|
100
|
-
self.organizations, self.users, self.projects, self.studies, self.files, self.jobs,
|
|
101
|
-
self.samples, self.individuals, self.families, self.cohorts,
|
|
102
|
-
self.disease_panels, self.alignments, self.variants, self.clinical, self.operations,
|
|
103
|
-
self.variant_operations, self.meta, self.ga4gh, self.admin, self.workflows
|
|
104
|
-
]
|
|
105
|
-
|
|
106
|
-
for client in self.clients:
|
|
107
|
-
client.on_retry = self.on_retry
|
|
108
|
-
|
|
109
|
-
def _make_login_handler(self, user=None, password=None, organization=None):
|
|
110
|
-
"""
|
|
111
|
-
Returns a closure that performs the log-in. This will be called on retries
|
|
112
|
-
if the current session ever expires.
|
|
113
|
-
The reason for using a closure and not a normal function is that a normal
|
|
114
|
-
function would require storing the password in a field. It is more secure
|
|
115
|
-
not to do so. This way, the password stored in the closure is inaccessible
|
|
116
|
-
to other code
|
|
117
|
-
"""
|
|
118
|
-
def login_handler(refresh=False):
|
|
119
|
-
if refresh:
|
|
120
|
-
data = {'refreshToken': self.refresh_token}
|
|
121
|
-
else:
|
|
122
|
-
data = {'user': user, 'password': password}
|
|
123
|
-
if organization:
|
|
124
|
-
data.update({'organization': organization})
|
|
125
|
-
tokens = User(self.configuration).login(data=data).get_result(0)
|
|
126
|
-
self.token = tokens['token']
|
|
127
|
-
self.refresh_token = tokens['refreshToken']
|
|
128
|
-
return self.token, self.refresh_token
|
|
129
|
-
return login_handler
|
|
130
|
-
|
|
131
|
-
def login(self, user=None, password=None, organization=None):
|
|
132
|
-
if user is not None and password is None:
|
|
133
|
-
password = getpass.getpass()
|
|
134
|
-
if not (user and password):
|
|
135
|
-
raise ValueError('User and password required')
|
|
136
|
-
|
|
137
|
-
self._login_handler = self._make_login_handler(user=user, password=password, organization=organization)
|
|
138
|
-
self._login_handler()
|
|
139
|
-
for client in self.clients:
|
|
140
|
-
client.token = self.token
|
|
141
|
-
client.refresh_token = self.refresh_token
|
|
142
|
-
client.login_handler = self._login_handler
|
|
143
|
-
|
|
144
|
-
def _sso_login(self):
|
|
145
|
-
# Getting token and refresh token from configuration
|
|
146
|
-
self.token = self.configuration.token
|
|
147
|
-
self.refresh_token = self.configuration.token
|
|
148
|
-
|
|
149
|
-
self._login_handler = self._make_login_handler()
|
|
150
|
-
for client in self.clients:
|
|
151
|
-
client.token = self.token
|
|
152
|
-
client.refresh_token = self.refresh_token
|
|
153
|
-
client.login_handler = self._login_handler
|
|
154
|
-
|
|
155
|
-
def logout(self):
|
|
156
|
-
self.token = None
|
|
157
|
-
self.refresh_token = None
|
|
158
|
-
for client in self.clients:
|
|
159
|
-
client.token = self.token
|
|
160
|
-
client.refresh_token = self.refresh_token
|
|
161
|
-
|
|
162
|
-
def wait_for_job(self, response=None, study_id=None, job_id=None, retry_seconds=10):
|
|
163
|
-
if response is not None:
|
|
164
|
-
study_id = response['results'][0]['study']['id']
|
|
165
|
-
job_id = response['results'][0]['id']
|
|
166
|
-
|
|
167
|
-
if response is None and (study_id is None or job_id is None):
|
|
168
|
-
raise ValueError('Argument "response" or arguments "study" and "job_id" must be provided')
|
|
169
|
-
|
|
170
|
-
if len(job_id.split(',')) > 1:
|
|
171
|
-
raise ValueError('Only one job ID is allowed')
|
|
172
|
-
|
|
173
|
-
retry_seconds = retry_seconds if retry_seconds >= 10 else 10
|
|
174
|
-
while True:
|
|
175
|
-
job_info = self.jobs.info(study=study_id, jobs=job_id).get_result(0)
|
|
176
|
-
if job_info['internal']['status']['id'] in ['ERROR', 'ABORTED']:
|
|
177
|
-
raise ValueError('{} ({}): {}'.format(
|
|
178
|
-
job_info['internal']['status']['id'],
|
|
179
|
-
job_info['internal']['status']['date'],
|
|
180
|
-
job_info['internal']['status']['description']
|
|
181
|
-
))
|
|
182
|
-
elif job_info['internal']['status']['id'] in ['DONE']:
|
|
183
|
-
break
|
|
184
|
-
time.sleep(retry_seconds)
|
|
185
|
-
|
|
186
|
-
def _get_help_info(self, client_name=None, parameters=False):
|
|
187
|
-
info = []
|
|
188
|
-
for client in self.clients:
|
|
189
|
-
# Name
|
|
190
|
-
cls_name = type(client).__name__
|
|
191
|
-
client_method = re.sub(r'(?<!^)(?=[A-Z])', '_', cls_name).lower() \
|
|
192
|
-
if cls_name != 'GA4GH' else cls_name.lower()
|
|
193
|
-
client_method = 'get_' + client_method + '_client'
|
|
194
|
-
|
|
195
|
-
if client_name is not None and client_name != cls_name:
|
|
196
|
-
continue
|
|
197
|
-
|
|
198
|
-
# Description and path
|
|
199
|
-
class_docstring = client.__doc__
|
|
200
|
-
cls_desc = re.findall('(This class contains methods .+)\n', class_docstring)[0]
|
|
201
|
-
cls_path = re.findall('PATH: (.+)\n', class_docstring)[0]
|
|
202
|
-
|
|
203
|
-
# Methods
|
|
204
|
-
methods = []
|
|
205
|
-
method_names = [method_name for method_name in dir(client)
|
|
206
|
-
if callable(getattr(client, method_name))
|
|
207
|
-
and not method_name.startswith('_') and method_name != 'login_handler']
|
|
208
|
-
for method_name in method_names:
|
|
209
|
-
if client_name is None:
|
|
210
|
-
continue
|
|
211
|
-
method_docstring = getattr(client, method_name).__doc__
|
|
212
|
-
desc = re.findall('(.+)\n +PATH', method_docstring, re.DOTALL)
|
|
213
|
-
desc = re.sub(' +', ' ', desc[0].replace('\n', ' ').strip())
|
|
214
|
-
path = re.findall('PATH: (.+)\n', method_docstring)[0]
|
|
215
|
-
|
|
216
|
-
args = []
|
|
217
|
-
arguments = re.findall(
|
|
218
|
-
' +:param (.+)', method_docstring, re.DOTALL
|
|
219
|
-
)
|
|
220
|
-
if arguments and parameters:
|
|
221
|
-
arguments = arguments[0].replace('\n', ' ').strip()
|
|
222
|
-
arguments = re.sub(' +', ' ', arguments)
|
|
223
|
-
arguments = arguments.split(' :param ')
|
|
224
|
-
for parameter in arguments:
|
|
225
|
-
param_info = parameter.split(' ', 2)
|
|
226
|
-
args.append({
|
|
227
|
-
'name': param_info[1].rstrip(':'),
|
|
228
|
-
'type': param_info[0],
|
|
229
|
-
'desc': param_info[2]
|
|
230
|
-
})
|
|
231
|
-
methods.append({
|
|
232
|
-
'name': method_name,
|
|
233
|
-
'desc': desc,
|
|
234
|
-
'path': path,
|
|
235
|
-
'params': args
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
info.append(
|
|
239
|
-
{'class_name': cls_name, 'client_method': client_method,
|
|
240
|
-
'desc': cls_desc, 'path': cls_path, 'methods': methods}
|
|
241
|
-
)
|
|
242
|
-
return info
|
|
243
|
-
|
|
244
|
-
def help(self, client_name=None, show_parameters=False):
|
|
245
|
-
help_txt = []
|
|
246
|
-
|
|
247
|
-
info = self._get_help_info(client_name, show_parameters)
|
|
248
|
-
if client_name is None:
|
|
249
|
-
help_txt += ['Available clients:']
|
|
250
|
-
for client in info:
|
|
251
|
-
txt = '{}- {}: {} ({}). USAGE: opencga_client.{}()'
|
|
252
|
-
help_txt += [txt.format(
|
|
253
|
-
' '*4, client['class_name'], client['desc'],
|
|
254
|
-
client['path'], client['client_method']
|
|
255
|
-
)]
|
|
256
|
-
else:
|
|
257
|
-
for client in info:
|
|
258
|
-
help_txt += ['{}: {} ({}). USAGE: opencga_client.{}()'.format(
|
|
259
|
-
client['class_name'], client['desc'], client['path'],
|
|
260
|
-
client['client_method']
|
|
261
|
-
)]
|
|
262
|
-
help_txt += ['{}Available methods:'.format(' '*4)]
|
|
263
|
-
for method in client['methods']:
|
|
264
|
-
help_txt += ['{}- {}: {} ({})'.format(
|
|
265
|
-
' '*8, method['name'], method['desc'], method['path']
|
|
266
|
-
)]
|
|
267
|
-
if not show_parameters:
|
|
268
|
-
continue
|
|
269
|
-
for param in method['params']:
|
|
270
|
-
help_txt += ['{}* {} ({}): {}'.format(
|
|
271
|
-
' ' * 12, param['name'], param['type'],
|
|
272
|
-
param['desc']
|
|
273
|
-
)]
|
|
274
|
-
sys.stdout.write('\n'.join(help_txt) + '\n')
|
|
275
|
-
|
|
276
|
-
def get_organization_client(self):
|
|
277
|
-
return self.organizations
|
|
278
|
-
|
|
279
|
-
def get_user_client(self):
|
|
280
|
-
return self.users
|
|
281
|
-
|
|
282
|
-
def get_project_client(self):
|
|
283
|
-
return self.projects
|
|
284
|
-
|
|
285
|
-
def get_study_client(self):
|
|
286
|
-
return self.studies
|
|
287
|
-
|
|
288
|
-
def get_file_client(self):
|
|
289
|
-
return self.files
|
|
290
|
-
|
|
291
|
-
def get_job_client(self):
|
|
292
|
-
return self.jobs
|
|
293
|
-
|
|
294
|
-
def get_sample_client(self):
|
|
295
|
-
return self.samples
|
|
296
|
-
|
|
297
|
-
def get_individual_client(self):
|
|
298
|
-
return self.individuals
|
|
299
|
-
|
|
300
|
-
def get_family_client(self):
|
|
301
|
-
return self.families
|
|
302
|
-
|
|
303
|
-
def get_cohort_client(self):
|
|
304
|
-
return self.cohorts
|
|
305
|
-
|
|
306
|
-
def get_disease_panel_client(self):
|
|
307
|
-
return self.disease_panels
|
|
308
|
-
|
|
309
|
-
def get_alignment_client(self):
|
|
310
|
-
return self.alignments
|
|
311
|
-
|
|
312
|
-
def get_variant_client(self):
|
|
313
|
-
return self.variants
|
|
314
|
-
|
|
315
|
-
def get_clinical_client(self):
|
|
316
|
-
return self.clinical
|
|
317
|
-
|
|
318
|
-
def get_operations_client(self):
|
|
319
|
-
return self.operations
|
|
320
|
-
|
|
321
|
-
def get_variant_operation_client(self):
|
|
322
|
-
return self.variant_operations
|
|
323
|
-
|
|
324
|
-
def get_meta_client(self):
|
|
325
|
-
return self.meta
|
|
326
|
-
|
|
327
|
-
def get_ga4gh_client(self):
|
|
328
|
-
return self.ga4gh
|
|
329
|
-
|
|
330
|
-
def get_admin_client(self):
|
|
331
|
-
return self.admin
|
|
332
|
-
|
|
333
|
-
def get_workflows_client(self):
|
|
334
|
-
return self.workflows
|
pyopencga/opencga_config.py
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import json
|
|
3
|
-
import requests
|
|
4
|
-
import yaml
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class ClientConfiguration(object):
|
|
8
|
-
"""PyOpenCGA configuration"""
|
|
9
|
-
|
|
10
|
-
def __init__(self, config_input):
|
|
11
|
-
"""
|
|
12
|
-
:param dict or str config_input: a dict, or a yaml/json file containing an OpenCGA valid client configuration.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
if isinstance(config_input, dict):
|
|
16
|
-
self._config = config_input
|
|
17
|
-
else:
|
|
18
|
-
self._config = self._get_dictionary_from_file(config_input)
|
|
19
|
-
|
|
20
|
-
self.get_sso_login_info()
|
|
21
|
-
|
|
22
|
-
self._validate_configuration()
|
|
23
|
-
|
|
24
|
-
@staticmethod
|
|
25
|
-
def _get_dictionary_from_file(config_fpath):
|
|
26
|
-
config_fhand = open(config_fpath, 'r')
|
|
27
|
-
|
|
28
|
-
if config_fpath.endswith('.yml') or config_fpath.endswith('.yaml'):
|
|
29
|
-
config_dict = yaml.safe_load(config_fhand)
|
|
30
|
-
elif config_fpath.endswith('.json'):
|
|
31
|
-
config_dict = json.loads(config_fhand.read())
|
|
32
|
-
else:
|
|
33
|
-
raise NotImplementedError('Input must be a dictionary, a yaml file (.yml or .yaml) or a json file (.json)')
|
|
34
|
-
|
|
35
|
-
config_fhand.close()
|
|
36
|
-
|
|
37
|
-
return config_dict
|
|
38
|
-
|
|
39
|
-
def get_sso_login_info(self):
|
|
40
|
-
# Checking if SSO login is specified
|
|
41
|
-
if (('sso_login' in self._config and self._config['sso_login']) or
|
|
42
|
-
('cookies' in self._config and self._config['cookies'])):
|
|
43
|
-
|
|
44
|
-
# Getting session file name
|
|
45
|
-
if 'name' in self._config['rest'] and self._config['rest']['name']:
|
|
46
|
-
host_name = self._config['rest']['name']
|
|
47
|
-
else:
|
|
48
|
-
host_name = 'opencga'
|
|
49
|
-
python_session_fhand = open(os.path.expanduser("~/.opencga/{}_session.json".format(host_name)), 'r')
|
|
50
|
-
|
|
51
|
-
# Loading info from session file
|
|
52
|
-
session_info = json.loads(python_session_fhand.read())
|
|
53
|
-
self._config['sso_login'] = True
|
|
54
|
-
self._config['cookies'] = session_info['attributes']['cookies']
|
|
55
|
-
self._config['token'] = session_info['token']
|
|
56
|
-
|
|
57
|
-
def _validate_configuration(self):
|
|
58
|
-
if self._config is None:
|
|
59
|
-
raise ValueError('Missing configuration dictionary.')
|
|
60
|
-
|
|
61
|
-
if 'rest' not in self._config:
|
|
62
|
-
raise ValueError('Missing configuration field "rest".')
|
|
63
|
-
|
|
64
|
-
if 'host' not in self._config['rest'] or not self._config['rest']['host']:
|
|
65
|
-
raise ValueError('Missing configuration field "host".')
|
|
66
|
-
|
|
67
|
-
self._validate_host()
|
|
68
|
-
|
|
69
|
-
def _validate_host(self):
|
|
70
|
-
try:
|
|
71
|
-
r = requests.head(self.host, timeout=2, verify=not self.tlsAllowInvalidCertificates)
|
|
72
|
-
if r.status_code == 302:
|
|
73
|
-
return
|
|
74
|
-
except requests.exceptions.SSLError:
|
|
75
|
-
raise Exception('Invalid SSL certificate from "{}"'.format(self.host))
|
|
76
|
-
except requests.ConnectionError:
|
|
77
|
-
raise Exception('Unreachable host "{}"'.format(self.host))
|
|
78
|
-
|
|
79
|
-
@property
|
|
80
|
-
def host(self):
|
|
81
|
-
return self._config['rest']['host']
|
|
82
|
-
|
|
83
|
-
@host.setter
|
|
84
|
-
def host(self, new_host):
|
|
85
|
-
self._config['rest']['host'] = new_host
|
|
86
|
-
|
|
87
|
-
@property
|
|
88
|
-
def tlsAllowInvalidCertificates(self):
|
|
89
|
-
if ('tlsAllowInvalidCertificates' in self._config['rest']
|
|
90
|
-
and self._config['rest']['tlsAllowInvalidCertificates'] is not None):
|
|
91
|
-
return self._config['rest']['tlsAllowInvalidCertificates']
|
|
92
|
-
else:
|
|
93
|
-
return False
|
|
94
|
-
|
|
95
|
-
@property
|
|
96
|
-
def version(self):
|
|
97
|
-
return self._config['version'] if 'version' in self._config else 'v2'
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def cookies(self):
|
|
101
|
-
if 'cookies' in self._config and self._config['cookies']:
|
|
102
|
-
python_session_fhand = open(os.path.expanduser("~/.opencga/python_session.json"), 'r')
|
|
103
|
-
session_info = json.loads(python_session_fhand.read())
|
|
104
|
-
return session_info['cookies']
|
|
105
|
-
else:
|
|
106
|
-
return None
|
|
107
|
-
|
|
108
|
-
@property
|
|
109
|
-
def configuration(self):
|
|
110
|
-
return self._config
|
|
111
|
-
|
|
112
|
-
@property
|
|
113
|
-
def host(self):
|
|
114
|
-
return self._config['rest']['host']
|
|
115
|
-
|
|
116
|
-
@host.setter
|
|
117
|
-
def host(self, host):
|
|
118
|
-
self._config['rest']['host'] = host
|
|
119
|
-
self._validate_host()
|
|
120
|
-
|
|
121
|
-
@property
|
|
122
|
-
def tlsAllowInvalidCertificates(self):
|
|
123
|
-
if ('tlsAllowInvalidCertificates' in self._config['rest'] and
|
|
124
|
-
self._config['rest']['tlsAllowInvalidCertificates'] is not None):
|
|
125
|
-
return self._config['rest']['tlsAllowInvalidCertificates']
|
|
126
|
-
else:
|
|
127
|
-
return False
|
|
128
|
-
|
|
129
|
-
@tlsAllowInvalidCertificates.setter
|
|
130
|
-
def tlsAllowInvalidCertificates(self, tlsAllowInvalidCertificates):
|
|
131
|
-
self._config['rest']['tlsAllowInvalidCertificates'] = tlsAllowInvalidCertificates
|
|
132
|
-
|
|
133
|
-
@property
|
|
134
|
-
def version(self):
|
|
135
|
-
return self._config['version'] if 'version' in self._config else 'v2'
|
|
136
|
-
|
|
137
|
-
@version.setter
|
|
138
|
-
def version(self, version):
|
|
139
|
-
self._config['version'] = version
|
|
140
|
-
|
|
141
|
-
@property
|
|
142
|
-
def sso_login(self):
|
|
143
|
-
if 'sso_login' in self._config and self._config['sso_login']:
|
|
144
|
-
return self._config['sso_login']
|
|
145
|
-
else:
|
|
146
|
-
return False
|
|
147
|
-
|
|
148
|
-
@sso_login.setter
|
|
149
|
-
def sso_login(self, sso_login):
|
|
150
|
-
if isinstance(str, sso_login):
|
|
151
|
-
self._config['sso_login'] = sso_login.lower() == 'true'
|
|
152
|
-
if isinstance(bool, sso_login):
|
|
153
|
-
self._config['sso_login'] = sso_login
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def cookies(self):
|
|
157
|
-
if 'cookies' in self._config and self._config['cookies']:
|
|
158
|
-
return self._config['cookies']
|
|
159
|
-
else:
|
|
160
|
-
return None
|
|
161
|
-
|
|
162
|
-
@cookies.setter
|
|
163
|
-
def cookies(self, cookies):
|
|
164
|
-
self._config['cookies'] = cookies
|
|
165
|
-
|
|
166
|
-
@property
|
|
167
|
-
def token(self):
|
|
168
|
-
if 'token' in self._config and self._config['token']:
|
|
169
|
-
return self._config['token']
|
|
170
|
-
else:
|
|
171
|
-
return None
|
|
172
|
-
|
|
173
|
-
@token.setter
|
|
174
|
-
def token(self, token):
|
|
175
|
-
self._config['token'] = token
|
|
176
|
-
|
|
177
|
-
@property
|
|
178
|
-
def max_attempts(self):
|
|
179
|
-
"""Returns configured max_attempts or 1 if not configured"""
|
|
180
|
-
if 'max_attempts' in self._config and self._config['max_attempts']:
|
|
181
|
-
return self._config['max_attempts']
|
|
182
|
-
else:
|
|
183
|
-
return 1
|
|
184
|
-
|
|
185
|
-
@max_attempts.setter
|
|
186
|
-
def max_attempts(self, max_attempts):
|
|
187
|
-
self._config['max_attempts'] = max_attempts
|
|
188
|
-
|
|
189
|
-
@property
|
|
190
|
-
def min_retry_secs(self):
|
|
191
|
-
"""Returns configured min_retry_seconds or 0 if not configured"""
|
|
192
|
-
if 'min_retry_secs' in self._config and self._config['min_retry_secs']:
|
|
193
|
-
return self._config['min_retry_secs']
|
|
194
|
-
else:
|
|
195
|
-
return 0
|
|
196
|
-
|
|
197
|
-
@min_retry_secs.setter
|
|
198
|
-
def min_retry_secs(self, min_retry_secs):
|
|
199
|
-
self._config['min_retry_secs'] = min_retry_secs
|
|
200
|
-
|
|
201
|
-
@property
|
|
202
|
-
def max_retry_secs(self):
|
|
203
|
-
"""Returns configured max_retry_seconds or 0 if not configured"""
|
|
204
|
-
if 'max_retry_secs' in self._config and self._config['max_retry_secs']:
|
|
205
|
-
return self._config['max_retry_secs']
|
|
206
|
-
else:
|
|
207
|
-
return 0
|
|
208
|
-
|
|
209
|
-
@max_retry_secs.setter
|
|
210
|
-
def max_retry_secs(self, max_retry_secs):
|
|
211
|
-
self._config['max_retry_secs'] = max_retry_secs
|
|
File without changes
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from pyopencga.commons import execute
|
|
4
|
-
from pyopencga.rest_response import RestResponse
|
|
5
|
-
from pyopencga.retry import retry
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class _ParentRestClient(object):
|
|
9
|
-
"""Queries the REST service given the different query params"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, configuration, token=None, login_handler=None,
|
|
12
|
-
auto_refresh=True):
|
|
13
|
-
self.auto_refresh = auto_refresh
|
|
14
|
-
self._cfg = configuration
|
|
15
|
-
self.token = token
|
|
16
|
-
self.refresh_token = None
|
|
17
|
-
self.login_handler = login_handler
|
|
18
|
-
self.on_retry = None
|
|
19
|
-
|
|
20
|
-
def _client_login_handler(self):
|
|
21
|
-
if self.login_handler:
|
|
22
|
-
self.token, self.refresh_token = self.login_handler()
|
|
23
|
-
|
|
24
|
-
def _refresh_token_client(self):
|
|
25
|
-
if self.login_handler:
|
|
26
|
-
self.token, self.refresh_token = self.login_handler(refresh=True)
|
|
27
|
-
|
|
28
|
-
@staticmethod
|
|
29
|
-
def _get_query_id_str(query_ids):
|
|
30
|
-
if query_ids is None:
|
|
31
|
-
return None
|
|
32
|
-
elif isinstance(query_ids, list):
|
|
33
|
-
return ','.join(map(str, query_ids))
|
|
34
|
-
else:
|
|
35
|
-
return str(query_ids)
|
|
36
|
-
|
|
37
|
-
def _rest_retry(self, method, category, resource, query_id=None, subcategory=None,
|
|
38
|
-
second_query_id=None, data=None, dont_retry=None,
|
|
39
|
-
**options):
|
|
40
|
-
|
|
41
|
-
query_ids_str = self._get_query_id_str(query_id)
|
|
42
|
-
|
|
43
|
-
def exec_retry():
|
|
44
|
-
return execute(config=self._cfg,
|
|
45
|
-
sid=self.token,
|
|
46
|
-
category=category,
|
|
47
|
-
subcategory=subcategory,
|
|
48
|
-
method=method,
|
|
49
|
-
query_id=query_ids_str,
|
|
50
|
-
second_query_id=second_query_id,
|
|
51
|
-
resource=resource,
|
|
52
|
-
data=data,
|
|
53
|
-
options=options)
|
|
54
|
-
|
|
55
|
-
def notify_retry(exc_type, exc_val, exc_tb):
|
|
56
|
-
if self.on_retry is not None:
|
|
57
|
-
self.on_retry(self, exc_type, exc_val, exc_tb, dict(
|
|
58
|
-
method=method, resource=resource, query_id=query_id,
|
|
59
|
-
category=category, subcategory=subcategory,
|
|
60
|
-
second_query_id=second_query_id, data=data,
|
|
61
|
-
options=options
|
|
62
|
-
))
|
|
63
|
-
|
|
64
|
-
response = retry(
|
|
65
|
-
exec_retry, self._cfg.max_attempts, self._cfg.min_retry_secs,
|
|
66
|
-
self._cfg.max_retry_secs, login_handler=self.login_handler,
|
|
67
|
-
on_retry=notify_retry, dont_retry=dont_retry
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
if self.auto_refresh:
|
|
71
|
-
self._refresh_token_client()
|
|
72
|
-
|
|
73
|
-
if isinstance(response, dict):
|
|
74
|
-
return RestResponse(response)
|
|
75
|
-
else: # Not a JSON (e.g. /{apiVersion}/files/{file}/download)
|
|
76
|
-
return response
|
|
77
|
-
|
|
78
|
-
def _get(self, category, resource, query_id=None, subcategory=None,
|
|
79
|
-
second_query_id=None, **options):
|
|
80
|
-
"""Queries the REST service and returns the result"""
|
|
81
|
-
return self._rest_retry(
|
|
82
|
-
method='get', category=category, resource=resource, query_id=query_id,
|
|
83
|
-
subcategory=subcategory, second_query_id=second_query_id,
|
|
84
|
-
**options
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
def _post(self, category, resource, data=None, query_id=None, subcategory=None,
|
|
88
|
-
second_query_id=None, **options):
|
|
89
|
-
"""Queries the REST service and returns the result"""
|
|
90
|
-
if data is not None:
|
|
91
|
-
return self._rest_retry(
|
|
92
|
-
method='post', category=category, resource=resource, query_id=query_id,
|
|
93
|
-
subcategory=subcategory, second_query_id=second_query_id,
|
|
94
|
-
data=data, **options
|
|
95
|
-
)
|
|
96
|
-
else:
|
|
97
|
-
return self._rest_retry(
|
|
98
|
-
method='post', category=category, resource=resource, query_id=query_id,
|
|
99
|
-
subcategory=subcategory, second_query_id=second_query_id,
|
|
100
|
-
**options
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
def _delete(self, category, resource, query_id=None, subcategory=None,
|
|
104
|
-
second_query_id=None, **options):
|
|
105
|
-
"""Queries the REST service and returns the result"""
|
|
106
|
-
return self._rest_retry(
|
|
107
|
-
method='delete', category=category, resource=resource, query_id=query_id,
|
|
108
|
-
subcategory=subcategory, second_query_id=second_query_id,
|
|
109
|
-
**options
|
|
110
|
-
)
|