added property_adder mixin. moved all "property" attributes of all classes to a Meta class. moved attribute setting code to LastfmBase.

master
Abhinav Sarkar 2009-04-18 05:11:22 +00:00
parent 03c5cb0046
commit b30839a26f
21 changed files with 280 additions and 889 deletions

View File

@ -7,28 +7,20 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, searchable, taggable, crawlable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property, top_property
@crawlable
@taggable
@searchable
@cacheable
@mixin("crawlable", "taggable", "searchable",
"cacheable", "property_adder")
class Album(LastfmBase):
"""A class representing an album."""
def init(self,
api,
name = None,
artist = None,
id = None,
mbid = None,
url = None,
release_date = None,
image = None,
stats = None,
top_tags = None,
streamable = None,
subject = None):
class Meta(object):
properties = ["name", "artist", "top_tags",
"streamable"]
fillable_properties = ["id", "mbid", "url",
"release_date", "image", "stats", ]
def init(self, api, subject = None, **kwargs):
"""
Create an Album object by providing all the data related to it.
@ -63,108 +55,16 @@ class Album(LastfmBase):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
self._artist = artist
self._id = id
self._mbid = mbid
self._url = url
self._release_date = release_date
self._image = image
self._stats = stats and Stats(
super(Album, self).init(**kwargs)
self._stats = hasattr(self, "_stats") and Stats(
subject = self,
listeners = stats.listeners,
playcount = stats.playcount,
match = stats.match,
rank = stats.rank
)
self._top_tags = top_tags
self._streamable = streamable
listeners = self._stats.listeners,
playcount = self._stats.playcount,
match = self._stats.match,
rank = self._stats.rank
) or None
self._subject = subject
@property
def name(self):
"""
name of the album
@rtype: L{str}
"""
return self._name
@property
def artist(self):
"""
artist of the album
@rtype: L{Artist}
"""
return self._artist
@property
def id(self):
"""
id of the album
@rtype: L{int}
"""
if self._id is None:
self._fill_info()
return self._id
@property
def mbid(self):
"""
MBID of the album
@rtype: L{str}
"""
if self._mbid is None:
self._fill_info()
return self._mbid
@property
def url(self):
"""
url of the album's page
@rtype: L{str}
"""
if self._url is None:
self._fill_info()
return self._url
@property
def release_date(self):
"""
release date of the album
@rtype: C{datetime.datetime}
"""
if self._release_date is None:
self._fill_info()
return self._release_date
@property
def image(self):
"""
cover images of the album
@rtype: L{dict}
"""
if self._image is None:
self._fill_info()
return self._image
@property
def stats(self):
"""
stats related to the album
@rtype: L{Stats}
"""
if self._stats is None:
self._fill_info()
return self._stats
@property
def streamable(self):
"""
is the album streamable on last.fm
@rtype: L{bool}
"""
return self._streamable
@cached_property
def top_tags(self):
"""

View File

@ -7,29 +7,19 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, searchable, sharable, shoutable, taggable, crawlable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property, top_property
@crawlable
@shoutable
@sharable
@taggable
@searchable
@cacheable
@mixin("crawlable", "shoutable", "sharable",
"taggable", "searchable", "cacheable", "property_adder")
class Artist(LastfmBase):
"""A class representing an artist."""
def init(self,
api,
name = None,
mbid = None,
url = None,
image = None,
streamable = None,
stats = None,
similar = None,
top_tags = None,
bio = None,
subject = None):
class Meta(object):
properties = ["name", "similar", "top_tags"]
fillable_properties = ["mbid", "url", "image",
"streamable", "stats", "bio"]
def init(self, api, subject = None, **kwargs):
"""
Create an Artist object by providing all the data related to it.
@ -63,87 +53,23 @@ class Artist(LastfmBase):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
self._mbid = mbid
self._url = url
self._image = image
self._streamable = streamable
self._stats = stats and Stats(
super(Artist, self).init(**kwargs)
self._stats = hasattr(self, "_stats") and Stats(
subject = self,
listeners = stats.listeners,
playcount = stats.playcount,
weight = stats.weight,
match = stats.match,
rank = stats.rank
)
self._similar = similar
self._top_tags = top_tags
self._bio = bio and Wiki(
listeners = self._stats.listeners,
playcount = self._stats.playcount,
weight = self._stats.weight,
match = self._stats.match,
rank = self._stats.rank
) or None
self._bio = hasattr(self, "_bio") and Wiki(
subject = self,
published = bio.published,
summary = bio.summary,
content = bio.content
)
published = self._bio.published,
summary = self._bio.summary,
content = self._bio.content
) or None
self._subject = subject
@property
def name(self):
"""
name of the artist
@rtype: L{str}
"""
return self._name
@property
def mbid(self):
"""
MBID of the artist
@rtype: L{str}
"""
if self._mbid is None:
self._fill_info()
return self._mbid
@property
def url(self):
"""
url of the artist's page
@rtype: L{str}
"""
if self._url is None:
self._fill_info()
return self._url
@property
def image(self):
"""
images of the artist
@rtype: L{dict}
"""
if self._image is None:
self._fill_info()
return self._image
@property
def streamable(self):
"""
is the artist streamable on last.fm
@rtype: L{bool}
"""
if self._streamable is None:
self._fill_info()
return self._streamable
@property
def stats(self):
"""
stats for the artist
@rtype: L{Stats}
"""
if self._stats is None:
self._fill_info()
return self._stats
def get_similar(self, limit = None):
"""
Get the artists similar to this artist.
@ -181,7 +107,7 @@ class Artist(LastfmBase):
artists similar to this artist
@rtype: L{list} of L{Artist}
"""
if self._similar is None or len(self._similar) < 6:
if not hasattr(self, "_similar") or self._similar is None or len(self._similar) < 6:
return self.get_similar()
return self._similar[:]
@ -199,7 +125,7 @@ class Artist(LastfmBase):
top tags for the artist
@rtype: L{list} of L{Tag}
"""
if self._top_tags is None or len(self._top_tags) < 6:
if not hasattr(self, "_top_tags") or self._top_tags is None or len(self._top_tags) < 6:
params = self._default_params({'method': 'artist.getTopTags'})
data = self._api._fetch_data(params).find('toptags')
self._top_tags = [
@ -221,16 +147,6 @@ class Artist(LastfmBase):
"""
pass
@property
def bio(self):
"""
biography of the artist
@rtype: L{Wiki}
"""
if self._bio is None:
self._fill_info()
return self._bio
@cached_property
def events(self):
"""

View File

@ -9,6 +9,13 @@ __package__ = "lastfm"
class LastfmBase(object):
"""Base class for all the classes in this package"""
def init(self, **kwargs):
for k in kwargs:
if (k in self.Meta.properties or
(hasattr(self.Meta, 'fillable_properties') and
k in self.Meta.fillable_properties)):
setattr(self, "_{0}".format(k), kwargs[k])
def __eq__(self, other):
raise NotImplementedError("The subclass must override this method")

View File

@ -7,13 +7,15 @@ __package__ = "lastfm"
from functools import reduce
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable
from lastfm.mixin import mixin
from lastfm.util import logging
from operator import xor
@cacheable
@mixin("cacheable", "property_adder")
class Chart(LastfmBase):
"""The base class for all the chart classes"""
class Meta(object):
properties = ["subject", "start", "end", "stats"]
def init(self, subject, start, end, stats = None):
self._subject = subject
@ -21,22 +23,6 @@ class Chart(LastfmBase):
self._end = end
self._stats = stats
@property
def subject(self):
return self._subject
@property
def start(self):
return self._start
@property
def end(self):
return self._end
@property
def stats(self):
return self._stats
@staticmethod
def _check_chart_params(params, subject, start = None, end = None):
if xor(start is None, end is None):
@ -93,42 +79,42 @@ class Chart(LastfmBase):
self.end.strftime("%x"),
)
@mixin("property_adder")
class AlbumChart(Chart):
class Meta(object):
properties = ["albums"]
def init(self, subject, start, end, stats, albums):
super(AlbumChart, self).init(subject, start, end, stats)
self._albums = albums
@property
def albums(self):
return self._albums
@mixin("property_adder")
class ArtistChart(Chart):
class Meta(object):
properties = ["artists"]
def init(self, subject, start, end, stats, artists):
super(ArtistChart, self).init(subject, start, end, stats)
self._artists = artists
@property
def artists(self):
return self._artists
@mixin("property_adder")
class TrackChart(Chart):
class Meta(object):
properties = ["tracks"]
def init(self, subject, start, end, tracks, stats):
super(TrackChart, self).init(subject, start, end, stats)
self._tracks = tracks
@property
def tracks(self):
return self._tracks
@mixin("property_adder")
class TagChart(Chart):
class Meta(object):
properties = ["tags"]
def init(self, subject, start, end, tags, stats):
super(TagChart, self).init(subject, start, end, stats)
self._tags = tags
@property
def tags(self):
return self._tags
class WeeklyChart(Chart):
"""A class for representing the weekly charts"""
@staticmethod

View File

@ -7,32 +7,23 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, sharable, shoutable, crawlable
from lastfm.mixin import mixin
@crawlable
@shoutable
@sharable
@cacheable
@mixin("crawlable", "shoutable", "sharable",
"cacheable", "property_adder")
class Event(LastfmBase):
"""A class representing an event."""
STATUS_ATTENDING = 0
STATUS_MAYBE = 1
STATUS_NOT = 2
def init(self,
api,
id = None,
title = None,
artists = None,
headliner = None,
venue = None,
start_date = None,
description = None,
image = None,
url = None,
stats = None,
tag = None,
**kwargs):
class Meta(object):
properties = ["id", "title", "artists",
"headliner", "venue", "start_date",
"description", "image", "url",
"stats", "tag"]
def init(self, api, **kwargs):
"""
Create an Event object by providing all the data related to it.
@ -65,109 +56,12 @@ class Event(LastfmBase):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._id = id
self._title = title
self._artists = artists
self._headliner = headliner
self._venue = venue
self._start_date = start_date
self._description = description
self._image = image
self._url = url
self._stats = stats and Stats(
super(Event, self).init(**kwargs)
self._stats = hasattr(self, "_stats") and Stats(
subject = self,
attendance = stats.attendance,
reviews = stats.reviews
)
self._tag = tag
@property
def id(self):
"""
id of the event
@rtype: L{int}
"""
return self._id
@property
def title(self):
"""
title of the event
@rtype: L{str}
"""
return self._title
@property
def artists(self):
"""
artists performing in the event
@rtype: L{list} of L{Artist}
"""
return self._artists
@property
def headliner(self):
"""
headliner artist of the event
@rtype: L{Artist}
"""
return self._headliner
@property
def venue(self):
"""
venue of the event
@rtype: L{Venue}
"""
return self._venue
@property
def start_date(self):
"""
start date of the event
@rtype: C{datetime.datetime}
"""
return self._start_date
@property
def description(self):
"""
description of the event
@rtype: L{str}
"""
return self._description
@property
def image(self):
"""
poster of the event
@rtype: L{dict}
"""
return self._image
@property
def url(self):
"""
url of the event's page
@rtype: L{str}
"""
return self._url
@property
def stats(self):
"""
statistics for the event
@rtype: L{Stats}
"""
return self._stats
@property
def tag(self):
"""
tag for the event
@rtype: L{str}
"""
return self._tag
attendance = self._stats.attendance,
reviews = self._stats.reviews
) or None
def attend(self, status = STATUS_ATTENDING):
"""

View File

@ -8,7 +8,7 @@ __package__ = "lastfm"
from functools import reduce
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, crawlable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property, top_property, depaginate
class Geo(object):
@ -146,22 +146,17 @@ class Geo(object):
for t in data.findall('track')
]
@crawlable
@cacheable
@mixin("crawlable", "cacheable", "property_adder")
class Location(LastfmBase):
"""A class representing a location of an event"""
XMLNS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
def init(self,
api,
city = None,
country = None,
street = None,
postal_code = None,
latitude = None,
longitude = None,
timezone = None,
**kwargs):
class Meta(object):
properties = ["city", "country", "street",
"postal_code", "latitude", "longitude",
"timezone"]
def init(self, api, **kwargs):
"""
Create a Location object by providing all the data related to it.
@ -188,69 +183,7 @@ class Location(LastfmBase):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._city = city
self._country = country
self._street = street
self._postal_code = postal_code
self._latitude = latitude
self._longitude = longitude
self._timezone = timezone
@property
def city(self):
"""
city in which the location is situated
@rtype: L{str}
"""
return self._city
@property
def country(self):
"""
country in which the location is situated
@rtype: L{Country}
"""
return self._country
@property
def street(self):
"""
street in which the location is situated
@rtype: L{str}
"""
return self._street
@property
def postal_code(self):
"""
postal code of the location
@rtype: L{str}
"""
return self._postal_code
@property
def latitude(self):
"""
latitude of the location
@rtype: L{float}
"""
return self._latitude
@property
def longitude(self):
"""
longitude of the location
@rtype: L{float}
"""
return self._longitude
@property
def timezone(self):
"""
timezone in which the location is situated
@rtype: L{str}
"""
return self._timezone
super(Location, self).init(**kwargs)
@cached_property
def top_tracks(self):
@ -280,11 +213,8 @@ class Location(LastfmBase):
@return: events taking place at the location
@rtype: L{lazylist} of L{Event}
"""
return Geo.get_events(self._api,
self.city,
self.latitude,
self.longitude,
distance)
return Geo.get_events(self._api, self.city,
self.latitude, self.longitude, distance)
@cached_property
def events(self):
@ -335,8 +265,7 @@ class Location(LastfmBase):
else:
return "<lastfm.geo.Location: %s>" % self.city
@crawlable
@cacheable
@mixin("crawlable", "cacheable", "property_adder")
class Country(LastfmBase):
"""A class representing a country."""
ISO_CODES = {
@ -587,7 +516,11 @@ class Country(LastfmBase):
'ZM': 'Zambia',
'ZW': 'Zimbabwe'}
"""ISO Codes of the countries"""
def init(self, api, name = None, **kwargs):
class Meta(object):
properties = ["name"]
def init(self, api, **kwargs):
"""
Create a Country object by providing all the data related to it.
@param api: an instance of L{Api}
@ -601,15 +534,7 @@ class Country(LastfmBase):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
@property
def name(self):
"""
name of the country
@rtype: L{str}
"""
return self._name
super(Country, self).init(**kwargs)
@cached_property
def top_artists(self):

View File

@ -7,14 +7,18 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, chartable
from lastfm.mixin import mixin, chartable
from lastfm.decorators import cached_property, depaginate
@chartable(['album', 'artist', 'track', 'tag'])
@cacheable
@chartable('album', 'artist', 'track', 'tag')
@mixin("cacheable", "property_adder")
class Group(LastfmBase):
"""A class representing a group on last.fm."""
def init(self, api, name = None, **kwargs):
class Meta(object):
properties = ["name"]
def init(self, api, **kwargs):
"""
Create a Group object by providing all the data related to it.
@ -30,15 +34,7 @@ class Group(LastfmBase):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
@property
def name(self):
"""
name of the group
@rtype: L{str}
"""
return self._name
super(Group, self).init(**kwargs)
@cached_property
@depaginate

View File

@ -12,6 +12,15 @@ from lastfm.mixin._shoutable import shoutable
from lastfm.mixin._taggable import taggable
from lastfm.mixin._chartable import chartable
from lastfm.mixin._crawlable import crawlable
from lastfm.mixin._propertyadder import property_adder
def mixin(*mixins):
def wrapper(cls):
for m in reversed(mixins):
if m in __all__:
cls = eval(m)(cls)
return cls
return wrapper
__all__ = ['cacheable', 'searchable', 'sharable', 'shoutable', 'taggable'
'chartable','crawlable']
'chartable','crawlable', 'property_adder']

View File

@ -8,7 +8,7 @@ __package__ = "lastfm.mixin"
from lastfm.util import lazylist, logging
from lastfm.decorators import cached_property
def chartable(chart_types):
def chartable(*chart_types):
def wrapper(cls):
@cached_property
def weekly_chart_list(self):

View File

@ -0,0 +1,43 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
def property_adder(cls):
for p in cls.Meta.properties:
if not hasattr(cls, p):
def wrapper():
q = p
@property
def get(self):
try:
return getattr(self, "_{0}".format(q))
except AttributeError:
return None
return get
setattr(cls, p, wrapper())
if hasattr(cls.Meta, 'fillable_properties'):
for p in cls.Meta.fillable_properties:
if not hasattr(cls, p):
def wrapper():
q = p
@property
def get(self):
fill = False
try:
attrval = getattr(self, "_{0}".format(q))
if attrval is None:
fill = True
else:
return attrval
except AttributeError:
fill = True
if fill:
self._fill_info()
return getattr(self, "_{0}".format(q))
return get
setattr(cls, p, wrapper())
return cls

View File

@ -6,12 +6,16 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property
@cacheable
@mixin("cacheable", "property_adder")
class Playlist(LastfmBase):
"""A class representing an XPSF playlist."""
class Meta(object):
properties = ["url"]
def init(self, api, url, **kwargs):
self._api = api
self._data = None
@ -25,11 +29,6 @@ class Playlist(LastfmBase):
ElementTree.ElementTree(self._api._fetch_data(params)[0]).write(tmp)
return tmp.getvalue()
@property
def url(self):
"""url of the playlist"""
return self._url
@staticmethod
def fetch(api, url):
return Playlist(api, url = url)

View File

@ -6,33 +6,18 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property
@cacheable
@mixin("cacheable", "property_adder")
class Shout(LastfmBase):
"""A class representing a shout."""
def init(self,
body = None,
author = None,
date = None,
**kwargs):
self._body = body
self._author = author
self._date = date
class Meta(object):
properties = ["body", "author", "date"]
@cached_property
def body(self):
return self._body
@cached_property
def author(self):
return self._author
@cached_property
def date(self):
return self._date
def init(self, **kwargs):
super(Shout, self).init(**kwargs)
@staticmethod
def _hash_func(*args, **kwds):

View File

@ -5,80 +5,27 @@ __version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
class Stats(object):
from lastfm.base import LastfmBase
from lastfm.mixin import mixin
@mixin("property_adder")
class Stats(LastfmBase):
"""A class representing the stats of an artist."""
def __init__(self,
subject,
listeners = None,
playcount = None,
tagcount = None,
count = None,
match = None,
rank = None,
weight = None,
attendance = None,
reviews = None,):
class Meta(object):
properties = ["listeners", "playcount",
"tagcount", "count", "match", "rank",
"weight", "attendance", "reviews"]
def __init__(self, subject, **kwargs):
self._subject = subject
self._listeners = listeners
self._playcount = playcount
self._tagcount = tagcount
self._count = count
self._match = match
self._rank = rank
self._weight = weight
self._attendance = attendance
self._reviews = reviews
super(Stats, self).init(**kwargs)
@property
def subject(self):
"""subject of the stats"""
return self._subject
@property
def rank(self):
"""rank of the subject"""
return self._rank
@property
def listeners(self):
"""number of listeners of the subject"""
return self._listeners
@property
def playcount(self):
"""playcount of the subject"""
return self._playcount
@property
def tagcount(self):
"""tagcount of the subject"""
return self._tagcount
@property
def count(self):
"""count of the subject"""
return self._count
@property
def match(self):
"""match of the subject"""
return self._match
@property
def weight(self):
"""weight of the subject"""
return self._weight
@property
def attendance(self):
"""attendance of the subject"""
return self._attendance
@property
def reviews(self):
"""reviews of the subject"""
return self._reviews
def __repr__(self):
if hasattr(self._subject, 'name'):
return "<lastfm.Stats: for '%s'>" % self._subject.name

View File

@ -6,53 +6,27 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, searchable, chartable, crawlable
from lastfm.mixin import mixin, chartable
from lastfm.decorators import cached_property, top_property
@crawlable
@chartable(['artist'])
@searchable
@cacheable
@chartable("artist")
@mixin("crawlable", "searchable", "cacheable", "property_adder")
class Tag(LastfmBase):
"""A class representing a tag."""
def init(self,
api,
name = None,
url = None,
streamable = None,
stats = None,
**kwargs):
class Meta(object):
properties = ["name", "url", "streamable", "stats"]
def init(self, api, **kwargs):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
self._url = url
self._streamable = streamable
self._stats = stats and Stats(
super(Tag, self).init(**kwargs)
self._stats = hasattr(self, '_stats') and Stats(
subject = self,
count = stats.count,
rank = stats.rank
)
@property
def name(self):
"""name of the tag"""
return self._name
@property
def url(self):
"""url of the tag's page"""
return self._url
@property
def streamable(self):
"""is the tag streamable"""
return self._streamable
@property
def stats(self):
return self._stats
count = self._stats.count,
rank = self._stats.rank
) or None
@cached_property
def similar(self):

View File

@ -6,141 +6,38 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, searchable, sharable, taggable, crawlable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property, top_property
@crawlable
@sharable
@taggable
@searchable
@cacheable
@mixin("crawlable", "sharable", "taggable",
"searchable", "cacheable", "property_adder")
class Track(LastfmBase):
"""A class representing a track."""
def init(self,
api,
name = None,
mbid = None,
url = None,
duration = None,
streamable = None,
full_track = None,
artist = None,
album = None,
position = None,
image = None,
stats = None,
played_on = None,
loved_on = None,
wiki = None,
subject = None):
class Meta(object):
properties = ["id", "name", "mbid", "url", "duration",
"artist", "image", "stats", "played_on", "loved_on",
"subject"]
fillable_properties = ["streamable", "full_track",
"album", "position", "wiki"]
def init(self, api, **kwargs):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._id = id
self._name = name
self._mbid = mbid
self._url = url
self._duration = duration
self._streamable = streamable
self._full_track = full_track
self._artist = artist
self._album = album
self._position = position
self._image = image
self._stats = stats and Stats(
super(Track, self).init(**kwargs)
self._stats = hasattr(self, "_stats") and Stats(
subject = self,
match = stats.match,
playcount = stats.playcount,
rank = stats.rank,
listeners = stats.listeners,
)
self._played_on = played_on
self._loved_on = loved_on
self._wiki = wiki and Wiki(
match = self._stats.match,
playcount = self._stats.playcount,
rank = self._stats.rank,
listeners = self._stats.listeners,
) or None
self._wiki = hasattr(self, "_wiki") and Wiki(
subject = self,
published = wiki.published,
summary = wiki.summary,
content = wiki.content
)
self._subject = subject
@property
def id(self):
"""id of the track"""
return self._id
@property
def name(self):
"""name of the track"""
return self._name
@property
def mbid(self):
"""mbid of the track"""
return self._mbid
@property
def url(self):
"""url of the tracks's page"""
return self._url
@property
def duration(self):
"""duration of the tracks's page"""
return self._duration
@property
def streamable(self):
"""is the track streamable"""
if self._streamable is None:
self._fill_info()
return self._streamable
@property
def full_track(self):
"""is the full track streamable"""
if self._full_track is None:
self._fill_info()
return self._full_track
@property
def artist(self):
"""artist of the track"""
return self._artist
@property
def album(self):
"""artist of the track"""
if self._album is None:
self._fill_info()
return self._album
@property
def position(self):
"""position of the track"""
if self._position is None:
self._fill_info()
return self._position
@property
def image(self):
"""image of the track's album cover"""
return self._image
@property
def stats(self):
"""stats of the track"""
return self._stats
@property
def played_on(self):
"""datetime the track was last played"""
return self._played_on
@property
def loved_on(self):
"""datetime the track was marked 'loved'"""
return self._loved_on
published = self._wiki.published,
summary = self._wiki.summary,
content = self._wiki.content
) or None
@property
def wiki(self):

View File

@ -6,66 +6,34 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, shoutable, chartable, crawlable
from lastfm.mixin import chartable, mixin
import lastfm.playlist
from lastfm.decorators import (
cached_property, top_property, authentication_required, depaginate)
@crawlable
@chartable(['album', 'artist', 'track', 'tag'])
@shoutable
@cacheable
@chartable('album', 'artist', 'track', 'tag')
@mixin("crawlable", "shoutable", "cacheable", "property_adder")
class User(LastfmBase):
"""A class representing an user."""
def init(self,
api,
name = None,
real_name = None,
url = None,
image = None,
stats = None,
**kwargs):
class Meta(object):
properties = ["name", "real_name",
"url", "image", "stats"]
def init(self, api, **kwargs):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._name = name
self._real_name = real_name
self._url = url
self._image = image
self._stats = stats and Stats(
super(User, self).init(**kwargs)
self._stats = hasattr(self, "_stats") and Stats(
subject = self,
match = stats.match,
weight = stats.weight,
playcount = stats.playcount
)
match = self._stats.match,
weight = self._stats.weight,
playcount = self._stats.playcount
) or None
self._library = User.Library(api, self)
@property
def name(self):
"""name of the user"""
return self._name
@property
def real_name(self):
"""real name of the user"""
return self._real_name
@property
def url(self):
"""url of the user's page"""
return self._url
@property
def image(self):
"""image of the user"""
return self._image
@property
def stats(self):
"""stats for the user"""
return self._stats
@property
@authentication_required
def language(self):
@ -340,8 +308,8 @@ class User(LastfmBase):
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
stats = Stats(
subject = a.findtext('name'),
playcount = int(a.findtext('playcount')),
rank = int(a.attrib['rank'])
playcount = a.findtext('playcount').strip() and int(a.findtext('playcount')),
rank = a.attrib['rank'].strip() and int(a.attrib['rank'])
)
)
for a in data.findall('album')
@ -372,7 +340,7 @@ class User(LastfmBase):
stats = Stats(
subject = a.findtext('name'),
rank = a.attrib['rank'].strip() and int(a.attrib['rank']) or None,
playcount = a.findtext('playcount') and int(a.findtext('playcount')) or None
playcount = a.findtext('playcount').strip() and int(a.findtext('playcount')) or None
),
url = a.findtext('url'),
streamable = (a.findtext('streamable') == "1"),
@ -555,8 +523,13 @@ class User(LastfmBase):
def __repr__(self):
return "<lastfm.User: %s>" % self.name
@mixin("property_adder")
class Playlist(lastfm.playlist.Playlist):
"""A class representing a playlist belonging to the user."""
class Meta(object):
properties = ["id", "title", "date", "size", "creator"]
def init(self, api, id, title, date, size, creator):
super(User.Playlist, self).init(api, "lastfm://playlist/%s" % id)
self._id = id
@ -565,26 +538,6 @@ class User(LastfmBase):
self._size = size
self._creator = creator
@property
def id(self):
return self._id
@property
def title(self):
return self._title
@property
def date(self):
return self._date
@property
def size(self):
return self._size
@property
def creator(self):
return self._creator
@property
def user(self):
return self._creator

View File

@ -4,7 +4,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm.util"
from lastfm.util.wormhole import Wormhole
from lastfm.util.lazylist import lazylist
from lastfm.util._lazylist import lazylist
from lastfm.util.safelist import SafeList
from lastfm.util.filecache import FileCache
from lastfm.util.objectcache import ObjectCache

View File

@ -6,48 +6,21 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixin import cacheable, searchable, crawlable
from lastfm.mixin import mixin
from lastfm.decorators import cached_property, depaginate
@crawlable
@searchable
@cacheable
@mixin("crawlable", "searchable", "cacheable", "property_adder")
class Venue(LastfmBase):
"""A class representing a venue of an event"""
def init(self,
api,
id = None,
name = None,
location = None,
url = None,
**kwargs):
class Meta(object):
properties = ["id", "name", "location", "url"]
def init(self, api, **kwargs):
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
self._api = api
self._id = id
self._name = name
self._location = location
self._url = url
@property
def id(self):
"""id of the venue"""
return self._id
@property
def name(self):
"""name of the venue"""
return self._name
@property
def location(self):
"""location of the event"""
return self._location
@property
def url(self):
"""url of the event's page"""
return self._url
super(Venue, self).init(**kwargs)
@cached_property
def events(self):

View File

@ -5,8 +5,15 @@ __version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.mixin import mixin
@mixin("property_adder")
class Wiki(object):
"""A class representing the information from the wiki of the subject."""
class Meta(object):
properties = ["subject", "published", "summary", "content"]
def __init__(self,
subject,
published = None,
@ -17,25 +24,5 @@ class Wiki(object):
self._summary = summary
self._content = content
@property
def subject(self):
"""artist for which the biography is"""
return self._subject
@property
def published(self):
"""publication time of the biography"""
return self._published
@property
def summary(self):
"""summary of the biography"""
return self._summary
@property
def content(self):
"""content of the biography"""
return self._content
def __repr__(self):
return "<lastfm.Wiki: for %s '%s'>" % (self.subject.__class__.__name__, self.subject.name)