forked from GabDug/sync-pre-commit-lock
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.py
More file actions
109 lines (81 loc) · 3.4 KB
/
config.py
File metadata and controls
109 lines (81 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from __future__ import annotations
import os
from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, TypedDict
from ._compat import toml
if TYPE_CHECKING:
from sync_pre_commit_lock.db import PackageRepoMapping
class HookRunner(str, Enum):
"""The hook runner to use for installing git hooks."""
PRE_COMMIT = "pre-commit"
PREK = "prek"
AUTO = "auto"
ENV_PREFIX = "SYNC_PRE_COMMIT_LOCK"
def env_as_bool(value: str) -> bool:
return (value or "False").lower() in ("true", "1")
def env_as_list(value: str) -> list[str]:
return [v.strip() for v in (value or "").split(",")]
def from_toml(data: dict[str, Any]) -> SyncPreCommitLockConfig:
if len(data) == 0:
return SyncPreCommitLockConfig()
fields = {f.metadata.get("toml", f.name): f for f in SyncPreCommitLockConfig.__dataclass_fields__.values()}
# XXX We should warn about unknown fields
return SyncPreCommitLockConfig(**{fields[name].name: data[name] for name in data if name in fields})
def update_from_env(config: SyncPreCommitLockConfig) -> SyncPreCommitLockConfig:
vars = {
f.metadata["env"]: f for f in SyncPreCommitLockConfig.__dataclass_fields__.values() if f.metadata.get("env")
}
for var, specs in vars.items():
if value := os.getenv(f"{ENV_PREFIX}_{var}"):
caster = specs.metadata.get("cast", lambda v: v)
setattr(config, specs.name, caster(value))
return config
class Metadata(TypedDict, total=False):
"""Configuration metadata known fields"""
toml: str
"""Map the `toml` field"""
env: str
"""Optionally map the environment variable suffix"""
cast: Callable[[str], Any]
"""Optionally provide a cast function for environment variable"""
@dataclass
class SyncPreCommitLockConfig:
automatically_install_hooks: bool = field(
default=True,
metadata=Metadata(toml="automatically-install-hooks", env="INSTALL", cast=env_as_bool),
)
disable_sync_from_lock: bool = field(
default=False,
metadata=Metadata(toml="disable-sync-from-lock", env="DISABLED", cast=env_as_bool),
)
ignore: list[str] = field(
default_factory=list,
metadata=Metadata(toml="ignore", env="IGNORE", cast=env_as_list),
)
pre_commit_config_file: str = field(
default=".pre-commit-config.yaml",
metadata=Metadata(toml="pre-commit-config-file", env="PRE_COMMIT_FILE"),
)
dependency_mapping: PackageRepoMapping = field(
default_factory=dict,
metadata=Metadata(toml="dependency-mapping"),
)
hook_runner: HookRunner = field(
default=HookRunner.PRE_COMMIT,
metadata=Metadata(toml="hook-runner", env="HOOK_RUNNER", cast=HookRunner),
)
def load_config(path: Path | None = None) -> SyncPreCommitLockConfig:
"""
Load the configuration from pyproject.toml file, and then from environment variables.
Args:
path (Path | None): The path to the pyproject.toml file. If None, defaults to "pyproject.toml". Best if provided by PDM or Poetry.
Returns:
SyncPreCommitLockConfig: The loaded configuration.
"""
path = path or Path("pyproject.toml")
with path.open("rb") as file:
config_dict = toml.load(file)
tool_dict: dict[str, Any] = config_dict.get("tool", {}).get("sync-pre-commit-lock", {})
return update_from_env(from_toml(tool_dict))