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

1"""Custom exceptions for file and I/O operations.""" 

2 

3from __future__ import annotations 

4 

5from .base import DataExceptError 

6from .redaction import redact_if_url 

7 

8 

9class CustomIOError(DataExceptError): 

10 """Base exception for I/O errors.""" 

11 

12 pass 

13 

14 

15class FileReadError(CustomIOError): 

16 """Raised when reading a file fails.""" 

17 

18 def __init__(self, path: str, original: Exception | None = None) -> None: 

19 """Initialize FileReadError. 

20 

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) 

31 

32 

33class FileWriteError(CustomIOError): 

34 """Raised when writing to a file fails.""" 

35 

36 def __init__(self, path: str, original: Exception | None = None) -> None: 

37 """Initialize FileWriteError. 

38 

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) 

49 

50 

51class FileLockError(CustomIOError): 

52 """Raised when a file lock cannot be acquired.""" 

53 

54 def __init__(self, path: str) -> None: 

55 """Initialize FileLockError. 

56 

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}'") 

62 

63 

64__all__ = [ 

65 "CustomIOError", 

66 "FileReadError", 

67 "FileWriteError", 

68 "FileLockError", 

69]