Files
compose_gen/src/docker_compose/cfg/replace.py
2026-01-10 14:26:03 -06:00

76 lines
2.0 KiB
Python

from collections.abc import Callable
from dataclasses import dataclass, field
from itertools import chain
from typing import ClassVar, Self, final, override
def format_src(src: str) -> str:
return f"${{_{src.upper()}}}"
@final
@dataclass(frozen=True, slots=True)
class ReplaceUnique:
src: str
dest: str # | Callable[[], str]
def __call__(self, string: str) -> str:
return string.replace(self.src, self.dest)
@classmethod
def auto_format(cls, src: str, dest: str):
return cls(format_src(src), dest)
# @override
# def __str__(self) -> str:
# if not self.dest:
# return ""
# if isinstance(self.dest, str):
# return self.dest
# return self.dest()
@final
@dataclass(frozen=True, slots=True)
class ReplaceDynamic:
val: str
fmt: str = field(init=False)
def __post_init__(self):
setter = super(ReplaceDynamic, self).__setattr__
setter("fmt", format_src(self.val))
def __call__(self, string: str) -> str:
return string.replace(self.fmt, self.val)
# def __str__(self) -> str:
# return self.val if isinstance(self.val, str) else self.val.fmt
def build_placeholder(self, *args: "ReplaceDynamic"):
data = ((rep.val.upper(), rep.fmt) for rep in chain((self,), args))
src: tuple[str, ...]
dest: tuple[str, ...]
src, dest = zip(*data)
return ReplaceUnique("_".join(src), "_".join(dest))
@dataclass(frozen=True, slots=True)
class ReplaceStatic:
src: ClassVar[ReplaceDynamic]
dest: None | str | Callable[[], str]
def __call__(self, string: str) -> str:
return string.replace(self.src.fmt, str(self))
@override
def __str__(self) -> str:
if not self.dest:
return ""
if isinstance(self.dest, str):
return self.dest
return self.dest()
@classmethod
def two_stage(cls, dest: str) -> tuple[Self, ReplaceDynamic]:
dest_var = ReplaceDynamic(dest)
return cls(dest_var.fmt), dest_var