]> kaliko git repositories - mpd-sima.git/commitdiff
New, slightly enhanced, meta Objects.
authorkaliko <kaliko@azylum.org>
Sun, 7 Dec 2014 14:11:56 +0000 (15:11 +0100)
committerkaliko <kaliko@azylum.org>
Sun, 7 Dec 2014 14:11:56 +0000 (15:11 +0100)
doc/Changelog
sima/client.py
sima/info.py
sima/lib/meta.py
sima/lib/player.py
sima/lib/simadb.py
sima/lib/simastr.py
sima/lib/track.py
sima/lib/webserv.py
tests/test_track.py

index b2f62efbd1c59c9af0e8ab2114ac55a65b829d4e..249e1e37ea577273e79090f3d406f6dd1ad4f3d3 100644 (file)
@@ -1,3 +1,10 @@
+MPD_sima v0.13.0
+
+ * 
+
+-- kaliko jack <kaliko@azylum.org>  UNRELEASED
+
+
 MPD_sima v0.12.3
 
  * Use albumartist to fetch similar artists
index 7c0e5a7c365758d1cced6d0b412b88486a6abbc8..1d3a0103c54353c4e74a4613fa68cda17489b9be 100644 (file)
@@ -58,6 +58,8 @@ def blacklist(artist=False, album=False, track=False):
     field = (artist, album, track)
     def decorated(func):
         def wrapper(*args, **kwargs):
+            if not args[0].database:
+                return func(*args, **kwargs)
             cls = args[0]
             boolgen = (bl for bl in field)
             bl_fun = (cls.database.get_bl_artist,
index e1262d4239f68183b12ce47973e8ca7b28820b01..8225b84d81c3fe5d910034a555030d8f7830fe97 100644 (file)
@@ -11,7 +11,7 @@ queue is getting short.
 """
 
 
-__version__ = '0.12.3'
+__version__ = '0.13.0'
 __author__ = 'kaliko jack'
 __email__ = 'kaliko@azylum.org'
 __url__ = 'git://git.kaliko.me/sima.git'
index 9265c3cddfe6103e36eb80d3203317295fa2aae7..1c3e511b48ea7faaf8eacef95d9177a0164aaa09 100644 (file)
 Defines some object to handle audio file metadata
 """
 
-from .simastr import SimaStr
+import re
+
+UUID_RE = r'^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$'
+
+def is_uuid4(uuid):
+    regexp = re.compile(UUID_RE, re.IGNORECASE)
+    if regexp.match(uuid):
+        return True
+    raise WrongUUID4(uuid)
 
 class MetaException(Exception):
     """Generic Meta Exception"""
     pass
 
-class NotSameArtist(MetaException):
+class WrongUUID4(MetaException):
     pass
 
 
 class Meta:
-    """Generic Class for Meta object"""
+    """Generic Class for Meta object
+    Meta(name=<str>[, mbid=UUID4])
+    """
 
     def __init__(self, **kwargs):
         self.name = None
-        self.mbid = None
-        if 'name' not in kwargs:
-            raise MetaException('need at least a "name" argument')
-        self.__dict__.update(kwargs)
+        self.__mbid = None
+        if 'name' not in kwargs or not kwargs.get('name'):
+            raise MetaException('Need a "name" argument')
+        if 'mbid' in kwargs and kwargs.get('mbid'):
+            is_uuid4(kwargs.get('mbid'))
+            # mbid immutable as hash rests on
+            self.__mbid = kwargs.pop('mbid')
+        self.__dict__.update(**kwargs)
 
     def __repr__(self):
-        fmt = '{0}(name="{1.name}", mbid="{1.mbid}")'
+        fmt = '{0}(name={1.name!r}, mbid={1.mbid!r})'
         return fmt.format(self.__class__.__name__, self)
 
     def __str__(self):
-        return str(self.name)
+        return self.name.__str__()
 
     def __eq__(self, other):
         """
-        Perform mbid equality test if present,
-        else fallback on fuzzy equality
+        Perform mbid equality test
         """
-        if hasattr(other, 'mbid'):
-            if other.mbid and self.mbid:
+        #if hasattr(other, 'mbid'):  # better isinstance?
+        if isinstance(other, Meta) and self.mbid and other.mbid:
+            if self.mbid and other.mbid:
                 return self.mbid == other.mbid
-        return SimaStr(str(self)) == SimaStr(str(other))
+        else:
+            return other.__str__() == self.__str__()
+        return False
 
     def __hash__(self):
-        if self.mbid is not None:
+        if self.mbid:
             return hash(self.mbid)
-        else:
-            return id(self)
-
-    def __bool__(self):  # empty name not possible for a valid obj
-        return bool(self.name)
+        return id(self)
 
-class Album(Meta):
-    """Info:
-    If a class that overrides __eq__() needs to retain the implementation of
-    __hash__() from a parent class, the interpreter must be told this explicitly
-    by setting __hash__ = <ParentClass>.__hash__.
-    """
-    __hash__ = Meta.__hash__
+    @property
+    def mbid(self):
+        return self.__mbid
 
-    def __init__(self, **kwargs):
-        super().__init__(**kwargs)
 
-    def __eq__(self, other):
-        """
-        Perform mbid equality test if present,
-        else fallback on self.name equality
-        """
-        if hasattr(other, 'mbid'):
-            if other.mbid and self.mbid:
-                return self.mbid == other.mbid
-        return str(self) == str(other)
+class Album(Meta):
 
     @property
     def album(self):
         return self.name
 
-
 class Artist(Meta):
 
-    def __init__(self, **kwargs):
-        self._aliases = set()
-        super().__init__(**kwargs)
-
-    def append(self, name):
-        self._aliases.update({name,})
+    def __init__(self, name=None, **kwargs):
+        """Artist object built from a mapping dict containing at least an
+        "artist" entry:
+            >>> trk = {'artist':'Art Name',
+            >>>        'albumartist': 'Alb Art Name',           # optional
+            >>>        'musicbrainz_artistid': '<UUID4>'    ,   # optional
+            >>>        'musicbrainz_albumartistid': '<UUID4>',  # optional
+            >>>       }
+            >>> artobj0 = Artist(**trk)
+            >>> artobj1 = Artist(name='Tool')
+        """
+        self.__aliases = set()
+        name = kwargs.get('artist', name)
+        mbid = kwargs.get('musicbrainz_artistid', None)
+        if (kwargs.get('albumartist', False) and
+                kwargs.get('albumartist') != 'Various Artists'):
+            name = kwargs.get('albumartist').split(', ')[0]
+        if (kwargs.get('musicbrainz_albumartistid', False) and
+                kwargs.get('musicbrainz_albumartistid') != '89ad4ac3-39f7-470e-963a-56509c546377'):
+            mbid = kwargs.get('musicbrainz_albumartistid').split(', ')[0]
+        super().__init__(name=name, mbid=mbid)
+
+    def add_alias(self, other):
+        if getattr(other, '__str__', None):
+            if callable(other.__str__):
+                self.__aliases |= {other.__str__()}
+        elif isinstance(other, Artist):
+            self.__aliases |= other._Artist__aliases
+        else:
+            raise MetaException('No __str__ method found in {!r}'.format(other))
 
     @property
     def names(self):
-        return self._aliases | {self.name,}
-
-    def __add__(self, other):
-        if isinstance(other, Artist):
-            if self.mbid == other.mbid:
-                res = Artist(**self.__dict__)
-                res._aliases.extend(other.names)
-                return res
-            else:
-                raise NotSameArtist('different mbids: {0} and {1}'.format(self, other))
+        return self.__aliases | {self.name,}
 
+# VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab
index ea57255f4713c6a6026c78ec11de625839ea31c1..cb562b5f9a3735d4a6edc2f72f3d6e15a6f1f0d1 100644 (file)
 
 # standard library import
 import logging
+from difflib import get_close_matches
 
+# local import
+from .simastr import SimaStr
+from ..utils.leven import levenshtein_ratio
 
 class Player(object):
     """Player interface to inherit from.
@@ -37,7 +41,6 @@ class Player(object):
         * current
         * queue
         * playlist
-        *
     """
 
     def __init__(self):
index 430e9c39fc2c141f13079b06eb5163a24dbb375a..280b23d228a8f885b3449920ca61f4f0f542fa20 100644 (file)
@@ -188,7 +188,7 @@ class SimaDB(object):
         get album information from the database.
         if not in database insert new entry.
         Attention: use Track() object!!
-        Use AlbumArtist tag is provided, fallback to Album tag
+        Use AlbumArtist tag if provided, fallback to Album tag
         """
         if with_connection:
             connection = with_connection
index 56edbb4d7e68b82a816ad2d30cb6a99698d78864..3e3c0812fc26dfda7725acf0b94e65d2368bc8d2 100644 (file)
@@ -156,40 +156,5 @@ class SimaStr(str):
         return hash(self) != hash(other)
 
 
-# Script starts here
-if __name__ == "__main__":
-    import time
-    print(SimaStr('Kétanoue'))
-    #from leven import levenshtein_ratio
-    CASES_LIST = list([
-        dict({
-                    'got': 'Guns N\' Roses (live)!! !',
-                'look for': 'Guns And Roses'}),
-        dict({
-                     'got': 'Jesus & Mary Chains',
-                'look for': 'The Jesus and Mary Chains - live'}),
-        dict({
-                         'got': 'Desert sessions',
-                    'look for': 'The Desert Sessions'}),
-        dict({
-                         'got': 'Têtes Raides',
-                    'look for': 'Les Têtes Raides'}),
-        dict({
-                         'got': 'Noir Désir',
-                    'look for': 'Noir Désir'}),
-        dict({
-                         'got': 'No Future',
-                    'look for': 'Future'})])
-
-    for case in CASES_LIST[:]:
-        str0 = case.get('got')
-        str1 = case.get('look for')
-        fz_str0 = SimaStr(str0)
-        fz_str1 = SimaStr(str1)
-        print(fz_str0, '\n', fz_str1)
-        print(fz_str0.stripped == fz_str1.stripped)
-        #print levenshtein_ratio(fz_str0.lower(), fz_str1.lower())
-        time.sleep(1)
-
 # VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab
index 6c2835146dc9c90021c20d67e249245dee07af93..1bed098f851cee6dd08d1601a3d34265bbd62bcd 100644 (file)
@@ -35,11 +35,11 @@ class Track:
         self.title = self.artist = self.album = self.albumartist = ''
         self.musicbrainz_artistid = self.musicbrainz_albumartistid = None
         self.pos = int(pos)
-        self._empty = False
         self._file = file
+        self._empty = False
+        self._time = time
         if not kwargs:
             self._empty = True
-        self._time = time
         self.__dict__.update(**kwargs)
         self.tags_to_collapse = ['artist', 'album', 'title', 'date',
                                  'genre', 'albumartist',
@@ -126,16 +126,10 @@ class Track:
             fmt = '%M:%S'
         return time.strftime(fmt, temps)
 
-    def get_artist(self):
+    @property
+    def Artist(self):
         """Get artist object from track"""
-        name = self.artist
-        mbid = self.musicbrainz_artistid
-        if self.albumartist and self.albumartist != 'Various Artists':
-            name = self.albumartist.split(', ')[0]
-        if (self.musicbrainz_albumartistid and
-            self.musicbrainz_albumartistid != '89ad4ac3-39f7-470e-963a-56509c546377'):
-            mbid = self.musicbrainz_albumartistid.split(', ')[0]
-        return Artist(name=name, mbid=mbid)
+        return Artist(**self.__dict__)
 
 # VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab
index 699385d7587c09d22f8553f71047880bb2cd22fc..547c9ceb388fed8db27eecb717c0329de657a49d 100644 (file)
@@ -201,10 +201,10 @@ class WebService(Plugin):
             if len(history) == 0:
                 break
             trk = history.popleft()
-            if (trk.get_artist() in extra_arts
-                or trk.get_artist() == last_trk.get_artist()):
+            if (trk.Artist in extra_arts
+                or trk.Artist == last_trk.Artist):
                 continue
-            extra_arts.append(trk.get_artist())
+            extra_arts.append(trk.Artist)
             depth += 1
         self.log.info('EXTRA ARTS: {}'.format(
             '/'.join([art.name for art in extra_arts])))
@@ -224,7 +224,7 @@ class WebService(Plugin):
         """
         if not self.player.playlist:
             return []
-        tolookfor = self.player.playlist[-1].get_artist()
+        tolookfor = self.player.playlist[-1].Artist
         self.log.info('Looking for artist similar to "{}"'.format(tolookfor))
         similar = self.ws_similar_artists(tolookfor)
         if not similar:
index b572221a3f2c214a42be23f6877f9ea27e80fae3..80a709e04fdfcb2034d2292a9215c7dc773e4373 100644 (file)
@@ -28,7 +28,7 @@ class TestTrackObject(unittest.TestCase):
         trk = Track(**DEVOLT)
         self.assertTrue(trk.collapsed_tags, 'Should have collapsed a tag')
         self.assertFalse(isinstance(trk.albumartist, list), 'Failed to collapse albumartist tag')
-        self.assertTrue(trk.get_artist().name in DEVOLT.get('albumartist'),
+        self.assertTrue(trk.Artist.name in DEVOLT.get('albumartist'),
                         'Failed to split multiple tag?')
 
     def test_boolean_type(self):
@@ -36,8 +36,8 @@ class TestTrackObject(unittest.TestCase):
 
     def test_albumartist(self):
         trk = Track(albumartist='album_artist', artist='track_artist')
-        self.assertEqual(trk.get_artist().name, 'album_artist')
+        self.assertEqual(trk.Artist.name, 'album_artist')
         trk = Track(artist='track_artist')
-        self.assertEqual(trk.get_artist().name, 'track_artist')
+        self.assertEqual(trk.Artist.name, 'track_artist')
 
 # vim: ai ts=4 sw=4 sts=4 expandtab