diff --git a/backend/app/registry_client.py b/backend/app/registry_client.py index df66139..f6b07d5 100644 --- a/backend/app/registry_client.py +++ b/backend/app/registry_client.py @@ -269,8 +269,18 @@ class PyPIRegistryClient(RegistryClient): return None # Parse constraint + # If constraint looks like a bare version (no operator), treat as exact match + # e.g., "2025.10.5" -> "==2025.10.5" + effective_constraint = constraint + if constraint and constraint[0].isdigit(): + effective_constraint = f"=={constraint}" + logger.debug( + f"Bare version '{constraint}' for {normalized}, " + f"treating as exact match '{effective_constraint}'" + ) + try: - specifier = SpecifierSet(constraint) + specifier = SpecifierSet(effective_constraint) except InvalidSpecifier: # Invalid constraint - treat as wildcard logger.warning( diff --git a/backend/tests/unit/test_registry_client.py b/backend/tests/unit/test_registry_client.py index 1938d08..045effc 100644 --- a/backend/tests/unit/test_registry_client.py +++ b/backend/tests/unit/test_registry_client.py @@ -176,6 +176,42 @@ class TestPyPIRegistryClient: assert result is None + @pytest.mark.asyncio + async def test_resolve_constraint_bare_version(self, client, mock_http_client): + """Test resolving bare version string as exact match.""" + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + "info": {"version": "2.0.0"}, + "releases": { + "1.0.0": [ + { + "packagetype": "bdist_wheel", + "url": "https://files.pythonhosted.org/test-1.0.0.whl", + "filename": "test-1.0.0.whl", + "digests": {"sha256": "abc123"}, + "size": 1000, + } + ], + "2.0.0": [ + { + "packagetype": "bdist_wheel", + "url": "https://files.pythonhosted.org/test-2.0.0.whl", + "filename": "test-2.0.0.whl", + "digests": {"sha256": "def456"}, + "size": 2000, + } + ], + }, + } + mock_http_client.get.return_value = mock_response + + # Bare version "1.0.0" should resolve to exactly 1.0.0, not latest + result = await client.resolve_constraint("test-package", "1.0.0") + + assert result is not None + assert result.version == "1.0.0" + class TestVersionInfo: """Tests for VersionInfo dataclass."""