Coverage for src / lexigram / contracts / tenancy / errors.py: 0%

44 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-15 18:57 +0800

1"""Tenancy domain exception classes.""" 

2 

3from __future__ import annotations 

4 

5from typing import Any 

6 

7from lexigram.contracts.exceptions.domain import DomainError 

8 

9 

10class TenantError(DomainError): 

11 """Base class for all tenancy-related domain errors.""" 

12 

13 _code = "LEX_ERR_TENANT_001" 

14 

15 def __init__(self, message: str = "Tenant error", **kwargs: Any) -> None: 

16 """Initialise a TenantError. 

17 

18 Args: 

19 message: Human-readable description of the error. 

20 **kwargs: Additional context forwarded to the base class. 

21 """ 

22 super().__init__(message, **kwargs) 

23 

24 

25class TenantNotFoundError(TenantError): 

26 """Raised when a requested tenant does not exist.""" 

27 

28 _code = "LEX_ERR_TENANT_002" 

29 

30 def __init__(self, tenant_id: str = "", **kwargs: Any) -> None: 

31 """Initialise a TenantNotFoundError. 

32 

33 Args: 

34 tenant_id: The tenant identifier that was not found. 

35 **kwargs: Additional context forwarded to the base class. 

36 """ 

37 msg = f"Tenant not found: {tenant_id}" if tenant_id else "Tenant not found" 

38 super().__init__(msg, **kwargs) 

39 

40 

41class TenantInactiveError(TenantError): 

42 """Raised when an operation is attempted on an inactive tenant.""" 

43 

44 _code = "LEX_ERR_TENANT_003" 

45 

46 def __init__(self, tenant_id: str = "", **kwargs: Any) -> None: 

47 """Initialise a TenantInactiveError. 

48 

49 Args: 

50 tenant_id: The inactive tenant identifier. 

51 **kwargs: Additional context forwarded to the base class. 

52 """ 

53 msg = f"Tenant is inactive: {tenant_id}" if tenant_id else "Tenant is inactive" 

54 super().__init__(msg, **kwargs) 

55 

56 

57class TenantProvisioningError(TenantError): 

58 """Raised when tenant provisioning (isolation setup) fails.""" 

59 

60 _code = "LEX_ERR_TENANT_004" 

61 

62 def __init__( 

63 self, message: str = "Tenant provisioning failed", **kwargs: Any 

64 ) -> None: 

65 """Initialise a TenantProvisioningError. 

66 

67 Args: 

68 message: Human-readable description of the provisioning failure. 

69 **kwargs: Additional context forwarded to the base class. 

70 """ 

71 super().__init__(message, **kwargs) 

72 

73 

74class TenantResolutionError(TenantError): 

75 """Raised when tenant resolution fails unexpectedly.""" 

76 

77 _code = "LEX_ERR_TENANT_005" 

78 

79 def __init__( 

80 self, message: str = "Tenant resolution failed", **kwargs: Any 

81 ) -> None: 

82 """Initialise a TenantResolutionError. 

83 

84 Args: 

85 message: Human-readable description of the resolution failure. 

86 **kwargs: Additional context forwarded to the base class. 

87 """ 

88 super().__init__(message, **kwargs) 

89 

90 

91class TenantConfigError(TenantError): 

92 """Raised when per-tenant configuration access or mutation fails.""" 

93 

94 _code = "LEX_ERR_TENANT_006" 

95 

96 def __init__(self, message: str = "Tenant config error", **kwargs: Any) -> None: 

97 """Initialise a TenantConfigError. 

98 

99 Args: 

100 message: Human-readable description of the config error. 

101 **kwargs: Additional context forwarded to the base class. 

102 """ 

103 super().__init__(message, **kwargs) 

104 

105 

106class TenantSlugConflictError(TenantError): 

107 """Raised when a tenant slug is already in use.""" 

108 

109 _code = "LEX_ERR_TENANT_007" 

110 

111 def __init__(self, slug: str = "", **kwargs: Any) -> None: 

112 """Initialise a TenantSlugConflictError. 

113 

114 Args: 

115 slug: The conflicting tenant slug. 

116 **kwargs: Additional context forwarded to the base class. 

117 """ 

118 msg = f"Tenant slug already in use: {slug}" if slug else "Tenant slug conflict" 

119 super().__init__(msg, **kwargs) 

120 

121 

122class TenantSuspendedError(TenantError): 

123 """Raised when an operation is attempted on a suspended tenant.""" 

124 

125 _code = "LEX_ERR_TENANT_008" 

126 

127 def __init__(self, tenant_id: str = "", **kwargs: Any) -> None: 

128 """Initialise a TenantSuspendedError. 

129 

130 Args: 

131 tenant_id: The suspended tenant identifier. 

132 **kwargs: Additional context forwarded to the base class. 

133 """ 

134 msg = ( 

135 f"Tenant is suspended: {tenant_id}" if tenant_id else "Tenant is suspended" 

136 ) 

137 super().__init__(msg, **kwargs) 

138 

139 

140class MigrationError(TenantError): 

141 """Raised when a tenant tier migration fails.""" 

142 

143 _code = "LEX_ERR_TENANT_009" 

144 

145 def __init__(self, message: str = "Tenant migration failed", **kwargs: Any) -> None: 

146 """Initialise a MigrationError. 

147 

148 Args: 

149 message: Human-readable description of the migration failure. 

150 **kwargs: Additional context forwarded to the base class. 

151 """ 

152 super().__init__(message, **kwargs) 

153 

154 

155__all__ = [ 

156 "MigrationError", 

157 "TenantConfigError", 

158 "TenantError", 

159 "TenantInactiveError", 

160 "TenantNotFoundError", 

161 "TenantProvisioningError", 

162 "TenantResolutionError", 

163 "TenantSlugConflictError", 

164 "TenantSuspendedError", 

165]