Skip to content
This repository has been archived by the owner on Feb 9, 2024. It is now read-only.

Commit

Permalink
db open cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mayhem committed Jan 8, 2024
1 parent 44844b1 commit 3b29b22
Show file tree
Hide file tree
Showing 14 changed files with 45 additions and 63 deletions.
4 changes: 1 addition & 3 deletions lb_content_resolver/artist_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ class LocalRecordingSearchByArtistService(RecordingSearchByArtistService):
Given the local database, search for artists that meet given tag criteria
'''

def __init__(self, db):
def __init__(self):
RecordingSearchByArtistService.__init__(self)
self.db = db

def search(self, artist_mbids, begin_percent, end_percent, num_recordings):
"""
Expand Down Expand Up @@ -52,7 +51,6 @@ def search(self, artist_mbids, begin_percent, end_percent, num_recordings):
ORDER BY artist_mbid
, popularity"""

self.db.open_db()
placeholders = ",".join(("?", ) * len(artist_mbids))
cursor = db.execute_sql(query % placeholders, params=tuple(artist_mbids))

Expand Down
4 changes: 1 addition & 3 deletions lb_content_resolver/content_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ class ContentResolver:
Scan a given path and enter/update the metadata in the search index
'''

def __init__(self, db):
self.db = db
def __init__(self):
self.fuzzy_index = None

def get_artist_recording_metadata(self):
Expand Down Expand Up @@ -135,7 +134,6 @@ def resolve_playlist(self, match_threshold, recordings=None, jspf_playlist=None)
"recording_name": rec.name,
"recording_mbid": rec.mbid})

self.db.open_db()
self.build_index()

hits = self.resolve_recordings(artist_recording_data, match_threshold)
Expand Down
20 changes: 10 additions & 10 deletions lb_content_resolver/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ def create(self):
db.connect()
db.create_tables([Recording, RecordingMetadata, Tag, RecordingTag, RecordingSubsonic, UnresolvedRecording])

def open_db(self):
def open(self):
"""
Open the database file and connect to the db.
"""
setup_db(self.db_file)
db.connect()

def close_db(self):
def close(self):
""" Close the db."""
db.close()

Expand All @@ -72,7 +72,6 @@ def scan(self, music_dir):

# Future improvement, commit to DB only every 1000 tracks or so.
print("Check collection size...")
self.open_db()
self.track_count_estimate = 0
self.traverse("", dry_run=True)
self.audio_file_count = self.track_count_estimate
Expand Down Expand Up @@ -270,20 +269,21 @@ def add(self, relative_path):
self.progress_bar.write(" error %s" % details)


def database_cleanup(self):
def database_cleanup(self, dry_run):
'''
Look for missing tracks and remove them from the DB. Then look for empty releases/artists and remove those too
'''

self.open_db()
query = Recording.select()
recording_ids = []
for recording in query:
if not os.path.exists(recording.file_path):
print("UNLINK %s" % recording.file_path)
print("RM %s" % recording.file_path)
recording_ids.append(recording.id)

placeholders = ",".join(("?", ) * len(recording_ids))
db.execute_sql("""DELETE FROM recording WHERE recording.id IN (%s)""" % placeholders, tuple(recording_ids))

self.close_db()
if not dry_run:
placeholders = ",".join(("?", ) * len(recording_ids))
db.execute_sql("""DELETE FROM recording WHERE recording.id IN (%s)""" % placeholders, tuple(recording_ids))
print("Stale references removed")
else:
print("--delete not specified, no refeences removed")
2 changes: 0 additions & 2 deletions lb_content_resolver/duplicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ def get_duplicate_recordings(self, include_different_releases):
HAVING cnt > 1
ORDER BY cnt DESC, artist_name, recording_name"""

self.db.open_db()

return [ (r[0], r[1], r[2], r[3], json.loads(r[4]), r[5]) for r in db.execute_sql(query).fetchall() ]


Expand Down
13 changes: 3 additions & 10 deletions lb_content_resolver/lb_radio.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ class ListenBrainzRadioLocal:
# TODO: Make this an argument
MATCH_THRESHOLD = .8

def __init__(self, db):
self.db = db

def sanity_check(self):
"""
Run a sanity check on the DB to see if data is missing that is required for LB Radio to work.
"""

self.db.open_db()

num_recordings = db.execute_sql("SELECT COUNT(*) FROM recording").fetchone()[0]
num_metadata = db.execute_sql("SELECT COUNT(*) FROM recording_metadata").fetchone()[0]
num_subsonic = db.execute_sql("SELECT COUNT(*) FROM recording_subsonic").fetchone()[0]
Expand All @@ -52,11 +47,9 @@ def generate(self, mode, prompt):
Generate a playlist given the mode and prompt.
"""

self.db.open_db()

patch = LBRadioPatch({"mode": mode, "prompt": prompt, "echo": True, "debug": True, "min_recordings": 1})
patch.register_service(LocalRecordingSearchByTagService(self.db))
patch.register_service(LocalRecordingSearchByArtistService(self.db))
patch.register_service(LocalRecordingSearchByTagService())
patch.register_service(LocalRecordingSearchByArtistService())

# Now generate the playlist
try:
Expand Down Expand Up @@ -89,7 +82,7 @@ def resolve_playlist(self, match_threshold, playlist):
return self.resolve_recordings(match_threshold, recordings)

def resolve_recordings(self, match_threshold, recordings):
cr = ContentResolver(self.db)
cr = ContentResolver()
resolved = cr.resolve_playlist(match_threshold, recordings)

for i, t_recording in enumerate(recordings):
Expand Down
2 changes: 0 additions & 2 deletions lb_content_resolver/metadata_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ def lookup(self):
Iterate over all recordings in the database and call lookup_chunk for chunks of recordings.
"""

self.db.open_db()

cursor = db.execute_sql("""SELECT recording.id, recording.recording_mbid, recording_metadata.id
FROM recording
LEFT JOIN recording_metadata
Expand Down
2 changes: 0 additions & 2 deletions lb_content_resolver/subsonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ def sync(self):
self.matched = 0
self.error = 0

self.open_db()
self.run_sync()
self.close_db()

print("Checked %s albums:" % self.total)
print(" %5d albums matched" % self.matched)
Expand Down
4 changes: 1 addition & 3 deletions lb_content_resolver/tag_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ class LocalRecordingSearchByTagService(RecordingSearchByTagService):
to make this work for tracks without subsonic ids.
'''

def __init__(self, db):
def __init__(self):
RecordingSearchByTagService.__init__(self)
self.db = db

def search(self, tags, operator, begin_percent, end_percent, num_recordings):
"""
Expand All @@ -48,7 +47,6 @@ def search(self, tags, operator, begin_percent, end_percent, num_recordings):
else:
query, params, pop_clause = self.and_search(tags)

self.db.open_db()
placeholders = ",".join(("?", ) * len(tags))
cursor = db.execute_sql(query % (placeholders, pop_clause), params)

Expand Down
4 changes: 0 additions & 4 deletions lb_content_resolver/top_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ class TopTags:
Class to fetch top tags
'''

def __init__(self, db):
self.db = db

def get_top_tags(self, limit=50):
"""
"""
Expand All @@ -35,7 +32,6 @@ def get_top_tags(self, limit=50):
ORDER BY cnt DESC
LIMIT ?"""

self.db.open_db()
cursor = db.execute_sql(query, (limit,))

top_tags = []
Expand Down
2 changes: 1 addition & 1 deletion lb_content_resolver/troi/patches/periodic_jams.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def create(self, inputs):
recs_lookup = troi.musicbrainz.recording_lookup.RecordingLookupElement()
recs_lookup.set_sources(latest_filter)

resolve = RecordingResolverElement(db, .8)
resolve = RecordingResolverElement(.8)
resolve.set_sources(recs_lookup)

pl_maker = PlaylistMakerElement(name="Local Periodic Jams for %s" % (user_name),
Expand Down
6 changes: 2 additions & 4 deletions lb_content_resolver/troi/periodic_jams.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@ class LocalPeriodicJams(ListenBrainzRadioLocal):
# TODO: Make this an argument
MATCH_THRESHOLD = .8

def __init__(self, db, user_name):
ListenBrainzRadioLocal.__init__(self, db)
def __init__(self, user_name):
ListenBrainzRadioLocal.__init__(self)
self.user_name = user_name

def generate(self):
"""
Generate a periodic jams playlist
"""

self.db.open_db()

patch = LocalPeriodicJamsPatch({"user_name": self.user_name, "echo": True, "debug": True, "min_recordings": 1})

# Now generate the playlist
Expand Down
5 changes: 2 additions & 3 deletions lb_content_resolver/troi/recording_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ class RecordingResolverElement(Element):
name set and resolves them to a local collection by using the ContentResolver class
"""

def __init__(self, db, match_threshold):
def __init__(self, match_threshold):
Element.__init__(self)
self.db = db
self.match_threshold = match_threshold
self.resolve = ContentResolver(db)
self.resolve = ContentResolver()

@staticmethod
def inputs():
Expand Down
4 changes: 2 additions & 2 deletions lb_content_resolver/unresolved_recording.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def add(self, recording_mbids):
for mbid in recording_mbids:
db.execute_sql(query, (mbid, datetime.datetime.now()))

def get_releases(self, num_items):
def get_releases(self):
"""
Organize the unresolved recordings into releases with a list of recordings.
Return up to num_item releases.
Expand Down Expand Up @@ -111,7 +111,7 @@ def get_releases(self, num_items):
"recordings": release
})

return self.multisort(release_list, (("lookup_count", True), ("artist_name", False), ("release_name", False)))[:num_items]
return self.multisort(release_list, (("lookup_count", True), ("artist_name", False), ("release_name", False)))

def print_releases(self, releases):
""" Neatly print all the release/recordings returned from the get_releases function """
Expand Down
36 changes: 22 additions & 14 deletions resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import config

# TODO: Make sure all functions work with subsonic and with local files
# TODO: avoid passing in db to objects and just open the db


def output_playlist(db, jspf, upload_to_subsonic, save_to_playlist, dont_ask):
Expand Down Expand Up @@ -58,22 +57,26 @@ def create(index_dir):
def scan(index_dir, music_dir):
"""Scan a directory and its subdirectories for music files to add to the collection"""
db = Database(index_dir)
db.open()
db.scan(music_dir)


@click.command()
@click.option('-d', '--delete', required=False, is_flag=True, default=True)
@click.argument('index_dir')
def cleanup(index_dir):
def cleanup(delete, index_dir):
"""Perform a database cleanup. Check that files exist and if they don't remove from the index"""
db = Database(index_dir)
db.database_cleanup()
db.open()
db.database_cleanup(delete)


@click.command()
@click.argument('index_dir')
def metadata(index_dir):
"""Lookup metadata (popularity and tags) for recordings"""
db = Database(index_dir)
db.open()
lookup = MetadataLookup(db)
lookup.lookup()

Expand All @@ -87,6 +90,7 @@ def metadata(index_dir):
def subsonic(index_dir):
"""Scan a remote subsonic music collection"""
db = SubsonicDatabase(index_dir)
db.open()
db.sync()


Expand All @@ -98,7 +102,8 @@ def subsonic(index_dir):
def playlist(index_dir, jspf_playlist, m3u_playlist, threshold):
""" Resolve a JSPF file with MusicBrainz recording MBIDs to files in the local collection"""
db = Database(index_dir)
cr = ContentResolver(db)
db.open()
cr = ContentResolver()
jspf = read_jspf_playlist(jspf_playlist)
results = cr.resolve_playlist(threshold, jspf_playlist=jspf)
write_m3u_playlist_from_results(m3u_playlist, jspf["playlist"]["title"], results)
Expand All @@ -114,7 +119,8 @@ def playlist(index_dir, jspf_playlist, m3u_playlist, threshold):
def lb_radio(upload_to_subsonic, save_to_playlist, dont_ask, index_dir, mode, prompt):
"""Use the ListenBrainz Radio engine to create a playlist from a prompt, using a local music collection"""
db = SubsonicDatabase(index_dir)
r = ListenBrainzRadioLocal(db)
db.open()
r = ListenBrainzRadioLocal()
jspf = r.generate(mode, prompt)
output_playlist(db, jspf, upload_to_subsonic, save_to_playlist, dont_ask)

Expand All @@ -123,18 +129,20 @@ def lb_radio(upload_to_subsonic, save_to_playlist, dont_ask, index_dir, mode, pr
@click.argument('index_dir')
@click.argument('count', required=False, default=250)
def top_tags(index_dir, count):
"Display the top most used tags in the music collection. Useful for writing LB Radio tag prompts" ""
"Display the top most used tags in the music collection. Useful for writing LB Radio tag prompts"
db = Database(index_dir)
tt = TopTags(db)
db.open()
tt = TopTags()
tt.print_top_tags_tightly(count)


@click.command()
@click.argument('index_dir')
@click.option('-e', '--exclude-different-release', required=False, default=False, is_flag=True)
def duplicates(exclude_different_release, index_dir):
"Print all the tracks in the DB that are duplciated as per recording_mbid" ""
"Print all the tracks in the DB that are duplciated as per recording_mbid"
db = Database(index_dir)
db.open()
fd = FindDuplicates(db)
fd.print_duplicate_recordings(exclude_different_release)

Expand All @@ -148,20 +156,20 @@ def duplicates(exclude_different_release, index_dir):
def periodic_jams(upload_to_subsonic, save_to_playlist, dont_ask, index_dir, user_name):
"Generate a periodic jams playlist"
db = SubsonicDatabase(index_dir)
pj = LocalPeriodicJams(db, user_name)
db.open()
pj = LocalPeriodicJams(user_name)
jspf = pj.generate()
output_playlist(db, jspf, upload_to_subsonic, save_to_playlist, dont_ask)

@click.command()
@click.option('-c', '--count', required=False, default=25)
@click.argument('index_dir')
def unresolved_releases(count, index_dir):
def unresolved(index_dir):
"Show the top unresolved releases"

db = SubsonicDatabase(index_dir)
db.open_db()
db.open()
urt = UnresolvedRecordingTracker()
releases = urt.get_releases(num_items=count)
releases = urt.get_releases()
urt.print_releases(releases)


Expand All @@ -175,7 +183,7 @@ def unresolved_releases(count, index_dir):
cli.add_command(top_tags)
cli.add_command(duplicates)
cli.add_command(periodic_jams)
cli.add_command(unresolved_releases)
cli.add_command(unresolved)


def usage(command):
Expand Down

0 comments on commit 3b29b22

Please sign in to comment.