@@ -441,6 +441,39 @@ def _resolve_and_update_lockfile(
441
441
return upgrade_lock_data
442
442
443
443
444
+ def _clean_unused_dependencies (
445
+ project , lockfile , category , full_lock_resolution , original_lockfile
446
+ ):
447
+ """
448
+ Remove dependencies that are no longer needed after an upgrade.
449
+
450
+ Args:
451
+ project: The project instance
452
+ lockfile: The current lockfile being built
453
+ category: The category to clean (e.g., 'default', 'develop')
454
+ full_lock_resolution: The complete resolution of dependencies
455
+ original_lockfile: The original lockfile before the upgrade
456
+ """
457
+ if category not in lockfile or category not in original_lockfile :
458
+ return
459
+
460
+ # Get the set of packages in the new resolution
461
+ resolved_packages = set (full_lock_resolution .keys ())
462
+
463
+ # Get the set of packages in the original lockfile for this category
464
+ original_packages = set (original_lockfile [category ].keys ())
465
+
466
+ # Find packages that were in the original lockfile but not in the new resolution
467
+ unused_packages = original_packages - resolved_packages
468
+
469
+ # Remove unused packages from the lockfile
470
+ for package_name in unused_packages :
471
+ if package_name in lockfile [category ]:
472
+ if project .s .is_verbose ():
473
+ err .print (f"Removing unused dependency: { package_name } " )
474
+ del lockfile [category ][package_name ]
475
+
476
+
444
477
def upgrade (
445
478
project ,
446
479
pre = False ,
@@ -456,6 +489,11 @@ def upgrade(
456
489
):
457
490
"""Enhanced upgrade command with dependency conflict detection."""
458
491
lockfile = project .lockfile ()
492
+ # Store the original lockfile for comparison later
493
+ original_lockfile = {
494
+ k : v .copy () if isinstance (v , dict ) else v for k , v in lockfile .items ()
495
+ }
496
+
459
497
if not pre :
460
498
pre = project .settings .get ("allow_prereleases" )
461
499
@@ -504,6 +542,8 @@ def upgrade(
504
542
505
543
# Process each category
506
544
requested_packages = defaultdict (dict )
545
+ category_resolutions = {}
546
+
507
547
for category in categories :
508
548
pipfile_category = get_pipfile_category_using_lockfile_section (category )
509
549
@@ -528,7 +568,7 @@ def upgrade(
528
568
)
529
569
530
570
# Resolve dependencies and update lockfile
531
- _resolve_and_update_lockfile (
571
+ upgrade_lock_data = _resolve_and_update_lockfile (
532
572
project ,
533
573
requested_packages ,
534
574
pipfile_category ,
@@ -540,6 +580,26 @@ def upgrade(
540
580
lockfile ,
541
581
)
542
582
583
+ # Store the full resolution for this category
584
+ if upgrade_lock_data :
585
+ complete_packages = project .parsed_pipfile .get (pipfile_category , {})
586
+ full_lock_resolution = venv_resolve_deps (
587
+ complete_packages ,
588
+ which = project ._which ,
589
+ project = project ,
590
+ lockfile = {},
591
+ pipfile_category = pipfile_category ,
592
+ pre = pre ,
593
+ allow_global = system ,
594
+ pypi_mirror = pypi_mirror ,
595
+ )
596
+ category_resolutions [category ] = full_lock_resolution
597
+
598
+ # Clean up unused dependencies
599
+ _clean_unused_dependencies (
600
+ project , lockfile , category , full_lock_resolution , original_lockfile
601
+ )
602
+
543
603
# Reset package args for next category if needed
544
604
if not has_package_args :
545
605
package_args = []
0 commit comments