configs.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from typing import TYPE_CHECKING
  2. if TYPE_CHECKING:
  3. from render import Render
  4. try:
  5. from .error import RenderError
  6. from .formatter import escape_dollar
  7. from .validations import valid_octal_mode_or_raise, valid_fs_path_or_raise
  8. except ImportError:
  9. from error import RenderError
  10. from formatter import escape_dollar
  11. from validations import valid_octal_mode_or_raise, valid_fs_path_or_raise
  12. class Configs:
  13. def __init__(self, render_instance: "Render"):
  14. self._render_instance = render_instance
  15. self._configs: dict[str, dict] = {}
  16. def add(self, name: str, data: str):
  17. if not isinstance(data, str):
  18. raise RenderError(f"Expected [data] to be a string, got [{type(data)}]")
  19. if name not in self._configs:
  20. self._configs[name] = {"name": name, "data": data}
  21. return
  22. if data == self._configs[name]["data"]:
  23. return
  24. raise RenderError(f"Config [{name}] already added with different data")
  25. def has_configs(self):
  26. return bool(self._configs)
  27. def render(self):
  28. return {
  29. c["name"]: {"content": escape_dollar(c["data"])}
  30. for c in sorted(self._configs.values(), key=lambda c: c["name"])
  31. }
  32. class ContainerConfigs:
  33. def __init__(self, render_instance: "Render", configs: Configs):
  34. self._render_instance = render_instance
  35. self.top_level_configs: Configs = configs
  36. self.container_configs: set[ContainerConfig] = set()
  37. def add(self, name: str, data: str, target: str, mode: str = ""):
  38. self.top_level_configs.add(name, data)
  39. if target == "":
  40. raise RenderError(f"Expected [target] to be set for config [{name}]")
  41. if mode != "":
  42. mode = valid_octal_mode_or_raise(mode)
  43. if target in [c.target for c in self.container_configs]:
  44. raise RenderError(f"Target [{target}] already used for another config")
  45. target = valid_fs_path_or_raise(target)
  46. self.container_configs.add(ContainerConfig(self._render_instance, name, target, mode))
  47. def has_configs(self):
  48. return bool(self.container_configs)
  49. def render(self):
  50. return [c.render() for c in sorted(self.container_configs, key=lambda c: c.source)]
  51. class ContainerConfig:
  52. def __init__(self, render_instance: "Render", source: str, target: str, mode: str):
  53. self._render_instance = render_instance
  54. self.source = source
  55. self.target = target
  56. self.mode = mode
  57. def render(self):
  58. result: dict[str, str | int] = {
  59. "source": self.source,
  60. "target": self.target,
  61. }
  62. if self.mode:
  63. result["mode"] = int(self.mode, 8)
  64. return result