# Copyright (C) 2015-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 import warnings class HashCollision(Exception): pass STORAGE_IMPLEMENTATION = { 'pipeline', 'local', 'remote', 'memory', 'filter', 'buffer', 'retry', 'validate', 'cassandra', } def get_storage(cls, **kwargs): """Get a storage object of class `storage_class` with arguments `storage_args`. Args: storage (dict): dictionary with keys: - cls (str): storage's class, either local, remote, memory, filter, buffer - args (dict): dictionary with keys Returns: an instance of swh.storage.Storage or compatible class Raises: ValueError if passed an unknown storage class. """ if cls not in STORAGE_IMPLEMENTATION: raise ValueError('Unknown storage class `%s`. Supported: %s' % ( cls, ', '.join(STORAGE_IMPLEMENTATION))) if 'args' in kwargs: warnings.warn( 'Explicit "args" key is deprecated, use keys directly instead.', DeprecationWarning) kwargs = kwargs['args'] if cls == 'pipeline': return get_storage_pipeline(**kwargs) if cls == 'remote': from .api.client import RemoteStorage as Storage elif cls == 'local': from .storage import Storage elif cls == 'cassandra': from .cassandra import CassandraStorage as Storage elif cls == 'memory': from .in_memory import InMemoryStorage as Storage elif cls == 'filter': from .filter import FilteringProxyStorage as Storage elif cls == 'buffer': from .buffer import BufferingProxyStorage as Storage elif cls == 'retry': from .retry import RetryingProxyStorage as Storage elif cls == 'validate': from .validate import ValidatingProxyStorage as Storage return Storage(**kwargs) def get_storage_pipeline(steps): """Recursively get a storage object that may use other storage objects as backends. Args: steps (List[dict]): List of dicts that may be used as kwargs for `get_storage`. Returns: an instance of swh.storage.Storage or compatible class Raises: ValueError if passed an unknown storage class. """ storage_config = None for step in reversed(steps): if 'args' in step: warnings.warn( 'Explicit "args" key is deprecated, use keys directly ' 'instead.', DeprecationWarning) step = { 'cls': step['cls'], **step['args'], } if storage_config: step['storage'] = storage_config storage_config = step return get_storage(**storage_config)