added property_adder mixin. moved all "property" attributes of all classes to a Meta class. moved attribute setting code to LastfmBase.
This commit is contained in:
parent
03c5cb0046
commit
b30839a26f
136
lastfm/album.py
136
lastfm/album.py
|
@ -7,28 +7,20 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
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
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "taggable", "searchable",
|
||||||
@taggable
|
"cacheable", "property_adder")
|
||||||
@searchable
|
|
||||||
@cacheable
|
|
||||||
class Album(LastfmBase):
|
class Album(LastfmBase):
|
||||||
"""A class representing an album."""
|
"""A class representing an album."""
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["name", "artist", "top_tags",
|
||||||
name = None,
|
"streamable"]
|
||||||
artist = None,
|
fillable_properties = ["id", "mbid", "url",
|
||||||
id = None,
|
"release_date", "image", "stats", ]
|
||||||
mbid = None,
|
|
||||||
url = None,
|
def init(self, api, subject = None, **kwargs):
|
||||||
release_date = None,
|
|
||||||
image = None,
|
|
||||||
stats = None,
|
|
||||||
top_tags = None,
|
|
||||||
streamable = None,
|
|
||||||
subject = None):
|
|
||||||
"""
|
"""
|
||||||
Create an Album object by providing all the data related to it.
|
Create an Album object by providing all the data related to it.
|
||||||
|
|
||||||
|
@ -63,108 +55,16 @@ class Album(LastfmBase):
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(Album, self).init(**kwargs)
|
||||||
self._artist = artist
|
self._stats = hasattr(self, "_stats") and Stats(
|
||||||
self._id = id
|
subject = self,
|
||||||
self._mbid = mbid
|
listeners = self._stats.listeners,
|
||||||
self._url = url
|
playcount = self._stats.playcount,
|
||||||
self._release_date = release_date
|
match = self._stats.match,
|
||||||
self._image = image
|
rank = self._stats.rank
|
||||||
self._stats = stats and Stats(
|
) or None
|
||||||
subject = self,
|
|
||||||
listeners = stats.listeners,
|
|
||||||
playcount = stats.playcount,
|
|
||||||
match = stats.match,
|
|
||||||
rank = stats.rank
|
|
||||||
)
|
|
||||||
self._top_tags = top_tags
|
|
||||||
self._streamable = streamable
|
|
||||||
self._subject = subject
|
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
|
@cached_property
|
||||||
def top_tags(self):
|
def top_tags(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -84,7 +84,7 @@ class Api(object):
|
||||||
self._debug = None
|
self._debug = None
|
||||||
if self._debug is not None:
|
if self._debug is not None:
|
||||||
Wormhole.enable()
|
Wormhole.enable()
|
||||||
logging.set_api(self)
|
logging.set_api(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_key(self):
|
def api_key(self):
|
||||||
|
|
136
lastfm/artist.py
136
lastfm/artist.py
|
@ -7,29 +7,19 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
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
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "shoutable", "sharable",
|
||||||
@shoutable
|
"taggable", "searchable", "cacheable", "property_adder")
|
||||||
@sharable
|
|
||||||
@taggable
|
|
||||||
@searchable
|
|
||||||
@cacheable
|
|
||||||
class Artist(LastfmBase):
|
class Artist(LastfmBase):
|
||||||
"""A class representing an artist."""
|
"""A class representing an artist."""
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["name", "similar", "top_tags"]
|
||||||
name = None,
|
fillable_properties = ["mbid", "url", "image",
|
||||||
mbid = None,
|
"streamable", "stats", "bio"]
|
||||||
url = None,
|
|
||||||
image = None,
|
def init(self, api, subject = None, **kwargs):
|
||||||
streamable = None,
|
|
||||||
stats = None,
|
|
||||||
similar = None,
|
|
||||||
top_tags = None,
|
|
||||||
bio = None,
|
|
||||||
subject = None):
|
|
||||||
"""
|
"""
|
||||||
Create an Artist object by providing all the data related to it.
|
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")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(Artist, self).init(**kwargs)
|
||||||
self._mbid = mbid
|
self._stats = hasattr(self, "_stats") and Stats(
|
||||||
self._url = url
|
subject = self,
|
||||||
self._image = image
|
listeners = self._stats.listeners,
|
||||||
self._streamable = streamable
|
playcount = self._stats.playcount,
|
||||||
self._stats = stats and Stats(
|
weight = self._stats.weight,
|
||||||
subject = self,
|
match = self._stats.match,
|
||||||
listeners = stats.listeners,
|
rank = self._stats.rank
|
||||||
playcount = stats.playcount,
|
) or None
|
||||||
weight = stats.weight,
|
self._bio = hasattr(self, "_bio") and Wiki(
|
||||||
match = stats.match,
|
subject = self,
|
||||||
rank = stats.rank
|
published = self._bio.published,
|
||||||
)
|
summary = self._bio.summary,
|
||||||
self._similar = similar
|
content = self._bio.content
|
||||||
self._top_tags = top_tags
|
) or None
|
||||||
self._bio = bio and Wiki(
|
|
||||||
subject = self,
|
|
||||||
published = bio.published,
|
|
||||||
summary = bio.summary,
|
|
||||||
content = bio.content
|
|
||||||
)
|
|
||||||
self._subject = subject
|
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):
|
def get_similar(self, limit = None):
|
||||||
"""
|
"""
|
||||||
Get the artists similar to this artist.
|
Get the artists similar to this artist.
|
||||||
|
@ -181,7 +107,7 @@ class Artist(LastfmBase):
|
||||||
artists similar to this artist
|
artists similar to this artist
|
||||||
@rtype: L{list} of L{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.get_similar()
|
||||||
return self._similar[:]
|
return self._similar[:]
|
||||||
|
|
||||||
|
@ -199,7 +125,7 @@ class Artist(LastfmBase):
|
||||||
top tags for the artist
|
top tags for the artist
|
||||||
@rtype: L{list} of L{Tag}
|
@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'})
|
params = self._default_params({'method': 'artist.getTopTags'})
|
||||||
data = self._api._fetch_data(params).find('toptags')
|
data = self._api._fetch_data(params).find('toptags')
|
||||||
self._top_tags = [
|
self._top_tags = [
|
||||||
|
@ -221,16 +147,6 @@ class Artist(LastfmBase):
|
||||||
"""
|
"""
|
||||||
pass
|
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
|
@cached_property
|
||||||
def events(self):
|
def events(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,6 +9,13 @@ __package__ = "lastfm"
|
||||||
class LastfmBase(object):
|
class LastfmBase(object):
|
||||||
"""Base class for all the classes in this package"""
|
"""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):
|
def __eq__(self, other):
|
||||||
raise NotImplementedError("The subclass must override this method")
|
raise NotImplementedError("The subclass must override this method")
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,15 @@ __package__ = "lastfm"
|
||||||
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable
|
from lastfm.mixin import mixin
|
||||||
from lastfm.util import logging
|
from lastfm.util import logging
|
||||||
from operator import xor
|
from operator import xor
|
||||||
|
|
||||||
@cacheable
|
@mixin("cacheable", "property_adder")
|
||||||
class Chart(LastfmBase):
|
class Chart(LastfmBase):
|
||||||
"""The base class for all the chart classes"""
|
"""The base class for all the chart classes"""
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["subject", "start", "end", "stats"]
|
||||||
|
|
||||||
def init(self, subject, start, end, stats = None):
|
def init(self, subject, start, end, stats = None):
|
||||||
self._subject = subject
|
self._subject = subject
|
||||||
|
@ -21,22 +23,6 @@ class Chart(LastfmBase):
|
||||||
self._end = end
|
self._end = end
|
||||||
self._stats = stats
|
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
|
@staticmethod
|
||||||
def _check_chart_params(params, subject, start = None, end = None):
|
def _check_chart_params(params, subject, start = None, end = None):
|
||||||
if xor(start is None, end is None):
|
if xor(start is None, end is None):
|
||||||
|
@ -93,42 +79,42 @@ class Chart(LastfmBase):
|
||||||
self.end.strftime("%x"),
|
self.end.strftime("%x"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@mixin("property_adder")
|
||||||
class AlbumChart(Chart):
|
class AlbumChart(Chart):
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["albums"]
|
||||||
|
|
||||||
def init(self, subject, start, end, stats, albums):
|
def init(self, subject, start, end, stats, albums):
|
||||||
super(AlbumChart, self).init(subject, start, end, stats)
|
super(AlbumChart, self).init(subject, start, end, stats)
|
||||||
self._albums = albums
|
self._albums = albums
|
||||||
|
|
||||||
@property
|
@mixin("property_adder")
|
||||||
def albums(self):
|
|
||||||
return self._albums
|
|
||||||
|
|
||||||
class ArtistChart(Chart):
|
class ArtistChart(Chart):
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["artists"]
|
||||||
|
|
||||||
def init(self, subject, start, end, stats, artists):
|
def init(self, subject, start, end, stats, artists):
|
||||||
super(ArtistChart, self).init(subject, start, end, stats)
|
super(ArtistChart, self).init(subject, start, end, stats)
|
||||||
self._artists = artists
|
self._artists = artists
|
||||||
|
|
||||||
@property
|
@mixin("property_adder")
|
||||||
def artists(self):
|
|
||||||
return self._artists
|
|
||||||
|
|
||||||
class TrackChart(Chart):
|
class TrackChart(Chart):
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["tracks"]
|
||||||
|
|
||||||
def init(self, subject, start, end, tracks, stats):
|
def init(self, subject, start, end, tracks, stats):
|
||||||
super(TrackChart, self).init(subject, start, end, stats)
|
super(TrackChart, self).init(subject, start, end, stats)
|
||||||
self._tracks = tracks
|
self._tracks = tracks
|
||||||
|
|
||||||
@property
|
@mixin("property_adder")
|
||||||
def tracks(self):
|
|
||||||
return self._tracks
|
|
||||||
|
|
||||||
class TagChart(Chart):
|
class TagChart(Chart):
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["tags"]
|
||||||
|
|
||||||
def init(self, subject, start, end, tags, stats):
|
def init(self, subject, start, end, tags, stats):
|
||||||
super(TagChart, self).init(subject, start, end, stats)
|
super(TagChart, self).init(subject, start, end, stats)
|
||||||
self._tags = tags
|
self._tags = tags
|
||||||
|
|
||||||
@property
|
|
||||||
def tags(self):
|
|
||||||
return self._tags
|
|
||||||
|
|
||||||
class WeeklyChart(Chart):
|
class WeeklyChart(Chart):
|
||||||
"""A class for representing the weekly charts"""
|
"""A class for representing the weekly charts"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
138
lastfm/event.py
138
lastfm/event.py
|
@ -7,32 +7,23 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable, sharable, shoutable, crawlable
|
from lastfm.mixin import mixin
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "shoutable", "sharable",
|
||||||
@shoutable
|
"cacheable", "property_adder")
|
||||||
@sharable
|
|
||||||
@cacheable
|
|
||||||
class Event(LastfmBase):
|
class Event(LastfmBase):
|
||||||
"""A class representing an event."""
|
"""A class representing an event."""
|
||||||
STATUS_ATTENDING = 0
|
STATUS_ATTENDING = 0
|
||||||
STATUS_MAYBE = 1
|
STATUS_MAYBE = 1
|
||||||
STATUS_NOT = 2
|
STATUS_NOT = 2
|
||||||
|
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["id", "title", "artists",
|
||||||
id = None,
|
"headliner", "venue", "start_date",
|
||||||
title = None,
|
"description", "image", "url",
|
||||||
artists = None,
|
"stats", "tag"]
|
||||||
headliner = None,
|
|
||||||
venue = None,
|
def init(self, api, **kwargs):
|
||||||
start_date = None,
|
|
||||||
description = None,
|
|
||||||
image = None,
|
|
||||||
url = None,
|
|
||||||
stats = None,
|
|
||||||
tag = None,
|
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Create an Event object by providing all the data related to it.
|
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")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._id = id
|
super(Event, self).init(**kwargs)
|
||||||
self._title = title
|
self._stats = hasattr(self, "_stats") and Stats(
|
||||||
self._artists = artists
|
subject = self,
|
||||||
self._headliner = headliner
|
attendance = self._stats.attendance,
|
||||||
self._venue = venue
|
reviews = self._stats.reviews
|
||||||
self._start_date = start_date
|
) or None
|
||||||
self._description = description
|
|
||||||
self._image = image
|
|
||||||
self._url = url
|
|
||||||
self._stats = 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
|
|
||||||
|
|
||||||
def attend(self, status = STATUS_ATTENDING):
|
def attend(self, status = STATUS_ATTENDING):
|
||||||
"""
|
"""
|
||||||
|
|
111
lastfm/geo.py
111
lastfm/geo.py
|
@ -8,7 +8,7 @@ __package__ = "lastfm"
|
||||||
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from lastfm.base import LastfmBase
|
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
|
from lastfm.decorators import cached_property, top_property, depaginate
|
||||||
|
|
||||||
class Geo(object):
|
class Geo(object):
|
||||||
|
@ -146,22 +146,17 @@ class Geo(object):
|
||||||
for t in data.findall('track')
|
for t in data.findall('track')
|
||||||
]
|
]
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "cacheable", "property_adder")
|
||||||
@cacheable
|
|
||||||
class Location(LastfmBase):
|
class Location(LastfmBase):
|
||||||
"""A class representing a location of an event"""
|
"""A class representing a location of an event"""
|
||||||
XMLNS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
|
XMLNS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
|
||||||
|
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["city", "country", "street",
|
||||||
city = None,
|
"postal_code", "latitude", "longitude",
|
||||||
country = None,
|
"timezone"]
|
||||||
street = None,
|
|
||||||
postal_code = None,
|
def init(self, api, **kwargs):
|
||||||
latitude = None,
|
|
||||||
longitude = None,
|
|
||||||
timezone = None,
|
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Create a Location object by providing all the data related to it.
|
Create a Location object by providing all the data related to it.
|
||||||
|
|
||||||
|
@ -188,69 +183,7 @@ class Location(LastfmBase):
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
self._api = api
|
self._api = api
|
||||||
self._city = city
|
super(Location, self).init(**kwargs)
|
||||||
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
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def top_tracks(self):
|
def top_tracks(self):
|
||||||
|
@ -280,11 +213,8 @@ class Location(LastfmBase):
|
||||||
@return: events taking place at the location
|
@return: events taking place at the location
|
||||||
@rtype: L{lazylist} of L{Event}
|
@rtype: L{lazylist} of L{Event}
|
||||||
"""
|
"""
|
||||||
return Geo.get_events(self._api,
|
return Geo.get_events(self._api, self.city,
|
||||||
self.city,
|
self.latitude, self.longitude, distance)
|
||||||
self.latitude,
|
|
||||||
self.longitude,
|
|
||||||
distance)
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def events(self):
|
def events(self):
|
||||||
|
@ -335,8 +265,7 @@ class Location(LastfmBase):
|
||||||
else:
|
else:
|
||||||
return "<lastfm.geo.Location: %s>" % self.city
|
return "<lastfm.geo.Location: %s>" % self.city
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "cacheable", "property_adder")
|
||||||
@cacheable
|
|
||||||
class Country(LastfmBase):
|
class Country(LastfmBase):
|
||||||
"""A class representing a country."""
|
"""A class representing a country."""
|
||||||
ISO_CODES = {
|
ISO_CODES = {
|
||||||
|
@ -587,7 +516,11 @@ class Country(LastfmBase):
|
||||||
'ZM': 'Zambia',
|
'ZM': 'Zambia',
|
||||||
'ZW': 'Zimbabwe'}
|
'ZW': 'Zimbabwe'}
|
||||||
"""ISO Codes of the countries"""
|
"""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.
|
Create a Country object by providing all the data related to it.
|
||||||
@param api: an instance of L{Api}
|
@param api: an instance of L{Api}
|
||||||
|
@ -601,15 +534,7 @@ class Country(LastfmBase):
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(Country, self).init(**kwargs)
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""
|
|
||||||
name of the country
|
|
||||||
@rtype: L{str}
|
|
||||||
"""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def top_artists(self):
|
def top_artists(self):
|
||||||
|
|
|
@ -7,14 +7,18 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable, chartable
|
from lastfm.mixin import mixin, chartable
|
||||||
from lastfm.decorators import cached_property, depaginate
|
from lastfm.decorators import cached_property, depaginate
|
||||||
|
|
||||||
@chartable(['album', 'artist', 'track', 'tag'])
|
@chartable('album', 'artist', 'track', 'tag')
|
||||||
@cacheable
|
@mixin("cacheable", "property_adder")
|
||||||
class Group(LastfmBase):
|
class Group(LastfmBase):
|
||||||
"""A class representing a group on last.fm."""
|
"""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.
|
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")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(Group, self).init(**kwargs)
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""
|
|
||||||
name of the group
|
|
||||||
@rtype: L{str}
|
|
||||||
"""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@depaginate
|
@depaginate
|
||||||
|
|
|
@ -12,6 +12,15 @@ from lastfm.mixin._shoutable import shoutable
|
||||||
from lastfm.mixin._taggable import taggable
|
from lastfm.mixin._taggable import taggable
|
||||||
from lastfm.mixin._chartable import chartable
|
from lastfm.mixin._chartable import chartable
|
||||||
from lastfm.mixin._crawlable import crawlable
|
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'
|
__all__ = ['cacheable', 'searchable', 'sharable', 'shoutable', 'taggable'
|
||||||
'chartable','crawlable']
|
'chartable','crawlable', 'property_adder']
|
|
@ -8,7 +8,7 @@ __package__ = "lastfm.mixin"
|
||||||
from lastfm.util import lazylist, logging
|
from lastfm.util import lazylist, logging
|
||||||
from lastfm.decorators import cached_property
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
def chartable(chart_types):
|
def chartable(*chart_types):
|
||||||
def wrapper(cls):
|
def wrapper(cls):
|
||||||
@cached_property
|
@cached_property
|
||||||
def weekly_chart_list(self):
|
def weekly_chart_list(self):
|
||||||
|
|
|
@ -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
|
|
@ -6,12 +6,16 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable
|
from lastfm.mixin import mixin
|
||||||
from lastfm.decorators import cached_property
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
@cacheable
|
@mixin("cacheable", "property_adder")
|
||||||
class Playlist(LastfmBase):
|
class Playlist(LastfmBase):
|
||||||
"""A class representing an XPSF playlist."""
|
"""A class representing an XPSF playlist."""
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["url"]
|
||||||
|
|
||||||
def init(self, api, url, **kwargs):
|
def init(self, api, url, **kwargs):
|
||||||
self._api = api
|
self._api = api
|
||||||
self._data = None
|
self._data = None
|
||||||
|
@ -25,11 +29,6 @@ class Playlist(LastfmBase):
|
||||||
ElementTree.ElementTree(self._api._fetch_data(params)[0]).write(tmp)
|
ElementTree.ElementTree(self._api._fetch_data(params)[0]).write(tmp)
|
||||||
return tmp.getvalue()
|
return tmp.getvalue()
|
||||||
|
|
||||||
@property
|
|
||||||
def url(self):
|
|
||||||
"""url of the playlist"""
|
|
||||||
return self._url
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fetch(api, url):
|
def fetch(api, url):
|
||||||
return Playlist(api, url = url)
|
return Playlist(api, url = url)
|
||||||
|
|
|
@ -6,33 +6,18 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable
|
from lastfm.mixin import mixin
|
||||||
from lastfm.decorators import cached_property
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
@cacheable
|
@mixin("cacheable", "property_adder")
|
||||||
class Shout(LastfmBase):
|
class Shout(LastfmBase):
|
||||||
"""A class representing a shout."""
|
"""A class representing a shout."""
|
||||||
|
|
||||||
def init(self,
|
class Meta(object):
|
||||||
body = None,
|
properties = ["body", "author", "date"]
|
||||||
author = None,
|
|
||||||
date = None,
|
|
||||||
**kwargs):
|
|
||||||
self._body = body
|
|
||||||
self._author = author
|
|
||||||
self._date = date
|
|
||||||
|
|
||||||
@cached_property
|
def init(self, **kwargs):
|
||||||
def body(self):
|
super(Shout, self).init(**kwargs)
|
||||||
return self._body
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def author(self):
|
|
||||||
return self._author
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def date(self):
|
|
||||||
return self._date
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hash_func(*args, **kwds):
|
def _hash_func(*args, **kwds):
|
||||||
|
|
|
@ -5,80 +5,27 @@ __version__ = "0.2"
|
||||||
__license__ = "GNU Lesser General Public License"
|
__license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__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."""
|
"""A class representing the stats of an artist."""
|
||||||
def __init__(self,
|
|
||||||
subject,
|
class Meta(object):
|
||||||
listeners = None,
|
properties = ["listeners", "playcount",
|
||||||
playcount = None,
|
"tagcount", "count", "match", "rank",
|
||||||
tagcount = None,
|
"weight", "attendance", "reviews"]
|
||||||
count = None,
|
|
||||||
match = None,
|
def __init__(self, subject, **kwargs):
|
||||||
rank = None,
|
|
||||||
weight = None,
|
|
||||||
attendance = None,
|
|
||||||
reviews = None,):
|
|
||||||
self._subject = subject
|
self._subject = subject
|
||||||
self._listeners = listeners
|
super(Stats, self).init(**kwargs)
|
||||||
self._playcount = playcount
|
|
||||||
self._tagcount = tagcount
|
|
||||||
self._count = count
|
|
||||||
self._match = match
|
|
||||||
self._rank = rank
|
|
||||||
self._weight = weight
|
|
||||||
self._attendance = attendance
|
|
||||||
self._reviews = reviews
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def subject(self):
|
def subject(self):
|
||||||
"""subject of the stats"""
|
"""subject of the stats"""
|
||||||
return self._subject
|
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):
|
def __repr__(self):
|
||||||
if hasattr(self._subject, 'name'):
|
if hasattr(self._subject, 'name'):
|
||||||
return "<lastfm.Stats: for '%s'>" % self._subject.name
|
return "<lastfm.Stats: for '%s'>" % self._subject.name
|
||||||
|
|
|
@ -6,53 +6,27 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
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
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
@crawlable
|
@chartable("artist")
|
||||||
@chartable(['artist'])
|
@mixin("crawlable", "searchable", "cacheable", "property_adder")
|
||||||
@searchable
|
|
||||||
@cacheable
|
|
||||||
class Tag(LastfmBase):
|
class Tag(LastfmBase):
|
||||||
"""A class representing a tag."""
|
"""A class representing a tag."""
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["name", "url", "streamable", "stats"]
|
||||||
name = None,
|
|
||||||
url = None,
|
def init(self, api, **kwargs):
|
||||||
streamable = None,
|
|
||||||
stats = None,
|
|
||||||
**kwargs):
|
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(Tag, self).init(**kwargs)
|
||||||
self._url = url
|
self._stats = hasattr(self, '_stats') and Stats(
|
||||||
self._streamable = streamable
|
|
||||||
self._stats = stats and Stats(
|
|
||||||
subject = self,
|
subject = self,
|
||||||
count = stats.count,
|
count = self._stats.count,
|
||||||
rank = stats.rank
|
rank = self._stats.rank
|
||||||
)
|
) or None
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def similar(self):
|
def similar(self):
|
||||||
|
|
159
lastfm/track.py
159
lastfm/track.py
|
@ -6,141 +6,38 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
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
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "sharable", "taggable",
|
||||||
@sharable
|
"searchable", "cacheable", "property_adder")
|
||||||
@taggable
|
|
||||||
@searchable
|
|
||||||
@cacheable
|
|
||||||
class Track(LastfmBase):
|
class Track(LastfmBase):
|
||||||
"""A class representing a track."""
|
"""A class representing a track."""
|
||||||
def init(self,
|
class Meta(object):
|
||||||
api,
|
properties = ["id", "name", "mbid", "url", "duration",
|
||||||
name = None,
|
"artist", "image", "stats", "played_on", "loved_on",
|
||||||
mbid = None,
|
"subject"]
|
||||||
url = None,
|
fillable_properties = ["streamable", "full_track",
|
||||||
duration = None,
|
"album", "position", "wiki"]
|
||||||
streamable = None,
|
|
||||||
full_track = None,
|
def init(self, api, **kwargs):
|
||||||
artist = None,
|
|
||||||
album = None,
|
|
||||||
position = None,
|
|
||||||
image = None,
|
|
||||||
stats = None,
|
|
||||||
played_on = None,
|
|
||||||
loved_on = None,
|
|
||||||
wiki = None,
|
|
||||||
subject = None):
|
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
self._api = api
|
self._api = api
|
||||||
self._id = id
|
super(Track, self).init(**kwargs)
|
||||||
self._name = name
|
self._stats = hasattr(self, "_stats") and Stats(
|
||||||
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(
|
|
||||||
subject = self,
|
subject = self,
|
||||||
match = stats.match,
|
match = self._stats.match,
|
||||||
playcount = stats.playcount,
|
playcount = self._stats.playcount,
|
||||||
rank = stats.rank,
|
rank = self._stats.rank,
|
||||||
listeners = stats.listeners,
|
listeners = self._stats.listeners,
|
||||||
)
|
) or None
|
||||||
self._played_on = played_on
|
self._wiki = hasattr(self, "_wiki") and Wiki(
|
||||||
self._loved_on = loved_on
|
|
||||||
self._wiki = wiki and Wiki(
|
|
||||||
subject = self,
|
subject = self,
|
||||||
published = wiki.published,
|
published = self._wiki.published,
|
||||||
summary = wiki.summary,
|
summary = self._wiki.summary,
|
||||||
content = wiki.content
|
content = self._wiki.content
|
||||||
)
|
) or None
|
||||||
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
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def wiki(self):
|
def wiki(self):
|
||||||
|
@ -155,11 +52,11 @@ class Track(LastfmBase):
|
||||||
def similar(self):
|
def similar(self):
|
||||||
"""tracks similar to this track"""
|
"""tracks similar to this track"""
|
||||||
params = Track._check_params(
|
params = Track._check_params(
|
||||||
{'method': 'track.getSimilar'},
|
{'method': 'track.getSimilar'},
|
||||||
self.artist.name,
|
self.artist.name,
|
||||||
self.name,
|
self.name,
|
||||||
self.mbid
|
self.mbid
|
||||||
)
|
)
|
||||||
data = self._api._fetch_data(params).find('similartracks')
|
data = self._api._fetch_data(params).find('similartracks')
|
||||||
return [
|
return [
|
||||||
Track(
|
Track(
|
||||||
|
|
|
@ -6,66 +6,34 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable, shoutable, chartable, crawlable
|
from lastfm.mixin import chartable, mixin
|
||||||
import lastfm.playlist
|
import lastfm.playlist
|
||||||
from lastfm.decorators import (
|
from lastfm.decorators import (
|
||||||
cached_property, top_property, authentication_required, depaginate)
|
cached_property, top_property, authentication_required, depaginate)
|
||||||
|
|
||||||
@crawlable
|
@chartable('album', 'artist', 'track', 'tag')
|
||||||
@chartable(['album', 'artist', 'track', 'tag'])
|
@mixin("crawlable", "shoutable", "cacheable", "property_adder")
|
||||||
@shoutable
|
|
||||||
@cacheable
|
|
||||||
class User(LastfmBase):
|
class User(LastfmBase):
|
||||||
"""A class representing an user."""
|
"""A class representing an user."""
|
||||||
def init(self,
|
|
||||||
api,
|
class Meta(object):
|
||||||
name = None,
|
properties = ["name", "real_name",
|
||||||
real_name = None,
|
"url", "image", "stats"]
|
||||||
url = None,
|
|
||||||
image = None,
|
def init(self, api, **kwargs):
|
||||||
stats = None,
|
|
||||||
**kwargs):
|
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
super(User, self).init(**kwargs)
|
||||||
self._real_name = real_name
|
self._stats = hasattr(self, "_stats") and Stats(
|
||||||
self._url = url
|
subject = self,
|
||||||
self._image = image
|
match = self._stats.match,
|
||||||
self._stats = stats and Stats(
|
weight = self._stats.weight,
|
||||||
subject = self,
|
playcount = self._stats.playcount
|
||||||
match = stats.match,
|
) or None
|
||||||
weight = stats.weight,
|
|
||||||
playcount = stats.playcount
|
|
||||||
)
|
|
||||||
self._library = User.Library(api, self)
|
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
|
@property
|
||||||
@authentication_required
|
@authentication_required
|
||||||
def language(self):
|
def language(self):
|
||||||
|
@ -340,8 +308,8 @@ class User(LastfmBase):
|
||||||
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
|
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
|
||||||
stats = Stats(
|
stats = Stats(
|
||||||
subject = a.findtext('name'),
|
subject = a.findtext('name'),
|
||||||
playcount = int(a.findtext('playcount')),
|
playcount = a.findtext('playcount').strip() and int(a.findtext('playcount')),
|
||||||
rank = int(a.attrib['rank'])
|
rank = a.attrib['rank'].strip() and int(a.attrib['rank'])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for a in data.findall('album')
|
for a in data.findall('album')
|
||||||
|
@ -372,7 +340,7 @@ class User(LastfmBase):
|
||||||
stats = Stats(
|
stats = Stats(
|
||||||
subject = a.findtext('name'),
|
subject = a.findtext('name'),
|
||||||
rank = a.attrib['rank'].strip() and int(a.attrib['rank']) or None,
|
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'),
|
url = a.findtext('url'),
|
||||||
streamable = (a.findtext('streamable') == "1"),
|
streamable = (a.findtext('streamable') == "1"),
|
||||||
|
@ -555,8 +523,13 @@ class User(LastfmBase):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<lastfm.User: %s>" % self.name
|
return "<lastfm.User: %s>" % self.name
|
||||||
|
|
||||||
|
@mixin("property_adder")
|
||||||
class Playlist(lastfm.playlist.Playlist):
|
class Playlist(lastfm.playlist.Playlist):
|
||||||
"""A class representing a playlist belonging to the user."""
|
"""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):
|
def init(self, api, id, title, date, size, creator):
|
||||||
super(User.Playlist, self).init(api, "lastfm://playlist/%s" % id)
|
super(User.Playlist, self).init(api, "lastfm://playlist/%s" % id)
|
||||||
self._id = id
|
self._id = id
|
||||||
|
@ -565,26 +538,6 @@ class User(LastfmBase):
|
||||||
self._size = size
|
self._size = size
|
||||||
self._creator = creator
|
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
|
@property
|
||||||
def user(self):
|
def user(self):
|
||||||
return self._creator
|
return self._creator
|
||||||
|
|
|
@ -4,7 +4,7 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm.util"
|
__package__ = "lastfm.util"
|
||||||
|
|
||||||
from lastfm.util.wormhole import Wormhole
|
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.safelist import SafeList
|
||||||
from lastfm.util.filecache import FileCache
|
from lastfm.util.filecache import FileCache
|
||||||
from lastfm.util.objectcache import ObjectCache
|
from lastfm.util.objectcache import ObjectCache
|
||||||
|
|
|
@ -6,48 +6,21 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixin import cacheable, searchable, crawlable
|
from lastfm.mixin import mixin
|
||||||
from lastfm.decorators import cached_property, depaginate
|
from lastfm.decorators import cached_property, depaginate
|
||||||
|
|
||||||
@crawlable
|
@mixin("crawlable", "searchable", "cacheable", "property_adder")
|
||||||
@searchable
|
|
||||||
@cacheable
|
|
||||||
class Venue(LastfmBase):
|
class Venue(LastfmBase):
|
||||||
"""A class representing a venue of an event"""
|
"""A class representing a venue of an event"""
|
||||||
def init(self,
|
|
||||||
api,
|
class Meta(object):
|
||||||
id = None,
|
properties = ["id", "name", "location", "url"]
|
||||||
name = None,
|
|
||||||
location = None,
|
def init(self, api, **kwargs):
|
||||||
url = None,
|
|
||||||
**kwargs):
|
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
self._api = api
|
self._api = api
|
||||||
self._id = id
|
super(Venue, self).init(**kwargs)
|
||||||
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
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def events(self):
|
def events(self):
|
||||||
|
|
|
@ -5,8 +5,15 @@ __version__ = "0.2"
|
||||||
__license__ = "GNU Lesser General Public License"
|
__license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
|
from lastfm.mixin import mixin
|
||||||
|
|
||||||
|
@mixin("property_adder")
|
||||||
class Wiki(object):
|
class Wiki(object):
|
||||||
"""A class representing the information from the wiki of the subject."""
|
"""A class representing the information from the wiki of the subject."""
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
properties = ["subject", "published", "summary", "content"]
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
subject,
|
subject,
|
||||||
published = None,
|
published = None,
|
||||||
|
@ -17,25 +24,5 @@ class Wiki(object):
|
||||||
self._summary = summary
|
self._summary = summary
|
||||||
self._content = content
|
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):
|
def __repr__(self):
|
||||||
return "<lastfm.Wiki: for %s '%s'>" % (self.subject.__class__.__name__, self.subject.name)
|
return "<lastfm.Wiki: for %s '%s'>" % (self.subject.__class__.__name__, self.subject.name)
|
Loading…
Reference in New Issue