Skip to content

Commit

Permalink
test the existence checkers
Browse files Browse the repository at this point in the history
  • Loading branch information
azuline committed Oct 10, 2023
1 parent c5f10f0 commit 4a0e99b
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 28 deletions.
2 changes: 1 addition & 1 deletion rose/cache/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from rose.foundation.conf import Config


def list_albums(c: Config) -> Iterator[CachedRelease]:
def list_releases(c: Config) -> Iterator[CachedRelease]:
with connect(c) as conn:
cursor = conn.execute(
r"""
Expand Down
93 changes: 70 additions & 23 deletions rose/cache/read_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@

from rose.cache.database import connect
from rose.cache.dataclasses import CachedArtist, CachedRelease
from rose.cache.read import list_albums, list_artists, list_genres, list_labels
from rose.cache.read import (
artist_exists,
genre_exists,
get_release,
label_exists,
list_artists,
list_genres,
list_labels,
list_releases,
)
from rose.foundation.conf import Config


Expand All @@ -14,41 +23,41 @@ def seed_data(c: Config) -> None:
VALUES ('r1', '/tmp/r1', 'r1', 'Release 1', 'album', 2023, true)
, ('r2', '/tmp/r2', 'r2', 'Release 2', 'album', 2021, false);
INSERT INTO releases_genres (release_id, genre)
VALUES ('r1', 'Techno')
, ('r1', 'Deep House')
, ('r2', 'Classical');
INSERT INTO releases_genres (release_id, genre, genre_sanitized)
VALUES ('r1', 'Techno', 'Techno')
, ('r1', 'Deep House', 'Deep House')
, ('r2', 'Classical', 'Classical');
INSERT INTO releases_labels (release_id, label)
VALUES ('r1', 'Silk Music')
, ('r2', 'Native State');
INSERT INTO releases_labels (release_id, label, label_sanitized)
VALUES ('r1', 'Silk Music', 'Silk Music')
, ('r2', 'Native State', 'Native State');
INSERT INTO tracks
(id, source_path, virtual_filename, title, release_id, track_number, disc_number, duration_seconds)
VALUES ('t1', '/tmp/r1/01.m4a', '01.m4a', 'Track 1', 'r1', '01', '01', 120)
, ('t2', '/tmp/r1/02.m4a', '02.m4a', 'Track 2', 'r1', '02', '01', 240)
, ('t3', '/tmp/r2/01.m4a', '01.m4a', 'Track 1', 'r2', '01', '01', 120);
INSERT INTO releases_artists (release_id, artist, role)
VALUES ('r1', 'Techno Man', 'main')
, ('r1', 'Bass Man', 'main')
, ('r2', 'Violin Woman', 'main')
, ('r2', 'Conductor Woman', 'guest');
INSERT INTO tracks_artists (track_id, artist, role)
VALUES ('t1', 'Techno Man', 'main')
, ('t1', 'Bass Man', 'main')
, ('t2', 'Techno Man', 'main')
, ('t2', 'Bass Man', 'main')
, ('t3', 'Violin Woman', 'main')
, ('t3', 'Conductor Woman', 'guest');
INSERT INTO releases_artists (release_id, artist, artist_sanitized, role)
VALUES ('r1', 'Techno Man', 'Techno Man', 'main')
, ('r1', 'Bass Man', 'Bass Man', 'main')
, ('r2', 'Violin Woman', 'Violin Woman', 'main')
, ('r2', 'Conductor Woman', 'Conductor Woman', 'guest');
INSERT INTO tracks_artists (track_id, artist, artist_sanitized, role)
VALUES ('t1', 'Techno Man', 'Techno Man', 'main')
, ('t1', 'Bass Man', 'Bass Man', 'main')
, ('t2', 'Techno Man', 'Techno Man', 'main')
, ('t2', 'Bass Man', 'Bass Man', 'main')
, ('t3', 'Violin Woman', 'Violin Woman', 'main')
, ('t3', 'Conductor Woman', 'Conductor Woman', 'guest');
"""
)


def test_list_albums(config: Config) -> None:
def test_list_releases(config: Config) -> None:
seed_data(config)
albums = list(list_albums(config))
albums = list(list_releases(config))
assert albums == [
CachedRelease(
id="r1",
Expand Down Expand Up @@ -99,3 +108,41 @@ def test_list_labels(config: Config) -> None:
seed_data(config)
labels = list(list_labels(config))
assert set(labels) == {"Silk Music", "Native State"}


def test_get_release(config: Config) -> None:
seed_data(config)
release = get_release(config, "r1")
assert release == CachedRelease(
id="r1",
source_path=Path("/tmp/r1"),
virtual_dirname="r1",
title="Release 1",
release_type="album",
release_year=2023,
new=True,
genres=["Deep House", "Techno"],
labels=["Silk Music"],
artists=[
CachedArtist(name="Techno Man", role="main"),
CachedArtist(name="Bass Man", role="main"),
],
)


def test_artist_exists(config: Config) -> None:
seed_data(config)
assert artist_exists(config, "Bass Man")
assert not artist_exists(config, "lalala")


def test_genre_exists(config: Config) -> None:
seed_data(config)
assert genre_exists(config, "Deep House")
assert not genre_exists(config, "lalala")


def test_label_exists(config: Config) -> None:
seed_data(config)
assert label_exists(config, "Silk Music")
assert not label_exists(config, "Cotton Music")
35 changes: 35 additions & 0 deletions rose/cache/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def update_cache_for_release(c: Config, release_dir: Path) -> Path:
if release is None:
logger.debug("Upserting release from first track's tags")

# Compute the album's visual directory name.
virtual_dirname = _format_artists(tags.album_artists) + " - "
if tags.year:
virtual_dirname += str(tags.year) + ". "
Expand All @@ -102,6 +103,23 @@ def update_cache_for_release(c: Config, release_dir: Path) -> Path:
if tags.label:
virtual_dirname += " {" + ";".join(tags.label) + "}"
virtual_dirname = sanitize_filename(virtual_dirname)
# And in case of a name collision, add an extra number at the end. Iterate to find
# the first unused number.
original_virtual_dirname = virtual_dirname
collision_no = 1
while True:
collision_no += 1
cursor = conn.execute(
"""
SELECT EXISTS(
SELECT * FROM releases WHERE virtual_dirname = ? AND id <> ?
)
""",
(virtual_dirname, release_id),
)
if not cursor.fetchone()[0]:
break
virtual_dirname = f"{original_virtual_dirname} [{collision_no}]"

release = CachedRelease(
id=release_id,
Expand Down Expand Up @@ -200,6 +218,23 @@ def update_cache_for_release(c: Config, release_dir: Path) -> Path:
if tags.artists != tags.album_artists:
virtual_filename += " (by " + _format_artists(tags.artists) + ")"
virtual_filename = sanitize_filename(virtual_filename)
# And in case of a name collision, add an extra number at the end. Iterate to find
# the first unused number.
original_virtual_filename = virtual_filename
collision_no = 1
while True:
collision_no += 1
cursor = conn.execute(
"""
SELECT EXISTS(
SELECT * FROM tracks WHERE virtual_filename = ? AND id <> ?
)
""",
(virtual_filename, track_id),
)
if not cursor.fetchone()[0]:
break
virtual_filename = f"{original_virtual_filename} [{collision_no}]"

track = CachedTrack(
id=track_id,
Expand Down
4 changes: 2 additions & 2 deletions rose/cache/update_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ def test_update_cache_for_all_releases(config: Config) -> None:
with connect(config) as conn:
conn.execute(
"""
INSERT INTO releases (id, source_path, title, release_type)
VALUES ('aaaaaa', '/nonexistent', 'aa', 'unknown')
INSERT INTO releases (id, source_path, virtual_dirname, title, release_type)
VALUES ('aaaaaa', '/nonexistent', 'nonexistent', 'aa', 'unknown')
"""
)

Expand Down
4 changes: 2 additions & 2 deletions rose/virtualfs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
genre_exists,
get_release,
label_exists,
list_albums,
list_artists,
list_genres,
list_labels,
list_releases,
)
from rose.foundation.conf import Config
from rose.virtualfs.sanitize import sanitize_filename
Expand Down Expand Up @@ -99,7 +99,7 @@ def readdir(self, path: str, _: Any) -> Iterator[fuse.Direntry]:
if path.startswith("/albums"):
if path == "/albums":
yield from [fuse.Direntry("."), fuse.Direntry("..")]
for album in list_albums(self.config):
for album in list_releases(self.config):
yield fuse.Direntry(album.virtual_dirname)
return
return
Expand Down

0 comments on commit 4a0e99b

Please sign in to comment.