mopidy/mopidy/models.py
2010-07-01 00:39:50 +02:00

214 lines
5.7 KiB
Python

from copy import copy
from mopidy.mpd import serializer
class ImmutableObject(object):
"""
Superclass for immutable objects whose fields can only be modified via the
constructor.
:param kwargs: kwargs to set as fields on the object
:type kwargs: any
"""
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
if not hasattr(self, key):
raise TypeError('__init__() got an unexpected keyword ' + \
'argument \'%s\'' % key)
self.__dict__[key] = value
def __setattr__(self, name, value):
if name.startswith('_'):
return super(ImmutableObject, self).__setattr__(name, value)
raise AttributeError('Object is immutable.')
def __hash__(self):
hash_sum = 0
for key, value in self.__dict__.items():
hash_sum += hash(key) + hash(value)
return hash_sum
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
return not self.__eq__(other)
class Artist(ImmutableObject):
"""
:param uri: artist URI
:type uri: string
:param name: artist name
:type name: string
"""
#: The artist URI. Read-only.
uri = None
#: The artist name. Read-only.
name = None
class Album(ImmutableObject):
"""
:param uri: album URI
:type uri: string
:param name: album name
:type name: string
:param artists: album artists
:type artists: list of :class:`Artist`
:param num_tracks: number of tracks in album
:type num_tracks: integer
"""
#: The album URI. Read-only.
uri = None
#: The album name. Read-only.
name = None
#: The number of tracks in the album. Read-only.
num_tracks = 0
def __init__(self, *args, **kwargs):
self._artists = frozenset(kwargs.pop('artists', []))
super(Album, self).__init__(*args, **kwargs)
@property
def artists(self):
"""List of :class:`Artist` elements. Read-only."""
return list(self._artists)
class Track(ImmutableObject):
"""
:param uri: track URI
:type uri: string
:param name: track name
:type name: string
:param artists: track artists
:type artists: list of :class:`Artist`
:param album: track album
:type album: :class:`Album`
:param track_no: track number in album
:type track_no: integer
:param date: track release date
:type date: :class:`datetime.date`
:param length: track length in milliseconds
:type length: integer
:param bitrate: bitrate in kbit/s
:type bitrate: integer
:param id: track ID (unique and non-changing as long as the process lives)
:type id: integer
"""
#: The track URI. Read-only.
uri = None
#: The track name. Read-only.
name = None
#: The track :class:`Album`. Read-only.
album = None
#: The track number in album. Read-only.
track_no = 0
#: The track release date. Read-only.
date = None
#: The track length in milliseconds. Read-only.
length = None
#: The track's bitrate in kbit/s. Read-only.
bitrate = None
#: The track ID. Read-only.
id = None
def __init__(self, *args, **kwargs):
self._artists = frozenset(kwargs.pop('artists', []))
super(Track, self).__init__(*args, **kwargs)
@property
def artists(self):
"""List of :class:`Artist`. Read-only."""
return list(self._artists)
def mpd_format(self, *args, **kwargs):
return serializer.track_to_mpd_format(self, *args, **kwargs)
class Playlist(ImmutableObject):
"""
:param uri: playlist URI
:type uri: string
:param name: playlist name
:type name: string
:param tracks: playlist's tracks
:type tracks: list of :class:`Track` elements
:param last_modified: playlist's modification time
:type last_modified: :class:`datetime.datetime`
"""
#: The playlist URI. Read-only.
uri = None
#: The playlist name. Read-only.
name = None
#: The playlist modification time. Read-only.
#:
#: :class:`datetime.datetime`, or :class:`None` if unknown.
last_modified = None
def __init__(self, *args, **kwargs):
self._tracks = kwargs.pop('tracks', [])
super(Playlist, self).__init__(*args, **kwargs)
@property
def tracks(self):
"""List of :class:`Track` elements. Read-only."""
return copy(self._tracks)
@property
def length(self):
"""The number of tracks in the playlist. Read-only."""
return len(self._tracks)
def mpd_format(self, *args, **kwargs):
return serializer.playlist_to_mpd_format(self, *args, **kwargs)
def with_(self, uri=None, name=None, tracks=None, last_modified=None):
"""
Create a new playlist object with the given values. The values that are
not given are taken from the object the method is called on.
Does not change the object on which it is called.
:param uri: playlist URI
:type uri: string
:param name: playlist name
:type name: string
:param tracks: playlist's tracks
:type tracks: list of :class:`Track` elements
:param last_modified: playlist's modification time
:type last_modified: :class:`datetime.datetime`
:rtype: :class:`Playlist`
"""
if uri is None:
uri = self.uri
if name is None:
name = self.name
if tracks is None:
tracks = self.tracks
if last_modified is None:
last_modified = self.last_modified
return Playlist(uri=uri, name=name, tracks=tracks,
last_modified=last_modified)