Source code for varlord.policy
"""
Priority policy for configuration sources.
Defines how sources are ordered and merged, with support for
per-key priority rules.
"""
from __future__ import annotations
import re
from dataclasses import dataclass
from typing import Dict, List, Optional
[docs]
@dataclass
class PriorityPolicy:
"""Defines priority ordering for configuration sources.
Supports:
- Default priority for all keys
- Per-key/namespace overrides using pattern matching
- Source ID (exact match) or name (match all of type)
Example:
>>> policy = PriorityPolicy(
... default=["defaults", "dotenv", "env", "cli"],
... overrides={
... "secrets.*": ["defaults", "etcd", "env"], # Different rules for secrets
... }
... )
>>> # Using source ID for exact match:
>>> policy = PriorityPolicy(
... default=["defaults", "yaml:/etc/config.yaml", "yaml:~/.config/app.yaml", "env", "cli"],
... )
>>> # Using source name to match all of type:
>>> policy = PriorityPolicy(
... default=["defaults", "yaml", "env", "cli"], # All yaml sources before env
... )
>>> # Mixed usage:
>>> policy = PriorityPolicy(
... default=["defaults", "yaml:/etc/config.yaml", "yaml", "env", "cli"],
... # First specific system config, then all other yaml sources, then env and CLI
... )
"""
default: List[str]
"""Default priority order for all keys.
Can contain:
- Source IDs (exact match, e.g., "yaml:/etc/config.yaml")
- Source names (match all of type, e.g., "yaml")
"""
overrides: Optional[Dict[str, List[str]]] = None
"""Per-key priority overrides.
Keys are glob patterns (e.g., "secrets.*", "db.*").
Values are priority lists for matching keys.
Can contain source IDs or names (same as default).
"""
[docs]
def get_priority(self, key: str) -> List[str]:
"""Get priority order for a specific key.
Args:
key: Configuration key (e.g., "db.host", "secrets.api_key")
Returns:
List of source IDs or names in priority order (highest to lowest).
- Source ID (e.g., "yaml:/etc/config.yaml"): Exact match
- Source name (e.g., "yaml"): Match all sources with this name
"""
if self.overrides:
for pattern, priority in self.overrides.items():
# Convert glob pattern to regex
regex_pattern = pattern.replace(".", r"\.").replace("*", ".*")
if re.match(regex_pattern, key):
return priority
return self.default
[docs]
def __repr__(self) -> str:
"""Return string representation."""
overrides_str = (
f", overrides={len(self.overrides or {})} patterns" if self.overrides else ""
)
return f"<PriorityPolicy(default={self.default}{overrides_str})>"