"""Module to parse file configuration values."""
from dataclasses import dataclass, field
from pathlib import Path
from .base import ConfigError, get_str, get_str_or_str_list, get_table
[docs]
@dataclass(frozen=True)
class FileConfig:
"""Dataclass to hold file configuration values."""
encoding: str = "utf-8"
changelog_paths: list[Path] = field(default_factory=lambda: [Path("CHANGELOG.md")])
_default_changelog_path: Path | None = None
@property
def default_changelog_path(self) -> Path:
"""Get the default changelog path.
Returns
-------
Path
The default changelog path.
"""
if self._default_changelog_path is not None:
return self._default_changelog_path
if not self.changelog_paths:
msg = (
"No changelog paths configured; "
"cannot determine default changelog path."
)
raise ConfigError(msg)
return self.changelog_paths[0]
[docs]
def to_toml_lines(self) -> list[str]:
"""Convert the FileConfig to TOML lines.
Returns
-------
list[str]
The list of TOML lines representing the configuration.
"""
lines = ["[file]\n"]
lines.append(f'#encoding = "{self.encoding}"\n')
paths_str = '", "'.join(str(p) for p in self.changelog_paths)
lines.append(f'#changelog_paths = ["{paths_str}"]\n')
lines.append(f'#default_changelog_path = "{self.default_changelog_path}"\n')
return lines
[docs]
def parse_file_config(raw_config: dict) -> FileConfig:
"""Parse file configuration from a raw dictionary.
Parameters
----------
raw_config: dict
The raw file configuration dictionary.
Returns
-------
FileConfig
The parsed FileConfig dataclass instance.
Raises
------
ConfigError
If the specified encoding is invalid.
"""
table = get_table(raw_config, "file")
encoding = parse_encoding(table)
changelog_paths = parse_changelog_path(table)
default_changelog_path = parse_default_changelog_path(table)
return FileConfig(
encoding=encoding,
changelog_paths=changelog_paths,
_default_changelog_path=default_changelog_path,
)
[docs]
def parse_encoding(table: dict) -> str:
"""Parse the encoding from a configuration table.
Parameters
----------
table: dict
The configuration table.
Returns
-------
str
The parsed encoding.
Raises
------
ConfigError
If the specified encoding is invalid.
"""
encoding = get_str(table, "encoding", default=FileConfig.encoding)
# Validate encoding
try:
Path(__file__).open("r", encoding=encoding).close()
except LookupError as e:
msg = f"Invalid file encoding specified in configuration: {encoding}"
raise ConfigError(msg) from e
return encoding
[docs]
def parse_changelog_path(table: dict) -> list[Path]:
"""Parse the changelog paths from a configuration table.
Parameters
----------
table: dict
The configuration table.
Returns
-------
list[Path]
The parsed list of changelog paths.
"""
# Use the same default as FileConfig, but expressed as a list of strings.
default_paths = [str(p) for p in FileConfig().changelog_paths]
changelog_paths = get_str_or_str_list(
table,
"changelog_paths",
default=default_paths,
)
# If the configuration explicitly provides no value, fall back to the default.
if changelog_paths is None:
changelog_paths = default_paths
if isinstance(changelog_paths, str):
changelog_paths = [changelog_paths]
return [Path(p) for p in changelog_paths]
[docs]
def parse_default_changelog_path(table: dict) -> Path | None:
"""Parse the default changelog path from a configuration table.
Parameters
----------
table: dict
The configuration table.
Returns
-------
Path | None
The parsed default changelog path, or None if not specified.
"""
default_path_str = get_str(table, "default_changelog_path", default=None)
if default_path_str is not None:
return Path(default_path_str)
return None