Skip to content

Conversation

@ibro45
Copy link
Contributor

@ibro45 ibro45 commented Nov 17, 2025

Summary

This PR modernizes the Sparkwheel API and improves developer experience through:

  • New .update() API: Replaces .load() with a cleaner, chainable method for loading configs and applying overrides
  • Freeze/Unfreeze: Add freeze()/unfreeze() methods and MISSING sentinel value for better state management
  • Type Coercion: Automatic type conversion during schema validation (e.g., "123"123)
  • Simplified CLI Pattern: Remove cli.py module in favor of manual override parsing with user's preferred CLI library
  • Comprehensive Documentation: Complete rewrite of guides to reflect new API patterns and best practices
  • Improved CI/CD: Modernized GitHub workflows with better test reporting and dependency review

Key Changes

API Improvements

  • Add Config.freeze() to prevent modifications and Config.unfreeze() to allow them again
  • Add MISSING sentinel for distinguishing unset values from None
  • Implement type coercion system for schema validation with configurable strictness

Documentation Overhaul

  • Updated all guides to use Config().update() pattern instead of deprecated .load()
  • Rewrote CLI guide to show integration with argparse, Click, Typer, and Fire
  • Added quick reference guide with concise API overview
  • Removed outdated examples, added advanced guide sections

CI/CD Enhancements

  • Split workflows into focused ci.yml (fast) and ci-full.yml (comprehensive)
  • Added reusable setup action and test summary script
  • Improved PR title validation and dependency review

Type of Change

  • 📚 Examples / docs / tutorials / dependencies update
  • 🔧 Bug fix (non-breaking change which fixes an issue)
  • 🥂 Improvement (non-breaking change which improves an existing feature)
  • 🚀 New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 🔐 Security fix

Checklist

  • I've read the CODE_OF_CONDUCT.md document.
  • I've read the CONTRIBUTING.md guide.
  • I've updated the code style using make codestyle.
  • I've written tests for all new methods and classes that I created.
  • I've written the docstring in Google format for all the methods and classes that I used.

ibro45 and others added 6 commits November 16, 2025 17:43
Remove the built-in CLI parsing utilities (`Config.from_cli()`, `parse_override()`, `parse_overrides()`) to simplify the library and encourage users to handle their own argument parsing with standard libraries like argparse, click, typer, or fire.

**Why:**
- Reduces library complexity and maintenance burden
- Users have full control over CLI behavior and flags
- Works better with diverse CLI frameworks
- The recommended pattern is simple: just 3 lines of code for basic CLI override parsing

**Migration path:**
```python
# Old way
config = Config.from_cli("config.yaml", sys.argv[1:])

# New way (3 lines)
config = Config()
config.update("config.yaml")
for arg in sys.argv[1:]:
    if "=" in arg:
        key, value = arg.split("=", 1)
        try:
            value = ast.literal_eval(value)
        except (ValueError, SyntaxError):
            pass
        config.set(key, value)
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Introduce automatic type coercion to convert compatible types during validation, making configs more flexible and user-friendly.

**Features:**
- String to numeric conversion (`"123"` → `123`, `"3.14"` → `3.14`)
- Numeric type conversion (`1` → `1.0` for float fields)
- String to bool parsing (`"true"`, `"yes"`, `"1"` → `True`)
- List/tuple interconversion
- Dict to dataclass conversion (nested structures)
- Preserves None values and handles Optional types correctly

**Example:**
```python
@DataClass
class Config:
    port: int
    rate: float

config = Config()
config.update({"port": "8080", "rate": "0.5"})  # Strings coerced!
config.validate(Config)  # ✓ Works! port=8080, rate=0.5
```

**Implementation:**
- `coerce_value()`: Core coercion logic with recursive support
- Smart type detection and conversion with fallback to original value
- Integration with `_validate_field()` in schema.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add advanced configuration features for better control and partial config support.

**New Features:**

1. **Frozen Configs** - Prevent mutations after initialization:
   ```python
   config.freeze()  # Lock config
   config.set("key", "value")  # Raises FrozenConfigError
   config.unfreeze()  # Allow mutations again
   ```

2. **MISSING Sentinel** - Support partial configs with required-but-not-yet-set values:
   ```python
   config = Config(allow_missing=True)
   config.update({"api_key": MISSING})  # Placeholder for later
   config.set("api_key", os.getenv("API_KEY"))  # Fill in
   config.validate(schema)  # Ensure complete (allow_missing=False by default)
   ```

3. **Continuous Validation** - Validate on every mutation when schema provided:
   ```python
   config = Config(schema=MySchema)  # Enable continuous validation
   config.update(data)  # Validates immediately!
   config.set("port", "invalid")  # Raises ValidationError
   ```

**API Changes:**
- Add `freeze()`, `unfreeze()`, `is_frozen()` methods
- Add `MISSING` sentinel constant
- Add `allow_missing` parameter to `Config()` and `validate()`
- Integrate type coercion into validation pipeline
- Enhanced error messages with field paths

**Tests:**
- Comprehensive test coverage for freeze/unfreeze behavior
- MISSING sentinel edge cases
- Continuous validation scenarios
- Updated existing tests for new API patterns

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Update all documentation to reflect the new API design, removed CLI module, and new features (type coercion, freeze/unfreeze, MISSING sentinel).

**Major Changes:**

1. **Installation Guide** (`installation.md`):
   - Simplified just installation instructions (use package managers)
   - Removed optional dependencies section (minimal deps by design)
   - Cleaner setup instructions

2. **Quickstart Guide** (`quickstart.md`):
   - Update to new API: `Config()` + `.update()` pattern (no more `.load()`)
   - Show manual CLI override parsing (3-line pattern with ast.literal_eval)
   - Method chaining examples for cleaner code

3. **CLI Overrides** (`cli.md` - major rewrite):
   - Remove `Config.from_cli()`, `parse_override()` references
   - Show auto-detection pattern: `.update()` handles both files and overrides
   - Examples for argparse, Click, Typer, Fire
   - Manual override parsing with `parse_overrides()` for advanced use
   - Simplified mental model: just loop over args!

4. **Core User Guides**:
   - `basics.md`: Update all examples to `Config().update()` pattern
   - `operators.md`: Add composition decision flow diagram
   - `advanced.md`: Add frozen configs and MISSING sentinel sections
   - `schema-validation.md`: Document continuous validation and type coercion
   - `references.md`: Update API references

5. **Index Page** (`index.md`):
   - Update feature descriptions (continuous validation)
   - Modernize all code examples
   - Show new patterns throughout

6. **Examples Cleanup**:
   - Delete outdated examples: `simple.md`, `deep-learning.md`, `custom-classes.md`
   - Add new `quick-reference.md` with concise API overview

7. **MkDocs Config** (`mkdocs.yml`):
   - Remove examples section from navigation
   - Add quick-reference to user guide
   - Update structure for clearer organization

**Documentation Philosophy:**
- Show the simplest pattern first (Config().update())
- Encourage users to use their preferred CLI library
- Emphasize composition-by-default with explicit operators
- Highlight continuous validation benefits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@codecov
Copy link

codecov bot commented Nov 17, 2025

Workflow Fixes:
- Fix YAML syntax in check_pull_request_title.yml
- Remove problematic types parameter (not needed with custom subjectPattern)

Type Checking Fixes (66 errors resolved):
- Keep strict mypy flags enabled (disallow_any_generics, warn_unreachable)
- Add explicit type parameters throughout (dict[str, Any], list[Any], set[Any])
- Add type annotations to helper functions (_is_union_type, etc.)
- Fix PathLike type parameter (Union[str, os.PathLike[str]])
- Add proper type hints to levenshtein_distance and ensure_tuple
- Add type assertions for dataclass field types
- Handle false positive unreachable warnings with targeted type ignores

Files modified:
- schema.py, coercion.py: Type annotations and assertions
- config.py, loader.py, items.py: Dict/list/set type parameters
- preprocessor.py, operators.py, resolver.py: Type parameters
- utils/types.py, utils/misc.py, utils/module.py: Type fixes
- errors/suggestions.py: Levenshtein distance types

All 24 source files pass strict type checking.
@ibro45 ibro45 marked this pull request as ready for review November 17, 2025 02:13
@ibro45 ibro45 merged commit ead67d7 into main Nov 17, 2025
6 checks passed
@ibro45 ibro45 deleted the improve branch November 17, 2025 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants