Skip to content

Handle legacy fields in modify#6494

Open
snejus wants to merge 2 commits intomasterfrom
handle-legacy-fields-in-modify
Open

Handle legacy fields in modify#6494
snejus wants to merge 2 commits intomasterfrom
handle-legacy-fields-in-modify

Conversation

@snejus
Copy link
Copy Markdown
Member

@snejus snejus commented Apr 3, 2026

Handle legacy singular field names in modify

Fixes: #6483

The modify command now accepts legacy singular field names (genre, composer, lyricist, remixer, arranger) as assignment targets, automatically rewrites them to their plural multi-value equivalents, and emits a deprecation warning directing users to the correct names.

What changed

  • beets/util/deprecation.py: Two new constants — ALBUM_LIST_FIELD_BY_LEGACY_FIELD and ITEM_LIST_FIELD_BY_LEGACY_FIELD — act as a single source of truth for the legacy-to-plural field mappings. Previously these mappings were scattered across hooks.py.
  • beets/autotag/hooks.py: AlbumInfo and TrackInfo now reference the centralised constants instead of defining their own inline mappings.
  • beets/ui/commands/modify.py: modify_parse_args gains an is_album flag, selects the appropriate mapping, and — when a legacy field is detected — rewrites the key and warns the user via deprecate_for_user.
  • Tests: Existing modify_parse_args call-sites updated to pass is_album; new parametrised tests cover the rewrite and warning behaviour.

Impact

Users who run commands like beet modify genre="rock" will now get a working command plus a clear prompt to switch to genres="rock", rather than silently writing to a non-standard field or failing. No breaking change — purely additive compatibility layer.

@snejus snejus requested a review from a team as a code owner April 3, 2026 17:46
@snejus snejus linked an issue Apr 3, 2026 that may be closed by this pull request
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from da2d4bb to b41d349 Compare April 3, 2026 17:49
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.17%. Comparing base (06512c9) to head (03728f2).
⚠️ Report is 3 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6494      +/-   ##
==========================================
+ Coverage   70.16%   70.17%   +0.01%     
==========================================
  Files         147      147              
  Lines       18651    18660       +9     
  Branches     3039     3040       +1     
==========================================
+ Hits        13086    13095       +9     
  Misses       4923     4923              
  Partials      642      642              
Files with missing lines Coverage Δ
beets/autotag/hooks.py 98.85% <100.00%> (+<0.01%) ⬆️
beets/ui/commands/modify.py 94.28% <100.00%> (+0.53%) ⬆️
beets/util/deprecation.py 86.95% <100.00%> (+1.24%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@snejus snejus force-pushed the use-multi-value-remixers branch from 85969e8 to c77ea75 Compare April 3, 2026 17:56
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from b41d349 to 13f48d1 Compare April 3, 2026 17:57
@snejus snejus force-pushed the use-multi-value-remixers branch from c77ea75 to a95fea1 Compare April 3, 2026 18:13
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from 13f48d1 to 6eb483c Compare April 3, 2026 18:13
@snejus snejus requested a review from Copilot April 3, 2026 21:23
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

PR make beet modify accept old singular multi-value field names, then rewrite to new plural field names and warn user, so user no longer make wrong custom field by accident.

Changes:

  • Add central legacy->plural list field maps in beets/util/deprecation.py
  • Reuse those maps from autotag AlbumInfo / TrackInfo instead of inline maps
  • Update modify_parse_args to rewrite legacy assignment keys + emit user-facing deprecation warning; add tests + docs

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
beets/util/deprecation.py Add shared legacy singular → plural list-field mapping constants.
beets/autotag/hooks.py Switch Info subclasses to use shared mapping constants.
beets/ui/commands/modify.py Rewrite legacy assignment keys to plural fields + warn user.
test/ui/commands/test_modify.py Update call sites for new arg + add rewrite/warn tests.
test/autotag/test_hooks.py Stop using Info directly in legacy-field tests; use TrackInfo.
docs/reference/cli.rst Document legacy singular field support in modify.
docs/changelog.rst Add changelog entry for modify legacy-field rewrite behavior.

Comment on lines +100 to 107
list_field_by_legacy_field = (
ALBUM_LIST_FIELD_BY_LEGACY_FIELD
if is_album
else ITEM_LIST_FIELD_BY_LEGACY_FIELD
)
for arg in args:
if arg.endswith("!") and "=" not in arg and ":" not in arg:
dels.append(arg[:-1]) # Strip trailing !.
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

grug see docs say legacy singular fields (composer/lyricist/remixer/arranger) translate too. but here when is_album True you pick ALBUM_LIST_FIELD_BY_LEGACY_FIELD (only genre). so beet modify -a composer=... still make new composer flex field and not touch composers, so tag write still wrong. grug think modify_parse_args should use item legacy->list map even in album mode (or union maps) so album modify can still rewrite these fields when inherit push to items.

Suggested change
list_field_by_legacy_field = (
ALBUM_LIST_FIELD_BY_LEGACY_FIELD
if is_album
else ITEM_LIST_FIELD_BY_LEGACY_FIELD
)
for arg in args:
if arg.endswith("!") and "=" not in arg and ":" not in arg:
dels.append(arg[:-1]) # Strip trailing !.
list_field_by_legacy_field = dict(ITEM_LIST_FIELD_BY_LEGACY_FIELD)
if is_album:
list_field_by_legacy_field.update(ALBUM_LIST_FIELD_BY_LEGACY_FIELD)
for arg in args:
if arg.endswith("!") and "=" not in arg and ":" not in arg:
key = arg[:-1] # Strip trailing !.
if list_field := list_field_by_legacy_field.get(key):
deprecate_for_user(
log,
f"The '{key}' field",
f"'{list_field}' (separate values by '; ')",
)
key = list_field
dels.append(key)

Copilot uses AI. Check for mistakes.
IGNORED_FIELDS: ClassVar[set[str]] = {"data_url"}
MEDIA_FIELD_MAP: ClassVar[dict[str, str]] = {}
LIST_BY_LEGACY_FIELD: ClassVar[dict[str, str]] = {"genre": "genres"}
LIST_BY_LEGACY_FIELD: ClassVar[dict[str, str]]
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

grug see base Info declare LIST_BY_LEGACY_FIELD but no value. if someone ever make Info() and set any key, self.LIST_BY_LEGACY_FIELD lookup can crash with AttributeError. grug think set safe default (empty dict or genre->genres) on Info class so no surprise crash.

Suggested change
LIST_BY_LEGACY_FIELD: ClassVar[dict[str, str]]
LIST_BY_LEGACY_FIELD: ClassVar[dict[str, str]] = {}

Copilot uses AI. Check for mistakes.
@snejus snejus force-pushed the use-multi-value-remixers branch from a95fea1 to 753c398 Compare April 3, 2026 21:59
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from 6eb483c to 43e4469 Compare April 3, 2026 21:59
@snejus snejus force-pushed the use-multi-value-remixers branch from 753c398 to 809cbca Compare April 3, 2026 22:05
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from 43e4469 to b5a59b5 Compare April 3, 2026 22:05
@JOJ0 JOJ0 added the core Pull requests that modify the beets core `beets` label Apr 4, 2026
@snejus snejus force-pushed the use-multi-value-remixers branch from 809cbca to 392962e Compare April 4, 2026 12:27
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from b5a59b5 to 2427ad7 Compare April 4, 2026 12:31
@snejus snejus force-pushed the use-multi-value-remixers branch 3 times, most recently from 8997fa5 to 8c57b87 Compare April 5, 2026 08:15
Base automatically changed from use-multi-value-remixers to master April 5, 2026 08:21
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from 2427ad7 to 297bcc7 Compare April 5, 2026 08:36
@snejus snejus force-pushed the handle-legacy-fields-in-modify branch from 297bcc7 to 03728f2 Compare April 5, 2026 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Pull requests that modify the beets core `beets`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Modifying "genre" instead of "genres" fails silently

3 participants