Files
compose_gen/src/docker_compose/cfg/src_path.py
2026-01-11 12:35:27 -06:00

102 lines
2.6 KiB
Python

from collections.abc import Iterator
from dataclasses import dataclass
from pathlib import Path
from typing import Self, cast, final
from docker_compose.cfg.compose_paths import ServicePath, VolumePath
from docker_compose.cfg.org_yaml import OrgYaml
from docker_compose.util.Ts import TypeYamlCompatibleDict, TypeYamlCompatibleRes
from docker_compose.util.yaml_util import read_yaml, write_yaml
YAML_EXTS = frozenset((".yml", ".yaml"))
class ComposeFileTemplate(Path):
def write_dict(self, data: TypeYamlCompatibleDict) -> None:
write_yaml(data, self)
def write(self, data: str) -> None:
with self.open("wt") as f:
_ = f.write(data)
class OrgFile(Path):
@property
def as_dict(self) -> OrgYaml:
return cast(OrgYaml, cast(object, read_yaml(self)))
class YamlDir(Path):
@property
def yaml_files(self) -> Iterator[Path]:
if not self:
raise FileNotFoundError(self)
for service in self.iterdir():
if service.suffix not in YAML_EXTS:
continue
yield service
def __bool__(self) -> bool:
return self.exists()
class CfgDir(YamlDir):
@property
def cfg_file(self) -> OrgFile:
for file in self.yaml_files:
if file.stem != "cfg":
continue
return OrgFile(file)
raise FileNotFoundError(self.joinpath("cfg.y(a)ml"))
class ServiceDir(YamlDir):
@property
def files(self) -> Iterator[ServicePath]:
for file in self.yaml_files:
yield ServicePath(file)
class VolumesDir(YamlDir):
@property
def files(self) -> Iterator[VolumePath]:
try:
for file in self.yaml_files:
yield VolumePath(file)
except FileNotFoundError:
return
class VolumeData(Path):
def write(self, data: TypeYamlCompatibleRes) -> None:
write_yaml(data, self)
@final
@dataclass(frozen=True, slots=True)
class SrcPaths:
cfg_dir: CfgDir
org_file: OrgFile
env_file: Path
service_dir: ServiceDir
vol_dir: VolumesDir
compose_file: ComposeFileTemplate
volume_data: VolumeData
@classmethod
def from_path(cls, src: Path) -> Self:
cfg_dir = CfgDir(src)
return cls(
cfg_dir,
cfg_dir.cfg_file,
src.joinpath(".env"),
ServiceDir(src.joinpath("services")),
VolumesDir(src.joinpath("volumes")),
ComposeFileTemplate(src.joinpath("docker-compose.yml")),
VolumeData(src.joinpath("volume_paths.yml")),
)
@property
def app(self) -> str:
return self.cfg_dir.stem