diff --git a/audmodel/core/api.py b/audmodel/core/api.py index 8ce3245..dacc9b4 100644 --- a/audmodel/core/api.py +++ b/audmodel/core/api.py @@ -1068,6 +1068,41 @@ def update_meta( return meta_backend +def _url( + backend_interface: audbackend.interface.Base, + path: str, +) -> str: + r"""Convert a backend path into a URL. + + Depending on the underlying backend + of the given backend interface, + the path on the backend + is turned into a URL + pointing to the corresponding file. + + Args: + backend_interface: backend interface + path: path on the backend, including version + + Returns: + URL to the file on the backend + + """ + backend = backend_interface.backend + if isinstance(backend, audbackend.backend.FileSystem): + path = backend_interface.sep.join([backend._root, path]) + elif isinstance(backend, audbackend.backend.Minio): + scheme = "https" if backend._client._base_url.is_https else "http" + path = backend_interface.sep.join( + [ + f"{scheme}://{backend.host}", + backend.repository, + backend.path(path), + ] + ) + return path + + def url( uid: str, *, @@ -1133,10 +1168,7 @@ def url( f"'type' has to be one of 'model', 'header', 'meta', not '{type}'" ) path = backend_interface._path_with_version(path, version) - # Check for underlying backend of backend interface - if isinstance(backend_interface.backend, audbackend.backend.FileSystem): - path = backend_interface.sep.join([backend_interface.backend._root, path]) - return path + return _url(backend_interface, path) def version( diff --git a/tests/test_api.py b/tests/test_api.py index 9027966..d52b94d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -8,6 +8,8 @@ import audeer import audmodel +import audmodel.core.api +import audmodel.core.define as define audmodel.config.CACHE_ROOT = pytest.CACHE_ROOT @@ -284,11 +286,49 @@ def test_update_meta(): def test_url(): + uid = audmodel.uid( + pytest.NAME, + pytest.PARAMS, + "1.0.0", + subgroup=SUBGROUP, + ) + + # Wrong type with pytest.raises(ValueError): - uid = audmodel.uid( - pytest.NAME, - pytest.PARAMS, - "1.0.0", - subgroup=SUBGROUP, - ) audmodel.url(uid, type="something") + + # File-system backend + # (the test models are published to a file-system repository) + for type, ext in [ + ("model", "zip"), + ("header", "header.yaml"), + ("meta", "meta.yaml"), + ]: + path = audmodel.url(uid, type=type) + assert os.path.exists(path) + assert path.startswith(audeer.path(pytest.HOST, pytest.REPOSITORIES[0].name)) + assert os.path.basename(path) == f"{uid}.{ext}" + + +def test_url_minio(): + """URL construction for the Minio/S3 backend. + + The Minio backend is not tested against a running server, + so we verify the URL construction + of the helper function directly. + + """ + host = "s3.dualstack.eu-north-1.amazonaws.com" + repository = "audmodel-public" + repository_object = audmodel.Repository(repository, host, "s3") + backend_interface = repository_object.create_backend_interface() + + path = backend_interface.join( + "/", define.UID_FOLDER, f"d4e9c65b.{define.HEADER_EXT}" + ) + path = backend_interface._path_with_version(path, "3.0.0") + + url = audmodel.core.api._url(backend_interface, path) + assert url == ( + f"https://{host}/{repository}/_uid/d4e9c65b/3.0.0/d4e9c65b-3.0.0.header.yaml" + )