Coverage for src/blob_dict/dict/path/__init__.py: 0%
66 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-19 01:12 -0700
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-19 01:12 -0700
1import shutil
2from collections.abc import Iterator
3from pathlib import Path
4from typing import override
6from cloudpathlib import CloudPath
8from ...blob import BytesBlob
9from .. import BlobDictBase
12class LocalPath(Path):
13 def rmtree(self) -> None:
14 shutil.rmtree(self)
17class PathBlobDict(BlobDictBase):
18 def __init__(self, path: LocalPath | CloudPath) -> None:
19 super().__init__()
21 self.__path: LocalPath | CloudPath = path
23 @override
24 def create(self) -> None:
25 self.__path.mkdir(
26 parents=True,
27 exist_ok=True,
28 )
30 @override
31 def delete(self) -> None:
32 self.__path.rmtree()
34 @override
35 def __len__(self) -> int:
36 return sum(1 for _ in self)
38 @override
39 def __contains__(self, key: str) -> bool:
40 return (self.__path / key).is_file()
42 @override
43 def get(self, key: str, default: BytesBlob | None = None) -> BytesBlob | None:
44 if key not in self:
45 return default
47 return BytesBlob((self.__path / key).read_bytes())
49 @override
50 def __getitem__(self, key: str) -> BytesBlob:
51 blob: BytesBlob | None = self.get(key)
52 if blob is None:
53 raise KeyError
55 return blob
57 @override
58 def __iter__(self) -> Iterator[str]:
59 for root, _, files in self.__path.walk(top_down=False):
60 for filename in files:
61 yield str((root / filename).relative_to(self.__path))
63 @override
64 def clear(self) -> None:
65 for root, dirs, files in self.__path.walk(top_down=False):
66 for filename in files:
67 (root / filename).unlink()
68 for dirname in dirs:
69 (root / dirname).rmdir()
71 @override
72 def pop(self, key: str, default: BytesBlob | None = None) -> BytesBlob | None:
73 blob: BytesBlob | None = self.get(key)
75 (self.__path / key).unlink()
77 return blob
79 @override
80 def __delitem__(self, key: str) -> None:
81 if key not in self:
82 raise KeyError
84 (self.__path / key).unlink()
86 # Skip last one which is self.__path
87 for parent in (self.__path / key).parents[:-1]:
88 if next(parent.iterdir(), None) is None:
89 parent.rmdir()
91 @override
92 def __setitem__(self, key: str, blob: BytesBlob) -> None:
93 (self.__path / key).parent.mkdir(
94 parents=True,
95 exist_ok=True,
96 )
98 (self.__path / key).write_bytes(blob.as_bytes())