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
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "polystore"
version = "0.6.1"
version = "0.6.2"
description = "Framework-agnostic multi-backend storage abstraction for ML and scientific computing"
readme = "README.md"
requires-python = ">=3.11"
Expand Down Expand Up @@ -40,12 +40,12 @@ dependencies = [
"arraybridge>=0.3.0",
"numpy>=1.26.0",
"portalocker>=2.8.0", # Cross-platform file locking
"metaclass-registry>=0.1.5",
"metaclass-registry>=0.4.0",
"imageio>=2.37.0",
"zarr>=3.0.10", # Reads Zarr 2 and 3 stores; output format is backend-owned
"numcodecs>=0.14.0",
"ome-zarr>=0.12.2", # Required for OME-ZARR HCS compliance
"zmqruntime>=0.6,<0.7",
"zmqruntime>=0.6.4,<0.7",
"platformdirs>=4.0.0",
]

Expand Down
6 changes: 6 additions & 0 deletions src/polystore/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ def __init__(self):

def register(self, ext: str, writer: Callable, reader: Callable):
ext = ext.lower()
if ext in self._writers and (
self._writers[ext] is not writer or self._readers[ext] is not reader
):
raise ValueError(
f"File format {ext!r} already has a writer and a reader registered."
)
self._writers[ext] = writer
self._readers[ext] = reader

Expand Down
4 changes: 2 additions & 2 deletions tests/test_disk_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,8 @@ def test_save_dispatches_registered_compound_extension(self, tmp_path):
def writer(path, data, **kwargs):
written.append((path, data, kwargs))

self.backend.format_registry.register(".roi.zip", writer, lambda path: path)
output_path = tmp_path / "objects.roi.zip"
self.backend.format_registry.register(".witness.zip", writer, lambda path: path)
output_path = tmp_path / "objects.witness.zip"
payload = {"object_id": 1}

self.backend.save(payload, output_path, source="regression")
Expand Down
17 changes: 17 additions & 0 deletions tests/test_disk_more.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,20 @@ def test_list_files_breadth_first_order(tmp_path: Path):
assert str_files.index(
next(s for s in str_files if s.endswith("rootfile.txt"))
) < str_files.index(next(s for s in str_files if s.endswith("deep.txt")))


def test_file_format_registry_rejects_a_second_codec_for_one_extension():
registry = FileFormatRegistry()

def writer(path, data):
path.write_text(str(data))

def reader(path):
return path.read_text()

registry.register(".foo", writer, reader)
registry.register(".FOO", writer, reader) # the same codec again is not a conflict

with pytest.raises(ValueError, match="'.foo' already has a writer and a reader"):
registry.register(".foo", lambda path, data: None, reader)
assert registry.get_writer(".foo") is writer
18 changes: 9 additions & 9 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading