Coverage for dataexcept/io_exceptions.py: 93%
26 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-03 20:46 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-03 20:46 +0000
1"""Custom exceptions for file and I/O operations."""
3from __future__ import annotations
5from .base import DataExceptError
6from .redaction import redact_if_url
9class CustomIOError(DataExceptError):
10 """Base exception for I/O errors."""
12 pass
15class FileReadError(CustomIOError):
16 """Raised when reading a file fails."""
18 def __init__(self, path: str, original: Exception | None = None) -> None:
19 """Initialize FileReadError.
21 Args:
22 path: File path that could not be read.
23 original: Optional underlying exception.
24 """
25 self.path = redact_if_url(path)
26 self.original = original
27 msg = f"Failed to read file '{path}'"
28 if original:
29 msg += f": {original}"
30 super().__init__(msg)
33class FileWriteError(CustomIOError):
34 """Raised when writing to a file fails."""
36 def __init__(self, path: str, original: Exception | None = None) -> None:
37 """Initialize FileWriteError.
39 Args:
40 path: File path that could not be written to.
41 original: Optional underlying exception.
42 """
43 self.path = redact_if_url(path)
44 self.original = original
45 msg = f"Failed to write file '{path}'"
46 if original: 46 ↛ 47line 46 didn't jump to line 47 because the condition on line 46 was never true
47 msg += f": {original}"
48 super().__init__(msg)
51class FileLockError(CustomIOError):
52 """Raised when a file lock cannot be acquired."""
54 def __init__(self, path: str) -> None:
55 """Initialize FileLockError.
57 Args:
58 path: Path of the lock file.
59 """
60 self.path = redact_if_url(path)
61 super().__init__(f"Unable to obtain lock for '{path}'")
64__all__ = [
65 "CustomIOError",
66 "FileReadError",
67 "FileWriteError",
68 "FileLockError",
69]