Implement __hash__ method for custom classes (close #45)

Implement a reasonable __hash__ method() for the classes MCGAlbum and
MCGTrack and use a separate id for referencing albums.
This commit is contained in:
coderkun 2018-11-04 17:44:52 +01:00
commit 670d50cefd
3 changed files with 55 additions and 50 deletions

View file

@ -12,9 +12,8 @@ import sys
import threading import threading
import urllib.request import urllib.request
from hashlib import md5
from mcg.utils import SortOrder from mcg.utils import SortOrder
from mcg.utils import Utils
@ -519,7 +518,7 @@ class Client(Base):
self._logger.debug("track: %r", track) self._logger.debug("track: %r", track)
# Album # Album
album = self._extract_album(song, lookup=False) album = self._extract_album(song, lookup=False)
if len(self._playlist) == 0 or self._playlist[len(self._playlist)-1].get_hash() != album.get_hash(): if len(self._playlist) == 0 or self._playlist[len(self._playlist)-1] != album:
self._playlist.append(album) self._playlist.append(album)
else: else:
album = self._playlist[len(self._playlist)-1] album = self._playlist[len(self._playlist)-1]
@ -736,13 +735,13 @@ class Client(Base):
album = None album = None
if 'album' not in song: if 'album' not in song:
song['album'] = MCGAlbum.DEFAULT_ALBUM song['album'] = MCGAlbum.DEFAULT_ALBUM
hash = MCGAlbum.hash(song['album']) id = Utils.generate_id(song['album'])
if lookup and hash in self._albums.keys(): if lookup and id in self._albums.keys():
album = self._albums[hash] album = self._albums[id]
else: else:
album = MCGAlbum(song['album'], self._host, self._image_dir) album = MCGAlbum(song['album'], self._host, self._image_dir)
if lookup: if lookup:
self._albums[hash] = album self._albums[id] = album
return album return album
@ -822,11 +821,19 @@ class MCGAlbum:
self._length = 0 self._length = 0
self._cover = None self._cover = None
self._cover_searched = False self._cover_searched = False
self._set_hash() self._id = Utils.generate_id(title)
def __eq__(self, other): def __eq__(self, other):
return self._hash == other.get_hash() return (other and self.get_id() == other.get_id())
def __hash__(self):
return hash(self._title)
def get_id(self):
return self._id
def get_artists(self): def get_artists(self):
@ -889,16 +896,6 @@ class MCGAlbum:
return self._cover return self._cover
def hash(title):
if type(title) is list:
title = title[0]
return md5(title.encode('utf-8')).hexdigest()
def get_hash(self):
return self._hash
def filter(self, filter_string): def filter(self, filter_string):
if len(filter_string) == 0: if len(filter_string) == 0:
return True return True
@ -951,10 +948,6 @@ class MCGAlbum:
return 1 return 1
def _set_hash(self):
self._hash = MCGAlbum.hash(self._title)
def _find_cover(self): def _find_cover(self):
names = list(MCGAlbum._FILE_NAMES) names = list(MCGAlbum._FILE_NAMES)
names.append(self._title) names.append(self._title)
@ -1028,6 +1021,10 @@ class MCGTrack:
return self._file == other.get_file() return self._file == other.get_file()
def __hash__(self):
return hash(self._file)
def get_artists(self): def get_artists(self):
if self._albumartists: if self._albumartists:
return [artist for artist in self._artists if artist not in self._albumartists] return [artist for artist in self._artists if artist not in self._albumartists]
@ -1161,7 +1158,7 @@ class MCGCache():
def create_filename(self, album): def create_filename(self, album):
return os.path.join(self._dirname, '-'.join([album.get_hash()])) return os.path.join(self._dirname, '-'.join([album.get_id()]))
def _read_size(self): def _read_size(self):

View file

@ -3,6 +3,7 @@
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
import hashlib
import locale import locale
import os import os
import urllib import urllib
@ -75,6 +76,15 @@ class Utils:
return title return title
def generate_id(values):
if type(values) is not list:
values = [values]
m = hashlib.md5()
for value in values:
m.update(value.encode('utf-8'))
return m.hexdigest()
class SortOrder: class SortOrder:

View file

@ -1088,9 +1088,7 @@ class CoverPanel(GObject.GObject):
def _set_cover(self, current_album, new_album): def _set_cover(self, current_album, new_album):
self._cover_stack.set_visible_child(self._cover_spinner) self._cover_stack.set_visible_child(self._cover_spinner)
self._cover_spinner.start() self._cover_spinner.start()
current_hash = current_album.get_hash() if current_album else None if not current_album or not new_album or current_album != new_album:
new_hash = new_album.get_hash() if new_album else None
if not current_hash or not new_hash or current_hash != new_hash:
url = new_album.get_cover() if new_album else None url = new_album.get_cover() if new_album else None
if url and url is not "": if url and url is not "":
# Load image and draw it # Load image and draw it
@ -1365,7 +1363,7 @@ class PlaylistPanel(GObject.GObject):
self._playlist = playlist self._playlist = playlist
self._playlist_albums = {} self._playlist_albums = {}
for album in playlist: for album in playlist:
self._playlist_albums[album.get_hash()] = album self._playlist_albums[album.get_id()] = album
self._playlist_grid.set_model(None) self._playlist_grid.set_model(None)
self._playlist_grid.freeze_child_notify() self._playlist_grid.freeze_child_notify()
self._playlist_grid_model.clear() self._playlist_grid_model.clear()
@ -1393,7 +1391,7 @@ class PlaylistPanel(GObject.GObject):
', '.join(album.get_dates()), ', '.join(album.get_dates()),
Utils.create_artists_label(album) Utils.create_artists_label(album)
])), ])),
album.get_hash() album.get_id()
]) ])
if self._playlist_stop.is_set(): if self._playlist_stop.is_set():
@ -1690,8 +1688,8 @@ class LibraryPanel(GObject.GObject):
# Get selected album # Get selected album
path = self._library_grid_filter.convert_path_to_child_path(path) path = self._library_grid_filter.convert_path_to_child_path(path)
iter = self._library_grid_model.get_iter(path) iter = self._library_grid_model.get_iter(path)
hash = self._library_grid_model.get_value(iter, 2) id = self._library_grid_model.get_value(iter, 2)
album = self._albums[hash] album = self._albums[id]
self._selected_albums = [album] self._selected_albums = [album]
# Show standalone album # Show standalone album
@ -1712,15 +1710,15 @@ class LibraryPanel(GObject.GObject):
for path in widget.get_selected_items(): for path in widget.get_selected_items():
path = self._library_grid_filter.convert_path_to_child_path(path) path = self._library_grid_filter.convert_path_to_child_path(path)
iter = self._library_grid_model.get_iter(path) iter = self._library_grid_model.get_iter(path)
hash = self._library_grid_model.get_value(iter, 2) id = self._library_grid_model.get_value(iter, 2)
self._selected_albums.insert(0, self._albums[hash]) self._selected_albums.insert(0, self._albums[id])
def on_filter_visible(self, model, iter, data): def on_filter_visible(self, model, iter, data):
hash = model.get_value(iter, 2) id = model.get_value(iter, 2)
if not hash in self._albums.keys(): if not id in self._albums.keys():
return return
album = self._albums[hash] album = self._albums[id]
return album.filter(self._filter_string) return album.filter(self._filter_string)
@ -1729,8 +1727,8 @@ class LibraryPanel(GObject.GObject):
def on_selection_add_clicked(self, widget): def on_selection_add_clicked(self, widget):
hashes = [album.get_hash() for album in self._selected_albums] ids = [album.get_id() for album in self._selected_albums]
self.emit('queue-multiple', hashes) self.emit('queue-multiple', ids)
self._select_button.set_active(False) self._select_button.set_active(False)
@ -1739,12 +1737,12 @@ class LibraryPanel(GObject.GObject):
def on_standalone_play_clicked(self, widget): def on_standalone_play_clicked(self, widget):
self.emit('play', self._selected_albums[0].get_hash()) self.emit('play', self._selected_albums[0].get_id())
self._close_standalone() self._close_standalone()
def on_standalone_queue_clicked(self, widget): def on_standalone_queue_clicked(self, widget):
self.emit('queue', self._selected_albums[0].get_hash()) self.emit('queue', self._selected_albums[0].get_id())
self._close_standalone() self._close_standalone()
@ -1800,12 +1798,12 @@ class LibraryPanel(GObject.GObject):
def compare_albums(self, model, row1, row2, criterion): def compare_albums(self, model, row1, row2, criterion):
hash1 = model.get_value(row1, 2) id1 = model.get_value(row1, 2)
hash2 = model.get_value(row2, 2) id2 = model.get_value(row2, 2)
if hash1 == "" or hash2 == "": if not id1 or not id2:
return return
return client.MCGAlbum.compare(self._albums[hash1], self._albums[hash2], criterion) return client.MCGAlbum.compare(self._albums[id1], self._albums[id2], criterion)
def stop_threads(self): def stop_threads(self):
@ -1833,8 +1831,8 @@ class LibraryPanel(GObject.GObject):
n = len(albums) n = len(albums)
cache = client.MCGCache(host, size) cache = client.MCGCache(host, size)
self._grid_pixbufs.clear() self._grid_pixbufs.clear()
for hash in albums.keys(): for album_id in albums.keys():
album = albums[hash] album = albums[album_id]
pixbuf = None pixbuf = None
try: try:
pixbuf = Utils.load_thumbnail(cache, album, size) pixbuf = Utils.load_thumbnail(cache, album, size)
@ -1847,7 +1845,7 @@ class LibraryPanel(GObject.GObject):
Gtk.IconLookupFlags.FORCE_SVG & Gtk.IconLookupFlags.FORCE_SIZE Gtk.IconLookupFlags.FORCE_SVG & Gtk.IconLookupFlags.FORCE_SIZE
) )
if pixbuf is not None: if pixbuf is not None:
self._grid_pixbufs[album.get_hash()] = pixbuf self._grid_pixbufs[album.get_id()] = pixbuf
self._library_grid_model.append([ self._library_grid_model.append([
pixbuf, pixbuf,
GObject.markup_escape_text("\n".join([ GObject.markup_escape_text("\n".join([
@ -1855,7 +1853,7 @@ class LibraryPanel(GObject.GObject):
', '.join(album.get_dates()), ', '.join(album.get_dates()),
Utils.create_artists_label(album) Utils.create_artists_label(album)
])), ])),
hash album_id
]) ])
i += 1 i += 1
@ -1910,8 +1908,8 @@ class LibraryPanel(GObject.GObject):
for index in cur_range: for index in cur_range:
iter = grid_filter.convert_iter_to_child_iter(grid_filter[index].iter) iter = grid_filter.convert_iter_to_child_iter(grid_filter[index].iter)
if index in vis_range: if index in vis_range:
hash = grid_model.get_value(iter, 2) album_id = grid_model.get_value(iter, 2)
pixbuf = self._grid_pixbufs[hash] pixbuf = self._grid_pixbufs[album_id]
pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.NEAREST) pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.NEAREST)
else: else:
pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 1, 1) pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 1, 1)