arranged imports, refactored events methods (moved the code to Events.fromData method), made the call to register method in base.py threadsafe.

This commit is contained in:
Abhinav Sarkar 2008-08-18 13:19:41 +00:00
parent 0fdbc32cf8
commit 291ec6846a
14 changed files with 245 additions and 294 deletions

View File

@ -4,22 +4,21 @@ __author__ = "Abhinav Sarkar"
__version__ = "0.1" __version__ = "0.1"
__license__ = "GNU Lesser General Public License" __license__ = "GNU Lesser General Public License"
from album import Album
from api import Api
from artist import Artist
from base import LastfmBase from base import LastfmBase
from error import LastfmError from error import LastfmError
from api import Api
from registry import Registry
from album import Album
from artist import Artist
from event import Event from event import Event
from geo import Location, Country from geo import Location, Country
from group import Group from group import Group
from playlist import Playlist from playlist import Playlist
from registry import Registry
from search import SearchResult
from tag import Tag from tag import Tag
from tasteometer import Tasteometer from tasteometer import Tasteometer
from track import Track from track import Track
from user import User from user import User
from search import SearchResult
__all__ = ['LastfmError', 'Api', 'Album', 'Artist', 'Event', __all__ = ['LastfmError', 'Api', 'Album', 'Artist', 'Event',
'Location', 'Country', 'Group', 'Playlist', 'Tag', 'Location', 'Country', 'Group', 'Playlist', 'Tag',

View File

@ -201,7 +201,7 @@ from datetime import datetime
import time import time
from api import Api from api import Api
from error import LastfmError
from tag import Tag
from artist import Artist from artist import Artist
from stats import Stats from error import LastfmError
from stats import Stats
from tag import Tag

View File

@ -177,10 +177,13 @@ class Api(object):
limit = None): limit = None):
return Tasteometer.compare(self, type1, type2, value1, value2, limit) return Tasteometer.compare(self, type1, type2, value1, value2, limit)
def getTrack(self, name, artist = None): def getTrack(self, track, artist):
if isinstance(artist, Artist): if isinstance(artist, Artist):
artist = artist.name artist = artist.name
return Track(self, name = name, artist = artist) result = Track.search(self, track, artist)
if len(result.matches) == 0:
raise LastfmError("'%s' by %s: no such track found" % (track, artist))
return result.matches[0]
def searchTrack(self, def searchTrack(self,
track, track,
@ -260,22 +263,17 @@ class Api(object):
def __repr__(self): def __repr__(self):
return "<lastfm.Api: %s>" % self.__apiKey return "<lastfm.Api: %s>" % self.__apiKey
import sys
import time
import urllib import urllib
import urllib2 import urllib2
import urlparse import urlparse
import time
import sys
if sys.version.startswith('2.5'):
import xml.etree.cElementTree as ElementTree
else:
import cElementTree as ElementTree
from error import LastfmError
from filecache import FileCache
from album import Album from album import Album
from artist import Artist from artist import Artist
from error import LastfmError
from event import Event from event import Event
from filecache import FileCache
from geo import Location, Country from geo import Location, Country
from group import Group from group import Group
from playlist import Playlist from playlist import Playlist
@ -283,3 +281,14 @@ from tag import Tag
from tasteometer import Tasteometer from tasteometer import Tasteometer
from track import Track from track import Track
from user import User from user import User
if sys.version.startswith('2.5'):
import xml.etree.cElementTree as ElementTree
else:
try:
import cElementTree as ElementTree
except ImportError:
try:
import ElementTree
except ImportError:
raise LastfmError("Install ElementTree package for using python-lastfm")

View File

@ -117,12 +117,12 @@ class Artist(LastfmBase):
if self.__similar is None or len(self.__similar) < 6: if self.__similar is None or len(self.__similar) < 6:
return self.getSimilar() return self.getSimilar()
return self.__similar return self.__similar
@property @property
def mostSimilar(self): def mostSimilar(self):
"""artist most similar to this artist""" """artist most similar to this artist"""
return (len(self.similar) and self.similar[0] or None) return (len(self.similar) and self.similar[0] or None)
@property @property
def topTags(self): def topTags(self):
"""top tags for the artist""" """top tags for the artist"""
@ -141,7 +141,7 @@ class Artist(LastfmBase):
for t in data.findall('tag') for t in data.findall('tag')
] ]
return self.__topTags return self.__topTags
@property @property
def topTag(self): def topTag(self):
"""top tag for the artist""" """top tag for the artist"""
@ -153,63 +153,27 @@ class Artist(LastfmBase):
if self.__bio is None: if self.__bio is None:
self._fillInfo() self._fillInfo()
return self.__bio return self.__bio
@property @property
def events(self): def events(self):
"""events for the artist""" """events for the artist"""
if self.__events is None: if self.__events is None:
params = {'method': 'artist.getevents', 'artist': self.name} params = {'method': 'artist.getevents', 'artist': self.name}
data = self.__api._fetchData(params).find('events') data = self.__api._fetchData(params).find('events')
self.__events = [ self.__events = [
Event( Event.createFromData(self.__api, e)
self.__api, for e in data.findall('event')
id = int(e.findtext('id')), ]
title = e.findtext('title'),
artists = [Artist(self.__api, name = a.text) for a in e.findall('artists/artist')],
headliner = Artist(self.__api, name = e.findtext('artists/headliner')),
venue = Venue(
name = e.findtext('venue/name'),
location = Location(
self.__api,
city = e.findtext('venue/location/city'),
country = Country(
self.__api,
name = e.findtext('venue/location/country')
),
street = e.findtext('venue/location/street'),
postalCode = e.findtext('venue/location/postalcode'),
latitude = float(e.findtext(
'venue/location/{%s}point/{%s}lat' % ((Location.xmlns,)*2)
)),
longitude = float(e.findtext(
'venue/location/{%s}point/{%s}long' % ((Location.xmlns,)*2)
)),
timezone = e.findtext('venue/location/timezone')
),
url = e.findtext('venue/url')
),
startDate = e.findtext('startDate') and
datetime(*(time.strptime(e.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or
None,
startTime = e.findtext('startTime') and
datetime(*(time.strptime(e.findtext('startTime').strip(), '%H:%M')[0:6])) or
None,
description = e.findtext('description'),
image = dict([(i.get('size'), i.text) for i in e.findall('image')]),
url = e.findtext('url')
)
for e in data.findall('event')
]
return self.__events return self.__events
@property @property
def topAlbums(self): def topAlbums(self):
"""top albums of the artist""" """top albums of the artist"""
if self.__topAlbums is None: if self.__topAlbums is None:
params = {'method': 'artist.gettopalbums', 'artist': self.name} params = {'method': 'artist.gettopalbums', 'artist': self.name}
data = self.__api._fetchData(params).find('topalbums') data = self.__api._fetchData(params).find('topalbums')
self.__topAlbums = [ self.__topAlbums = [
Album( Album(
self.__api, self.__api,
@ -227,12 +191,12 @@ class Artist(LastfmBase):
for a in data.findall('album') for a in data.findall('album')
] ]
return self.__topAlbums return self.__topAlbums
@property @property
def topAlbum(self): def topAlbum(self):
"""top album of the artist""" """top album of the artist"""
return (len(self.topAlbums) and self.topAlbums[0] or None) return (len(self.topAlbums) and self.topAlbums[0] or None)
@property @property
def topFans(self): def topFans(self):
"""top fans of the artist""" """top fans of the artist"""
@ -253,12 +217,12 @@ class Artist(LastfmBase):
for u in data.findall('user') for u in data.findall('user')
] ]
return self.__topFans return self.__topFans
@property @property
def topFan(self): def topFan(self):
"""top fan of the artist""" """top fan of the artist"""
return (len(self.topFans) and self.topFans[0] or None) return (len(self.topFans) and self.topFans[0] or None)
@property @property
def topTracks(self): def topTracks(self):
"""top tracks of the artist""" """top tracks of the artist"""
@ -283,11 +247,11 @@ class Artist(LastfmBase):
for t in data.findall('track') for t in data.findall('track')
] ]
return self.__topTracks return self.__topTracks
@property @property
def topTrack(self): def topTrack(self):
return (len(self.topTracks) and self.topTracks[0] or None) return (len(self.topTracks) and self.topTracks[0] or None)
@staticmethod @staticmethod
def search(api, def search(api,
artist, artist,
@ -318,7 +282,7 @@ class Artist(LastfmBase):
for a in data.findall('artistmatches/artist') for a in data.findall('artistmatches/artist')
] ]
) )
@staticmethod @staticmethod
def _fetchData(api, def _fetchData(api,
artist = None, artist = None,
@ -358,7 +322,7 @@ class Artist(LastfmBase):
self.__api, self.__api,
name = t.findtext('name'), name = t.findtext('name'),
url = t.findtext('url') url = t.findtext('url')
) )
for t in data.findall('tags/tag') for t in data.findall('tags/tag')
] ]
self.__bio = Bio( self.__bio = Bio(
@ -370,18 +334,18 @@ class Artist(LastfmBase):
summary = data.findtext('bio/summary'), summary = data.findtext('bio/summary'),
content = data.findtext('bio/content') content = data.findtext('bio/content')
) )
@staticmethod @staticmethod
def getInfo(api, def getInfo(api,
artist = None, artist = None,
mbid = None): mbid = None):
data = Artist._fetchData(api, artist, mbid) data = Artist._fetchData(api, artist, mbid)
a = Artist(api, name = data.findtext('name')) a = Artist(api, name = data.findtext('name'))
if a.bio is None: if a.bio is None:
a._fillInfo() a._fillInfo()
return a return a
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
@ -392,20 +356,20 @@ class Artist(LastfmBase):
return hash(args[1].lower()) return hash(args[1].lower())
except IndexError: except IndexError:
raise LastfmError("name has to be provided for hashing") raise LastfmError("name has to be provided for hashing")
def __hash__(self): def __hash__(self):
return self.__class__.hashFunc(name = self.name) return self.__class__.hashFunc(name = self.name)
def __eq__(self, other): def __eq__(self, other):
if self.mbid and other.mbid: if self.mbid and other.mbid:
return self.mbid == other.mbid return self.mbid == other.mbid
if self.url and other.url: if self.url and other.url:
return self.url == other.url return self.url == other.url
return self.name == other.name return self.name == other.name
def __lt__(self, other): def __lt__(self, other):
return self.name < other.name return self.name < other.name
def __repr__(self): def __repr__(self):
return "<lastfm.Artist: %s>" % self.__name return "<lastfm.Artist: %s>" % self.__name
@ -447,13 +411,13 @@ class Bio(object):
from datetime import datetime from datetime import datetime
import time import time
from api import Api
from album import Album from album import Album
from api import Api
from error import LastfmError from error import LastfmError
from event import Event from event import Event
from geo import Country, Location, Venue from geo import Country, Location, Venue
from search import SearchResult
from stats import Stats
from tag import Tag from tag import Tag
from track import Track from track import Track
from user import User from user import User
from search import SearchResult
from stats import Stats

View File

@ -4,24 +4,34 @@ __author__ = "Abhinav Sarkar"
__version__ = "0.1" __version__ = "0.1"
__license__ = "GNU Lesser General Public License" __license__ = "GNU Lesser General Public License"
try:
from threading import Lock
except ImportError:
from dummy_threading import Lock
class LastfmBase(object): class LastfmBase(object):
"""Base class for all the classes in this package""" """Base class for all the classes in this package"""
registry = {} registry = {}
_lock = Lock()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
if 'bypassRegistry' in kwds: if 'bypassRegistry' in kwds:
del kwds['bypassRegistry'] del kwds['bypassRegistry']
inst = object.__new__(cls) inst = object.__new__(cls)
inst.init(*args, **kwds) inst.init(*args, **kwds)
return inst return inst
key = cls.hashFunc(*args, **kwds) key = cls.hashFunc(*args, **kwds)
inst, alreadyRegistered = LastfmBase.register(object.__new__(cls), key) LastfmBase._lock.acquire()
if not alreadyRegistered: try:
inst.init(*args, **kwds) inst, alreadyRegistered = LastfmBase.register(object.__new__(cls), key)
return inst if not alreadyRegistered:
inst.init(*args, **kwds)
finally:
LastfmBase._lock.release()
return inst
@staticmethod @staticmethod
def register(ob, key): def register(ob, key):
if not ob.__class__ in LastfmBase.registry: if not ob.__class__ in LastfmBase.registry:
@ -34,15 +44,15 @@ class LastfmBase(object):
#print "not already registered: %s" % ob.__class__ #print "not already registered: %s" % ob.__class__
LastfmBase.registry[ob.__class__][key] = ob LastfmBase.registry[ob.__class__][key] = ob
return (ob, False) return (ob, False)
def __gt__(self, other): def __gt__(self, other):
return not (self.__lt__(other) or self.__eq(other)) return not (self.__lt__(other) or self.__eq(other))
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
def __ge__(self, other): def __ge__(self, other):
return not self.__lt__(other) return not self.__lt__(other)
def __le__(self, other): def __le__(self, other):
return not self.__gt__(other) return not self.__gt__(other)

View File

@ -31,14 +31,13 @@ class Event(LastfmBase):
self.__headliner = headliner self.__headliner = headliner
self.__venue = venue self.__venue = venue
self.__startDate = startDate self.__startDate = startDate
self.__startTime = startTime
self.__description = description self.__description = description
self.__image = image self.__image = image
self.__url = url self.__url = url
self.__stats = stats and Stats( self.__stats = stats and Stats(
subject = self, subject = self,
attendance = self.attendance, attendance = stats.attendance,
reviews = self.reviews reviews = stats.reviews
) )
self.__tag = tag self.__tag = tag
@ -56,7 +55,7 @@ class Event(LastfmBase):
def artists(self): def artists(self):
"""artists performing in the event""" """artists performing in the event"""
return self.__artists return self.__artists
@property @property
def headliner(self): def headliner(self):
"""headliner artist of the event""" """headliner artist of the event"""
@ -72,11 +71,6 @@ class Event(LastfmBase):
"""start date of the event""" """start date of the event"""
return self.__startDate return self.__startDate
@property
def startTime(self):
"""start time of the event"""
return self.__startTime
@property @property
def description(self): def description(self):
"""description of the event""" """description of the event"""
@ -101,12 +95,47 @@ class Event(LastfmBase):
def tag(self): def tag(self):
"""tags for the event""" """tags for the event"""
return self.__tag return self.__tag
@staticmethod @staticmethod
def getInfo(api, event): def getInfo(api, event):
params = {'method': 'event.getinfo', 'event': event} params = {'method': 'event.getinfo', 'event': event}
data = api._fetchData(params).find('event') data = api._fetchData(params).find('event')
return Event.createFromData(api, data)
@staticmethod
def createFromData(api, data):
startDate = None
if data.findtext('startTime') is not None:
startDate = datetime(*(
time.strptime(
"%s %s" % (
data.findtext('startDate').strip(),
data.findtext('startTime').strip()
),
'%a, %d %b %Y %H:%M'
)[0:6])
)
else:
try:
startDate = datetime(*(
time.strptime(
data.findtext('startDate').strip(),
'%a, %d %b %Y %H:%M:%S'
)[0:6])
)
except ValueError:
try:
startDate = datetime(*(
time.strptime(
data.findtext('startDate').strip(),
'%a, %d %b %Y'
)[0:6])
)
except ValueError:
pass
return Event( return Event(
api, api,
id = int(data.findtext('id')), id = int(data.findtext('id')),
@ -134,12 +163,7 @@ class Event(LastfmBase):
), ),
url = data.findtext('venue/url') url = data.findtext('venue/url')
), ),
startDate = data.findtext('startDate') and startDate = startDate,
datetime(*(time.strptime(data.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or
None,
startTime = data.findtext('startTime') and
datetime(*(time.strptime(data.findtext('startTime').strip(), '%H:%M')[0:6])) or
None,
description = data.findtext('description'), description = data.findtext('description'),
image = dict([(i.get('size'), i.text) for i in data.findall('image')]), image = dict([(i.get('size'), i.text) for i in data.findall('image')]),
url = data.findtext('url'), url = data.findtext('url'),
@ -150,31 +174,31 @@ class Event(LastfmBase):
), ),
tag = data.findtext('tag') tag = data.findtext('tag')
) )
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
return hash(kwds['id']) return hash(kwds['id'])
except KeyError: except KeyError:
raise LastfmError("id has to be provided for hashing") raise LastfmError("id has to be provided for hashing")
def __hash__(self): def __hash__(self):
return Event.hashFunc(id = self.id) return Event.hashFunc(id = self.id)
def __eq__(self, other): def __eq__(self, other):
return self.id == other.id return self.id == other.id
def __lt__(self, other): def __lt__(self, other):
return self.startDate < other.startDate return self.startDate < other.startDate
def __repr__(self): def __repr__(self):
return "<lastfm.Event: %s at %s on %s>" % (self.title, self.venue.name, self.startDate.strftime("%x")) return "<lastfm.Event: %s at %s on %s>" % (self.title, self.venue.name, self.startDate.strftime("%x"))
from datetime import datetime from datetime import datetime
import time import time
from api import Api from api import Api
from error import LastfmError
from artist import Artist from artist import Artist
from error import LastfmError
from geo import Venue, Location, Country from geo import Venue, Location, Country
from stats import Stats from stats import Stats

View File

@ -4,9 +4,9 @@ __author__ = "Abhinav Sarkar"
__version__ = "0.1" __version__ = "0.1"
__license__ = "GNU Lesser General Public License" __license__ = "GNU Lesser General Public License"
import tempfile
import os
import md5 import md5
import os
import tempfile
class _FileCacheError(Exception): class _FileCacheError(Exception):
'''Base exception class for FileCache related errors''' '''Base exception class for FileCache related errors'''

View File

@ -15,7 +15,7 @@ class Geo(object):
page = None): page = None):
params = {'method': 'geo.getevents', 'location': location} params = {'method': 'geo.getevents', 'location': location}
data = api._fetchData(params).find('events') data = api._fetchData(params).find('events')
return SearchResult( return SearchResult(
type = 'event', type = 'event',
searchTerms = data.attrib['location'], searchTerms = data.attrib['location'],
@ -23,47 +23,11 @@ class Geo(object):
totalResults = int(data.attrib['total']), totalResults = int(data.attrib['total']),
itemsPerPage = int(math.ceil(float(data.attrib['total']))/float(data.attrib['totalpages'])), itemsPerPage = int(math.ceil(float(data.attrib['total']))/float(data.attrib['totalpages'])),
matches = [ matches = [
Event( Event.createFromData(self.__api, e)
api, for e in data.findall('event')
id = int(e.findtext('id')), ]
title = e.findtext('title'),
artists = [Artist(api, name = a.text) for a in e.findall('artists/artist')],
headliner = Artist(api, name = e.findtext('artists/headliner')),
venue = Venue(
name = e.findtext('venue/name'),
location = Location(
api,
city = e.findtext('venue/location/city'),
country = Country(
api,
name = e.findtext('venue/location/country')
),
street = e.findtext('venue/location/street'),
postalCode = e.findtext('venue/location/postalcode'),
latitude = float(e.findtext(
'venue/location/{%s}point/{%s}lat' % ((Location.xmlns,)*2)
)),
longitude = float(e.findtext(
'venue/location/{%s}point/{%s}long' % ((Location.xmlns,)*2)
)),
timezone = e.findtext('venue/location/timezone')
),
url = e.findtext('venue/url')
),
startDate = e.findtext('startDate') and
datetime(*(time.strptime(e.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or
None,
startTime = e.findtext('startTime') and
datetime(*(time.strptime(e.findtext('startTime').strip(), '%H:%M')[0:6])) or
None,
description = e.findtext('description'),
image = dict([(i.get('size'), i.text) for i in e.findall('image')]),
url = e.findtext('url')
)
for e in data.findall('event')
]
) )
@staticmethod @staticmethod
def getTopArtists(api, country): def getTopArtists(api, country):
params = {'method': 'geo.gettopartists', 'country': country} params = {'method': 'geo.gettopartists', 'country': country}
@ -83,7 +47,7 @@ class Geo(object):
) )
for a in data.findall('artist') for a in data.findall('artist')
] ]
@staticmethod @staticmethod
def getTopTracks(api, country): def getTopTracks(api, country):
params = {'method': 'geo.gettoptracks', 'country': country} params = {'method': 'geo.gettoptracks', 'country': country}
@ -105,7 +69,7 @@ class Geo(object):
playcount = int(t.findtext('playcount')) playcount = int(t.findtext('playcount'))
), ),
streamable = (t.findtext('streamable') == '1'), streamable = (t.findtext('streamable') == '1'),
fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'), fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'),
url = 'http://' + t.findtext('url'), url = 'http://' + t.findtext('url'),
image = {'large': t.findtext('image')} image = {'large': t.findtext('image')}
) )
@ -136,30 +100,30 @@ class Venue(LastfmBase):
def url(self): def url(self):
"""url of the event's page""" """url of the event's page"""
return self.__url return self.__url
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
return hash(kwds['url']) return hash(kwds['url'])
except KeyError: except KeyError:
raise LastfmError("url has to be provided for hashing") raise LastfmError("url has to be provided for hashing")
def __hash__(self): def __hash__(self):
return self.__class__.hashFunc(url = self.url) return self.__class__.hashFunc(url = self.url)
def __eq__(self, other): def __eq__(self, other):
return self.url == other.url return self.url == other.url
def __lt__(self, other): def __lt__(self, other):
return self.name < other.name return self.name < other.name
def __repr__(self): def __repr__(self):
return "<lastfm.geo.Venue: %s, %s>" % (self.name, self.location.city) return "<lastfm.geo.Venue: %s, %s>" % (self.name, self.location.city)
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, def init(self,
api, api,
name = None, name = None,
@ -181,57 +145,57 @@ class Location(LastfmBase):
self.__latitude = latitude self.__latitude = latitude
self.__longitude = longitude self.__longitude = longitude
self.__timezone = timezone self.__timezone = timezone
@property @property
def name(self): def name(self):
"""name of the location""" """name of the location"""
return self.__name return self.__name
@property @property
def city(self): def city(self):
"""city in which the location is situated""" """city in which the location is situated"""
return self.__city return self.__city
@property @property
def country(self): def country(self):
"""country in which the location is situated""" """country in which the location is situated"""
return self.__country return self.__country
@property @property
def street(self): def street(self):
"""street in which the location is situated""" """street in which the location is situated"""
return self.__street return self.__street
@property @property
def postalCode(self): def postalCode(self):
"""postal code of the location""" """postal code of the location"""
return self.__postalCode return self.__postalCode
@property @property
def latitude(self): def latitude(self):
"""latitude of the location""" """latitude of the location"""
return self.__latitude return self.__latitude
@property @property
def longitude(self): def longitude(self):
"""longitude of the location""" """longitude of the location"""
return self.__longitude return self.__longitude
@property @property
def timezone(self): def timezone(self):
"""timezone in which the location is situated""" """timezone in which the location is situated"""
return self.__timezone return self.__timezone
def getEvents(self, def getEvents(self,
distance = None, distance = None,
page = None): page = None):
return Geo.getEvents(self.__api, self.name, distance, page).matches return Geo.getEvents(self.__api, self.name, distance, page).matches
@property @property
def events(self): def events(self):
"""events taking place at/around the location""" """events taking place at/around the location"""
return self.getEvents() return self.getEvents()
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
@ -241,7 +205,7 @@ class Location(LastfmBase):
return hash("name%s" % kwds['name']) return hash("name%s" % kwds['name'])
except KeyError: except KeyError:
raise LastfmError("either latitude and longitude or name has to be provided for hashing") raise LastfmError("either latitude and longitude or name has to be provided for hashing")
def __hash__(self): def __hash__(self):
if not self.name: if not self.name:
return self.__class__.hashFunc( return self.__class__.hashFunc(
@ -249,22 +213,22 @@ class Location(LastfmBase):
longitude = self.longitude) longitude = self.longitude)
else: else:
return self.__class__.hashFunc(name = self.name) return self.__class__.hashFunc(name = self.name)
def __eq__(self, other): def __eq__(self, other):
return self.latitude == other.latitude and self.longitude == other.longitude return self.latitude == other.latitude and self.longitude == other.longitude
def __lt__(self, other): def __lt__(self, other):
if self.country != other.country: if self.country != other.country:
return self.country < other.country return self.country < other.country
else: else:
return self.city < other.city return self.city < other.city
def __repr__(self): def __repr__(self):
if self.name is None: if self.name is None:
return "<lastfm.geo.Location: (%s, %s)>" % (self.latitude, self.longitude) return "<lastfm.geo.Location: (%s, %s)>" % (self.latitude, self.longitude)
else: else:
return "<lastfm.geo.Location: %s>" % self.name return "<lastfm.geo.Location: %s>" % self.name
class Country(LastfmBase): class Country(LastfmBase):
"""A class representing a country.""" """A class representing a country."""
def init(self, def init(self,
@ -275,58 +239,58 @@ class Country(LastfmBase):
self.__api = api self.__api = api
self.__name = name self.__name = name
@property @property
def name(self): def name(self):
"""name of the country""" """name of the country"""
return self.__name return self.__name
@property @property
def topArtists(self): def topArtists(self):
"""top artists of the country""" """top artists of the country"""
return Geo.getTopArtists(self.__api, self.name) return Geo.getTopArtists(self.__api, self.name)
@property @property
def topArtist(self): def topArtist(self):
"""top artist of the country""" """top artist of the country"""
return (len(self.topArtists) and self.topArtists[0] or None) return (len(self.topArtists) and self.topArtists[0] or None)
@property @property
def topTracks(self): def topTracks(self):
"""top tracks of the country""" """top tracks of the country"""
return Geo.getTopTracks(self.__api, self.name) return Geo.getTopTracks(self.__api, self.name)
@property @property
def topTrack(self): def topTrack(self):
"""top track of the country""" """top track of the country"""
return (len(self.topTracks) and self.topTracks[0] or None) return (len(self.topTracks) and self.topTracks[0] or None)
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
return hash(kwds['name']) return hash(kwds['name'])
except KeyError: except KeyError:
raise LastfmError("name has to be provided for hashing") raise LastfmError("name has to be provided for hashing")
def __hash__(self): def __hash__(self):
return self.__class__.hashFunc(name = self.name) return self.__class__.hashFunc(name = self.name)
def __eq__(self, other): def __eq__(self, other):
return self.name == other.name return self.name == other.name
def __lt__(self, other): def __lt__(self, other):
return self.name < other.name return self.name < other.name
def __repr__(self): def __repr__(self):
return "<lastfm.geo.Country: %s>" % self.name return "<lastfm.geo.Country: %s>" % self.name
import math
from datetime import datetime from datetime import datetime
import math
import time import time
from api import Api from api import Api
from error import LastfmError
from artist import Artist from artist import Artist
from track import Track from error import LastfmError
from event import Event from event import Event
from search import SearchResult from search import SearchResult
from stats import Stats from stats import Stats
from track import Track

View File

@ -4,11 +4,10 @@ __author__ = "Abhinav Sarkar"
__version__ = "0.1" __version__ = "0.1"
__license__ = "GNU Lesser General Public License" __license__ = "GNU Lesser General Public License"
from base import LastfmBase
from error import LastfmError
from album import Album from album import Album
from artist import Artist from artist import Artist
from base import LastfmBase
from error import LastfmError
from event import Event from event import Event
from geo import Location, Country from geo import Location, Country
from group import Group from group import Group
@ -16,12 +15,11 @@ from playlist import Playlist
from tag import Tag from tag import Tag
from track import Track from track import Track
from user import User from user import User
from search import SearchResult
class Registry(object): class Registry(object):
"""The registry to contain all the entities""" """The registry to contain all the entities"""
keys = [Album, Artist, Event, Location, Country, Group, keys = [Album, Artist, Event, Location, Country, Group,
Playlist, Tag, Track, User, SearchResult] Playlist, Tag, Track, User]
def get(self, name): def get(self, name):
if name not in Registry.keys: if name not in Registry.keys:

View File

@ -4,12 +4,10 @@ __author__ = "Abhinav Sarkar"
__version__ = "0.1" __version__ = "0.1"
__license__ = "GNU Lesser General Public License" __license__ = "GNU Lesser General Public License"
from base import LastfmBase class SearchResult(object):
class SearchResult(LastfmBase):
"""A class to represent a search result""" """A class to represent a search result"""
xmlns = "http://a9.com/-/spec/opensearch/1.1/" xmlns = "http://a9.com/-/spec/opensearch/1.1/"
def init(self, def __init__(self,
type = None, type = None,
searchTerms = None, searchTerms = None,
startPage = None, startPage = None,
@ -63,34 +61,7 @@ class SearchResult(LastfmBase):
@property @property
def topMatch(self): def topMatch(self):
return (len(self.matches) and self.matches[0] or None) return (len(self.matches) and self.matches[0] or None)
@staticmethod
def hashFunc(*args, **kwds):
try:
return hash("%s%s%s" % (kwds['searchTerms'], kwds['type'], kwds['startPage']))
except KeyError:
raise LastfmError("searchTerms, type and startPage have to be provided for hashing")
def __hash__(self):
return self.__class__.hashFunc(
searchTerms = self.searchTerms,
type = self.type,
startPage = self.startPage
)
def __eq__(self, other):
return (
self.searchTerms == other.searchTerms and
self.type == other.type and
self.startIndex == other.startIndex
)
def __lt__(self, other):
if self.searchTerms != other.searchTerms:
return self.searchTerms < other.searchTerms
else:
return self.startIndex < other.startIndex
def __repr__(self): def __repr__(self):
return "<lastfm.SearchResult: for %s '%s'>" % (self.type, self.searchTerms) return "<lastfm.SearchResult: for %s '%s'>" % (self.type, self.searchTerms)

View File

@ -230,10 +230,10 @@ class Tag(LastfmBase):
def __repr__(self): def __repr__(self):
return "<lastfm.Tag: %s>" % self.name return "<lastfm.Tag: %s>" % self.name
from api import Api
from error import LastfmError
from album import Album from album import Album
from api import Api
from artist import Artist from artist import Artist
from track import Track from error import LastfmError
from search import SearchResult
from stats import Stats from stats import Stats
from search import SearchResult from track import Track

View File

@ -12,7 +12,7 @@ class Tasteometer(object):
artists = None): artists = None):
self.__score = score self.__score = score
self.__matches = matches self.__matches = matches
self.__artists = artists#set self.__artists = artists
@property @property
def score(self): def score(self):
@ -63,6 +63,4 @@ class Tasteometer(object):
def __repr__(self): def __repr__(self):
return "<lastfm.Tasteometer>" return "<lastfm.Tasteometer>"
from artist import Artist from artist import Artist
from error import LastfmError

View File

@ -259,9 +259,9 @@ class Track(LastfmBase):
return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name) return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name)
from api import Api from api import Api
from error import LastfmError
from user import User
from tag import Tag
from stats import Stats
from artist import Artist from artist import Artist
from search import SearchResult from error import LastfmError
from search import SearchResult
from stats import Stats
from tag import Tag
from user import User

View File

@ -25,6 +25,7 @@ class User(LastfmBase):
match = stats.match, match = stats.match,
weight = stats.weight weight = stats.weight
) )
self.__events = None
@property @property
def name(self): def name(self):
@ -45,99 +46,111 @@ class User(LastfmBase):
def stats(self): def stats(self):
"""stats for the user""" """stats for the user"""
return self.__stats return self.__stats
@property @property
def events(self): def events(self):
if self.__events is None:
params = {'method': 'user.getevents', 'user': self.name}
data = self.__api._fetchData(params).find('events')
self.__events = [
Event.createFromData(self.__api, e)
for e in data.findall('event')
]
return self.__events
@property
def pastEvents(self):
pass pass
def getFriends(self, def getFriends(self,
recentTracks = False, recentTracks = False,
limit = None): limit = None):
pass pass
@property @property
def friends(self): def friends(self):
"""friends of the user""" """friends of the user"""
return self.getFriends() return self.getFriends()
def getNeighbours(self, limit = None): def getNeighbours(self, limit = None):
pass pass
@property @property
def neighbours(self): def neighbours(self):
"""neightbours of the user""" """neightbours of the user"""
return self.getNeighbours() return self.getNeighbours()
@property @property
def playlists(self): def playlists(self):
"""playlists of the user""" """playlists of the user"""
pass pass
def getRecentTracks(self, limit = None): def getRecentTracks(self, limit = None):
pass pass
@property @property
def recentTracks(self): def recentTracks(self):
"""recent tracks played by the user""" """recent tracks played by the user"""
return self.getRecentTracks() return self.getRecentTracks()
@property @property
def mostRecentTrack(self): def mostRecentTrack(self):
"""most recent track played by the user""" """most recent track played by the user"""
return (len(self.recentTracks) and self.recentTracks[0] or None) return (len(self.recentTracks) and self.recentTracks[0] or None)
def getTopAlbums(self, period = None): def getTopAlbums(self, period = None):
pass pass
@property @property
def topAlbums(self): def topAlbums(self):
"""top albums of the user""" """top albums of the user"""
return self.getTopAlbums() return self.getTopAlbums()
@property @property
def topAlbum(self): def topAlbum(self):
"""top album fo the user""" """top album fo the user"""
return (len(self.topAlbums) and self.topAlbums[0] or None) return (len(self.topAlbums) and self.topAlbums[0] or None)
def getTopArtists(self, period = None): def getTopArtists(self, period = None):
pass pass
@property @property
def topArtists(self): def topArtists(self):
"""top artists of the user""" """top artists of the user"""
return self.getTopArtists() return self.getTopArtists()
@property @property
def topArtist(self): def topArtist(self):
"""top artist of the user""" """top artist of the user"""
return (len(self.topArtists) and self.topArtists[0] or None) return (len(self.topArtists) and self.topArtists[0] or None)
def getTopTracks(self, period = None): def getTopTracks(self, period = None):
pass pass
@property @property
def topTracks(self): def topTracks(self):
"""top tracks of the user""" """top tracks of the user"""
return self.getTopTracks() return self.getTopTracks()
@property @property
def topTrack(self): def topTrack(self):
"""top track of the user""" """top track of the user"""
return (len(self.topTracks) and self.topTracks[0] or None) return (len(self.topTracks) and self.topTracks[0] or None)
def getTopTags(self, limit = None): def getTopTags(self, limit = None):
pass pass
@property @property
def topTags(self): def topTags(self):
"""top tags of the user""" """top tags of the user"""
return self.getTopTags() return self.getTopTags()
@property @property
def topTag(self): def topTag(self):
"""top tag of the user""" """top tag of the user"""
return (len(self.topTags) and self.topTags[0] or None) return (len(self.topTags) and self.topTags[0] or None)
@property @property
def weeklyChartList(self): def weeklyChartList(self):
pass pass
@ -146,48 +159,49 @@ class User(LastfmBase):
start = None, start = None,
end = None): end = None):
pass pass
@property @property
def recentWeeklyAlbumChart(self): def recentWeeklyAlbumChart(self):
return self.getWeeklyAlbumChart() return self.getWeeklyAlbumChart()
def getWeeklyArtistChart(self, def getWeeklyArtistChart(self,
start = None, start = None,
end = None): end = None):
pass pass
@property @property
def recentWeeklyArtistChart(self): def recentWeeklyArtistChart(self):
return self.getWeeklyArtistChart() return self.getWeeklyArtistChart()
def getWeeklyTrackChart(self, def getWeeklyTrackChart(self,
start = None, start = None,
end = None): end = None):
pass pass
@property @property
def recentWeeklyTrackChart(self): def recentWeeklyTrackChart(self):
return self.getWeeklyTrackChart() return self.getWeeklyTrackChart()
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:
return hash(kwds['name']) return hash(kwds['name'])
except KeyError: except KeyError:
raise LastfmError("name has to be provided for hashing") raise LastfmError("name has to be provided for hashing")
def __hash__(self): def __hash__(self):
return self.__class__.hashFunc(name = self.name) return self.__class__.hashFunc(name = self.name)
def __eq__(self, other): def __eq__(self, other):
return self.name == other.name return self.name == other.name
def __lt__(self, other): def __lt__(self, other):
return self.name < other.name return self.name < other.name
def __repr__(self): def __repr__(self):
return "<lastfm.User: %s>" % self.name return "<lastfm.User: %s>" % self.name
from api import Api from api import Api
from error import LastfmError from error import LastfmError
from stats import Stats from event import Event
from stats import Stats