Skip to content

Commit

Permalink
Add backend interface (#167)
Browse files Browse the repository at this point in the history
* first rough implementation

* introduce interface classes

* Interface: add backend property

* Versioned.latest_version(): raise error if no version is found

* Interface: add host, join(), repository, split(), sep

* TST: add tests for unversioned interface

* Backend.*: call utils.check_path()

* TST: rename backend to interface

* Backend: add get_archive() and put_archive()

* TST: test unversioned interface in docstring

* DOC: add interfaces

* DOC: update docstring of interface classes

* TST: fix PEP8 errors

* TST: full code coverage

* TST: fix owner in test_unversioned

* TST: fix owner in test_versioned

* access()/create(): set interface class

* DOC: add Interface

* interface as sub module

* access()/create(): add interface_kwargs argument

* DOC: usage section on interface

* DOC: fix typo

* DOC: mention interface section in preamble

* TST: test versioned interface only on file-system

* TST: improve names of tests scripts

* fix github actions after renaming test files

* TST: fix ignored test
  • Loading branch information
frankenjoe authored Jan 23, 2024
1 parent a64eba6 commit d94b6e2
Show file tree
Hide file tree
Showing 22 changed files with 2,386 additions and 715 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- name: Test file-system only package
run: |
python -m pytest --cov-fail-under=0 tests/test_filesystem_only.py tests/test_filesystem.py
python -m pytest --cov-fail-under=0 tests/test_backend_filesystem_only.py tests/test_backend_filesystem.py
- name: Install package with all dependencies
run: |
Expand Down
1 change: 1 addition & 0 deletions audbackend/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from audbackend import interface
from audbackend.core.api import access
from audbackend.core.api import available
from audbackend.core.api import create
Expand Down
69 changes: 42 additions & 27 deletions audbackend/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from audbackend.core import utils
from audbackend.core.backend import Backend
from audbackend.core.filesystem import FileSystem
from audbackend.core.interface.base import Base as Interface
from audbackend.core.interface.versioned import Versioned


backends = {}
Expand Down Expand Up @@ -31,26 +33,31 @@ def _backend(
if host not in backends[name]:
backends[name][host] = {}
if repository not in backends[name][host]:
backends[name][host][repository] = utils.call_function_on_backend(
backend = utils.call_function_on_backend(
backend_registry[name],
host,
repository,
)
backends[name][host][repository] = backend

return backends[name][host][repository]
backend = backends[name][host][repository]
return backend


def access(
name: str,
host: str,
repository: str,
) -> Backend:
*,
interface: typing.Type[Interface] = Versioned,
interface_kwargs: dict = None,
) -> Interface:
r"""Access repository.
Returns a backend instance
for the ``repository``
Returns an ``interface`` instance
to access the ``repository``
on the ``host``.
The instance is an object of the class
The backend is an object of the class
registered under the alias ``name``
with :func:`audbackend.register`.
Expand All @@ -68,9 +75,11 @@ def access(
name: alias under which backend class is registered
host: host address
repository: repository name
interface: interface class
interface_kwargs: keyword arguments for interface class
Returns:
backend object
interface object
Raises:
BackendError: if an error is raised on the backend,
Expand All @@ -79,13 +88,14 @@ def access(
has been registered
Examples:
>>> access('file-system', 'host', 'doctest')
('audbackend.core.filesystem.FileSystem', 'host', 'doctest')
>>> access('file-system', 'host', 'repo')
audbackend.core.interface.versioned.Versioned('audbackend.core.filesystem.FileSystem', 'host', 'repo')
"""
""" # noqa: E501
backend = _backend(name, host, repository)
utils.call_function_on_backend(backend._access)
return backend
interface_kwargs = interface_kwargs or {}
return interface(backend, **interface_kwargs)


def available() -> typing.Dict[str, typing.List[Backend]]:
Expand All @@ -103,8 +113,8 @@ def available() -> typing.Dict[str, typing.List[Backend]]:
Examples:
>>> list(available())
['artifactory', 'file-system']
>>> available()['file-system']
[('audbackend.core.filesystem.FileSystem', 'host', 'doctest')]
>>> available()['file-system'][0]
('audbackend.core.filesystem.FileSystem', 'host', 'repo')
""" # noqa: E501
result = {}
Expand All @@ -123,13 +133,15 @@ def create(
name: str,
host: str,
repository: str,
) -> Backend:
*,
interface: typing.Type[Interface] = Versioned,
interface_kwargs: dict = None
) -> Interface:
r"""Create repository.
Creates the ``repository``
on the ``host``
and returns a backend instance for it.
The instance is an object of the class
Creates ``repository`` on the ``host``
and returns an ``interface`` instance for it.
The backend is an object of the class
registered under the alias ``name``
with :func:`audbackend.register`.
Expand All @@ -147,9 +159,11 @@ def create(
name: alias under which backend class is registered
host: host address
repository: repository name
interface: interface class
interface_kwargs: keyword arguments for interface class
Returns:
backend object
interface object
Raises:
BackendError: if an error is raised on the backend,
Expand All @@ -160,12 +174,13 @@ def create(
Examples:
>>> create('file-system', 'host', 'repository')
('audbackend.core.filesystem.FileSystem', 'host', 'repository')
audbackend.core.interface.versioned.Versioned('audbackend.core.filesystem.FileSystem', 'host', 'repository')
"""
""" # noqa: E501
backend = _backend(name, host, repository)
utils.call_function_on_backend(backend._create)
return backend
interface_kwargs = interface_kwargs or {}
return interface(backend, **interface_kwargs)


def delete(
Expand Down Expand Up @@ -193,15 +208,15 @@ def delete(
has been registered
Examples:
>>> access('file-system', 'host', 'doctest').ls()
>>> access('file-system', 'host', 'repo').ls()
[('/a.zip', '1.0.0'), ('/a/b.ext', '1.0.0'), ('/f.ext', '1.0.0'), ('/f.ext', '2.0.0')]
>>> delete('file-system', 'host', 'doctest')
>>> create('file-system', 'host', 'doctest').ls()
>>> delete('file-system', 'host', 'repo')
>>> create('file-system', 'host', 'repo').ls()
[]
""" # noqa: E501
backend = access(name, host, repository)
utils.call_function_on_backend(backend._delete)
interface = access(name, host, repository)
utils.call_function_on_backend(interface._backend._delete)
backends[name][host].pop(repository)


Expand Down
Loading

0 comments on commit d94b6e2

Please sign in to comment.