Coverage for src/prosemark/templates/ports/template_repository_port.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-10-01 00:05 +0000

1"""Template Repository Port Contract. 

2 

3Defines the interface for template storage and retrieval operations. 

4""" 

5 

6from abc import ABC, abstractmethod 

7from pathlib import Path 

8 

9from prosemark.templates.domain.entities.template import Template 

10from prosemark.templates.domain.entities.template_directory import TemplateDirectory 

11 

12 

13class TemplateRepositoryPort(ABC): 

14 """Port for template storage and retrieval operations.""" 

15 

16 @abstractmethod 

17 def find_template_by_name(self, name: str, search_path: Path) -> Template | None: 

18 """Find a template by name in the given search path. 

19 

20 Args: 

21 name: Template name (without .md extension) 

22 search_path: Directory path to search for templates 

23 

24 Returns: 

25 Template instance if found, None otherwise 

26 

27 Raises: 

28 TemplateDirectoryNotFoundError: If search_path does not exist 

29 

30 """ 

31 

32 @abstractmethod 

33 def find_template_directory(self, name: str, search_path: Path) -> TemplateDirectory | None: 

34 """Find a template directory by name. 

35 

36 Args: 

37 name: Directory name 

38 search_path: Parent directory to search in 

39 

40 Returns: 

41 TemplateDirectory instance if found, None otherwise 

42 

43 Raises: 

44 TemplateDirectoryNotFoundError: If search_path does not exist 

45 

46 """ 

47 

48 @abstractmethod 

49 def get_templates_root(self) -> Path: 

50 """Get the root directory for templates. 

51 

52 Returns: 

53 Path to templates root directory 

54 

55 """ 

56 raise NotImplementedError # pragma: no cover 

57 

58 @abstractmethod 

59 def get_template(self, template_name: str) -> Template: 

60 """Load a single template by name from the templates root. 

61 

62 Args: 

63 template_name: Name of the template (without .md extension) 

64 

65 Returns: 

66 Template instance 

67 

68 Raises: 

69 TemplateNotFoundError: If template doesn't exist 

70 

71 """ 

72 

73 @abstractmethod 

74 def get_template_directory(self, directory_name: str) -> TemplateDirectory: 

75 """Load a template directory by name from the templates root. 

76 

77 Args: 

78 directory_name: Name of the template directory 

79 

80 Returns: 

81 TemplateDirectory instance 

82 

83 Raises: 

84 TemplateDirectoryNotFoundError: If directory doesn't exist 

85 

86 """ 

87 

88 @abstractmethod 

89 def list_templates(self, search_path: Path) -> list[Template]: 

90 """List all individual templates in the search path. 

91 

92 Args: 

93 search_path: Directory path to search for templates 

94 

95 Returns: 

96 List of Template instances (excludes directory templates) 

97 

98 Raises: 

99 TemplateDirectoryNotFoundError: If search_path does not exist 

100 

101 """ 

102 

103 @abstractmethod 

104 def list_template_directories(self, search_path: Path) -> list[TemplateDirectory]: 

105 """List all template directories in the search path. 

106 

107 Args: 

108 search_path: Directory path to search for template directories 

109 

110 Returns: 

111 List of TemplateDirectory instances 

112 

113 Raises: 

114 TemplateDirectoryNotFoundError: If search_path does not exist 

115 

116 """ 

117 

118 @abstractmethod 

119 def load_template_content(self, template_path: Path) -> str: 

120 """Load raw content from a template file. 

121 

122 Args: 

123 template_path: Absolute path to template file 

124 

125 Returns: 

126 Raw template content as string 

127 

128 Raises: 

129 TemplateNotFoundError: If template file does not exist 

130 FilePermissionError: If template file is not readable 

131 

132 """ 

133 

134 @abstractmethod 

135 def validate_template_path(self, path: Path) -> bool: 

136 """Validate that a path points to a valid template location. 

137 

138 Args: 

139 path: Path to validate 

140 

141 Returns: 

142 True if path is valid for template operations 

143 

144 """