Coverage for src/prosemark/templates/container.py: 100%

71 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-09-30 23:09 +0000

1"""Dependency injection container for template module.""" 

2 

3from pathlib import Path 

4 

5from prosemark.templates.adapters.cli_user_prompter import CLIUserPrompter 

6from prosemark.templates.adapters.file_template_repository import FileTemplateRepository 

7from prosemark.templates.adapters.prosemark_template_validator import ProsemarkTemplateValidator 

8from prosemark.templates.application.use_cases.create_from_template_use_case import ( 

9 CreateFromTemplateUseCase, 

10) 

11from prosemark.templates.application.use_cases.list_templates_use_case import ( 

12 ListTemplatesUseCase, 

13) 

14from prosemark.templates.domain.services.placeholder_service import PlaceholderService 

15from prosemark.templates.domain.services.template_service import TemplateService 

16from prosemark.templates.ports.template_repository_port import TemplateRepositoryPort 

17from prosemark.templates.ports.template_validator_port import TemplateValidatorPort 

18from prosemark.templates.ports.user_prompter_port import UserPrompterPort 

19 

20 

21class TemplatesContainer: 

22 """Dependency injection container for templates module.""" 

23 

24 def __init__(self, templates_root: Path | str) -> None: 

25 """Initialize container with templates root directory. 

26 

27 Args: 

28 templates_root: Path to the root templates directory 

29 

30 """ 

31 self._templates_root = Path(templates_root) 

32 

33 # Adapters - lazy-loaded singletons 

34 self._repository: TemplateRepositoryPort | None = None 

35 self._validator: TemplateValidatorPort | None = None 

36 self._prompter: UserPrompterPort | None = None 

37 

38 # Services - lazy-loaded singletons 

39 self._template_service: TemplateService | None = None 

40 self._placeholder_service: PlaceholderService | None = None 

41 

42 # Use cases (singletons) 

43 self._create_from_template_use_case: CreateFromTemplateUseCase | None = None 

44 self._list_templates_use_case: ListTemplatesUseCase | None = None 

45 

46 @property 

47 def repository(self) -> TemplateRepositoryPort: 

48 """Get template repository instance.""" 

49 if self._repository is None: 

50 self._repository = FileTemplateRepository(self._templates_root) 

51 return self._repository 

52 

53 @property 

54 def validator(self) -> TemplateValidatorPort: 

55 """Get template validator instance.""" 

56 if self._validator is None: 

57 self._validator = ProsemarkTemplateValidator() 

58 return self._validator 

59 

60 @property 

61 def prompter(self) -> UserPrompterPort: 

62 """Get user prompter instance.""" 

63 if self._prompter is None: 

64 self._prompter = CLIUserPrompter() 

65 return self._prompter 

66 

67 @property 

68 def template_service(self) -> TemplateService: 

69 """Get template service instance.""" 

70 if self._template_service is None: 

71 self._template_service = TemplateService( 

72 repository=self.repository, 

73 validator=self.validator, 

74 prompter=self.prompter, 

75 ) 

76 return self._template_service 

77 

78 @property 

79 def placeholder_service(self) -> PlaceholderService: 

80 """Get placeholder service instance.""" 

81 if self._placeholder_service is None: 

82 self._placeholder_service = PlaceholderService() 

83 return self._placeholder_service 

84 

85 @property 

86 def create_from_template_use_case(self) -> CreateFromTemplateUseCase: 

87 """Get create from template use case instance.""" 

88 if self._create_from_template_use_case is None: 

89 self._create_from_template_use_case = CreateFromTemplateUseCase(template_service=self.template_service) 

90 return self._create_from_template_use_case 

91 

92 @property 

93 def list_templates_use_case(self) -> ListTemplatesUseCase: 

94 """Get list templates use case instance.""" 

95 if self._list_templates_use_case is None: 

96 self._list_templates_use_case = ListTemplatesUseCase(template_service=self.template_service) 

97 return self._list_templates_use_case 

98 

99 def configure_custom_repository(self, repository: TemplateRepositoryPort) -> None: 

100 """Configure a custom template repository. 

101 

102 Args: 

103 repository: Custom repository implementation 

104 

105 """ 

106 self._repository = repository 

107 # Reset dependent services 

108 self._template_service = None 

109 self._create_from_template_use_case = None 

110 self._list_templates_use_case = None 

111 

112 def configure_custom_validator(self, validator: TemplateValidatorPort) -> None: 

113 """Configure a custom template validator. 

114 

115 Args: 

116 validator: Custom validator implementation 

117 

118 """ 

119 self._validator = validator 

120 # Reset dependent services 

121 self._template_service = None 

122 self._create_from_template_use_case = None 

123 self._list_templates_use_case = None 

124 

125 def configure_custom_prompter(self, prompter: UserPrompterPort) -> None: 

126 """Configure a custom user prompter. 

127 

128 Args: 

129 prompter: Custom prompter implementation 

130 

131 """ 

132 self._prompter = prompter 

133 # Reset dependent services 

134 self._template_service = None 

135 self._create_from_template_use_case = None 

136 self._list_templates_use_case = None