Skip to content

importer: improve handling of duplicates#6702

Open
snejus wants to merge 9 commits into
masterfrom
improve-import-task-duplicates-handling
Open

importer: improve handling of duplicates#6702
snejus wants to merge 9 commits into
masterfrom
improve-import-task-duplicates-handling

Conversation

@snejus
Copy link
Copy Markdown
Member

@snejus snejus commented Jun 3, 2026

This change centralizes duplicate handling in the import pipeline.

  • ImportTask now carries a single duplicate_action state instead of separate duplicate flags, so duplicate decisions are represented in one place.
  • ImportSession.get_duplicate_action() becomes the shared entry point for resolving the configured duplicate policy.
  • TerminalImportSession now only prompts the user when the configured action is ASK; otherwise it reuses the shared session logic.
  • Duplicate resolution in beets/importer/stages.py is simplified to call the session API instead of re-implementing config lookup and branching.

High-level impact

  • Makes duplicate behavior more consistent across importer stages and UI sessions.
  • Reduces duplicated logic between core importer flow, terminal prompting, and test fixtures.
  • Simplifies future changes to duplicate handling because policy resolution now lives behind one session-level interface.
  • Cleans up tests to use real config-driven duplicate behavior instead of custom fixture-only overrides.

Copilot AI review requested due to automatic review settings June 3, 2026 15:49
@snejus snejus requested a review from a team as a code owner June 3, 2026 15:49
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

❌ Patch coverage is 76.81159% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.66%. Comparing base (0786ea8) to head (252e414).

Files with missing lines Patch % Lines
beets/ui/commands/import_/session.py 30.00% 14 Missing ⚠️
beets/importer/actions.py 93.54% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6702      +/-   ##
==========================================
- Coverage   72.77%   72.66%   -0.12%     
==========================================
  Files         162      163       +1     
  Lines       20810    20825      +15     
  Branches     3294     3284      -10     
==========================================
- Hits        15145    15133      -12     
- Misses       4938     4972      +34     
+ Partials      727      720       -7     
Files with missing lines Coverage Δ
beets/importer/__init__.py 100.00% <100.00%> (ø)
beets/importer/session.py 93.10% <100.00%> (-1.27%) ⬇️
beets/importer/stages.py 93.12% <100.00%> (+4.36%) ⬆️
beets/importer/tasks.py 90.99% <100.00%> (-0.15%) ⬇️
beets/library/__init__.py 100.00% <100.00%> (ø)
beets/library/models.py 87.38% <100.00%> (+0.01%) ⬆️
beets/importer/actions.py 93.54% <93.54%> (ø)
beets/ui/commands/import_/session.py 61.33% <30.00%> (+3.00%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

snejus added 8 commits June 3, 2026 16:53
- Store duplicate decisions on `ImportTask.duplicate_action` instead of
  separate `should_remove_duplicates` and `should_merge_duplicates`
  flags.
- Update duplicate resolution, stage branching, and duplicate logging to
  read from the enum value consistently.
- This centralizes duplicate action state and prevents behavior drift
  across importer flow.
- Move configured duplicate-action lookup into
  ImportSession.get_duplicate_action.
- Let TerminalImportSession prompt only when the configured action is ASK.
- Simplify duplicate stage flow and remove obsolete fixture override logic.
@snejus snejus force-pushed the improve-import-task-duplicates-handling branch from cd6dfe9 to 252e414 Compare June 3, 2026 15:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

grug see PR want make duplicate handling live in one place (session API) so stages and UI stop copy-paste policy logic. this fit importer pipeline: one config decision, then task carry that decision.

Changes:

  • move duplicate policy resolution behind ImportSession.get_duplicate_action() and store result on ImportTask.
  • simplify duplicate resolution in importer stages to call session API.
  • update tests/fixtures to drive duplicate behavior via config instead of fixture-only flags.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/test_importer.py update duplicate tests to set import.duplicate_action via config.
beets/ui/commands/import_/session.py make terminal session prompt only when policy is ASK; refactor duplicate prompt output.
beets/test/helper.py adjust importer test helper defaults for new duplicate behavior (but current diff sets wrong config key).
beets/library/models.py add AnyLibModel typing helper.
beets/library/__init__.py export AnyLibModel.
beets/importer/tasks.py add duplicate_action state to task; update skip logic to account for duplicate skip.
beets/importer/stages.py simplify duplicate resolution to use session API and duplicate_action.
beets/importer/session.py add get_duplicate_action() default config lookup; update logging for duplicate replace.
beets/importer/__init__.py re-export DuplicateAction.
.git-blame-ignore-revs add ignore rev entry.

Comment thread beets/test/helper.py
Comment on lines 521 to 525
"resume": False,
"singletons": False,
"timid": True,
"import": {"duplicate_action": "remove"},
}
Comment on lines +152 to +156
def report_item_summary(self, items: list[Item], is_album: bool) -> None:
ui.print_(f"Old: {summarize_items(items, not is_album)}")
if self.config["duplicate_verbose_prompt"].get(bool):
for dup in items:
print(f" {dup}")
sel = ui.input_options(
("Skip new", "Keep all", "Remove old", "Merge all")
)
self.report_item_summary(task.imported_items(), is_album)
Comment thread beets/importer/stages.py
Comment on lines +345 to 349
task.duplicate_action = session.get_duplicate_action(
task, found_duplicates
)
log.debug("default action for duplicates: {}", duplicate_action)

if duplicate_action == "s":
# Skip new.
task.set_choice(Action.SKIP)
elif duplicate_action == "k":
# Keep both. Do nothing; leave the choice intact.
pass
elif duplicate_action == "r":
# Remove old.
task.should_remove_duplicates = True
elif duplicate_action == "m":
# Merge duplicates together
task.should_merge_duplicates = True
else:
# No default action set; ask the session.
session.resolve_duplicate(task, found_duplicates)

session.log_choice(task, True)
Comment thread beets/importer/tasks.py
Comment thread beets/importer/__init__.py
Comment thread beets/importer/session.py
Comment thread beets/importer/stages.py
@semohr semohr self-assigned this Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants