Track path formats not expanding in `set_fields` during import
- Dominant language
- Python
- Stars
- 15.7k
- Forks
- 2.1k
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 31
Description
When importing or re-importing albums I use the `set_fields` option to format incoming field metadata -- in my case using the `beets-titlecase` plugin. I would expect my configuration to format the `artist` and `title` fields using the `%tcp{}` function, but instead they are not expanded and written as `$Title` and `$Artist_diff`.
Disabling plugins completely prevents, the issue, but also negates the value of using this software for me. Disabling `bandcamp convert deezer discogs spotify replaygain web` specifically also prevents the issue, but I haven't been able to figure out why.
### Problem
Running this command in verbose (`-vv`) mode:
```sh
$ beet -vv /downloads/!!!\ -\ Let\ It\ Be\ Blue\ \(2022\)\ -\ WEB\ V0/
```
Led to this problem:
```
Should be imported as `/music/!!! - (2002) Let It Be Blue [VBR V0]/01. Normal People.mp3...` but is instead imported as `/music/!!! - (2002) Let It Be Blue [VBR V0]/01. $Title ($Artist_feat).mp3...
```
### Setup
* OS: Alpine Linux
* Python version: 3.10
* beets version: 2.2.0
* Turning off plugins made problem go away (yes/no): See note above
My configuration (output of `beet config`) is:
```yaml
album_fields:
mp3_info: |
import re
m = items[0].get('bitrate_mode', '')
s = re.sub('b|vbr-new|vbr-old|-| ', '', items[0].get('encoder_settings', ''))
if m == '':
m = 'CBR'
if not all(item.bitrate == items[0].bitrate for item in items):
m = 'VBR'
if 'preset' in s:
s = re.sub('altpreset|preset', 'AP', s)
s = s.replace('extreme', 'E').replace('insane', 'I').replace('standard', 'S')
if s == '':
if m == 'CBR':
s = items[0].get('bitrate', 0) // 1000
else:
t = 0
for item in items:
t += item.bitrate
s = t // len(items) // 1000
return ' '.join(filter(None, [m,str(s)]))
albumtypes:
bracket: '()'
ignore_va: compilation soundtrack
types:
- ep: 'EP'
- single: 'Single'
art_filename: front
bandcamp:
art: yes
search_max: 4
convert:
auto: yes
command: /config/convert.sh $source $dest
extension: mp3
ffmpeg: /usr/bin/ffmpeg
never_convert_lossy_files: yes
threads: 2
directory: /music
fetchart:
auto: yes
cover_format: JPEG
deinterlace: yes
high_resolution: yes
minwidth: 1000
maxwidth: 1000
quality: 100
sources:
- itunes
- coverart: releasegroup
- deezer
- coverart: releasegroup
- filesystem
format_album: $albumartist/($year) $album
format_item: ($year) $album/%if{$multi_disc,$disc_alt}$track. $title ($artist)
ftintitle:
auto: yes
format: (Feat. {0})
import:
bell: yes
copy: yes
detail: yes
from_scratch: yes
log: /config/beets.log
resume: ask
set_fields:
album: %tcp{$album%if{$albumdisambig, [$albumdisambig]}%if{$atypes, $atypes}}
albumartist: %tcp{$albumartist}
artist: %tcp{$artist_feat}
title: %tcp{$title}
timid: yes
write: yes
importadded:
preserve_mtimes: yes
preserve_write_mtimes: yes
importreplace:
replacements:
- album_fields: album artist title
item_fields: album artist title
replace:
'[\u2010-\u2015]': '-'
'[\u2018-\u201B]': ''''
'[\u201C-\u201F]': '"'
'[\u2026]': '...'
'\b([Aa]\.?[Kk]\.?[Aa]\.?)': 'AKA'
'\b(Mr\.?)\b': 'Mr.'
'\b(Mrs\.?)\b': 'Mrs.'
'\b(Ms\.?)\b': 'Ms.'
'\b([Vv]\.?[Ss]\.?)\b': 'vs.'
item_fields:
artist_diff: 1 if albumartist != artist else 0
artist_feat: |
a = artist
if 'Feat.' in a:
a = ' & '.join(a.rsplit(' and ', 1))
return a
disc_alt: u'%d' % (disc)
multi_disc: 1 if disctotal > 1 else 0
library: library.db
match:
preferred:
countries: ['US']
media: ['Digital Media|File', 'CD']
paths:
default: $albumartist - ($year) $album%if{$mp3_info, [$mp3_info]}/%if{$multi_disc,$disc_alt}$track. $title%if{$artist_diff, ($artist)}
singleton: Non-Album/$track. $title ($artist)
per_disc_numbering: yes
pluginpath:
- /config/plugins/beets-importreplace
- /config/plugins/beets-tcp
plugins: albumtypes bandcamp chroma convert deezer discogs duplicates edit fetchart ftintitle fuzzy importadded importreplace info inline missing replaygain tcp web zero
replace:
'[\x00-\x1F]': _
'[\xE2-\xE6]': a
'[\xE8-\xEB]': e
'[\xEC-\xEF]': i
'[\xF2-\xF6]': o
'[\xF8]': o
'[<>:"\?\*\|]': _
'\.$': ''
'\s+$': ''
'^\.': ''
sort_album: albumartist+ year+ album+
sort_item: year+ album+ disc+ track+ artist+
tcp:
asis: [
# artists
'$hort', 'AFI', 'INXS', 'MGMT',
# default overrides
'The',
# misc.
'ABC', 'AT&T', 'DJ', 'DNA', 'XXX',
# road abbreviations
'Blvd', 'Ln', 'Rd', 'St',
]
threaded: yes
va_name: Various Artists
ui:
color: yes
zero:
keep_fields: album albumartist albumtype artist comp disc disctotal rg_album_gain rg_album_peak rg_track_gain rg_track_peak singleton title track year
```
Contributor guide
Research direction
Reproduce the import with the provided `beet -vv` command and configuration, focusing on `import.set_fields` and the `tcp` plugin while disabling the listed plugins to isolate the interaction. Trace why `%tcp{}` remains unexpanded during import; done means the configured artist and title fields expand correctly and the imported paths no longer contain `$Title` or `$Artist_diff`.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100