diff --git a/swh/storage/api/client.py b/swh/storage/api/client.py --- a/swh/storage/api/client.py +++ b/swh/storage/api/client.py @@ -9,6 +9,8 @@ from ..exc import StorageAPIError, StorageArgumentException from ..interface import StorageInterface +from .serializers import ENCODERS, DECODERS + class RemoteStorage(RPCClient): """Proxy to a remote storage API""" @@ -17,6 +19,8 @@ reraise_exceptions = [ StorageArgumentException, ] + extra_type_decoders = DECODERS + extra_type_encoders = ENCODERS def raise_for_status(self, response) -> None: try: diff --git a/swh/storage/api/serializers.py b/swh/storage/api/serializers.py new file mode 100644 --- /dev/null +++ b/swh/storage/api/serializers.py @@ -0,0 +1,26 @@ +# Copyright (C) 2020 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + +"""Decoder and encoders for swh-model objects.""" + +from typing import Callable, Dict, List, Tuple + +import swh.model.model as model + + +def _encode_model_object(obj): + d = obj.to_dict() + d['__type__'] = type(obj).__name__ + return d + + +ENCODERS: List[Tuple[type, str, Callable]] = [ + (model.BaseModel, 'model', _encode_model_object), +] + + +DECODERS: Dict[str, Callable] = { + 'model': lambda d: getattr(model, d.pop('__type__')).from_dict(d) +} diff --git a/swh/storage/api/server.py b/swh/storage/api/server.py --- a/swh/storage/api/server.py +++ b/swh/storage/api/server.py @@ -16,6 +16,8 @@ from ..metrics import timed from ..exc import StorageArgumentException +from .serializers import ENCODERS, DECODERS + def get_storage(): global storage @@ -25,9 +27,14 @@ return storage -app = RPCServerApp(__name__, - backend_class=StorageInterface, - backend_factory=get_storage) +class StorageServerApp(RPCServerApp): + extra_type_decoders = DECODERS + extra_type_encoders = ENCODERS + + +app = StorageServerApp(__name__, + backend_class=StorageInterface, + backend_factory=get_storage) storage = None diff --git a/swh/storage/tests/test_api_client.py b/swh/storage/tests/test_api_client.py --- a/swh/storage/tests/test_api_client.py +++ b/swh/storage/tests/test_api_client.py @@ -7,9 +7,9 @@ import pytest -from swh.storage.api.client import RemoteStorage import swh.storage.api.server as server import swh.storage.storage +from swh.storage import get_storage from swh.storage.tests.test_storage import TestStorageGeneratedData # noqa from swh.storage.tests.test_storage import TestStorage as _TestStorage @@ -21,13 +21,10 @@ @pytest.fixture def app_server(): storage_config = { - 'cls': 'validate', - 'storage': { + 'cls': 'memory', + 'journal_writer': { 'cls': 'memory', - 'journal_writer': { - 'cls': 'memory', - }, - } + }, } server.storage = swh.storage.get_storage(**storage_config) yield server @@ -40,7 +37,17 @@ @pytest.fixture def swh_rpc_client_class(): - return RemoteStorage + def storage_factory(**kwargs): + storage_config = { + 'cls': 'validate', + 'storage': { + 'cls': 'remote', + **kwargs, + } + } + return get_storage(**storage_config) + + return storage_factory @pytest.fixture @@ -55,6 +62,7 @@ # in-memory backend storage is attached to the RemoteStorage as its # journal_writer attribute. storage = swh_rpc_client + journal_writer = getattr(storage, 'journal_writer', None) storage.journal_writer = app_server.storage.journal_writer yield storage diff --git a/swh/storage/tests/test_api_client.py b/swh/storage/tests/test_api_client_dicts.py copy from swh/storage/tests/test_api_client.py copy to swh/storage/tests/test_api_client_dicts.py