Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backend interface #167

Merged
merged 27 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
868151f
first rough implementation
frankenjoe Jan 18, 2024
abe3410
introduce interface classes
frankenjoe Jan 19, 2024
0e2b5e4
Interface: add backend property
frankenjoe Jan 19, 2024
59fdf08
Versioned.latest_version(): raise error if no version is found
frankenjoe Jan 19, 2024
228d1c1
Interface: add host, join(), repository, split(), sep
frankenjoe Jan 19, 2024
6f75004
TST: add tests for unversioned interface
frankenjoe Jan 19, 2024
d97563c
Backend.*: call utils.check_path()
frankenjoe Jan 19, 2024
80ce246
TST: rename backend to interface
frankenjoe Jan 19, 2024
95e4ad2
Backend: add get_archive() and put_archive()
frankenjoe Jan 19, 2024
3681564
TST: test unversioned interface in docstring
frankenjoe Jan 19, 2024
a1b181e
DOC: add interfaces
frankenjoe Jan 19, 2024
07b289c
DOC: update docstring of interface classes
frankenjoe Jan 19, 2024
585550b
TST: fix PEP8 errors
frankenjoe Jan 19, 2024
7b4e95f
TST: full code coverage
frankenjoe Jan 19, 2024
ff84d33
TST: fix owner in test_unversioned
frankenjoe Jan 19, 2024
54962a7
TST: fix owner in test_versioned
frankenjoe Jan 19, 2024
f11ae06
access()/create(): set interface class
frankenjoe Jan 20, 2024
2c2ef6e
DOC: add Interface
frankenjoe Jan 20, 2024
d53c847
interface as sub module
frankenjoe Jan 21, 2024
3b465c8
access()/create(): add interface_kwargs argument
frankenjoe Jan 22, 2024
f8f82bd
DOC: usage section on interface
frankenjoe Jan 22, 2024
c618e3d
DOC: fix typo
frankenjoe Jan 22, 2024
c42c6da
DOC: mention interface section in preamble
frankenjoe Jan 23, 2024
d64ee97
TST: test versioned interface only on file-system
frankenjoe Jan 23, 2024
a29fcfc
TST: improve names of tests scripts
frankenjoe Jan 23, 2024
028bb44
fix github actions after renaming test files
frankenjoe Jan 23, 2024
ec65725
TST: fix ignored test
frankenjoe Jan 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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