Coverage for formkit_ninja / parser / template_loader.py: 68.75%

16 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-02-27 05:19 +0000

1""" 

2Template loader abstraction for code generation. 

3 

4This module provides: 

5- TemplateLoader: Abstract base class for template loading 

6- DefaultTemplateLoader: Loads templates from formkit_ninja.parser.templates 

7- ExtendedTemplateLoader: Supports multiple package sources with template inheritance 

8""" 

9 

10from abc import ABC, abstractmethod 

11from typing import List 

12 

13from jinja2 import ChoiceLoader, Environment, PackageLoader, select_autoescape 

14 

15 

16class TemplateLoader(ABC): 

17 """ 

18 Abstract base class for template loaders. 

19 

20 Subclasses must implement get_environment() to return a configured Jinja2 Environment. 

21 """ 

22 

23 @abstractmethod 

24 def get_environment(self) -> Environment: 

25 """ 

26 Get a configured Jinja2 Environment. 

27 

28 Returns: 

29 Environment: A Jinja2 Environment instance configured with appropriate 

30 template loaders and settings. 

31 """ 

32 pass 

33 

34 

35class DefaultTemplateLoader(TemplateLoader): 

36 """ 

37 Default template loader that loads templates from formkit_ninja.parser.templates. 

38 

39 This loader provides access to the base templates included with formkit-ninja. 

40 """ 

41 

42 def get_environment(self) -> Environment: 

43 """ 

44 Get a Jinja2 Environment configured to load from formkit_ninja.parser.templates. 

45 

46 Returns: 

47 Environment: A Jinja2 Environment with PackageLoader for base templates. 

48 """ 

49 return Environment( 

50 loader=PackageLoader("formkit_ninja.parser", "templates"), 

51 autoescape=select_autoescape(), 

52 trim_blocks=True, 

53 lstrip_blocks=True, 

54 ) 

55 

56 

57class ExtendedTemplateLoader(TemplateLoader): 

58 """ 

59 Extended template loader that supports multiple package sources. 

60 

61 Templates are loaded from packages in order, with earlier packages taking precedence. 

62 This allows projects to override base templates with custom versions. 

63 

64 The loader looks for a "templates" subdirectory within each package. 

65 

66 Args: 

67 template_packages: List of package names (e.g., ["myapp", "formkit_ninja.parser"]). 

68 Templates are expected to be in a "templates" subdirectory of each package. 

69 """ 

70 

71 def __init__(self, template_packages: List[str]) -> None: 

72 """ 

73 Initialize ExtendedTemplateLoader. 

74 

75 Args: 

76 template_packages: List of package names where templates can be found. 

77 Templates are expected in a "templates" subdirectory. 

78 Packages are checked in order, first match wins. 

79 """ 

80 self.template_packages = template_packages 

81 

82 def get_environment(self) -> Environment: 

83 """ 

84 Get a Jinja2 Environment configured to load from multiple package sources. 

85 

86 Returns: 

87 Environment: A Jinja2 Environment with ChoiceLoader for multiple sources. 

88 """ 

89 loaders = [PackageLoader(package, "templates") for package in self.template_packages] 

90 

91 return Environment( 

92 loader=ChoiceLoader(loaders), 

93 autoescape=select_autoescape(), 

94 trim_blocks=True, 

95 lstrip_blocks=True, 

96 )