|
10 | 10 | from zarr import create_array |
11 | 11 | from zarr.core.buffer import Buffer, cpu |
12 | 12 | from zarr.storage import LocalStore |
| 13 | +from zarr.storage._local import _atomic_write |
13 | 14 | from zarr.testing.store import StoreTests |
14 | 15 | from zarr.testing.utils import assert_bytes_equal |
15 | 16 |
|
@@ -109,3 +110,46 @@ async def test_move( |
109 | 110 | FileExistsError, match=re.escape(f"Destination root {destination} already exists") |
110 | 111 | ): |
111 | 112 | await store2.move(destination) |
| 113 | + |
| 114 | + |
| 115 | +@pytest.mark.parametrize("exclusive", [True, False]) |
| 116 | +def test_atomic_write_successful(tmp_path: pathlib.Path, exclusive: bool) -> None: |
| 117 | + path = pathlib.Path(tmp_path) / 'data' |
| 118 | + with _atomic_write(path, 'wb', exclusive=exclusive) as f: |
| 119 | + f.write(b'abc') |
| 120 | + assert path.read_bytes() == b'abc' |
| 121 | + assert list(path.parent.iterdir()) == [path] # no temp files |
| 122 | + |
| 123 | + |
| 124 | +@pytest.mark.parametrize("exclusive", [True, False]) |
| 125 | +def test_atomic_write_incomplete(tmp_path: pathlib.Path, exclusive: bool) -> None: |
| 126 | + path = pathlib.Path(tmp_path) / 'data' |
| 127 | + with pytest.raises(RuntimeError): |
| 128 | + with _atomic_write(path, 'wb', exclusive=exclusive) as f: |
| 129 | + f.write(b'a') |
| 130 | + raise RuntimeError |
| 131 | + assert not path.exists() |
| 132 | + assert list(path.parent.iterdir()) == [] # no temp files |
| 133 | + |
| 134 | + |
| 135 | +def test_atomic_write_non_exclusive_preexisting(tmp_path: pathlib.Path) -> None: |
| 136 | + path = pathlib.Path(tmp_path) / 'data' |
| 137 | + with path.open('wb') as f: |
| 138 | + f.write(b'xyz') |
| 139 | + assert path.read_bytes() == b'xyz' |
| 140 | + with _atomic_write(path, 'wb', exclusive=False) as f: |
| 141 | + f.write(b'abc') |
| 142 | + assert path.read_bytes() == b'abc' |
| 143 | + assert list(path.parent.iterdir()) == [path] # no temp files |
| 144 | + |
| 145 | + |
| 146 | +def test_atomic_write_exclusive_preexisting(tmp_path: pathlib.Path) -> None: |
| 147 | + path = pathlib.Path(tmp_path) / 'data' |
| 148 | + with path.open('wb') as f: |
| 149 | + f.write(b'xyz') |
| 150 | + assert path.read_bytes() == b'xyz' |
| 151 | + with pytest.raises(FileExistsError): |
| 152 | + with _atomic_write(path, 'wb', exclusive=True) as f: |
| 153 | + f.write(b'abc') |
| 154 | + assert path.read_bytes() == b'xyz' |
| 155 | + assert list(path.parent.iterdir()) == [path] # no temp files |
0 commit comments