v1.9.6 - CLI Options Module Refactoring (2025-12-29)#

What Changed?#

This release refactors the monolithic cli/options.py (770 lines) into a modular directory structure with individual option classes in separate files. All functionality is preserved through re-exports, ensuring zero breaking changes. This improves code maintainability and follows the Single Responsibility Principle.


What’s New#

CLI Options Modularization#

What it does: The large src/haniwers/v1/cli/options.py file (770 lines, 9 option classes) has been decomposed into a modular package structure:

src/haniwers/v1/cli/options/
├── __init__.py           # Re-exports all option classes for backward compatibility
├── config.py             # ConfigOptions (1 option: config)
├── device.py             # DeviceOptions (4 options: port, baudrate, timeout, device_label)
├── logger.py             # LoggerOptions (2 options: verbose, logfile)
├── output.py             # OutputOptions (3 options: workspace, filename_prefix, filename_suffix)
├── preprocess.py         # PreprocessOptions (2 options: interval, offset)
├── sampler.py            # SamplerOptions (6 options: label, events_per_file, number_of_files, stream_mode, mode, duration)
├── scan.py               # ScanOptions (2 options: nsteps, step)
├── testing.py            # TestingOptions (10 options: mock, label, load_from, random, events, speed, shuffle, jitter, loop, seed)
└── threshold.py          # ThresholdOptions (4 options: thresholds, suppress_threshold, max_retry, history)

How to use it: No changes needed! All imports continue to work exactly as before:

# Old way (still works):
from haniwers.v1.cli.options import DeviceOptions, OutputOptions, SamplerOptions

# CLI commands can use options the same way:
def my_command(
    port: Optional[str] = DeviceOptions.port,
    workspace: Optional[Path] = OutputOptions.workspace,
    label: Optional[str] = SamplerOptions.label,
) -> None:
    """My CLI command using common options."""
    pass

Benefits:

  • Improved Maintainability: Each option class in its own file (max 190 lines) instead of 770 lines total

  • Single Responsibility: Each module has one clear purpose

  • Better Organization: Related options are grouped logically

  • Easier Navigation: IDE can quickly locate option definitions

  • Future-Proof: Easy to extend with new option classes without bloating a single file

  • Backward Compatible: Existing imports continue to work without modification


Installation#

Quick Start#

# Get the release
git checkout v1.9.6

# Setup
task env:setup

# Run CLI
haniwers-v1 --help

What’s Different from the Last Version?#

✅ Added#

  • Modular cli/options/ directory structure with 9 individual option class modules

  • Comprehensive __init__.py that re-exports all option classes for backward compatibility

🔧 Changed#

  • Moved ConfigOptions to cli/options/config.py

  • Moved DeviceOptions to cli/options/device.py

  • Moved LoggerOptions to cli/options/logger.py

  • Moved OutputOptions to cli/options/output.py

  • Moved PreprocessOptions to cli/options/preprocess.py

  • Moved SamplerOptions to cli/options/sampler.py

  • Moved ScanOptions to cli/options/scan.py

  • Moved TestingOptions to cli/options/testing.py

  • Moved ThresholdOptions to cli/options/threshold.py

🐛 Fixed#

  • No bug fixes in this release


Is It Safe to Upgrade?#

Backward Compatible: ✅ Yes

  • All existing imports continue to work without modification

  • No CLI interface changes—purely internal code organization

  • All option definitions and behaviors unchanged

  • Re-exports from __init__.py ensure drop-in compatibility


Tests Passed#

  • ✅ Builds without errors

  • ✅ All unit tests passing (379 selected)

  • ✅ Module structure validated

  • ✅ Import re-exports verified

  • ✅ Pre-commit hooks passing (ruff format, YAML, etc.)


Release Details#

  • Date: 2025-12-29

  • Version: v1.9.6

  • Files Changed: 11 (9 new modules + __init__.py + deleted original options.py)

  • Commits:

    • 715631c: refactor(cli/options): extract ConfigOptions to separate module

    • 5599148: refactor(cli/options): extract DeviceOptions to separate module

    • 83e41a8: refactor(cli/options): extract OutputOptions to separate module

    • 0b6c8da: refactor(cli/options): extract SamplerOptions to separate module

    • 73541ee: refactor(cli/options): extract ThresholdOptions to separate module

    • 81b6543: refactor(cli/options): extract PreprocessOptions to separate module

    • 1d7907f: refactor(cli/options): extract ScanOptions to separate module

    • 56bd858: refactor(cli/options): extract TestingOptions to separate module

    • 82ada3f: refactor(cli/options): extract LoggerOptions to separate module

    • cb8702a: refactor(cli/options): create __init__.py to re-export all option classes

    • d5bce12: refactor(cli/options): remove original monolithic options.py file

    • bfafd91: bump: version 1.9.5 → 1.9.6


Next Steps#

  • Phase 2.1 (v1.9.7 planned): Decompose sampler.py (1,591 lines) into modular structure

    • Similar modular pattern as cli/options.py

    • Split into: _base.py, _reader.py, _writer.py, _iterators.py, _progress.py

    • Maintain backward compatibility through re-exports

  • Phase 2.2 (v1.9.8 planned): Decompose config/model.py (1,184 lines)

    • Split into: device.py, acquisition.py, threshold.py, haniwers.py

    • Unified export structure

  • Phase 3 (v1.10.0): Technical debt resolution

    • Fix failing integration tests

    • Resolve TODO comments with implementations

  • v1.11.0: Complete removal of deprecated DaqConfig and ScanConfig models

    • Removal timeline: Deprecation warnings added in v1.9.5, removal in v1.11.0

    • Users have v1.9.6 - v1.10.x to migrate configurations