From 044a6c1d2773b02ba612413ad54c18293d6e53fd Mon Sep 17 00:00:00 2001 From: Mondo Diaz Date: Fri, 30 Jan 2026 17:43:49 -0600 Subject: [PATCH] Fix duplicate dependency constraint causing 500 errors - Deduplicate dependencies by package name before inserting - Some packages (like anyio) list the same dep (trio) multiple times with different version constraints for different extras - The unique constraint on (artifact_id, project, package) rejected these - Also removed debug logging from dependencies.py --- backend/app/dependencies.py | 17 ----------------- backend/app/pypi_proxy.py | 10 +++++++++- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/backend/app/dependencies.py b/backend/app/dependencies.py index 61150e8..24569fe 100644 --- a/backend/app/dependencies.py +++ b/backend/app/dependencies.py @@ -10,11 +10,8 @@ Handles: - Conflict detection """ -import logging import re import yaml - -logger = logging.getLogger(__name__) from typing import List, Dict, Any, Optional, Set, Tuple from sqlalchemy.orm import Session from sqlalchemy import and_ @@ -435,8 +432,6 @@ def _resolve_dependency_to_artifact( if not package: return None - logger.info(f"_resolve_dependency_to_artifact: package_id={package.id}, version={version!r}, tag={tag!r}") - if version: # Check if this is a version constraint (>=, <, etc.) or exact version if _is_version_constraint(version): @@ -454,7 +449,6 @@ def _resolve_dependency_to_artifact( Artifact.id == pkg_version.artifact_id ).first() if artifact: - logger.info(f"_resolve_dependency_to_artifact: found by version {version}") return (artifact.id, version, artifact.size) # Also check if there's a tag with this exact name @@ -462,7 +456,6 @@ def _resolve_dependency_to_artifact( Tag.package_id == package.id, Tag.name == version, ).first() - logger.info(f"_resolve_dependency_to_artifact: tag lookup by version name, found={tag_record is not None}") if tag_record: artifact = db.query(Artifact).filter( Artifact.id == tag_record.artifact_id @@ -476,7 +469,6 @@ def _resolve_dependency_to_artifact( Tag.package_id == package.id, Tag.name == tag, ).first() - logger.info(f"_resolve_dependency_to_artifact: tag lookup by tag param, found={tag_record is not None}") if tag_record: artifact = db.query(Artifact).filter( Artifact.id == tag_record.artifact_id @@ -484,9 +476,6 @@ def _resolve_dependency_to_artifact( if artifact: return (artifact.id, tag, artifact.size) - # Debug: list actual tags - sample_tags = db.query(Tag).filter(Tag.package_id == package.id).limit(3).all() - logger.info(f"_resolve_dependency_to_artifact: NOT FOUND. Sample tags: {[t.name for t in sample_tags]}") return None @@ -670,12 +659,9 @@ def resolve_dependencies( CircularDependencyError: If circular dependencies are detected DependencyConflictError: If conflicting versions are required """ - logger.info(f"resolve_dependencies: project={project_name}, package={package_name}, ref={ref!r}") - # Resolve the initial artifact project = db.query(Project).filter(Project.name == project_name).first() if not project: - logger.warning(f"resolve_dependencies: project '{project_name}' not found") raise DependencyNotFoundError(project_name, package_name, ref) package = db.query(Package).filter( @@ -683,11 +669,8 @@ def resolve_dependencies( Package.name == package_name, ).first() if not package: - logger.warning(f"resolve_dependencies: package '{package_name}' not found in project '{project_name}'") raise DependencyNotFoundError(project_name, package_name, ref) - logger.info(f"resolve_dependencies: found package id={package.id}") - # Try to find artifact by tag or version resolved = _resolve_dependency_to_artifact( db, project_name, package_name, ref, ref diff --git a/backend/app/pypi_proxy.py b/backend/app/pypi_proxy.py index 6aec04f..699c600 100644 --- a/backend/app/pypi_proxy.py +++ b/backend/app/pypi_proxy.py @@ -737,8 +737,16 @@ async def pypi_download_file( # Extract and store dependencies dependencies = _extract_dependencies(content, filename) if dependencies: - logger.info(f"PyPI proxy: extracted {len(dependencies)} dependencies from {filename}") + # Deduplicate dependencies by package name (keep first occurrence) + seen_packages = set() + unique_deps = [] for dep_name, dep_version in dependencies: + if dep_name not in seen_packages: + seen_packages.add(dep_name) + unique_deps.append((dep_name, dep_version)) + + logger.info(f"PyPI proxy: extracted {len(unique_deps)} dependencies from {filename} (deduped from {len(dependencies)})") + for dep_name, dep_version in unique_deps: # Check if this dependency already exists for this artifact existing_dep = db.query(ArtifactDependency).filter( ArtifactDependency.artifact_id == sha256,