1
2
3 __author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
4 __version__ = "0.2"
5 __license__ = "GNU Lesser General Public License"
6
7 from lastfm.base import LastfmBase
8 from lastfm.mixins import Cacheable, Searchable, Sharable, Taggable
9 from lastfm.lazylist import lazylist
10 from lastfm.decorators import cached_property, top_property
11
12 -class Track(LastfmBase, Cacheable, Sharable, Searchable, Taggable):
13 """A class representing a track."""
14 - def init(self,
15 api,
16 name = None,
17 mbid = None,
18 url = None,
19 duration = None,
20 streamable = None,
21 full_track = None,
22 artist = None,
23 album = None,
24 position = None,
25 image = None,
26 stats = None,
27 played_on = None,
28 loved_on = None,
29 wiki = None,
30 subject = None):
31 if not isinstance(api, Api):
32 raise InvalidParametersError("api reference must be supplied as an argument")
33 Taggable.init(self, api)
34 Sharable.init(self, api)
35 self._api = api
36 self._id = id
37 self._name = name
38 self._mbid = mbid
39 self._url = url
40 self._duration = duration
41 self._streamable = streamable
42 self._full_track = full_track
43 self._artist = artist
44 self._album = album
45 self._position = position
46 self._image = image
47 self._stats = stats and Stats(
48 subject = self,
49 match = stats.match,
50 playcount = stats.playcount,
51 rank = stats.rank,
52 listeners = stats.listeners,
53 )
54 self._played_on = played_on
55 self._loved_on = loved_on
56 self._wiki = wiki and Wiki(
57 subject = self,
58 published = wiki.published,
59 summary = wiki.summary,
60 content = wiki.content
61 )
62 self._subject = subject
63
64 @property
66 """id of the track"""
67 return self._id
68
69 @property
71 """name of the track"""
72 return self._name
73
74 @property
76 """mbid of the track"""
77 return self._mbid
78
79 @property
81 """url of the tracks's page"""
82 return self._url
83
84 @property
86 """duration of the tracks's page"""
87 return self._duration
88
89 @property
91 """is the track streamable"""
92 if self._streamable is None:
93 self._fill_info()
94 return self._streamable
95
96 @property
98 """is the full track streamable"""
99 if self._full_track is None:
100 self._fill_info()
101 return self._full_track
102
103 @property
105 """artist of the track"""
106 return self._artist
107
108 @property
110 """artist of the track"""
111 if self._album is None:
112 self._fill_info()
113 return self._album
114
115 @property
117 """position of the track"""
118 if self._position is None:
119 self._fill_info()
120 return self._position
121
122 @property
124 """image of the track's album cover"""
125 return self._image
126
127 @property
129 """stats of the track"""
130 return self._stats
131
132 @property
134 """datetime the track was last played"""
135 return self._played_on
136
137 @property
139 """datetime the track was marked 'loved'"""
140 return self._loved_on
141
142 @property
144 """wiki of the track"""
145 if self._wiki == "na":
146 return None
147 if self._wiki is None:
148 self._fill_info()
149 return self._wiki
150
151 @cached_property
153 """tracks similar to this track"""
154 params = Track._check_params(
155 {'method': 'track.getSimilar'},
156 self.artist.name,
157 self.name,
158 self.mbid
159 )
160 data = self._api._fetch_data(params).find('similartracks')
161 return [
162 Track(
163 self._api,
164 subject = self,
165 name = t.findtext('name'),
166 artist = Artist(
167 self._api,
168 subject = self,
169 name = t.findtext('artist/name'),
170 mbid = t.findtext('artist/mbid'),
171 url = t.findtext('artist/url')
172 ),
173 mbid = t.findtext('mbid'),
174 stats = Stats(
175 subject = t.findtext('name'),
176 match = float(t.findtext('match'))
177 ),
178 streamable = (t.findtext('streamable') == '1'),
179 full_track = (t.find('streamable').attrib['fulltrack'] == '1'),
180 image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
181 )
182 for t in data.findall('track')
183 ]
184
185 @top_property("similar")
187 """track most similar to this track"""
188 pass
189
190 @cached_property
192 """top fans of the track"""
193 params = Track._check_params(
194 {'method': 'track.getTopFans'},
195 self.artist.name,
196 self.name,
197 self.mbid
198 )
199 data = self._api._fetch_data(params).find('topfans')
200 return [
201 User(
202 self._api,
203 subject = self,
204 name = u.findtext('name'),
205 url = u.findtext('url'),
206 image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
207 stats = Stats(
208 subject = u.findtext('name'),
209 weight = int(u.findtext('weight'))
210 )
211 )
212 for u in data.findall('user')
213 ]
214
215 @top_property("top_fans")
217 """topmost fan of the track"""
218 pass
219
220 @cached_property
243
244 @top_property("top_tags")
246 """topmost tag for the track"""
247 pass
248
252
256
257 @staticmethod
258 - def get_info(api,
259 artist = None,
260 track = None,
261 mbid = None):
273
280
281 @staticmethod
283 return Track(
284 api,
285 name = track.findtext('name'),
286 artist = Artist(
287 api,
288 name=track.findtext('artist')
289 ),
290 url = track.findtext('url'),
291 stats = Stats(
292 subject=track.findtext('name'),
293 listeners=int(track.findtext('listeners'))
294 ),
295 streamable = (track.findtext('streamable') == '1'),
296 full_track = (track.find('streamable').attrib['fulltrack'] == '1'),
297 image = dict([(i.get('size'), i.text) for i in track.findall('image')]),
298 )
299
300 @staticmethod
301 - def _fetch_data(api,
302 artist = None,
303 track = None,
304 mbid = None):
307
309 data = Track._fetch_data(self._api, self.artist.name, self.name)
310 self._id = int(data.findtext('id'))
311 self._mbid = data.findtext('mbid')
312 self._url = data.findtext('url')
313 self._duration = int(data.findtext('duration'))
314 self._streamable = (data.findtext('streamable') == '1')
315 self._full_track = (data.find('streamable').attrib['fulltrack'] == '1')
316
317 self._image = dict([(i.get('size'), i.text) for i in data.findall('image')])
318 self._stats = Stats(
319 subject = self,
320 listeners = int(data.findtext('listeners')),
321 playcount = int(data.findtext('playcount')),
322 )
323 self._artist = Artist(
324 self._api,
325 name = data.findtext('artist/name'),
326 mbid = data.findtext('artist/mbid'),
327 url = data.findtext('artist/url')
328 )
329 if data.find('album') is not None:
330 self._album = Album(
331 self._api,
332 artist = self._artist,
333 name = data.findtext('album/title'),
334 mbid = data.findtext('album/mbid'),
335 url = data.findtext('album/url'),
336 image = dict([(i.get('size'), i.text) for i in data.findall('album/image')])
337 )
338 self._position = data.find('album').attrib['position'].strip() \
339 and int(data.find('album').attrib['position'])
340 if data.find('wiki') is not None:
341 self._wiki = Wiki(
342 self,
343 published = datetime(*(time.strptime(
344 data.findtext('wiki/published').strip(),
345 '%a, %d %b %Y %H:%M:%S +0000'
346 )[0:6])),
347 summary = data.findtext('wiki/summary'),
348 content = data.findtext('wiki/content')
349 )
350 else:
351 self._wiki = 'na'
352
353 @staticmethod
354 - def _check_params(params,
355 artist = None,
356 track = None,
357 mbid = None):
366
367 @staticmethod
369 try:
370 return hash("%s%s" % (kwds['name'], hash(kwds['artist'])))
371 except KeyError:
372 raise InvalidParametersError("name and artist have to be provided for hashing")
373
376
385
388
390 return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name)
391
392 import time
393 from datetime import datetime
394
395 from lastfm.api import Api
396 from lastfm.artist import Artist
397 from lastfm.album import Album
398 from lastfm.error import InvalidParametersError
399 from lastfm.stats import Stats
400 from lastfm.tag import Tag
401 from lastfm.user import User
402 from lastfm.wiki import Wiki
403