fix: use lenient conflict handling for dependency resolution
Instead of failing with 409 on version conflicts, use "first version wins" strategy. This allows resolution to succeed for complex dependency trees like tensorflow where transitive dependencies may have overlapping but not identical version requirements. The resolver now: - Checks if an already-resolved version satisfies a new constraint - If yes, reuses the existing version - If no, logs the mismatch and uses the first-encountered version This matches pip's behavior of picking a working version rather than failing on theoretical conflicts.
This commit is contained in:
@@ -873,10 +873,14 @@ class TestCircularDependencyDetection:
|
||||
|
||||
|
||||
class TestConflictDetection:
|
||||
"""Tests for #81: Dependency Conflict Detection and Reporting"""
|
||||
"""Tests for dependency conflict handling.
|
||||
|
||||
The resolver uses "first version wins" strategy for version conflicts,
|
||||
allowing resolution to succeed rather than failing with an error.
|
||||
"""
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_detect_version_conflict(
|
||||
def test_version_conflict_uses_first_version(
|
||||
self, integration_client, test_project, unique_test_id
|
||||
):
|
||||
"""Test conflict when two deps require different versions of same package."""
|
||||
@@ -968,21 +972,19 @@ class TestConflictDetection:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Try to resolve app - should report conflict
|
||||
# Try to resolve app - with lenient conflict handling, this should succeed
|
||||
# The resolver uses "first version wins" strategy for conflicting versions
|
||||
response = integration_client.get(
|
||||
f"/api/v1/project/{test_project}/{pkg_app}/+/1.0.0/resolve"
|
||||
)
|
||||
assert response.status_code == 409
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
# Error details are nested in "detail" for HTTPException
|
||||
detail = data.get("detail", data)
|
||||
assert detail.get("error") == "dependency_conflict"
|
||||
assert len(detail.get("conflicts", [])) > 0
|
||||
|
||||
# Verify conflict details
|
||||
conflict = detail["conflicts"][0]
|
||||
assert conflict["package"] == pkg_common
|
||||
assert len(conflict["requirements"]) == 2
|
||||
# Resolution should succeed with first-encountered version of common
|
||||
assert data["artifact_count"] >= 1
|
||||
# Find the common package in resolved list
|
||||
common_resolved = [r for r in data["resolved"] if r["package"] == pkg_common]
|
||||
assert len(common_resolved) == 1 # Only one version should be included
|
||||
|
||||
finally:
|
||||
for pkg in [pkg_app, pkg_lib_a, pkg_lib_b, pkg_common]:
|
||||
|
||||
Reference in New Issue
Block a user