Skip to content

Commit

Permalink
Add audmodle-internal S3 repo to defaults (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
hagenw authored Dec 11, 2024
1 parent bddeeba commit 7d2a6af
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 18 deletions.
5 changes: 5 additions & 0 deletions audmodel/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ class config:
"https://artifactory.audeering.com/artifactory",
"artifactory",
),
Repository(
"audmodel-internal",
"s3.dualstack.eu-north-1.amazonaws.com",
"s3",
),
]
r"""Default repositories (will be searched in given order)."""
42 changes: 32 additions & 10 deletions audmodel/core/repository.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sys

import audbackend

import audmodel.core.define as define
Expand All @@ -11,6 +13,10 @@ class Repository:
the repository name,
host,
and the backend name.
With :meth:`Repository.create_backend_interface`
it also provides a method
to create a backend interface
to access the repository.
Args:
name: repository name
Expand All @@ -25,6 +31,8 @@ class Repository:

_backends = {
"file-system": audbackend.backend.FileSystem,
"minio": audbackend.backend.Minio,
"s3": audbackend.backend.Minio,
}

if hasattr(audbackend.backend, "Artifactory"):
Expand All @@ -35,6 +43,8 @@ class Repository:
Holds mapping between registered backend names,
and their corresponding backend classes.
The ``"artifactory"`` backend is currently not available
under Python >=3.12.
"""

Expand Down Expand Up @@ -72,31 +82,43 @@ def __repr__(self): # noqa: D105
f")"
)

def create_backend_interface(self) -> audbackend.interface.Maven:
r"""Return interface to access repository.
def create_backend_interface(self) -> type[audbackend.interface.Base]:
r"""Create backend interface to access repository.
When :attr:`Repository.backend` equals ``artifactory``,
it creates an instance of :class:`audbackend.backend.Artifactory`.
When :attr:`Repository.backend` equals ``file-system``,
it creates an instance of :class:`audbackend.backend.FileSystem`.
It wraps an :class:`audbackend.interface.Maven` interface
around the backend.
A :class:`audbackend.interface.Maven` interface
is then wrapped around the backend.
The returned backend instance
has not yet established a connection to the backend.
To establish a connection,
use the backend with a ``with`` statement,
or use the ``open()`` and ``close()`` methods of the backend class.
The backend is stored as the inside the ``backend`` attribute
of the returned backend interface.
Returns:
interface to repository
Raises:
ValueError: if an artifactory backend is requested in Python>=3.12
ValueError: if a non-supported backend is requested
"""
if sys.version_info >= (3, 12) and self.backend == "artifactory":
raise ValueError( # pragma: no cover
"The 'artifactory' backend is not supported in Python>=3.12"
)
if self.backend not in self.backend_registry:
raise ValueError(f"'{self.backend}' is not a registered backend")
backend_class = self.backend_registry[self.backend]
backend = backend_class(self.host, self.name)
interface = audbackend.interface.Maven(
return audbackend.interface.Maven(
backend,
extensions=[
define.HEADER_EXT,
define.META_EXT,
],
)
return interface

@classmethod
def register(
Expand Down
28 changes: 26 additions & 2 deletions docs/authentication.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
Authentication
==============

Users have to store their credentials in :file:`~/.artifactory_python.cfg`:
To download or publish a model,
a user has to authenticate.

Credentials for the ``models-local`` repository
on Artifactory
are stored in ``~/.artifactory_python.cfg``:

.. code-block:: cfg
[artifactory.audeering.com/artifactory]
username = MY_USERNAME
password = MY_API_KEY
Alternatively, they can export them as environment variables:
Alternatively,
they can export them as environment variables:

.. code-block:: bash
export ARTIFACTORY_USERNAME="MY_USERNAME"
export ARTIFACTORY_API_KEY="MY_API_KEY"
Credentials for the ``audmodel-internal`` repository
on S3
are stored in ``~/.config/audbackend/minio.cfg``:

.. code-block:: cfg
[s3.dualstack.eu-north-1.amazonaws.com]
access_key = MY_ACCESS_KEY
secret_key = MY_SECRET_KEY
Alternatively,
users can export them as environment variables:

.. code-block:: bash
export MINIO_ACCESS_KEY="MY_ACCESS_KEY"
export MINIO_SECRET_KEY="MY_SECRET_KEY"
8 changes: 3 additions & 5 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,10 @@ Let's define the arguments for our example model:
}
subgroup = "emotion.cnn"

Per default :mod:`audmodel` uses a repository
on our internal Artifactory server,
and you don't have to care about it.
Per default :mod:`audmodel` uses repositories
on Artifactory and S3.
For this example
we don't want to interfere with Artifactory
and create a local temporary repository
we create a local temporary repository
in which the model is stored.

.. jupyter-execute::
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ classifiers = [
]
requires-python = '>=3.9'
dependencies = [
'audbackend[artifactory] >=2.0.0',
'audbackend[all] >=2.2.1',
'oyaml',
]
# Get version dynamically from git
Expand Down
35 changes: 35 additions & 0 deletions tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,38 @@ def test_repository_create_backend_interface(
assert isinstance(backend_interface, expected_interface)
assert isinstance(backend_interface.backend, expected_backend)
assert not backend_interface.backend.opened


@pytest.mark.parametrize(
"backend, host, repo, expected_error_msg, expected_error",
[
(
"custom",
"host",
"repo",
"'custom' is not a registered backend",
ValueError,
),
pytest.param(
"artifactory",
"host",
"repo",
"The 'artifactory' backend is not supported in Python>=3.12",
ValueError,
marks=pytest.mark.skipif(
sys.version_info < (3, 12),
reason="Should only fail for Python>=3.12",
),
),
],
)
def test_repository_create_backend_interface_errors(
backend,
host,
repo,
expected_error_msg,
expected_error,
):
repository = audmodel.Repository(repo, host, backend)
with pytest.raises(expected_error, match=expected_error_msg):
repository.create_backend_interface()

0 comments on commit 7d2a6af

Please sign in to comment.