Init repository
This commit is contained in:
38
skills/python-development-settings/SKILL.md
Normal file
38
skills/python-development-settings/SKILL.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: python-development-settings
|
||||
description: Application configuration and settings management. Use when defining, loading, validating, or extending application settings.
|
||||
---
|
||||
|
||||
## Rules
|
||||
- The root settings class must inherit from `pydantic_settings.BaseSettings`. This enables automatic loading from environment variables and `.env` files.
|
||||
- Every nested settings class (for individual services, adapters, or components) must inherit from `pydantic.BaseModel`, not from `BaseSettings`. Only the root class needs the env-loading behavior.
|
||||
- The root settings class exposes one field per top-level service or subsystem. Provide sensible defaults as plain values for immutable types (str, int, bool, None) and use `Field(default_factory=...)` only when the default is a mutable object (dict, list, or model instance). Never use mutable literals as class-attribute defaults in Pydantic v2. Provide defaults so the application starts without a config file when reasonable.
|
||||
- A settings class can accept either a settings object or a string key referencing another entry in the same config. The resolver (or a `@model_validator`) replaces string references with resolved instances after initial parsing. This is how services declare their dependencies declaratively.
|
||||
- Use `@model_validator(mode="after")` on the root settings class to validate cross-references between subsystems, resolve string keys to actual instances, and enforce consistency across the configuration graph.
|
||||
- Support loading from YAML config files with custom tags. Register `!include` for file inclusion and `!env` for environment variable interpolation inside YAML. The YAML loader builder must live as a `@staticmethod` inside the root settings class. Example:
|
||||
```python
|
||||
@staticmethod
|
||||
def get_yaml_loader(base_path: pathlib.Path) -> yaml.BaseLoader:
|
||||
loader = type("Loader", (yaml.SafeLoader,), {})
|
||||
loader.add_constructor(
|
||||
"!include",
|
||||
yaml_include.Constructor(base_dir=str(base_path)),
|
||||
)
|
||||
loader.add_constructor("!env", construct_env_tag)
|
||||
return loader
|
||||
```
|
||||
- Support loading from JSON config files using standard `json.load`. JSON does not support custom tags; use string interpolation or env var resolution handled by `BaseSettings` after load.
|
||||
- Provide a single `load()` classmethod on the root settings class that reads the config file (YAML or JSON), then passes the parsed dict into the `BaseSettings` constructor along with optional `_env_prefix` and `_env_file`. Example:
|
||||
```python
|
||||
@classmethod
|
||||
def load(cls, config_file: pathlib.Path | None = None) -> Self:
|
||||
data = {}
|
||||
if config_file is not None:
|
||||
if config_file.suffix in (".yaml", ".yml"):
|
||||
data.update(yaml.load(config_file.read_text(), Loader=get_loader()))
|
||||
elif config_file.suffix == ".json":
|
||||
data.update(json.loads(config_file.read_text()))
|
||||
return cls(**data)
|
||||
```
|
||||
- Keep each subsystem's settings in its own `settings.py` module inside the subsystem package. Import and compose them into the root settings class. Do not inline subsystem schemas into the root file.
|
||||
- Use `pydantic.Field(default_factory=...)` for mutable default values (dicts, lists, models). Never use mutable literals as class-attribute defaults in Pydantic v2.
|
||||
Reference in New Issue
Block a user