template.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import _io
  2. class template_exception(Exception):
  3. pass
  4. class template:
  5. def __init__(self, content: str | _io.TextIOWrapper, check: bool = True):
  6. self.__template = None
  7. self.__rendered = None
  8. self.__properties = dict()
  9. if type(content) is str:
  10. self.__template = content
  11. if type(content) is _io.TextIOWrapper:
  12. self.__template = content.read()
  13. if self.__template is None:
  14. raise Exception("Template content must be string or file.")
  15. if check is True:
  16. self.__prepare_template()
  17. @property
  18. def separators(self) -> [str, str]:
  19. return "<<!", "!>>"
  20. def __prepare_template(self) -> None:
  21. template = self.template
  22. start, end = self.separators
  23. count = 0
  24. current = 0
  25. while True:
  26. current_start = template.find(start, count)
  27. if current_start == -1:
  28. break
  29. current = current_start + len(start)
  30. current_end = template.find(end, count)
  31. current_after = current_end + len(end)
  32. if current > current_end:
  33. found = "Close char before start char on " + str(current)
  34. raise template_exception(found)
  35. key = template[current:current_end]
  36. key = key.strip()
  37. if len(key) == 0:
  38. raise template_exception("Empty key on " + str(current))
  39. before = template[:current_start]
  40. after = template[current_after:]
  41. template = before + start + key + end + after
  42. count = current + len(key) + len(end)
  43. self.__template = template
  44. @property
  45. def template(self) -> str:
  46. return self.__template
  47. def get(self, name: str) -> str:
  48. if not type(name) is str:
  49. raise Exception("Name of the key must be str.")
  50. if not name in self.__properties:
  51. raise Exception("Key " + name + " not exists in properties.")
  52. return self.__properties[name]
  53. def set(self, name: str, value: str | int | float) -> template:
  54. if not type(name) is str:
  55. raise Exception("Name of the attribute must be str.")
  56. if type(value) is str:
  57. self.__properties[name] = value
  58. return self
  59. if type(value) is int or type(value) is float:
  60. self.__properties[name] = str(value)
  61. return self
  62. raise Exception("Value to set must be str, int or float.")
  63. def clone(self) -> template:
  64. return template(self.template, False)
  65. def __key(self, target: str) -> str:
  66. start, end = self.separators
  67. return start + target + end
  68. def render(self) -> str:
  69. if not self.__rendered is None:
  70. return self.__rendered
  71. template = self.template
  72. for name, value in self.__properties.items():
  73. template = template.replace(self.__key(name), value)
  74. self.__rendered = template
  75. return self.render()