mirror of
https://github.com/beetbox/beets.git
synced 2026-02-19 05:45:33 +01:00
Refactor to use mutable mapping.
This commit is contained in:
parent
e147a21894
commit
4672ee0487
2 changed files with 224 additions and 217 deletions
|
|
@ -17,12 +17,10 @@
|
|||
"""
|
||||
|
||||
import re
|
||||
from collections.abc import MutableMapping
|
||||
from datetime import datetime
|
||||
from functools import cached_property
|
||||
from pathlib import Path
|
||||
from typing import TypedDict
|
||||
|
||||
from typing_extensions import NotRequired
|
||||
|
||||
from beets import config
|
||||
from beets.importer import ImportSession, ImportTask
|
||||
|
|
@ -113,20 +111,32 @@ RE_SPLIT = re.compile(r"[\-\_]+")
|
|||
RE_BRACKETS = re.compile(r"[\(\[\{].*?[\)\]\}]")
|
||||
|
||||
|
||||
class TrackMatch(TypedDict):
|
||||
disc: str | None
|
||||
track: str | None
|
||||
by: NotRequired[str | None]
|
||||
artist: str | None
|
||||
title: str | None
|
||||
class FilenameMatch(MutableMapping[str, str | None]):
|
||||
def __init__(self, matches: dict[str, str] = {}) -> None:
|
||||
self._matches: dict[str, str] = {}
|
||||
for key, value in matches.items():
|
||||
if value is not None:
|
||||
self._matches[key.lower()] = str(value).strip()
|
||||
|
||||
def __getitem__(self, key) -> str | None:
|
||||
return self._matches.get(key, None)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._matches)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self._matches)
|
||||
|
||||
def __setitem__(self, key: str, value: str | None) -> None:
|
||||
if value:
|
||||
self._matches[key] = value.strip()
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self._matches[key]
|
||||
|
||||
def values(self):
|
||||
return self._matches.values()
|
||||
|
||||
class AlbumMatch(TypedDict):
|
||||
albumartist: str | None
|
||||
album: str | None
|
||||
year: str | None
|
||||
catalognum: str | None
|
||||
media: str | None
|
||||
|
||||
|
||||
class FromFilenamePlugin(BeetsPlugin):
|
||||
|
|
@ -198,7 +208,6 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
@staticmethod
|
||||
def _escape(text: str) -> str:
|
||||
# escape brackets for fstring logs
|
||||
# TODO: Create an issue for brackets in logger
|
||||
return re.sub("}", "}}", re.sub("{", "{{", text))
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -214,15 +223,15 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
return parent_folder, filenames
|
||||
|
||||
def _check_user_matches(self, text: str,
|
||||
patterns: list[re.Pattern[str]]) -> dict[str, str]:
|
||||
patterns: list[re.Pattern[str]]) -> FilenameMatch:
|
||||
for p in patterns:
|
||||
if (usermatch := p.fullmatch(text)):
|
||||
return usermatch.groupdict()
|
||||
return FilenameMatch(usermatch.groupdict())
|
||||
return None
|
||||
|
||||
def _build_track_matches(self,
|
||||
item_filenames: dict[Item, str]) -> dict[Item, dict[str, str]]:
|
||||
track_matches: dict[Item, dict[str, str]] = {}
|
||||
item_filenames: dict[Item, str]) -> dict[Item, FilenameMatch]:
|
||||
track_matches: dict[Item, FilenameMatch] = {}
|
||||
for item, filename in item_filenames.items():
|
||||
if (m := self._check_user_matches(filename, self.file_patterns)):
|
||||
track_matches[item] = m
|
||||
|
|
@ -232,53 +241,32 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
return track_matches
|
||||
|
||||
@staticmethod
|
||||
def _parse_track_info(text: str) -> TrackMatch:
|
||||
trackmatch: TrackMatch = {
|
||||
"disc": None,
|
||||
"track": None,
|
||||
"by": None,
|
||||
"artist": None,
|
||||
"title": None,
|
||||
}
|
||||
def _parse_track_info(text: str) -> FilenameMatch:
|
||||
match = RE_TRACK_INFO.match(text)
|
||||
assert match is not None
|
||||
if disc := match.group("disc"):
|
||||
trackmatch["disc"] = str(disc)
|
||||
if track := match.group("track"):
|
||||
trackmatch["track"] = str(track).strip()
|
||||
if by := match.group("by"):
|
||||
trackmatch["by"] = str(by)
|
||||
if artist := match.group("artist"):
|
||||
trackmatch["artist"] = str(artist).strip()
|
||||
if title := match.group("title"):
|
||||
trackmatch["title"] = str(title).strip()
|
||||
trackmatch = FilenameMatch(match.groupdict())
|
||||
# if the phrase "by" is matched, swap artist and title
|
||||
if trackmatch["by"]:
|
||||
artist = trackmatch["title"]
|
||||
trackmatch["title"] = trackmatch["artist"]
|
||||
trackmatch["artist"] = artist
|
||||
# remove that key
|
||||
del trackmatch["by"]
|
||||
# remove that key
|
||||
del trackmatch["by"]
|
||||
# if all fields except `track` are none
|
||||
# set title to track number as well
|
||||
# we can't be sure if it's actually the track number
|
||||
# or track title
|
||||
if set(trackmatch.values()) == {None, trackmatch["track"]}:
|
||||
trackmatch["title"] = trackmatch["track"]
|
||||
track = match.group("track")
|
||||
if set(trackmatch.values()) == {track}:
|
||||
trackmatch["title"] = track
|
||||
|
||||
return trackmatch
|
||||
|
||||
def _parse_album_info(self, text: str) -> dict[str, str]:
|
||||
def _parse_album_info(self, text: str) -> FilenameMatch:
|
||||
# Check if a user pattern matches
|
||||
if (m := self._check_user_matches(text, self.folder_patterns)):
|
||||
return m
|
||||
matches: AlbumMatch = {
|
||||
"albumartist": None,
|
||||
"album": None,
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
}
|
||||
matches = FilenameMatch()
|
||||
# Start with the extra fields to make parsing
|
||||
# the album artist and artist field easier
|
||||
year, span = self._parse_year(text)
|
||||
|
|
@ -313,7 +301,7 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
return matches
|
||||
|
||||
def _apply_matches(
|
||||
self, album_match: AlbumMatch, track_matches: dict[Item, TrackMatch]
|
||||
self, album_match: FilenameMatch, track_matches: dict[Item, FilenameMatch]
|
||||
) -> None:
|
||||
"""Apply all valid matched fields to all items in the match dictionary."""
|
||||
match = album_match
|
||||
|
|
@ -434,7 +422,7 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
return text
|
||||
|
||||
def _sanity_check_matches(
|
||||
self, album_match: AlbumMatch, track_matches: dict[Item, TrackMatch]
|
||||
self, album_match: FilenameMatch, track_matches: dict[Item, FilenameMatch]
|
||||
) -> None:
|
||||
"""Check to make sure data is coherent between
|
||||
track and album matches. Largely looking to see
|
||||
|
|
@ -442,7 +430,7 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
identified.
|
||||
"""
|
||||
|
||||
def swap_artist_title(tracks: list[TrackMatch]):
|
||||
def swap_artist_title(tracks: list[FilenameMatch]):
|
||||
for track in tracks:
|
||||
artist = track["title"]
|
||||
track["title"] = track["artist"]
|
||||
|
|
@ -454,7 +442,7 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
if len(track_matches) < 2:
|
||||
return
|
||||
|
||||
tracks: list[TrackMatch] = list(track_matches.values())
|
||||
tracks: list[FilenameMatch] = list(track_matches.values())
|
||||
album_artist = album_match["albumartist"]
|
||||
one_artist = self._equal_fields(tracks, "artist")
|
||||
one_title = self._equal_fields(tracks, "title")
|
||||
|
|
@ -479,7 +467,7 @@ class FromFilenamePlugin(BeetsPlugin):
|
|||
return
|
||||
|
||||
@staticmethod
|
||||
def _equal_fields(dictionaries: list[TrackMatch], field: str) -> bool:
|
||||
def _equal_fields(dictionaries: list[FilenameMatch], field: str) -> bool:
|
||||
"""Checks if all values of a field on a dictionary match."""
|
||||
return len(set(d[field] for d in dictionaries)) <= 1 # type: ignore
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from beets.importer.tasks import ImportTask, SingletonImportTask
|
||||
from beets.library import Item
|
||||
from beets.test.helper import PluginMixin
|
||||
from beets.importer.tasks import ImportTask, SingletonImportTask
|
||||
from beetsplug.fromfilename import FromFilenamePlugin
|
||||
from beetsplug.fromfilename import FilenameMatch, FromFilenamePlugin
|
||||
|
||||
|
||||
class Session:
|
||||
|
|
@ -47,68 +47,79 @@ def mock_task(items):
|
|||
@pytest.mark.parametrize(
|
||||
"text,matchgroup",
|
||||
[
|
||||
("3", {"disc": None, "track": "3", "artist": None, "title": "3"}),
|
||||
("04", {"disc": None, "track": "04", "artist": None, "title": "04"}),
|
||||
("6.", {"disc": None, "track": "6", "artist": None, "title": "6"}),
|
||||
("3.5", {"disc": "3", "track": "5", "artist": None, "title": None}),
|
||||
("1-02", {"disc": "1", "track": "02", "artist": None, "title": None}),
|
||||
("100-4", {"disc": "100", "track": "4", "artist": None, "title": None}),
|
||||
("3", FilenameMatch({"track": "3", "title": "3"})),
|
||||
("04", FilenameMatch({"track": "04", "title": "04"})),
|
||||
("6.", FilenameMatch({"track": "6", "title": "6"})),
|
||||
("3.5", FilenameMatch({"disc": "3", "track": "5"})),
|
||||
("1-02", FilenameMatch({"disc": "1", "track": "02"})),
|
||||
("100-4", FilenameMatch({"disc": "100", "track": "4"})),
|
||||
(
|
||||
"04.Title",
|
||||
{"disc": None, "track": "04", "artist": None, "title": "Title"},
|
||||
FilenameMatch({"track": "04", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"5_-_Title",
|
||||
{"disc": None, "track": "5", "artist": None, "title": "Title"},
|
||||
FilenameMatch({"track": "5", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"1-02 Title",
|
||||
{"disc": "1", "track": "02", "artist": None, "title": "Title"},
|
||||
FilenameMatch({"disc": "1", "track": "02", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"3.5 - Title",
|
||||
{"disc": "3", "track": "5", "artist": None, "title": "Title"},
|
||||
FilenameMatch({"disc": "3", "track": "5", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"5_-_Artist_-_Title",
|
||||
{"disc": None, "track": "5", "artist": "Artist", "title": "Title"},
|
||||
FilenameMatch({"track": "5", "artist": "Artist", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"3-8- Artist-Title",
|
||||
{"disc": "3", "track": "8", "artist": "Artist", "title": "Title"},
|
||||
FilenameMatch(
|
||||
{
|
||||
"disc": "3",
|
||||
"track": "8",
|
||||
"artist": "Artist",
|
||||
"title": "Title",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"4-3 - Artist Name - Title",
|
||||
{
|
||||
"disc": "4",
|
||||
"track": "3",
|
||||
"artist": "Artist Name",
|
||||
"title": "Title",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"disc": "4",
|
||||
"track": "3",
|
||||
"artist": "Artist Name",
|
||||
"title": "Title",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"4-3_-_Artist_Name_-_Title",
|
||||
{
|
||||
"disc": "4",
|
||||
"track": "3",
|
||||
"artist": "Artist_Name",
|
||||
"title": "Title",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"disc": "4",
|
||||
"track": "3",
|
||||
"artist": "Artist_Name",
|
||||
"title": "Title",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"6 Title by Artist",
|
||||
{"disc": None, "track": "6", "artist": "Artist", "title": "Title"},
|
||||
FilenameMatch({"track": "6", "artist": "Artist", "title": "Title"}),
|
||||
),
|
||||
(
|
||||
"Title",
|
||||
{"disc": None, "track": None, "artist": None, "title": "Title"},
|
||||
FilenameMatch({"title": "Title"}),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parse_track_info(text, matchgroup):
|
||||
f = FromFilenamePlugin()
|
||||
m = f._parse_track_info(text)
|
||||
assert matchgroup == m
|
||||
assert dict(matchgroup.items()) == dict(m.items())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -117,134 +128,137 @@ def test_parse_track_info(text, matchgroup):
|
|||
(
|
||||
# highly unlikely
|
||||
"",
|
||||
{
|
||||
"albumartist": None,
|
||||
"album": None,
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": None,
|
||||
"album": None,
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"1970",
|
||||
{
|
||||
"albumartist": None,
|
||||
"album": None,
|
||||
"year": "1970",
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"year": "1970",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Album Title",
|
||||
{
|
||||
"albumartist": None,
|
||||
"album": "Album Title",
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"album": "Album Title",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Artist - Album Title",
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Artist - Album Title (2024)",
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Artist - 2024 - Album Title [flac]",
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"(2024) Album Title [CATALOGNUM] WEB",
|
||||
# sometimes things are just going to be unparsable
|
||||
{
|
||||
"albumartist": "Album Title",
|
||||
"album": "WEB",
|
||||
"year": "2024",
|
||||
"catalognum": "CATALOGNUM",
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Album Title",
|
||||
"album": "WEB",
|
||||
"year": "2024",
|
||||
"catalognum": "CATALOGNUM",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"{2024} Album Artist - Album Title [INFO-WAV]",
|
||||
{
|
||||
"albumartist": "Album Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
"catalognum": None,
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Album Artist",
|
||||
"album": "Album Title",
|
||||
"year": "2024",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"VA - Album Title [2025] [CD-FLAC]",
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "Album Title",
|
||||
"year": "2025",
|
||||
"catalognum": None,
|
||||
"media": "CD",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "Album Title",
|
||||
"year": "2025",
|
||||
"media": "CD",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Artist - Album Title 3000 (1998) [FLAC] {CATALOGNUM}",
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title 3000",
|
||||
"year": "1998",
|
||||
"catalognum": "CATALOGNUM",
|
||||
"media": None,
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Artist",
|
||||
"album": "Album Title 3000",
|
||||
"year": "1998",
|
||||
"catalognum": "CATALOGNUM",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"various - cd album (2023) [catalognum 123] {vinyl mp3}",
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "cd album",
|
||||
"year": "2023",
|
||||
"catalognum": "catalognum 123",
|
||||
"media": "Vinyl",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "cd album",
|
||||
"year": "2023",
|
||||
"catalognum": "catalognum 123",
|
||||
"media": "Vinyl",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"[CATALOG567] Album - Various (2020) [WEB-FLAC]",
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "Album",
|
||||
"year": "2020",
|
||||
"catalognum": "CATALOG567",
|
||||
"media": "Digital Media",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"albumartist": "Various Artists",
|
||||
"album": "Album",
|
||||
"year": "2020",
|
||||
"catalognum": "CATALOG567",
|
||||
"media": "Digital Media",
|
||||
}
|
||||
),
|
||||
),
|
||||
(
|
||||
"Album 3000 {web}",
|
||||
{
|
||||
"albumartist": None,
|
||||
"album": "Album 3000",
|
||||
"year": None,
|
||||
"catalognum": None,
|
||||
"media": "Digital Media",
|
||||
},
|
||||
FilenameMatch(
|
||||
{
|
||||
"album": "Album 3000",
|
||||
"media": "Digital Media",
|
||||
}
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
@ -253,17 +267,18 @@ def test_parse_album_info(text, matchgroup):
|
|||
m = f._parse_album_info(text)
|
||||
assert matchgroup == m
|
||||
|
||||
@pytest.mark.parametrize("string,pattern",[
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"string,pattern",
|
||||
[
|
||||
(
|
||||
"$albumartist - $album ($year) {$comments}",
|
||||
r"(?P<albumartist>.+)\ \-\ (?P<album>.+)\ \((?P<year>.+)\)\ \ \{(?P<comments>.+)\}"
|
||||
"$albumartist - $album ($year) {$comments}",
|
||||
r"(?P<albumartist>.+)\ \-\ (?P<album>.+)\ \((?P<year>.+)\)\ \ \{(?P<comments>.+)\}",
|
||||
),
|
||||
(
|
||||
"$",
|
||||
None
|
||||
),
|
||||
])
|
||||
def test_parse_user_pattern_strings(string,pattern):
|
||||
("$", None),
|
||||
],
|
||||
)
|
||||
def test_parse_user_pattern_strings(string, pattern):
|
||||
f = FromFilenamePlugin()
|
||||
assert f._parse_user_pattern_strings(string) == pattern
|
||||
|
||||
|
|
@ -555,8 +570,7 @@ class TestFromFilename(PluginMixin):
|
|||
|
||||
def test_singleton_import(self):
|
||||
task = SingletonImportTask(
|
||||
toppath=None,
|
||||
item=mock_item(path="/01 Track.wav")
|
||||
toppath=None, item=mock_item(path="/01 Track.wav")
|
||||
)
|
||||
f = FromFilenamePlugin()
|
||||
f.filename_task(task, Session())
|
||||
|
|
@ -630,39 +644,42 @@ class TestFromFilename(PluginMixin):
|
|||
assert res.year == expected.year
|
||||
assert res.title == expected.title
|
||||
|
||||
@pytest.mark.parametrize("patterns,expected", [
|
||||
(
|
||||
{
|
||||
"folder": ["($comments) - {$albumartist} - {$album}"],
|
||||
"file": ["$artist - $track - $title"]
|
||||
},
|
||||
mock_item(
|
||||
path="/(Comment) - {Album Artist} - {Album}/Artist - 02 - Title.flac",
|
||||
comments="Comment",
|
||||
albumartist="Album Artist",
|
||||
album="Album",
|
||||
artist="Artist",
|
||||
track=2,
|
||||
title="Title",
|
||||
)
|
||||
),
|
||||
(
|
||||
{
|
||||
"folder": ["[$comments] - {$albumartist} - {$album}"],
|
||||
"file": ["$artist - $track - $title"]
|
||||
},
|
||||
mock_item(
|
||||
path="/(Comment) - {Album Artist} - {Album}/Artist - 02 - Title.flac",
|
||||
artist="Artist",
|
||||
track=2,
|
||||
title="Title",
|
||||
catalognum="Comment"
|
||||
)
|
||||
)
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"patterns,expected",
|
||||
[
|
||||
(
|
||||
{
|
||||
"folder": ["($comments) - {$albumartist} - {$album}"],
|
||||
"file": ["$artist - $track - $title"],
|
||||
},
|
||||
mock_item(
|
||||
path="/(Comment) - {Album Artist} - {Album}/Artist - 02 - Title.flac",
|
||||
comments="Comment",
|
||||
albumartist="Album Artist",
|
||||
album="Album",
|
||||
artist="Artist",
|
||||
track=2,
|
||||
title="Title",
|
||||
),
|
||||
),
|
||||
(
|
||||
{
|
||||
"folder": ["[$comments] - {$albumartist} - {$album}"],
|
||||
"file": ["$artist - $track - $title"],
|
||||
},
|
||||
mock_item(
|
||||
path="/(Comment) - {Album Artist} - {Album}/Artist - 02 - Title.flac",
|
||||
artist="Artist",
|
||||
track=2,
|
||||
title="Title",
|
||||
catalognum="Comment",
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_user_patterns(self, patterns, expected):
|
||||
task = mock_task([mock_item(path=expected.path)])
|
||||
with self.configure_plugin({ "patterns": patterns }):
|
||||
with self.configure_plugin({"patterns": patterns}):
|
||||
f = FromFilenamePlugin()
|
||||
f.filename_task(task, Session())
|
||||
res = task.items[0]
|
||||
|
|
@ -675,3 +692,5 @@ class TestFromFilename(PluginMixin):
|
|||
assert res.year == expected.year
|
||||
assert res.title == expected.title
|
||||
|
||||
def test_escape(self):
|
||||
assert FromFilenamePlugin._escape("{text}") == "{{text}}"
|
||||
|
|
|
|||
Loading…
Reference in a new issue