Coverage for functions \ flipdare \ util \ template_file.py: 73%
62 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
14import re
15from pathlib import Path
17from flipdare.result.app_result import AppResult
18from flipdare.error.app_error import ServerError
19from flipdare.generated.shared.app_error_code import AppErrorCode
21_error_type: AppErrorCode = AppErrorCode.EMAIL_TEMPLATE
24class TemplateFile:
26 def __init__(self, file_path: Path) -> None:
27 self._file_path = file_path
29 @property
30 def file_path(self) -> Path:
31 return self._file_path
33 @staticmethod
34 def format_param(param_name: str) -> str:
35 return f"__{param_name.upper()}__"
37 @staticmethod
38 def format_param_regex() -> str:
39 return r"__([A-Z0-9_]+)__"
41 @staticmethod
42 def _get_actual_key(key: str, params: dict[str, str]) -> str:
43 if key in params:
44 return key
45 if f"{key}_html" in params:
46 return f"{key}_html"
47 if f"{key}_text" in params:
48 return f"{key}_text"
49 return key
51 @staticmethod
52 def valid(required: list[str], params: dict[str, str]) -> bool:
53 missing = []
54 for key in required:
55 actual_key = TemplateFile._get_actual_key(key, params)
56 if actual_key not in params:
57 missing.append(key)
59 if len(missing) <= 0:
60 return True
62 raise ServerError(
63 message=f"Missing required parameters: {', '.join(missing)}",
64 error_code=_error_type,
65 )
67 def parse(self, params: dict[str, str], start_at: int = 0, end_at: int = -1) -> str:
68 if not self._file_path.is_file():
69 raise ServerError(
70 message=f"Template path not found {self._file_path}",
71 error_code=_error_type,
72 )
74 result: AppResult = AppResult()
76 content = ""
77 with self._file_path.open(encoding="utf-8") as file:
78 content = file.read()
80 if end_at != -1:
81 # split to lines, get the range, and re-join
82 lines = content.splitlines()
83 selected_lines = lines[start_at:end_at]
84 content = "\n".join(selected_lines)
86 for key, value in params.items():
87 actual_key = self._get_actual_key(key, params)
88 formatted_key = TemplateFile.format_param(actual_key)
89 new_content = content.replace(formatted_key, value)
90 if new_content == content:
91 result.add_error(_error_type, f"Parameter {formatted_key} not found in template.")
92 content = new_content
94 re_matches = re.findall(TemplateFile.format_param_regex(), content)
95 for match in re_matches:
96 result.add_error(
97 _error_type,
98 f"Parameter __{match}__ not found in provided parameters.",
99 )
101 if result.is_error:
102 error_str = result.formatted
103 raise ServerError(message=error_str, error_code=_error_type)
105 return content