Coverage for src / lexigram / contracts / core / provider.py: 0%

30 statements  

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

1"""Provider types for Lexigram Framework.""" 

2 

3from __future__ import annotations 

4 

5from enum import IntEnum, StrEnum 

6from typing import TYPE_CHECKING, Protocol, runtime_checkable 

7 

8if TYPE_CHECKING: 

9 from collections.abc import Sequence 

10 

11 from lexigram.contracts.core.di import ( 

12 BootContainerProtocol, 

13 ContainerRegistrarProtocol, 

14 ) 

15 

16 

17class ProviderPriority(IntEnum): 

18 """Provider initialization priority. 

19 

20 Providers are booted in ascending order of priority. Lower values run 

21 first; the typical ordering is: 

22 

23 * ``CRITICAL`` (0) – absolutely foundational services that others depend on 

24 (e.g. configuration, diagnostics). 

25 * ``INFRASTRUCTURE`` (10) – low-level plumbing such as database connections, 

26 messaging clients, and cache providers. 

27 * ``SECURITY`` (20) – authentication/authorization infrastructure. 

28 * ``NORMAL`` (30) – everyday domain services with no special ordering. 

29 * ``APPLICATION`` (40) – application-level tools (CLI, admin utilities) 

30 that depend on domain services but are not themselves domain logic. 

31 * ``DOMAIN`` (50) – business-logic providers that may depend on earlier 

32 layers. 

33 * ``PRESENTATION`` (80) – web/API layers and other entry points. 

34 * ``COMMS`` (90) – outbound communication providers (email, SMS, webhooks) 

35 often run late to avoid interfering with core initialization. 

36 * ``LOW`` (100) – lowest-priority, optional providers that can boot last. 

37 """ 

38 

39 CRITICAL = 0 

40 INFRASTRUCTURE = 10 

41 SECURITY = 20 

42 NORMAL = 30 

43 APPLICATION = 40 

44 DOMAIN = 50 

45 PRESENTATION = 80 

46 COMMS = 90 

47 LOW = 100 

48 

49 

50@runtime_checkable 

51class ProviderProtocol(Protocol): 

52 """Contract for framework providers. 

53 

54 Providers are responsible for: 

55 - Registering bindings into the container (register phase) 

56 - Initializing external resources (boot phase) 

57 - Cleaning up resources on shutdown (shutdown phase) 

58 

59 Expected Behavior: 

60 - register: MUST be declarative. No external side effects or resolution. 

61 - boot: CAN resolve services. MUST be idempotent if called twice. 

62 - shutdown: MUST gracefully close resources. SHOULD NOT raise. 

63 """ 

64 

65 @property 

66 def name(self) -> str: 

67 """Unique provider identifier (e.g. 'auth', 'database').""" 

68 ... 

69 

70 @property 

71 def priority(self) -> ProviderPriority: 

72 """Initialization order hint.""" 

73 ... 

74 

75 @property 

76 def dependencies(self) -> Sequence[str]: 

77 """Names of providers that must be booted before this one.""" 

78 ... 

79 

80 async def register(self, container: ContainerRegistrarProtocol) -> None: 

81 """Bind services into the container. declarative phase.""" 

82 ... 

83 

84 async def boot(self, container: BootContainerProtocol) -> None: 

85 """Initialize and wire services. Resolution and registration allowed here.""" 

86 ... 

87 

88 async def shutdown(self) -> None: 

89 """Tear down resources on application exit.""" 

90 ... 

91 

92 async def on_error(self, error: Exception, phase: str) -> None: 

93 """Called when boot() or shutdown() raises an exception. 

94 

95 Override to perform cleanup on startup/shutdown failure. 

96 

97 Args: 

98 error: The exception that was raised. 

99 phase: Either 'boot' or 'shutdown'. 

100 """ 

101 ... 

102 

103 

104class Lifecycle(StrEnum): 

105 """Provider lifecycle stages.""" 

106 

107 REGISTER = "register" 

108 STARTUP = "startup" 

109 SHUTDOWN = "shutdown" 

110 

111 

112__all__ = ["Lifecycle", "ProviderPriority", "ProviderProtocol"]