diff --git a/opencga-client/src/main/python/pyopencga/rest_clients/_parent_rest_clients.py b/opencga-client/src/main/python/pyopencga/rest_clients/_parent_rest_clients.py index 5c72da9033..ae01f995e0 100644 --- a/opencga-client/src/main/python/pyopencga/rest_clients/_parent_rest_clients.py +++ b/opencga-client/src/main/python/pyopencga/rest_clients/_parent_rest_clients.py @@ -1,6 +1,7 @@ -import json +import os +import requests -from pyopencga.commons import execute +from pyopencga.commons import execute, _create_rest_url, snake_to_camel_case from pyopencga.rest_response import RestResponse from pyopencga.retry import retry @@ -87,18 +88,23 @@ def _get(self, category, resource, query_id=None, subcategory=None, def _post(self, category, resource, data=None, query_id=None, subcategory=None, second_query_id=None, **options): """Queries the REST service and returns the result""" - if data is not None: - return self._rest_retry( - method='post', category=category, resource=resource, query_id=query_id, - subcategory=subcategory, second_query_id=second_query_id, - data=data, **options - ) + # Special treatment for the "/{apiVersion}/files/upload" endpoint + if category == 'files' and resource == 'upload': + response = self._upload(category=category, resource=resource, **options) + return RestResponse(response) else: - return self._rest_retry( - method='post', category=category, resource=resource, query_id=query_id, - subcategory=subcategory, second_query_id=second_query_id, - **options - ) + if data is not None: + return self._rest_retry( + method='post', category=category, resource=resource, query_id=query_id, + subcategory=subcategory, second_query_id=second_query_id, + data=data, **options + ) + else: + return self._rest_retry( + method='post', category=category, resource=resource, query_id=query_id, + subcategory=subcategory, second_query_id=second_query_id, + **options + ) def _delete(self, category, resource, query_id=None, subcategory=None, second_query_id=None, **options): @@ -108,3 +114,31 @@ def _delete(self, category, resource, query_id=None, subcategory=None, subcategory=subcategory, second_query_id=second_query_id, **options ) + + def _upload(self, category, resource, **options): + """Upload files""" + + # Checking that the parameter file contains the file path to upload + if 'file' not in options or not isinstance(options['file'], str): + raise ValueError('To upload a file, please specify the file path as the "file" parameter.') + + # Creating URL and headers + url, header = _create_rest_url(host=self._cfg.host, version=self._cfg.version, sid=self.token, + category=category, resource=resource, options=options) + + # Creating data + data = {} + for k, v in options.items(): + if k == 'file': # Param "file" is not included in data + continue + data[snake_to_camel_case(k)] = v + + # Uploading + fpath = os.path.realpath(os.path.expanduser(options['file'])) + with open(fpath, "rb") as f: + fhand = {"file": (fpath, f, "application/octet-stream")} + response = requests.post(url, headers=header, files=fhand, data=data or None) + if response.status_code != 200: + raise Exception(response.content) + + return response.json()