Coverage for src/lexigram/features/exceptions.py: 100%

19 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-26 02:04 +0800

1"""Exceptions for the feature-flag subsystem. 

2 

3All exceptions derive from :class:`FeatureFlagError` (defined in 

4``lexigram.contracts``) so they can be caught uniformly at the package level. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import Any 

10 

11from lexigram.contracts.exceptions.feature_flags import FeatureFlagError 

12 

13 

14class FlagNotFoundError(FeatureFlagError): 

15 """Raised when a requested feature flag does not exist in any provider. 

16 

17 Attributes: 

18 flag_key: The key of the missing flag. 

19 """ 

20 

21 _code = "LEX_ERR_FEAT_002" 

22 

23 def __init__(self, flag_key: str, **kwargs: Any) -> None: 

24 super().__init__(f"Feature flag not found: {flag_key!r}", **kwargs) 

25 self.flag_key = flag_key 

26 

27 

28class FlagEvaluationError(FeatureFlagError): 

29 """Raised when a flag provider fails during evaluation. 

30 

31 Attributes: 

32 flag_key: The key of the flag that failed to evaluate. 

33 """ 

34 

35 _code = "LEX_ERR_FEAT_003" 

36 

37 def __init__( 

38 self, 

39 flag_key: str, 

40 message: str = "Flag evaluation failed", 

41 **kwargs: Any, 

42 ) -> None: 

43 super().__init__(f"{message}: {flag_key!r}", **kwargs) 

44 self.flag_key = flag_key 

45 

46 

47class FeatureFlagDisabledError(FeatureFlagError): 

48 """Raised when a feature-guarded path is called with the flag disabled.""" 

49 

50 _code = "LEX_ERR_FEAT_004" 

51 

52 def __init__(self, flag_name: str) -> None: 

53 super().__init__(f"Feature flag is disabled: {flag_name!r}") 

54 self.flag_name = flag_name 

55 

56 

57__all__ = [ 

58 "FeatureFlagDisabledError", 

59 "FeatureFlagError", 

60 "FlagEvaluationError", 

61 "FlagNotFoundError", 

62]