Skip to content

Commit

Permalink
Make open a backend mandatory (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
hagenw committed May 3, 2024
1 parent f8a4d3e commit 3226a96
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 45 deletions.
36 changes: 16 additions & 20 deletions audbackend/core/backend/artifactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,6 @@ def __init__(
):
super().__init__(host, repository)

self._username, self._api_key = _authentication(host)
path = _artifactory_path(
self.host,
self._username,
self._api_key,
)
self._repo = path.find_repository_local(self.repository)

def _checksum(
self,
path: str,
Expand Down Expand Up @@ -191,20 +183,16 @@ def _create(
self,
):
r"""Access existing repository."""
if self._repo is not None:
utils.raise_file_exists_error(str(self._repo.path))

path = _artifactory_path(
self.host,
self._username,
self._api_key,
)
self._repo = dohq_artifactory.RepositoryLocal(
username, api_key = _authentication(self.host)
path = _artifactory_path(self.host, username, api_key)
repo = dohq_artifactory.RepositoryLocal(
path,
self.repository,
package_type=dohq_artifactory.RepositoryLocal.GENERIC,
)
self._repo.create()
if repo.path.exists():
utils.raise_file_exists_error(str(repo.path))
repo.create()

def _date(
self,
Expand All @@ -220,7 +208,8 @@ def _delete(
self,
):
r"""Delete repository and all its content."""
self._repo.delete()
with self:
self._repo.delete()

def _exists(
self,
Expand Down Expand Up @@ -288,8 +277,15 @@ def _open(
self,
):
r"""Open connection to backend."""
self._username, self._api_key = _authentication(self.host)
path = _artifactory_path(
self.host,
self._username,
self._api_key,
)
self._repo = path.find_repository_local(self.repository)
if self._repo is None:
utils.raise_file_not_found_error(str(self._repo.path))
utils.raise_file_not_found_error(self.repository)

def _owner(
self,
Expand Down
70 changes: 66 additions & 4 deletions audbackend/core/backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
from audbackend.core.errors import BackendError


backend_not_opened_error = (
"Call 'Backend.open()' to establish a connection to the repository first."
)


class Base:
r"""Backend base class.
Expand All @@ -25,6 +30,8 @@ def __init__(
r"""Host path."""
self.repository = repository
r"""Repository name."""
self.opened = False
r"""If a connection to the repository has been established."""

def __enter__(self):
r"""Open connection via context manager."""
Expand Down Expand Up @@ -108,8 +115,11 @@ def checksum(
ValueError: if ``path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)
path = utils.check_path(path)
return utils.call_function_on_backend(
self._checksum,
Expand All @@ -119,7 +129,13 @@ def checksum(
def _close(
self,
): # pragma: no cover
r"""Close connection to repository."""
r"""Close connection to repository.
An error should be raised,
if the connection to the backend
cannot be closed.
"""
pass

def close(
Expand All @@ -131,7 +147,9 @@ def close(
BackendError: if an error is raised on the backend
"""
utils.call_function_on_backend(self._close)
if self.opened:
utils.call_function_on_backend(self._close)
self.opened = False

def _copy_file(
self,
Expand Down Expand Up @@ -190,8 +208,12 @@ def copy_file(
does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

src_path = utils.check_path(src_path)
dst_path = utils.check_path(dst_path)

Expand Down Expand Up @@ -282,8 +304,11 @@ def date(
ValueError: if ``path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)
path = utils.check_path(path)
return utils.call_function_on_backend(
self._date,
Expand Down Expand Up @@ -353,8 +378,11 @@ def exists(
or does not match ``'[A-Za-z0-9/._-]+'``
ValueError: if ``version`` is empty or
does not match ``'[A-Za-z0-9._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)
path = utils.check_path(path)
return utils.call_function_on_backend(
self._exists,
Expand Down Expand Up @@ -413,8 +441,12 @@ def get_archive(
ValueError: if ``src_path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

src_path = utils.check_path(src_path)

with tempfile.TemporaryDirectory(dir=tmp_root) as tmp:
Expand Down Expand Up @@ -493,8 +525,12 @@ def get_file(
ValueError: if ``src_path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

src_path = utils.check_path(src_path)
dst_path = audeer.path(dst_path)
if os.path.isdir(dst_path):
Expand Down Expand Up @@ -620,8 +656,12 @@ def ls(
e.g. ``path`` does not exist
ValueError: if ``path`` does not start with ``'/'`` or
does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

path = utils.check_path(path, allow_sub_path=True)

if path.endswith("/"): # find files under sub-path
Expand Down Expand Up @@ -715,8 +755,12 @@ def move_file(
does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

src_path = utils.check_path(src_path)
dst_path = utils.check_path(dst_path)

Expand Down Expand Up @@ -749,7 +793,9 @@ def _open(
): # pragma: no cover
r"""Open connection to backend.
* If repository does not exist an error should be raised
If repository does not exist,
or the backend cannot be opened,
an error should be raised.
"""
pass
Expand Down Expand Up @@ -780,7 +826,9 @@ def open(
.. _with: https://docs.python.org/3/reference/compound_stmts.html#with
"""
utils.call_function_on_backend(self._open)
if not self.opened:
utils.call_function_on_backend(self._open)
self.opened = True

def _owner(
self,
Expand Down Expand Up @@ -815,8 +863,11 @@ def owner(
ValueError: if ``path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)
path = utils.check_path(path)
return utils.call_function_on_backend(
self._owner,
Expand Down Expand Up @@ -878,8 +929,12 @@ def put_archive(
ValueError: if ``dst_path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

dst_path = utils.check_path(dst_path)
src_root = audeer.path(src_root)

Expand Down Expand Up @@ -951,8 +1006,12 @@ def put_file(
ValueError: if ``dst_path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)

dst_path = utils.check_path(dst_path)
if not os.path.exists(src_path):
utils.raise_file_not_found_error(src_path)
Expand Down Expand Up @@ -1001,8 +1060,11 @@ def remove_file(
ValueError: if ``path`` does not start with ``'/'``,
ends on ``'/'``,
or does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
"""
if not self.opened:
raise RuntimeError(backend_not_opened_error)
path = utils.check_path(path)
utils.call_function_on_backend(
self._remove_file,
Expand Down
3 changes: 2 additions & 1 deletion audbackend/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ class BackendError(Exception):
>>> import audeer
>>> audeer.rmdir("host", "repo")
>>> _ = audeer.mkdir("host")
>>> _ = audeer.mkdir("host", "repo")
Examples:
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> backend.open()
>>> try:
... interface = audbackend.interface.Unversioned(backend)
... interface.checksum("/does/not/exist")
Expand Down
3 changes: 3 additions & 0 deletions audbackend/core/interface/maven.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Maven(Versioned):
Examples:
>>> file = "src.txt"
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> backend.open()
>>> interface = Maven(backend)
>>> interface.put_archive(".", "/sub/archive.zip", "1.0.0", files=[file])
>>> for version in ["1.0.0", "2.0.0"]:
Expand Down Expand Up @@ -135,9 +136,11 @@ def ls(
e.g. ``path`` does not exist
ValueError: if ``path`` does not start with ``'/'`` or
does not match ``'[A-Za-z0-9/._-]+'``
RuntimeError: if backend was not opened
..
>>> backend = audbackend.backend.FileSystem("host", "repo")
>>> backend.open()
>>> interface = Maven(backend)
Examples:
Expand Down
Loading

0 comments on commit 3226a96

Please sign in to comment.