Coverage for src / lexigram / contracts / core / config.py: 0%
42 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""Configuration protocol for the Lexigram framework.
3Defines the runtime-checkable protocol that all configuration implementations
4must satisfy. This enables DI-based config access without coupling to concrete
5config classes (Pydantic, DomainModel, etc.).
6"""
8from __future__ import annotations
10from dataclasses import dataclass
11from enum import StrEnum
12import os
13from typing import Any, Protocol, TypeVar, runtime_checkable
15T = TypeVar("T")
18class Environment(StrEnum):
19 """Deployment environment discriminator.
21 Use ``Environment.from_env()`` to read the current environment from the
22 ``LEX_ENV`` (or ``APP_ENV``) environment variable.
23 """
25 DEVELOPMENT = "development"
26 STAGING = "staging"
27 PRODUCTION = "production"
28 TEST = "test"
30 @classmethod
31 def from_env(cls, default: Environment = "development") -> Environment: # type: ignore[assignment]
32 """Read the active environment from ``LEX_ENV`` or ``APP_ENV``.
34 Args:
35 default: Fallback when neither variable is set.
37 Returns:
38 The resolved ``Environment`` member.
39 """
40 raw = os.environ.get("LEX_ENV") or os.environ.get("APP_ENV") or default
41 try:
42 return cls(raw.lower())
43 except ValueError:
44 return cls(default)
47@dataclass(frozen=True)
48class ConfigIssue:
49 """A single configuration validation issue.
51 Attributes:
52 field: Dot-notation path to the offending field (e.g. ``"db.url"``).
53 message: Human-readable description of the problem.
54 severity: ``"error"`` blocks startup; ``"warning"`` is informational.
55 suggestion: Optional remediation hint shown to operators.
56 """
58 field: str
59 message: str
60 severity: str = "error"
61 suggestion: str = ""
64@runtime_checkable
65class ConfigProtocol(Protocol):
66 """Protocol for configuration access across the framework.
68 Any configuration object (BaseConfig, LexigramConfig, or custom
69 implementations) can satisfy this protocol by implementing ``get()``,
70 ``get_section()``, and ``has_section()``.
72 Example::
74 config = container.resolve(ConfigProtocol)
75 db_url = config.get("database.url", "sqlite:///default.db")
76 logging = config.get_section("logging", LoggingConfig)
77 """
79 @property
80 def environment(self) -> Environment:
81 """The active deployment environment."""
82 ...
84 @property
85 def is_production(self) -> bool:
86 """Return ``True`` when the active environment is production."""
87 ...
89 @property
90 def is_development(self) -> bool:
91 """Return ``True`` when the active environment is development."""
92 ...
94 @property
95 def is_testing(self) -> bool:
96 """Return ``True`` when the active environment is testing."""
97 ...
99 @property
100 def is_staging(self) -> bool:
101 """Return ``True`` when the active environment is staging."""
102 ...
104 @property
105 def is_debug(self) -> bool:
106 """Return ``True`` when debug mode is enabled."""
107 ...
109 def get(self, key: str, default: Any = None) -> Any:
110 """Get a configuration value by dot-notation key.
112 Args:
113 key: Configuration key (e.g. ``"app.name"`` or ``"database.url"``).
114 default: Value returned when the key is not found.
116 Returns:
117 The configuration value, or *default* if not found.
118 """
119 ...
121 def get_section(
122 self,
123 name: str,
124 model_cls: type[T] | None = None,
125 ) -> T | dict[str, Any]:
126 """Get a typed configuration section.
128 Args:
129 name: Section name (e.g. ``"logging"``).
130 model_cls: Optional model class to coerce the section into.
132 Returns:
133 A model instance when *model_cls* is provided, otherwise a raw
134 dict or the attribute value.
135 """
136 ...
138 def has_section(self, name: str) -> bool:
139 """Check whether a configuration section exists.
141 Args:
142 name: Section name to check.
144 Returns:
145 True if the section is present.
146 """
147 ...
150__all__ = ["ConfigIssue", "ConfigProtocol", "Environment"]