Skip to content

refactor(api): decouple optional dependency imports and support minimal base installation - #13

Merged
MichalRedm merged 3 commits into
mainfrom
refactor/9-decouple-optional-dependencies
Oct 2, 2026
Merged

MichalRedm merged 3 commits into
mainfrom
refactor/9-decouple-optional-dependencies

Conversation

@MichalRedm

Copy link
Copy Markdown
Collaborator

Summary

  • Promotes river to core dependencies in pyproject.toml as it is the foundational streaming generator and drift descriptor engine for STRIDE.
  • Decouples optional dependency imports (umap-learn, shap, lime, pyclustering, hdbscan, tensorflow, matplotlib, seaborn, click) so import stride succeeds in a clean base environment without optional dependencies.
  • Enhances OptionalDependencyError with standardized, actionable installation guidance (pip install stride-xai[extra]).
  • Adds a comprehensive test suite in tests/test_minimal_install_import.py verifying clean minimal import, base execution, and proper OptionalDependencyError guardrails.

Motivation

Key Changes

1. Dependency Specifications & Error Handling

  • pyproject.toml: Moved "river" into core dependencies while retaining drift = ["river"] in [project.optional-dependencies].
  • src/stride/exceptions.py: Updated OptionalDependencyError to accept (package_name, feature_name, extra_name=None) and output actionable pip install hints.

2. Optional Import Decoupling

  • src/stride/common/__init__.py: Lazily imported UMAP in _create_reducer(), raising OptionalDependencyError with extra_name="clustering".
  • src/stride/xai/importance/methods.py: Lazily imported shap and lime within _calculate_shap and _calculate_lime, raising OptionalDependencyError with extra_name="xai".
  • src/stride/xai/clustering/xmeans.py: Lazily imported pyclustering in run_xmeans(), raising OptionalDependencyError with extra_name="clustering".
  • src/stride/xai/recurrence/methods.py: Removed unused top-level visualization imports and lazily imported hdbscan in cluster_windows(), raising OptionalDependencyError with extra_name="clustering".
  • src/stride/xai/recurrence/protree/metrics/compare.py: Removed stray icecream debug import.
  • src/stride/xai/boundary/ssnp.py & analysis.py: Guarded TensorFlow imports and raised OptionalDependencyError with extra_name="deeplearning" when TensorFlow is unavailable.
  • src/stride/plotting/stream.py & _renderers.py: Guarded matplotlib imports with from __future__ import annotations and runtime guard checking _HAS_MATPLOTLIB.
  • src/stride/xai/{clustering,importance,stats}/__init__.py: Guarded optional visualization imports with try/except ImportError to support minimal installations without matplotlib/seaborn.
  • src/stride/datasets/protree_data/__init__.py: Guarded click CLI import.

3. Automated Verification & Guardrail Tests

  • tests/test_minimal_install_import.py: Added 10 tests verifying isolated top-level import without optional packages, core model and drift estimator execution on base dependencies, and actionable OptionalDependencyError triggers for missing optional packages.

Verification

  • ruff check . passed with 0 errors
  • ruff format --check . passed cleanly
  • python -m unittest discover tests passed with 0 failures (22 tests executed)
  • Manual / runtime verification performed (optional, describe below):
    • Verified isolated minimal environment import simulation using mock.patch.dict('sys.modules', {'shap': None, 'lime': None, 'umap': None, 'tensorflow': None, 'pyclustering': None, 'hdbscan': None, 'matplotlib': None, 'seaborn': None}): import stride succeeded cleanly.

- Promote river to core dependencies in pyproject.toml as foundational streaming drift engine
- Enhance OptionalDependencyError to produce clear, actionable pip install extra suggestions
- Guard optional imports (umap-learn, shap, lime, pyclustering, hdbscan, tensorflow, matplotlib, seaborn, click) across core modules
- Add lazy import wrappers raising OptionalDependencyError on actual usage
… tests

- Validate clean top-level import of stride without optional packages in sys.modules
- Validate core estimators and analyzers execute on pure base dependencies
- Validate OptionalDependencyError triggers with actionable install hints for missing optional features
@MichalRedm
MichalRedm merged commit 3ee86b6 into main Oct 2, 2026
1 check passed
@MichalRedm
MichalRedm deleted the refactor/9-decouple-optional-dependencies branch October 2, 2026 10:56
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.

refactor: Decouple optional dependency imports and support minimal base installation

1 participant