Coverage for src/paperap/exceptions.py: 92%

37 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-11 21:37 -0400

1""" 

2---------------------------------------------------------------------------- 

3 

4 METADATA: 

5 

6 File: exceptions.py 

7 Project: paperap 

8 Created: 2025-03-04 

9 Version: 0.0.5 

10 Author: Jess Mann 

11 Email: jess@jmann.me 

12 Copyright (c) 2025 Jess Mann 

13 

14---------------------------------------------------------------------------- 

15 

16 LAST MODIFIED: 

17 

18 2025-03-04 By Jess Mann 

19 

20""" 

21 

22from __future__ import annotations 

23 

24from string import Template 

25 

26 

27class PaperlessError(Exception): 

28 """Base exception for all paperless client errors.""" 

29 

30 

31class ConfigurationError(PaperlessError): 

32 """Raised when the configuration is invalid.""" 

33 

34 

35class APIError(PaperlessError): 

36 """Raised when the API returns an error.""" 

37 

38 status_code: int | None = None 

39 

40 def __init__(self, message: str | None = None, status_code: int | None = None) -> None: 

41 self.status_code = status_code 

42 if not message: 

43 message = "An error occurred." 

44 message = f"API Error {status_code}: {message}" 

45 message = Template(message).safe_substitute(status_code=status_code) 

46 super().__init__(message) 

47 

48 

49class AuthenticationError(APIError): 

50 """Raised when authentication fails.""" 

51 

52 

53class InsufficientPermissionError(APIError): 

54 """Raised when a user does not have permission to perform an action.""" 

55 

56 

57class FeatureNotAvailableError(APIError): 

58 """Raised when a feature is not available.""" 

59 

60 

61class FilterDisabledError(FeatureNotAvailableError): 

62 """Raised when a filter is not available.""" 

63 

64 

65class RequestError(APIError): 

66 """Raised when an error occurs while making a request.""" 

67 

68 

69class BadResponseError(APIError): 

70 """Raised when a response is returned, but the status code is not 200.""" 

71 

72 

73class ResponseParsingError(APIError): 

74 """Raised when the response can't be parsed.""" 

75 

76 

77class ResourceNotFoundError(APIError): 

78 """Raised when a requested resource is not found.""" 

79 

80 resource_name: str | None = None 

81 

82 def __init__(self, message: str | None = None, resource_name: str | None = None) -> None: 

83 self.resource_name = resource_name 

84 if not message: 

85 message = "Resource ${resource} not found." 

86 message = Template(message).safe_substitute(resource=resource_name) 

87 super().__init__(message, 404) 

88 

89 

90class ObjectNotFoundError(ResourceNotFoundError): 

91 """Raised when a requested object is not found.""" 

92 

93 model_id: int | None = None 

94 

95 def __init__( 

96 self, message: str | None = None, resource_name: str | None = None, model_id: int | None = None 

97 ) -> None: 

98 self.model_id = model_id 

99 if not message: 

100 message = "Resource ${resource} (#${pk}) not found." 

101 message = Template(message).safe_substitute(resource=resource_name, pk=model_id) 

102 super().__init__(message, resource_name) 

103 

104 

105class MultipleObjectsFoundError(APIError): 

106 """Raised when multiple objects are found when only one was expected."""