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
parent e318194274
commit 670d50cefd
3 changed files with 55 additions and 50 deletions

View file

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

View file

@ -3,6 +3,7 @@
import gi
gi.require_version('Gtk', '3.0')
import hashlib
import locale
import os
import urllib
@ -75,6 +76,15 @@ class Utils:
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:

View file

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