Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions audmodel/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ def publish(
repository: Repository,
alias: str | None = None,
author: str | None = None,
compression: int = 1,
date: datetime.date | None = None,
meta: dict[str, object] | None = None,
subgroup: str | None = None,
Expand Down Expand Up @@ -509,6 +510,21 @@ def publish(
If provided, the model can be accessed using this alias
in addition to its UID
author: author name(s), defaults to user name
compression: compression level
of the model archive.
``0`` stores the model files
without compression,
``1``-``9`` selects a deflate level.
Deflate is single threaded,
and dominates the publication time
of large models.
Higher levels than ``1``
hardly compress better
on model weights,
but take at least twice as long.
Select ``0``,
if you want to publish
as fast as possible
Comment thread
hagenw marked this conversation as resolved.
date: date, defaults to current timestamp
meta: dictionary with meta information
subgroup: subgroup under which
Expand Down Expand Up @@ -540,6 +556,7 @@ def publish(
FileNotFoundError: if ``root`` folder cannot be found
ValueError: if ``alias`` can be confused with an UID,
or it does contain chars other than ``[A-Za-z0-9._-]+``
ValueError: if ``compression`` is not between 0 and 9

Examples:
>>> # Assuming your model files are stored under `model_root`
Expand Down Expand Up @@ -616,6 +633,9 @@ def publish(
"and are not allowed to be confused with a model ID."
)

if not 0 <= compression <= 9:
raise ValueError(f"'compression' has to be between 0 and 9, not {compression}.")
Comment thread
frankenjoe marked this conversation as resolved.

if not os.path.isdir(root):
raise FileNotFoundError(
errno.ENOENT,
Expand Down Expand Up @@ -662,6 +682,7 @@ def publish(
subgroup,
root,
backend_interface,
compression,
verbose,
tmp_root=tmp_root,
)
Expand Down
7 changes: 7 additions & 0 deletions audmodel/core/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ def put_archive(
subgroup: str,
root: str,
backend_interface: audbackend.interface.Maven,
compression: int,
verbose: bool,
tmp_root: str | None = None,
) -> str:
Expand All @@ -401,6 +402,11 @@ def put_archive(
subgroup: model subgroup
root: path to model root folder
backend_interface: backend interface instance
compression: compression level
of the model archive.
``0`` stores the model files
without compression,
``1``-``9`` selects a deflate level
verbose: if ``True`` show message
when uploading file
tmp_root: folder under which the temporary archive
Expand Down Expand Up @@ -433,6 +439,7 @@ def put_archive(
root,
files,
src_path,
compression=compression,
verbose=verbose,
)
with backend_interface.backend:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ classifiers = [
requires-python = '>=3.10'
dependencies = [
'audbackend[all] >=3.0.0',
'audeer >=2.6.0',
'filelock >=3.10',
'oyaml',
]
Expand All @@ -46,7 +47,6 @@ documentation = 'http://tools.pp.audeering.com/audmodel/'
# ===== Dependency groups =================================================
[dependency-groups]
dev = [
'audeer >=1.3.0',
'parse',
'pytest',
'pytest-cov',
Expand Down
66 changes: 66 additions & 0 deletions tests/test_publish.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import zipfile

import pytest

Expand Down Expand Up @@ -297,3 +298,68 @@ def test_publish_missing_repository_raises():
"1.0.0",
repository=None,
)


@pytest.mark.parametrize(
"compression, expected_compress_type",
[
# deflate level 1 by default
(None, zipfile.ZIP_DEFLATED),
(0, zipfile.ZIP_STORED),
(1, zipfile.ZIP_DEFLATED),
(9, zipfile.ZIP_DEFLATED),
],
)
def test_publish_compression(tmp_path, compression, expected_compress_type):
r"""Test compression of the published model archive.

Args:
tmp_path: tmp_path fixture
compression: compression level,
``None`` publishes without the argument
expected_compress_type: expected compression method
of the entries in the model archive

"""
root = audeer.mkdir(tmp_path, "model")
with open(os.path.join(root, "model.bin"), "w") as file:
file.write("a" * 10000)

kwargs = {} if compression is None else {"compression": compression}
effective_compression = 1 if compression is None else compression
uid = audmodel.publish(
root,
pytest.NAME,
{"compression": effective_compression, "compression_arg": compression},
"1.0.0",
Comment thread
Copilot marked this conversation as resolved.
author=pytest.AUTHOR,
date=pytest.DATE,
subgroup=f"{SUBGROUP}.compression",
repository=pytest.REPOSITORIES[0],
**kwargs,
)

with zipfile.ZipFile(audmodel.url(uid)) as archive:
infos = archive.infolist()
assert [info.filename for info in infos] == ["model.bin"]
assert infos[0].compress_type == expected_compress_type


@pytest.mark.parametrize("compression", [-1, 10])
def test_publish_compression_error(compression):
r"""Test error for a compression level outside 0-9.

Args:
compression: invalid compression level

"""
error_msg = f"'compression' has to be between 0 and 9, not {compression}."
with pytest.raises(ValueError, match=error_msg):
audmodel.publish(
pytest.MODEL_ROOT,
pytest.NAME,
{},
"1.0.0",
compression=compression,
repository=pytest.REPOSITORIES[0],
)