Configuration System Overview
Pyrig’s configuration system provides a declarative, idempotent way to manage all project configuration files. The system automatically creates, validates, and updates configuration files while preserving user customizations.Core Concepts
Declarative Configuration
Each configuration file is managed by aConfigFile subclass that defines:
- Expected structure: The minimum required configuration
- File location: Where the file should be created
- File format: TOML, YAML, JSON, Python, or Markdown
- Validation rules: How to check if the file is correct
- Merge behavior: How to combine expected and existing configurations
Subset Validation
Pyrig uses subset validation to preserve user customizations:- Users can add: Extra configuration not defined by pyrig
- Users cannot remove: Required configuration defined by pyrig
- Intelligent merging: Missing keys are added without removing user additions
Automatic Discovery
Pyrig automatically discovers allConfigFile subclasses in:
pyrig.rig.configs.*(pyrig’s built-in configurations)your_package.rig.configs.*(your custom configurations)
Configuration File Types
Base Classes
The root base class providing:
- Automatic discovery and priority-based validation
- Subset validation and intelligent merging
- Cached loading and cache-invalidating dumps
- Create/validate/merge lifecycle management
For TOML configuration files using tomlkit:
- Preserves formatting and comments
- Multiline arrays for readability
- Used by: pyproject.toml
For YAML configuration files using PyYAML:
- Safe load/dump (no code execution)
- Preserves key order
- Used by: GitHub Actions workflows, mkdocs.yml
For JSON configuration files:
- 4-space indentation
- Used by: branch-protection.json, issue templates config
For Python source files:
- Module docstring preservation
- Used by: init.py files, main.py, CLI scripts
For Markdown documentation:
- Badge generation
- Template rendering
- Used by: README.md, CONTRIBUTING.md, docs/*.md
Validation Process
Priority-Based Validation
Configuration files are validated in priority order:pyproject.toml has priority 20 (MEDIUM) because other configuration files read from it to get project name, dependencies, etc.
Validation Steps
For each configuration file:- Check existence: If file doesn’t exist, create it
- Check correctness: Validate expected config is subset of actual
- Merge configs: If incorrect, add missing keys/values
- Dump merged: Write merged configuration back to file
- Verify: Confirm file is now correct
Parallel Execution
Files at the same priority level are validated in parallel usingThreadPoolExecutor for performance.
Usage
Initialize All Configurations
- Discovers all
ConfigFilesubclasses - Groups by priority
- Validates each group in priority order (parallel within groups)
- Creates missing files and updates incorrect files
Check Single Configuration
Opt Out of Configuration
To opt out of any configuration file, make it empty:Customization
See Custom Configs for detailed examples of creating custom configuration files.Override Existing Configuration
Create a subclass with the same name in your project’srig.configs package:
Add New Configuration File
Create a newConfigFile subclass in your project:
uv run pyrig mkroot.
Built-in Configurations
Pyrig provides configurations for:Project Files
- pyproject.toml - Python project metadata and dependencies
- LICENSE - Project license
- README.md - Project documentation
- .gitignore - Git ignore patterns
- .python-version - Python version specification
- .env - Environment variables template
GitHub Files
- GitHub Actions Workflows - CI/CD automation
- Branch Protection - Repository protection rules
- Issue Templates - Bug reports and feature requests
- Pull Request Template - PR description template
- CONTRIBUTING.md - Contribution guidelines
- SECURITY.md - Security policy
- CODE_OF_CONDUCT.md - Community guidelines
Python Package Files
- init.py files - Package initialization
- py.typed - Type information marker
- main.py - CLI entry point
- Subcommands - CLI command structure
Testing Files
- conftest.py - Pytest configuration
- test_*.py - Test files
- fixtures - Test fixtures
Documentation Files
- mkdocs.yml - Documentation site configuration
- docs/index.md - Documentation homepage
- docs/api.md - API reference
Container Files
- Containerfile - Container image definition
Best Practices
Do’s
- Subclass for customization: Override
_configs()in a subclass rather than editing generated files directly - Use priorities correctly: Set higher priority for files that others depend on
- Preserve user additions: Don’t remove keys/values users added
- Document custom configs: Add docstrings explaining why you customized
- Test validation: Run
uv run pyrig mkrootafter creating custom configs
Don’ts
- Don’t edit generated files directly: Changes will be overwritten if they conflict with expected configuration
- Don’t remove required configuration: Subset validation will add it back
- Don’t skip validation: Always run
uv run pyrig mkrootafter changes - Don’t use circular dependencies: Files should not depend on each other in a cycle
- Don’t forget to implement required methods: All abstract methods must be implemented
Advanced Topics
Caching
Bothload() and configs() are cached using @cache decorator:
- First call: Loads/generates configuration
- Subsequent calls: Returns cached value
- Cache invalidation: Calling
dump()clears the cache
Merging Behavior
When merging configurations:- Dicts: Recursively merged (user keys preserved, expected keys added)
- Lists: Expected items inserted at same indices if missing
- Scalars: Expected value replaces actual if different