Coverage for src/blob_dict/blob/__init__.py: 0%

47 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-05-29 23:07 -0700

1from __future__ import annotations 

2 

3from base64 import b64decode, b64encode 

4from pathlib import Path 

5from typing import Any, Self, override 

6 

7from simple_zstd import compress, decompress 

8 

9 

10class BytesBlob: 

11 def __init__(self, blob: bytes) -> None: 

12 super().__init__() 

13 

14 self._blob_bytes: bytes = blob 

15 

16 def as_blob( 

17 self, 

18 blob_class: type[BytesBlob], 

19 blob_class_args: dict[str, Any] | None = None, 

20 ) -> BytesBlob: 

21 return blob_class(self._blob_bytes, **(blob_class_args or {})) 

22 

23 def as_bytes(self, *, compression: bool = False) -> bytes: 

24 return compress(self._blob_bytes) if compression else self._blob_bytes 

25 

26 @staticmethod 

27 def from_bytes(b: bytes, *, compression: bool = False) -> BytesBlob: 

28 return BytesBlob(decompress(b) if compression else b) 

29 

30 @staticmethod 

31 def from_b64_str(s: str) -> BytesBlob: 

32 return BytesBlob(b64decode(s)) 

33 

34 def as_b64_str(self) -> str: 

35 return b64encode(self._blob_bytes).decode("ascii") 

36 

37 def __repr__(self) -> str: 

38 return f"{self.__class__.__name__}({self.as_bytes().__repr__()})" 

39 

40 @classmethod 

41 def load(cls: type[Self], f: Path | str) -> Self: 

42 return cls(Path(f).expanduser().read_bytes()) 

43 

44 def dump(self, f: Path | str) -> None: 

45 Path(f).expanduser().write_bytes(self.as_bytes()) 

46 

47 @override 

48 def __eq__(self, value: object) -> bool: 

49 if isinstance(value, bytes): 

50 return self._blob_bytes == value 

51 

52 if isinstance(value, BytesBlob): 

53 return self._blob_bytes == value._blob_bytes 

54 

55 return False 

56 

57 

58class StrBlob(BytesBlob): 

59 def __init__(self, blob: bytes | str) -> None: 

60 if isinstance(blob, str): 

61 blob = blob.encode() 

62 

63 super().__init__(blob) 

64 

65 def as_str(self) -> str: 

66 return self._blob_bytes.decode() 

67 

68 def __str__(self) -> str: 

69 return self.as_str() 

70 

71 @override 

72 def __repr__(self) -> str: 

73 return f"{self.__class__.__name__}({self.as_str().__repr__()})"