# Dependency Audit Report: Optional Dependencies

**Date**: October 31, 2025
**Issue**: Verify that numpy, scipy, and matplotlib are properly optional dependencies

## Summary

[x] **All optional dependencies are properly implemented** after fixing `mmap_file.py`.

## Findings

### 1. NumPy Dependency [x] FIXED

**Status**: Now properly optional

**Issue Found**:

- `src/coremusic/audio/mmap_file.py` had unconditional `import numpy as np` at module level
- This caused `ImportError` when importing coremusic without numpy installed

**Fix Applied**:

```python
# Before (line 11):
import numpy as np

# After:
try:
    import numpy as np
    NUMPY_AVAILABLE = True
except ImportError:
    NUMPY_AVAILABLE = False
    np = None  # type: ignore
    if TYPE_CHECKING:
        import numpy as np
```

**Runtime Checks Added**:

- `MMapAudioFile.read_as_numpy()`: Raises helpful ImportError if numpy not available
- `MMapAudioFile.__getitem__()`: Raises helpful ImportError for array access without numpy

**Files Audited**:

- [x] `src/coremusic/objects.py` - Conditional import (already correct)
- [x] `src/coremusic/buffer_utils.py` - Function-level imports (lazy loading, correct)
- [x] `src/coremusic/audio/analysis.py` - Conditional import (already correct)
- [x] `src/coremusic/audio/slicing.py` - Conditional import (already correct)
- [x] `src/coremusic/audio/visualization.py` - Conditional import (already correct)
- [x] `src/coremusic/audio/utilities.py` - Conditional import (already correct)
- [x] `src/coremusic/audio/streaming.py` - Function-level imports (lazy loading, correct)
- [x] `src/coremusic/audio/async_io.py` - Conditional import (already correct)
- [x] `src/coremusic/audio/mmap_file.py` - **FIXED** - Now conditional

### 2. SciPy Dependency [x] CORRECT

**Status**: Properly optional (no issues found)

**Implementation**:

- `src/coremusic/utils/scipy.py` has conditional imports:

  ```python
  try:
      import scipy.signal
      import scipy.fft
      SCIPY_AVAILABLE = True
  except ImportError:
      SCIPY_AVAILABLE = False
  ```

- All scipy functionality is isolated in the utils.scipy module
- Module can be imported even without scipy installed
- Functions raise clear errors when called without scipy

**Files Checked**:

- [x] `src/coremusic/utils/scipy.py` - Conditional import
- [x] `src/coremusic/utils/__init__.py` - Safe module-level import

### 3. Matplotlib Dependency [x] CORRECT

**Status**: Properly optional (no issues found)

**Implementation**:

- All matplotlib imports are either:
  - Inside try/except blocks at module level
  - Inside functions (lazy loading)
- Visualization module handles missing matplotlib gracefully
- `MATPLOTLIB_AVAILABLE` flag exported for runtime checks

**Files Checked**:

- [x] `src/coremusic/audio/visualization.py` - Conditional import
- [x] `src/coremusic/utils/scipy.py` - Function-level imports (lazy loading)

## Verification Tests

### Test 1: Import Without Optional Dependencies

```python
# Block numpy, scipy, matplotlib
sys.modules['numpy'] = FakeModule('numpy')
sys.modules['scipy'] = FakeModule('scipy')
sys.modules['matplotlib'] = FakeModule('matplotlib')

import coremusic  # [x] Success
```

**Result**: [x] All imports successful

### Test 2: Core Functionality Without NumPy

```python
from coremusic import AudioFile, AudioQueue, AudioUnit  # [x] Success
import coremusic.capi as capi  # [x] Success
```

**Result**: [x] All core functionality available

### Test 3: Full Test Suite

```bash
make test
```

**Result**: [x] 1170 passed, 70 skipped (all tests passing)

## Dependency Configuration

### pyproject.toml

```toml
[project]
dependencies = []  # [x] No required dependencies beyond stdlib

[dependency-groups]
dev = [
    "numpy>=2.3.4",      # Optional - for array operations
    "scipy>=1.16.2",     # Optional - for signal processing
    # matplotlib not listed - completely optional
    "pytest>=8.4.2",     # Dev only
    ...
]
```

## Recommendations

### 1. Documentation [x] Already Clear

The README already documents optional dependencies well, but could add:

```markdown
## Optional Dependencies

- **NumPy** (optional): Required for array-based operations and memory-mapped file I/O
- **SciPy** (optional): Required for advanced signal processing utilities
- **Matplotlib** (optional): Required for audio visualization features

Install with optional dependencies:

```bash
pip install coremusic[audio]  # includes numpy
pip install coremusic[full]   # includes numpy, scipy, matplotlib
```
```


```text

### 2. Setup.py Extras (Future Enhancement)
Consider adding optional dependency groups to setup.py:

```python
extras_require = {
    'audio': ['numpy>=2.3.4'],
    'dsp': ['numpy>=2.3.4', 'scipy>=1.16.2'],
    'viz': ['numpy>=2.3.4', 'matplotlib>=3.5.0'],
    'full': ['numpy>=2.3.4', 'scipy>=1.16.2', 'matplotlib>=3.5.0'],
}
```

### 3. Runtime Feature Detection [x] Already Implemented

All modules properly export availability flags:

- `coremusic.NUMPY_AVAILABLE`
- `coremusic.audio.mmap_file.NUMPY_AVAILABLE`
- `coremusic.utils.scipy.SCIPY_AVAILABLE`
- `coremusic.audio.visualization.MATPLOTLIB_AVAILABLE`

## Conclusion

[x] **All optional dependencies are now properly implemented**

The package can be installed and used without numpy, scipy, or matplotlib. When optional dependencies are not available:

1. **Import succeeds** - Package always imports successfully
2. **Clear errors** - Functions that require optional deps raise helpful ImportError messages
3. **Feature flags** - Runtime detection via `*_AVAILABLE` flags
4. **Gradual degradation** - Core functionality works without optional deps

**Files Modified**: 1
**Tests Passing**: 1170/1170 (100%)
**Breaking Changes**: None
