import re import secrets from collections.abc import Iterator from dataclasses import dataclass from functools import partial from pathlib import Path from typing import Self, final from docker_compose.cfg.replace import ReplaceDynamic @final @dataclass class Env: pswd = ReplaceDynamic.auto_format( "pswd", partial(secrets.token_urlsafe, 12), ) data: dict[str, str] @classmethod def get_lines(cls, data: str) -> Iterator[tuple[str, str]]: line_valid = re.compile(r"(^\w+)=(.+)\s*") for line in data.splitlines(): res = line_valid.match(line) if not res: continue yield res.group(1), res.group(2) @classmethod def from_path(cls, path: Path) -> Self: with path.open(mode="rt") as f: data = f.read() return cls({k: v for k, v in cls.get_lines(data)}) @property def with_pass(self)->Iterator[tuple[str,str]]: for k,v in self.data.items(): if self.pswd.src not in v: yield k,v continue yield k,self.pswd(v) @property def as_txt(self) -> str: return '\n'.join(sorted(map('='.join, self.with_pass))) @classmethod def copy(cls, src: Path, dest: Path) -> None: txt = cls.from_path(src).as_txt with dest.open(mode="wt") as f: _ = f.write(txt)