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
This commit is contained in:
@@ -10,11 +10,8 @@ Handles:
|
|||||||
- Conflict detection
|
- Conflict detection
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
|
||||||
import re
|
import re
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
from typing import List, Dict, Any, Optional, Set, Tuple
|
from typing import List, Dict, Any, Optional, Set, Tuple
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
@@ -435,8 +432,6 @@ def _resolve_dependency_to_artifact(
|
|||||||
if not package:
|
if not package:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.info(f"_resolve_dependency_to_artifact: package_id={package.id}, version={version!r}, tag={tag!r}")
|
|
||||||
|
|
||||||
if version:
|
if version:
|
||||||
# Check if this is a version constraint (>=, <, etc.) or exact version
|
# Check if this is a version constraint (>=, <, etc.) or exact version
|
||||||
if _is_version_constraint(version):
|
if _is_version_constraint(version):
|
||||||
@@ -454,7 +449,6 @@ def _resolve_dependency_to_artifact(
|
|||||||
Artifact.id == pkg_version.artifact_id
|
Artifact.id == pkg_version.artifact_id
|
||||||
).first()
|
).first()
|
||||||
if artifact:
|
if artifact:
|
||||||
logger.info(f"_resolve_dependency_to_artifact: found by version {version}")
|
|
||||||
return (artifact.id, version, artifact.size)
|
return (artifact.id, version, artifact.size)
|
||||||
|
|
||||||
# Also check if there's a tag with this exact name
|
# 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.package_id == package.id,
|
||||||
Tag.name == version,
|
Tag.name == version,
|
||||||
).first()
|
).first()
|
||||||
logger.info(f"_resolve_dependency_to_artifact: tag lookup by version name, found={tag_record is not None}")
|
|
||||||
if tag_record:
|
if tag_record:
|
||||||
artifact = db.query(Artifact).filter(
|
artifact = db.query(Artifact).filter(
|
||||||
Artifact.id == tag_record.artifact_id
|
Artifact.id == tag_record.artifact_id
|
||||||
@@ -476,7 +469,6 @@ def _resolve_dependency_to_artifact(
|
|||||||
Tag.package_id == package.id,
|
Tag.package_id == package.id,
|
||||||
Tag.name == tag,
|
Tag.name == tag,
|
||||||
).first()
|
).first()
|
||||||
logger.info(f"_resolve_dependency_to_artifact: tag lookup by tag param, found={tag_record is not None}")
|
|
||||||
if tag_record:
|
if tag_record:
|
||||||
artifact = db.query(Artifact).filter(
|
artifact = db.query(Artifact).filter(
|
||||||
Artifact.id == tag_record.artifact_id
|
Artifact.id == tag_record.artifact_id
|
||||||
@@ -484,9 +476,6 @@ def _resolve_dependency_to_artifact(
|
|||||||
if artifact:
|
if artifact:
|
||||||
return (artifact.id, tag, artifact.size)
|
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
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -670,12 +659,9 @@ def resolve_dependencies(
|
|||||||
CircularDependencyError: If circular dependencies are detected
|
CircularDependencyError: If circular dependencies are detected
|
||||||
DependencyConflictError: If conflicting versions are required
|
DependencyConflictError: If conflicting versions are required
|
||||||
"""
|
"""
|
||||||
logger.info(f"resolve_dependencies: project={project_name}, package={package_name}, ref={ref!r}")
|
|
||||||
|
|
||||||
# Resolve the initial artifact
|
# Resolve the initial artifact
|
||||||
project = db.query(Project).filter(Project.name == project_name).first()
|
project = db.query(Project).filter(Project.name == project_name).first()
|
||||||
if not project:
|
if not project:
|
||||||
logger.warning(f"resolve_dependencies: project '{project_name}' not found")
|
|
||||||
raise DependencyNotFoundError(project_name, package_name, ref)
|
raise DependencyNotFoundError(project_name, package_name, ref)
|
||||||
|
|
||||||
package = db.query(Package).filter(
|
package = db.query(Package).filter(
|
||||||
@@ -683,11 +669,8 @@ def resolve_dependencies(
|
|||||||
Package.name == package_name,
|
Package.name == package_name,
|
||||||
).first()
|
).first()
|
||||||
if not package:
|
if not package:
|
||||||
logger.warning(f"resolve_dependencies: package '{package_name}' not found in project '{project_name}'")
|
|
||||||
raise DependencyNotFoundError(project_name, package_name, ref)
|
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
|
# Try to find artifact by tag or version
|
||||||
resolved = _resolve_dependency_to_artifact(
|
resolved = _resolve_dependency_to_artifact(
|
||||||
db, project_name, package_name, ref, ref
|
db, project_name, package_name, ref, ref
|
||||||
|
|||||||
@@ -737,8 +737,16 @@ async def pypi_download_file(
|
|||||||
# Extract and store dependencies
|
# Extract and store dependencies
|
||||||
dependencies = _extract_dependencies(content, filename)
|
dependencies = _extract_dependencies(content, filename)
|
||||||
if dependencies:
|
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:
|
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
|
# Check if this dependency already exists for this artifact
|
||||||
existing_dep = db.query(ArtifactDependency).filter(
|
existing_dep = db.query(ArtifactDependency).filter(
|
||||||
ArtifactDependency.artifact_id == sha256,
|
ArtifactDependency.artifact_id == sha256,
|
||||||
|
|||||||
Reference in New Issue
Block a user