emmental/tests/audio/test_tagger.py

246 lines
11 KiB
Python

# Copyright 2023 (c) Anna Schumaker
"""Tests our tag extractor class."""
import pathlib
import unittest
import emmental.audio.tagger
_Tags = emmental.audio.tagger._Tags
class TestAudioTagger(unittest.TestCase):
"""Test case for the Tagger."""
def setUp(self):
"""Set up common variables."""
self.file = pathlib.Path("/a/b/c/track.ogg")
def test_init(self):
"""Test that the tagger was initialized properly."""
tags = dict()
tagger = _Tags(self.file, tags)
self.assertEqual(tagger.file, self.file)
self.assertEqual(tagger.tags, tags)
def test_get_album_artist(self):
"""Test that the album artist is tagged properly."""
tagger = _Tags(self.file, dict())
self.assertEqual(tagger.get_album_artist(), "")
for (tag, artist) in [("artist", "Artist"),
("albumartist", "Album Artist")]:
with self.subTest(tag=tag, artist=artist):
tagger.tags[tag] = [artist]
self.assertEqual(tagger.get_album_artist(), artist)
def test_get_release(self):
"""Test that the release date is tagged properly."""
tagger = _Tags(self.file, dict())
self.assertEqual(tagger.get_release(), "")
for (tag, date) in [("year", "1987"),
("date", "1988-06-17"),
("originalyear", "1986"),
("originaldate", "1985-08")]:
with self.subTest(tag=tag, date=date):
tagger.tags[tag] = [date]
self.assertEqual(tagger.get_release(), date)
def test_empty(self):
"""Test handling an empty tag dict."""
tagger = _Tags(self.file, dict())
self.assertEqual(tagger.album.name, "")
self.assertEqual(tagger.album.mbid, "")
self.assertEqual(tagger.album.artist, "")
self.assertEqual(tagger.album.release, "")
self.assertEqual(tagger.album.cover, pathlib.Path("/a/b/c/cover.jpg"))
self.assertListEqual(tagger.album.artists, [])
self.assertEqual(tagger.medium.name, "")
self.assertEqual(tagger.medium.number, 1)
self.assertEqual(tagger.medium.type, "")
self.assertListEqual(tagger.artists, [])
self.assertListEqual(tagger.genres, [])
self.assertIsNone(tagger.year)
def test_album(self):
"""Test that the album was tagged correctly."""
tagger = _Tags(self.file, {"album": ["Album Name"],
"musicbrainz_releasegroupid": ["ab-cd-ef"],
"albumartist": ["Album Artist"],
"date": ["1988-06"]})
self.assertEqual(tagger.album.name, "Album Name")
self.assertEqual(tagger.album.mbid, "ab-cd-ef")
self.assertEqual(tagger.album.artist, "Album Artist")
self.assertEqual(tagger.album.release, "1988-06")
self.assertEqual(tagger.album.cover, pathlib.Path("/a/b/c/cover.jpg"))
self.assertEqual(len(tagger.album.artists), 1)
self.assertEqual(id(tagger.album.artists[0]), id(tagger.artists[0]))
tagger = _Tags(self.file, {"album": ["Album Name"],
"musicbrainz_releasegroupid": ["ab-cd-ef"],
"albumartist": ["Album Artist"],
"musicbrainz_albumartistid": ["gh-ij-kl",
"mn-op-qr"],
"date": ["1988-06"]})
self.assertEqual(tagger.album.name, "Album Name")
self.assertEqual(tagger.album.mbid, "ab-cd-ef")
self.assertEqual(tagger.album.artist, "Album Artist")
self.assertEqual(tagger.album.release, "1988-06")
self.assertEqual(tagger.album.cover, pathlib.Path("/a/b/c/cover.jpg"))
self.assertListEqual([(a.name, a.mbid) for a in tagger.album.artists],
[(None, "gh-ij-kl"), (None, "mn-op-qr")])
def test_artists(self):
"""Test that the artists were tagged correctly."""
tagger = _Tags(self.file, {"artist": ["Artist"],
"albumartist": ["Album Artist"]})
self.assertListEqual([(a.name, a.mbid) for a in tagger.artists],
[("Album Artist", ""), ("Artist", "")])
tagger = _Tags(self.file, {"artist": ["No Artist"],
"artists": ["Artist", "Other Artist"],
"musicbrainz_artistid":
["ab-cd-ef", "gh-ij-kl"],
"albumartist":
["Album Artist", "Other Artist"],
"musicbrainz_albumartistid":
["mn-op-qr", "gh-ij-kl"]})
self.assertListEqual([(a.name, a.mbid) for a in tagger.artists],
[("Album Artist", "mn-op-qr"),
("Artist", "ab-cd-ef"),
("Other Artist", "gh-ij-kl")])
tagger = _Tags(self.file, {"artist": ["No Artist"],
"artists": ["Artist"],
"musicbrainz_artistid":
["ab-cd-ef", "gh-ij-kl"],
"albumartist": ["Album Artist"],
"musicbrainz_albumartistid":
["mn-op-qr", "gh-ij-kl"]})
self.assertListEqual([(a.name, a.mbid) for a in tagger.artists],
[(None, "ab-cd-ef"), (None, "gh-ij-kl"),
(None, "mn-op-qr")])
tagger = _Tags(self.file, {"artists": ["Artist 1", "Artist 2"],
"musicbrainz_artistid":
["ab-cd-ef", "gh-ij-kl"],
"albumartist": ["Artist 1 & 2"],
"musicbrainz_albumartistid":
["ab-cd-ef", "gh-ij-kl"]})
self.assertListEqual([(a.name, a.mbid) for a in tagger.artists],
[("Artist 1", "ab-cd-ef"),
("Artist 2", "gh-ij-kl")])
def test_medium(self):
"""Test that media information was tagged correctly."""
tagger = _Tags(self.file, {"discnumber": ["2"],
"discsubtitle": ["Subtitle"],
"media": ["CD"]})
self.assertEqual(tagger.medium.number, 2)
self.assertEqual(tagger.medium.name, "Subtitle")
self.assertEqual(tagger.medium.type, "CD")
def test_genre(self):
"""Test that genres can be tagged correctly."""
genre = "Genre 1, Genre 2 / Genre 3; Genre 4"
tagger = _Tags(self.file, {"genre": [genre]})
self.assertListEqual(tagger.genres, ["Genre 1", "Genre 2",
"Genre 3", "Genre 4"])
genre = ["Genre 1 / Genre 2", "Genre 3; Genre 4"]
reltype = ["album", "ep", "single", "compilation"]
tagger = _Tags(self.file, {"genre": genre, "releasetype": reltype})
self.assertListEqual(tagger.genres, ["EP", "Genre 1", "Genre 2",
"Genre 3", "Genre 4", "Single"])
def test_track(self):
"""Test that tracks can be tagged corretly."""
tagger = _Tags(self.file, {"artist": ["Test Artist"],
"title": ["Test Title"],
"tracknumber": ["2"],
"musicbrainz_releasetrackid": ["ab-cd-ef"]},
12345, 678.90)
self.assertEqual(tagger.track.artist, "Test Artist")
self.assertEqual(tagger.track.length, 12345)
self.assertEqual(tagger.track.mbid, "ab-cd-ef")
self.assertEqual(tagger.track.mtime, 678.90)
self.assertEqual(tagger.track.number, 2)
self.assertEqual(tagger.track.title, "Test Title")
tagger = _Tags(self.file, {})
self.assertEqual(tagger.track.artist, "")
self.assertEqual(tagger.track.length, 0)
self.assertEqual(tagger.track.mbid, "")
self.assertEqual(tagger.track.mtime, 0.0)
self.assertEqual(tagger.track.number, 0)
self.assertEqual(tagger.track.title, "")
def test_year(self):
"""Test the year property."""
tagger = _Tags(self.file, {"date": ["1988-06-17"]})
self.assertEqual(tagger.year, 1988)
@unittest.mock.patch("pathlib.Path.is_file")
@unittest.mock.patch("pathlib.Path.stat")
class TestTagFile(unittest.TestCase):
"""Test case for the tag_file() function."""
def test_not_file(self, mock_stat: unittest.mock.Mock(),
mock_is_file: unittest.mock.Mock):
"""Test calling tag_file() on something other than a file."""
path = pathlib.Path("/a/b/c")
mock_is_file.return_value = False
self.assertIsNone(emmental.audio.tagger.tag_file(path, None))
mock_is_file.assert_called()
@unittest.mock.patch("mutagen.File")
def test_no_tags(self, mock_mutagen_file: unittest.mock.Mock,
mock_stat: unittest.mock.Mock(),
mock_is_file: unittest.mock.Mock):
"""Test calling tag_file() on a file that doesn't have tags."""
path = pathlib.Path("/a/b/c/notags.txt")
mock_is_file.return_value = True
mock_mutagen_file.return_value = None
self.assertIsNone(emmental.audio.tagger.tag_file(path, None))
mock_is_file.assert_called()
mock_mutagen_file.assert_called_with(path)
def test_not_updated(self, mock_stat: unittest.mock.Mock,
mock_is_file: unittest.mock.Mock):
"""Test calling tag_file() with an mtime <= mtime reported by stat."""
path = pathlib.Path("/a/b/c/track.ogg")
mock_is_file.return_value = True
mock_stat.return_value.st_mtime = 123.45
self.assertIsNone(emmental.audio.tagger.tag_file(path, 123.45))
self.assertIsNone(emmental.audio.tagger.tag_file(path, 246.8))
@unittest.mock.patch("mutagen.File")
def test_have_tags(self, mock_mutagen_file: unittest.mock.Mock,
mock_stat: unittest.mock.Mock,
mock_is_file: unittest.mock.Mock):
"""Test calling tag_file() successfully."""
path = pathlib.Path("/a/b/c/track.ogg")
mock_is_file.return_value = True
mock_stat.return_value.st_mtime = 67.890
mock_mutagen_file.return_value = unittest.mock.MagicMock()
mock_mutagen_file.return_value.info.length = 12345
for mtime in [None, 70.123]:
with self.subTest(mtime=mtime):
tags = emmental.audio.tagger.tag_file(path, None)
self.assertIsInstance(tags, emmental.audio.tagger._Tags)
self.assertEqual(tags.track.length, 12345)
self.assertEqual(tags.track.mtime, 67.890)
mock_is_file.assert_called()
mock_stat.assert_called()
mock_mutagen_file.assert_called_with(path)