Coverage for src / minibook / utils.py: 100%
21 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-27 10:03 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-27 10:03 +0000
1"""Utility functions for MiniBook.
3This module provides shared utility functions used across MiniBook modules.
4"""
6from datetime import datetime
7from pathlib import Path
9from jinja2 import Environment, FileSystemLoader, Template, select_autoescape
11TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
13# Extensions that should have autoescape enabled
14AUTOESCAPE_EXTENSIONS = ("html", "htm", "xml", "j2", "jinja", "jinja2")
17def get_timestamp() -> str:
18 r"""Generate a formatted timestamp string.
20 Returns:
21 A timestamp string in the format 'YYYY-MM-DD HH:MM:SS'.
23 Examples:
24 >>> import re
25 >>> ts = get_timestamp()
26 >>> bool(re.match(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', ts))
27 True
28 """
29 return datetime.now().strftime(TIMESTAMP_FORMAT)
32def create_jinja_env(template_dir: Path) -> Environment:
33 """Create a Jinja2 environment with secure defaults.
35 Args:
36 template_dir: Directory containing template files.
38 Returns:
39 A configured Jinja2 Environment with autoescape enabled.
40 """
41 return Environment(
42 loader=FileSystemLoader(template_dir),
43 autoescape=select_autoescape(enabled_extensions=AUTOESCAPE_EXTENSIONS, default=True),
44 )
47def load_template(template_path: str | None = None, default_template: str = "html.j2") -> Template:
48 """Load a Jinja2 template from a path or use the default.
50 Args:
51 template_path: Optional path to a custom Jinja2 template file.
52 default_template: Name of the default template to use if no custom path provided.
54 Returns:
55 A loaded Jinja2 Template object.
57 Raises:
58 FileNotFoundError: If the specified template file does not exist.
60 Examples:
61 >>> template = load_template() # Uses default html.j2
62 >>> template.name
63 'html.j2'
64 >>> template = load_template(default_template="bare.j2")
65 >>> template.name
66 'bare.j2'
67 """
68 if template_path:
69 template_file = Path(template_path)
70 if not template_file.exists():
71 msg = f"Template file not found: {template_path}"
72 raise FileNotFoundError(msg)
74 template_dir = template_file.parent
75 env = create_jinja_env(template_dir)
76 return env.get_template(template_file.name)
78 # Use default template from package
79 template_dir = Path(__file__).parent / "templates"
80 env = create_jinja_env(template_dir)
81 return env.get_template(default_template)