diff --git a/swh/objstorage/api/client.py b/swh/objstorage/api/client.py --- a/swh/objstorage/api/client.py +++ b/swh/objstorage/api/client.py @@ -3,23 +3,14 @@ # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information -import abc - -from swh.core.api import SWHRemoteAPI, MetaSWHRemoteAPI +from swh.core.api import SWHRemoteAPI from swh.model import hashutil -from ..objstorage import ObjStorage, DEFAULT_CHUNK_SIZE +from ..objstorage import DEFAULT_CHUNK_SIZE from ..exc import ObjNotFoundError, ObjStorageAPIError -class MetaRemoteObjStorage(MetaSWHRemoteAPI, abc.ABCMeta): - """Hackish class to make multiple inheritance with different metaclasses - work.""" - pass - - -class RemoteObjStorage(ObjStorage, SWHRemoteAPI, - metaclass=MetaRemoteObjStorage): +class RemoteObjStorage: """Proxy to a remote object storage. This class allows to connect to an object storage server via @@ -32,56 +23,65 @@ """ - def __init__(self, url, **kwargs): - super().__init__(api_exception=ObjStorageAPIError, url=url, **kwargs) + def __init__(self, **kwargs): + self._proxy = SWHRemoteAPI(api_exception=ObjStorageAPIError, **kwargs) def check_config(self, *, check_write): - return self.post('check_config', {'check_write': check_write}) + return self._proxy.post('check_config', {'check_write': check_write}) def __contains__(self, obj_id): - return self.post('content/contains', {'obj_id': obj_id}) + return self._proxy.post('content/contains', {'obj_id': obj_id}) def add(self, content, obj_id=None, check_presence=True): - return self.post('content/add', {'content': content, 'obj_id': obj_id, - 'check_presence': check_presence}) + return self._proxy.post('content/add', { + 'content': content, 'obj_id': obj_id, + 'check_presence': check_presence}) def add_batch(self, contents, check_presence=True): - return self.post('content/add/batch', { + return self._proxy.post('content/add/batch', { 'contents': contents, 'check_presence': check_presence, }) + def restore(self, content, obj_id=None, *args, **kwargs): + return self.add(content, obj_id, check_presence=False) + def get(self, obj_id): - ret = self.post('content/get', {'obj_id': obj_id}) + ret = self._proxy.post('content/get', {'obj_id': obj_id}) if ret is None: raise ObjNotFoundError(obj_id) else: return ret def get_batch(self, obj_ids): - return self.post('content/get/batch', {'obj_ids': obj_ids}) + return self._proxy.post('content/get/batch', {'obj_ids': obj_ids}) def check(self, obj_id): - return self.post('content/check', {'obj_id': obj_id}) + return self._proxy.post('content/check', {'obj_id': obj_id}) def delete(self, obj_id): - super().delete(obj_id) # Check delete permission - return self.post('content/delete', {'obj_id': obj_id}) + # deletion permission are checked server-side + return self._proxy.post('content/delete', {'obj_id': obj_id}) # Management methods def get_random(self, batch_size): - return self.post('content/get/random', {'batch_size': batch_size}) + return self._proxy.post('content/get/random', + {'batch_size': batch_size}) # Streaming methods def add_stream(self, content_iter, obj_id, check_presence=True): obj_id = hashutil.hash_to_hex(obj_id) - return self.post_stream('content/add_stream/{}'.format(obj_id), - params={'check_presence': check_presence}, - data=content_iter) + return self._proxy.post_stream( + 'content/add_stream/{}'.format(obj_id), + params={'check_presence': check_presence}, + data=content_iter) def get_stream(self, obj_id, chunk_size=DEFAULT_CHUNK_SIZE): obj_id = hashutil.hash_to_hex(obj_id) - return super().get_stream('content/get_stream/{}'.format(obj_id), - chunk_size=chunk_size) + return self._proxy.get_stream('content/get_stream/{}'.format(obj_id), + chunk_size=chunk_size) + + def __iter__(self): + yield from self._proxy.get_stream('content') diff --git a/swh/objstorage/objstorage.py b/swh/objstorage/objstorage.py --- a/swh/objstorage/objstorage.py +++ b/swh/objstorage/objstorage.py @@ -62,7 +62,6 @@ def __init__(self, *, allow_delete=False, **kwargs): # A more complete permission system could be used in place of that if # it becomes needed - super().__init__(**kwargs) self.allow_delete = allow_delete @abc.abstractmethod diff --git a/swh/objstorage/tests/test_objstorage_cloud.py b/swh/objstorage/tests/test_objstorage_cloud.py --- a/swh/objstorage/tests/test_objstorage_cloud.py +++ b/swh/objstorage/tests/test_objstorage_cloud.py @@ -79,8 +79,8 @@ class MockCloudObjStorage(CloudObjStorage): """ Cloud object storage that uses a mocked driver """ - def _get_driver(self, api_key, api_secret_key): - return MockLibcloudDriver(api_key, api_secret_key) + def _get_driver(self, **kwargs): + return MockLibcloudDriver(**kwargs) def _get_provider(self): # Implement this for the abc requirement, but behavior is defined in @@ -92,5 +92,7 @@ def setUp(self): super().setUp() - self.storage = MockCloudObjStorage(API_KEY, API_SECRET_KEY, - CONTAINER_NAME) + self.storage = MockCloudObjStorage( + CONTAINER_NAME, + api_key=API_KEY, api_secret_key=API_SECRET_KEY, + )