Adjust log message. Initial fix for group albums. Test outlines written. TODO: Write tests.

This commit is contained in:
Henry 2026-01-19 21:34:02 -08:00
parent 177e997cb0
commit 7a1c92d861
3 changed files with 63 additions and 6 deletions

View file

@ -164,6 +164,7 @@ class FromFilenamePlugin(BeetsPlugin):
],
"patterns": {"folder": [], "file": []},
"ignore_dirs": [],
"guess": {"folder": True, "file": True},
}
)
self.fields = set(self.config["fields"].as_str_seq())
@ -341,10 +342,17 @@ class FromFilenamePlugin(BeetsPlugin):
return trackmatch
def _parse_album_info(self, text: str) -> FilenameMatch:
matches = FilenameMatch()
if not self.config["guess"]["folder"] or (
config["import"]["group_albums"] or config["import"]["singletons"]
):
# If the group albums flag is thrown, we can't trust the parent directory
# likewise for singletons - return an empty match
return matches
# Check if a user pattern matches
if m := self._check_user_matches(text, self.folder_patterns):
return m
matches = FilenameMatch()
# Start with the extra fields to make parsing
# the album artist and artist field easier
year, span = self._parse_year(text)
@ -388,16 +396,24 @@ class FromFilenamePlugin(BeetsPlugin):
for item in track_matches:
match.update(track_matches[item]._matches)
found_data: dict[str, int | str] = {}
self._log.debug(f"Attempting keys: {match.keys()}")
self._log.debug(f"keys: {', '.join(match.keys())}")
# Check every key we are supposed to match.
for key in match.keys():
# If the key is applicable to the session, we will update it.
if key in self.session_fields:
old_value = item.get(key)
new_value = match[key]
# If the field is bad, and we have a new value
if self._bad_field(old_value) and new_value:
found_data[key] = new_value
self._log.info(f"Item updated with: {found_data.items()}")
self._log.info(f"guessing {self._format_guesses(found_data)}")
item.update(found_data)
@staticmethod
def _format_guesses(guesses: dict[str, int | str]) -> str:
"""Format guesses in a 'field="guess"' style for logging"""
return ", ".join([f'{g[0]}="{g[1]}"' for g in guesses.items()])
@staticmethod
def _parse_album_and_albumartist(
text: str,

View file

@ -84,3 +84,14 @@ Default
Specify parent directory names that will not be searched for album
information. Useful if you use a regular directory for importing
single files.
.. conf:: guess
Disable guessing from the folder or filename. Be aware that disabling both
will cause the plugin to have no effect!
.. code-block:: yaml
guess:
folder: yes
file: yes

View file

@ -735,7 +735,7 @@ class TestFromFilename(PluginMixin):
],
)
def test_alphanumeric_index(self, expected):
"""Test parsing an alphanumeric index string."""
"""Assert that an alphanumeric index is guessed in order."""
task = mock_task([mock_item(path=item.path) for item in expected])
f = FromFilenamePlugin()
f.filename_task(task, Session())
@ -743,7 +743,9 @@ class TestFromFilename(PluginMixin):
assert task.items[1].track == expected[1].track
assert task.items[2].track == expected[2].track
def test_no_changes(self):
def test_no_guesses(self):
"""Assert that an item with complete information is
has no guesses attempted."""
item = mock_item(
path="/Folder/File.wav",
albumartist="AlbumArtist",
@ -758,7 +760,9 @@ class TestFromFilename(PluginMixin):
f.filename_task(task, Session())
mock.assert_not_called()
def test_changes_missing_values(self):
def test_only_one_guess(self):
"""Assert that an item missing only one value
will just have that key in session fields."""
item = mock_item(
path="/Folder/File.wav",
albumartist="AlbumArtist",
@ -782,9 +786,35 @@ class TestFromFilename(PluginMixin):
mock.assert_called()
def test_ignored_directories(self):
"""Assert that a given parent directory name is ignored."""
ignored = "Incoming"
item = mock_item(path="/tmp/" + ignored + "/01 - File.wav")
with self.configure_plugin({"ignore_dirs": [ignored]}):
f = FromFilenamePlugin()
parent_folder, _ = f._get_path_strings([item])
assert parent_folder == ""
def test_guess_folder(self):
"""Assert that from filename does not
guess from the folder, if guess folder is `no`."""
return
def test_guess_file(self):
"""Assert that from filename does not guess
from the file, if guess file is `no`."""
return
def test_singleton_flag_import(self):
"""If the import task is a singleton, assert that
the plugin does not guess from the folder."""
return
def test_group_album_flag_import(self):
"""If the group albums flag is thrown, assert
that the plugin does not guess from the folder."""
return
def test_import_split_by_group(self):
"""Asser that an initial run without group by album, and an inaccurate
album guess, results in a run omitting it with the group album flag."""
return