mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2025-12-16 18:02:58 +08:00
Add comprehensive pip dependency conflict resolution framework as draft implementation. This is self-contained and does not affect existing ComfyUI Manager functionality. Key components: - pip_util.py with PipBatch class for policy-driven package management - Lazy-loaded policy system supporting base + user overrides - Multi-stage policy execution (uninstall → apply_first_match → apply_all_matches → restore) - Conditional policies based on platform, installed packages, and ComfyUI version - Comprehensive test suite covering edge cases, workflows, and platform scenarios - Design and implementation documentation Policy capabilities (draft): - Package replacement (e.g., PIL → Pillow, opencv-python → opencv-contrib-python) - Version pinning to prevent dependency conflicts - Dependency protection during installations - Platform-specific handling (Linux/Windows, GPU detection) - Pre-removal and post-restoration workflows Testing infrastructure: - Pytest-based test suite with isolated environments - Dependency analysis tools for conflict detection - Coverage for policy priority, edge cases, and environment recovery Status: Draft implementation complete, integration with manager workflows pending.
306 lines
8.4 KiB
Markdown
306 lines
8.4 KiB
Markdown
# pip_util Integration Tests
|
|
|
|
Real integration tests for `pip_util.py` using actual PyPI packages and pip operations.
|
|
|
|
## Overview
|
|
|
|
These tests use a **real isolated venv** to verify pip_util behavior with actual package installations, deletions, and version changes. No mocks - real pip operations only.
|
|
|
|
## Quick Start
|
|
|
|
### 1. Setup Test Environment
|
|
|
|
```bash
|
|
cd tests/common/pip_util
|
|
./setup_test_env.sh
|
|
```
|
|
|
|
This creates `test_venv/` with base packages:
|
|
- urllib3==1.26.15
|
|
- certifi==2023.7.22
|
|
- charset-normalizer==3.2.0
|
|
- colorama==0.4.6
|
|
- six==1.16.0
|
|
- attrs==23.1.0
|
|
- packaging==23.1
|
|
- pytest (latest)
|
|
|
|
### 2. Run Tests
|
|
|
|
```bash
|
|
# Run all integration tests
|
|
pytest -v --override-ini="addopts="
|
|
|
|
# Run specific test
|
|
pytest test_dependency_protection.py -v --override-ini="addopts="
|
|
|
|
# Run with markers
|
|
pytest -m integration -v --override-ini="addopts="
|
|
```
|
|
|
|
## Test Architecture
|
|
|
|
### Real venv Integration
|
|
|
|
- **No subprocess mocking** - uses real pip install/uninstall
|
|
- **Isolated test venv** - prevents system contamination
|
|
- **Automatic cleanup** - `reset_test_venv` fixture restores state after each test
|
|
|
|
### Test Fixtures
|
|
|
|
**venv Management**:
|
|
- `test_venv_path` - Path to test venv (session scope)
|
|
- `test_pip_cmd` - pip command for test venv
|
|
- `reset_test_venv` - Restore venv to initial state after each test
|
|
|
|
**Helpers**:
|
|
- `get_installed_packages()` - Get current venv packages
|
|
- `install_packages(*packages)` - Install packages in test venv
|
|
- `uninstall_packages(*packages)` - Uninstall packages in test venv
|
|
|
|
**Policy Configuration**:
|
|
- `temp_policy_dir` - Temporary directory for base policies
|
|
- `temp_user_policy_dir` - Temporary directory for user policies
|
|
- `mock_manager_util` - Mock manager_util paths to use temp dirs
|
|
- `mock_context` - Mock context paths to use temp dirs
|
|
|
|
## Test Scenarios
|
|
|
|
### Scenario 1: Dependency Version Protection
|
|
**File**: `test_dependency_protection.py::test_dependency_version_protection_with_pin`
|
|
|
|
**Initial State**:
|
|
```python
|
|
urllib3==1.26.15
|
|
certifi==2023.7.22
|
|
charset-normalizer==3.2.0
|
|
```
|
|
|
|
**Action**: Install `requests` with pin_dependencies policy
|
|
|
|
**Expected Result**:
|
|
```python
|
|
# Dependencies stay at old versions (protected by pin)
|
|
urllib3==1.26.15 # NOT upgraded to 2.x
|
|
certifi==2023.7.22 # NOT upgraded
|
|
charset-normalizer==3.2.0 # NOT upgraded
|
|
requests==2.31.0 # newly installed
|
|
```
|
|
|
|
### Scenario 2: Click-Colorama Dependency Chain
|
|
**File**: `test_dependency_protection.py::test_dependency_chain_with_click_colorama`
|
|
|
|
**Initial State**:
|
|
```python
|
|
colorama==0.4.6
|
|
```
|
|
|
|
**Action**: Install `click` with force_version + pin_dependencies
|
|
|
|
**Expected Result**:
|
|
```python
|
|
colorama==0.4.6 # PINNED
|
|
click==8.1.3 # FORCED to specific version
|
|
```
|
|
|
|
### Scenario 3: Package Deletion and Restore
|
|
**File**: `test_environment_recovery.py::test_package_deletion_and_restore`
|
|
|
|
**Initial State**:
|
|
```python
|
|
six==1.16.0
|
|
attrs==23.1.0
|
|
packaging==23.1
|
|
```
|
|
|
|
**Action**: Delete `six` → call `batch.ensure_installed()`
|
|
|
|
**Expected Result**:
|
|
```python
|
|
six==1.16.0 # RESTORED to required version
|
|
```
|
|
|
|
### Scenario 4: Version Change and Restore
|
|
**File**: `test_environment_recovery.py::test_version_change_and_restore`
|
|
|
|
**Initial State**:
|
|
```python
|
|
urllib3==1.26.15
|
|
```
|
|
|
|
**Action**: Upgrade `urllib3` to 2.1.0 → call `batch.ensure_installed()`
|
|
|
|
**Expected Result**:
|
|
```python
|
|
urllib3==1.26.15 # RESTORED to required version (downgraded)
|
|
```
|
|
|
|
## Test Categories
|
|
|
|
### Priority 1 (Essential) ✅ ALL PASSING
|
|
- ✅ Dependency version protection (enhanced with exact versions)
|
|
- ✅ Package deletion and restore (enhanced with exact versions)
|
|
- ✅ Version change and restore (enhanced with downgrade verification)
|
|
- ✅ Pin only affects specified packages ✨ NEW
|
|
- ✅ Major version jump prevention ✨ NEW
|
|
|
|
### Priority 2 (Important)
|
|
- ✅ Complex dependency chains (python-dateutil + six)
|
|
- ⏳ Full workflow integration (TODO: update to real venv)
|
|
- ⏳ Pin failure retry (TODO: update to real venv)
|
|
|
|
### Priority 3 (Edge Cases)
|
|
- ⏳ Platform conditions (TODO: update to real venv)
|
|
- ⏳ Policy priority (TODO: update to real venv)
|
|
- ⏳ Unit tests (no venv needed)
|
|
- ⏳ Edge cases (no venv needed)
|
|
|
|
## Package Selection
|
|
|
|
All test packages are **real PyPI packages < 200KB**:
|
|
|
|
| Package | Size | Version | Purpose |
|
|
|---------|------|---------|---------|
|
|
| **urllib3** | ~100KB | 1.26.15 | Protected dependency (prevent 2.x upgrade) |
|
|
| **certifi** | ~10KB | 2023.7.22 | SSL certificates (pinned) |
|
|
| **charset-normalizer** | ~46KB | 3.2.0 | Charset detection (pinned) |
|
|
| **requests** | ~100KB | 2.31.0 | Main package to install |
|
|
| **colorama** | ~25KB | 0.4.6 | Terminal colors (pinned) |
|
|
| **click** | ~90KB | 8.1.3 | CLI framework (forced version) |
|
|
| **six** | ~11KB | 1.16.0 | Python 2/3 compatibility (restore) |
|
|
| **attrs** | ~61KB | 23.1.0 | Bystander package |
|
|
| **packaging** | ~48KB | 23.1 | Bystander package |
|
|
|
|
## Cleanup
|
|
|
|
### Manual Cleanup
|
|
```bash
|
|
# Remove test venv
|
|
rm -rf test_venv/
|
|
|
|
# Recreate fresh venv
|
|
./setup_test_env.sh
|
|
```
|
|
|
|
### Automatic Cleanup
|
|
The `reset_test_venv` fixture automatically:
|
|
1. Records initial package state
|
|
2. Runs test
|
|
3. Removes all packages (except pip/setuptools/wheel)
|
|
4. Reinstalls initial packages
|
|
|
|
## Troubleshooting
|
|
|
|
### Error: "Test venv not found"
|
|
**Solution**: Run `./setup_test_env.sh`
|
|
|
|
### Error: "Package not installed in initial state"
|
|
**Solution**: Check `requirements-test-base.txt` and recreate venv
|
|
|
|
### Tests are slow
|
|
**Reason**: Real pip operations take 2-3 seconds per test
|
|
**This is expected** - we're doing actual pip install/uninstall
|
|
|
|
## Implementation Details
|
|
|
|
### How reset_test_venv Works
|
|
|
|
```python
|
|
@pytest.fixture
|
|
def reset_test_venv(test_pip_cmd):
|
|
# 1. Record initial state
|
|
initial = subprocess.run(test_pip_cmd + ["freeze"], ...)
|
|
|
|
yield # Run test here
|
|
|
|
# 2. Remove all packages
|
|
current = subprocess.run(test_pip_cmd + ["freeze"], ...)
|
|
subprocess.run(test_pip_cmd + ["uninstall", "-y", ...], ...)
|
|
|
|
# 3. Restore initial state
|
|
subprocess.run(test_pip_cmd + ["install", "-r", initial], ...)
|
|
```
|
|
|
|
### How make_pip_cmd is Patched
|
|
|
|
```python
|
|
@pytest.fixture(autouse=True)
|
|
def setup_pip_util(monkeypatch, test_pip_cmd):
|
|
from comfyui_manager.common import pip_util
|
|
|
|
def make_test_pip_cmd(args: List[str]) -> List[str]:
|
|
return test_pip_cmd + args # Use test venv pip
|
|
|
|
monkeypatch.setattr(
|
|
pip_util.manager_util,
|
|
"make_pip_cmd",
|
|
make_test_pip_cmd
|
|
)
|
|
```
|
|
|
|
## Dependency Analysis Tool
|
|
|
|
Use `analyze_dependencies.py` to examine package dependencies before adding new tests:
|
|
|
|
```bash
|
|
# Analyze specific package
|
|
python analyze_dependencies.py requests
|
|
|
|
# Analyze all test packages
|
|
python analyze_dependencies.py --all
|
|
|
|
# Show current environment
|
|
python analyze_dependencies.py --env
|
|
```
|
|
|
|
**Output includes**:
|
|
- Latest available versions
|
|
- Dependencies that would be installed
|
|
- Version upgrades that would occur
|
|
- Impact of pin constraints
|
|
|
|
**Example output**:
|
|
```
|
|
📦 Latest version: 2.32.5
|
|
🔍 Scenario A: Install without constraints
|
|
Would install 5 packages:
|
|
• urllib3 1.26.15 → 2.5.0 ⚠️ UPGRADE
|
|
|
|
🔍 Scenario B: Install with pin constraints
|
|
Would install 5 packages:
|
|
• urllib3 1.26.15 (no change) 📌 PINNED
|
|
|
|
✅ Pin prevented 2 upgrade(s)
|
|
```
|
|
|
|
## Test Statistics
|
|
|
|
**Current Status**: 6 tests, 100% passing
|
|
|
|
```
|
|
test_dependency_version_protection_with_pin PASSED (2.28s)
|
|
test_dependency_chain_with_six_pin PASSED (2.00s)
|
|
test_pin_only_affects_specified_packages PASSED (2.25s) ✨ NEW
|
|
test_major_version_jump_prevention PASSED (3.53s) ✨ NEW
|
|
test_package_deletion_and_restore PASSED (2.25s)
|
|
test_version_change_and_restore PASSED (2.24s)
|
|
|
|
Total: 14.10s
|
|
```
|
|
|
|
**Test Improvements**:
|
|
- ✅ All tests verify exact version numbers
|
|
- ✅ All tests reference DEPENDENCY_TREE_CONTEXT.md
|
|
- ✅ Added 2 new critical tests (pin selectivity, major version prevention)
|
|
- ✅ Enhanced error messages with expected vs actual values
|
|
|
|
## Design Documents
|
|
|
|
- **TEST_IMPROVEMENTS.md** - Summary of test enhancements based on dependency context
|
|
- **DEPENDENCY_TREE_CONTEXT.md** - Verified dependency trees for all test packages
|
|
- **DEPENDENCY_ANALYSIS.md** - Dependency analysis methodology
|
|
- **CONTEXT_FILES_GUIDE.md** - Guide for using context files
|
|
- **TEST_SCENARIOS.md** - Detailed test scenario specifications
|
|
- **pip_util.test-design.md** - Test design and architecture
|
|
- **pip_util.design.en.md** - pip_util design documentation
|