works with CDATA tags
This commit is contained in:
parent
78aac5c437
commit
e2cc69a7e8
2
AUTHORS
Normal file
2
AUTHORS
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Amr Hassan <amr.hassan@gmail.com>
|
||||||
|
Lukas Lipka <lukaslipka@gmail.com>
|
|
@ -1,6 +0,0 @@
|
||||||
include pylast.py
|
|
||||||
include setup.py
|
|
||||||
include README
|
|
||||||
include COPYING
|
|
||||||
include INSTALL
|
|
||||||
include .build
|
|
10
PKG-INFO
Normal file
10
PKG-INFO
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: pylast
|
||||||
|
Version: 0.5.11
|
||||||
|
Summary: A Python interface to Last.fm (and other API compatible social networks)
|
||||||
|
Home-page: http://code.google.com/p/pylast/
|
||||||
|
Author: Amr Hassan <amr.hassan@gmail.com>
|
||||||
|
Author-email: amr.hassan@gmail.com
|
||||||
|
License: Apache2
|
||||||
|
Description: UNKNOWN
|
||||||
|
Platform: UNKNOWN
|
4
README
4
README
|
@ -3,5 +3,5 @@ pylast
|
||||||
|
|
||||||
A python interface to Last.fm. Try using the pydoc utility for help
|
A python interface to Last.fm. Try using the pydoc utility for help
|
||||||
on usage.
|
on usage.
|
||||||
|
For more info check out the project's home page at http://code.google.com/p/pylast/
|
||||||
Original code can be found at: http://code.google.com/p/pylast/
|
or the mailing list http://groups.google.com/group/pylast/
|
||||||
|
|
103
pylast.py
103
pylast.py
|
@ -313,6 +313,37 @@ class _Network(object):
|
||||||
|
|
||||||
return Playlist(user, e_id, self)
|
return Playlist(user, e_id, self)
|
||||||
|
|
||||||
|
def get_top_artists(self, limit=None):
|
||||||
|
"""Returns a sequence of the most played artists."""
|
||||||
|
|
||||||
|
doc = _Request(self, "chart.getTopArtists").execute(True)
|
||||||
|
seq = []
|
||||||
|
for node in doc.getElementsByTagName("artist"):
|
||||||
|
title = _extract(node, "name")
|
||||||
|
artist = Artist(title, self)
|
||||||
|
seq.append(artist)
|
||||||
|
|
||||||
|
if limit:
|
||||||
|
seq = seq[:limit]
|
||||||
|
|
||||||
|
return seq
|
||||||
|
|
||||||
|
def get_top_tracks(self, limit=None):
|
||||||
|
"""Returns a sequence of the most played tracks."""
|
||||||
|
|
||||||
|
doc = _Request(self, "chart.getTopTracks").execute(True)
|
||||||
|
seq = []
|
||||||
|
for node in doc.getElementsByTagName("track"):
|
||||||
|
title = _extract(node, "name")
|
||||||
|
artist = _extract(node, "name", 1)
|
||||||
|
track = Track(artist, title, self)
|
||||||
|
seq.append(track)
|
||||||
|
|
||||||
|
if limit:
|
||||||
|
seq = seq[:limit]
|
||||||
|
|
||||||
|
return seq
|
||||||
|
|
||||||
def get_top_tags(self, limit=None):
|
def get_top_tags(self, limit=None):
|
||||||
"""Returns a sequence of the most used tags as a sequence of TopItem objects."""
|
"""Returns a sequence of the most used tags as a sequence of TopItem objects."""
|
||||||
|
|
||||||
|
@ -352,6 +383,8 @@ class _Network(object):
|
||||||
|
|
||||||
def enable_caching(self, file_path = None):
|
def enable_caching(self, file_path = None):
|
||||||
"""Enables caching request-wide for all cachable calls.
|
"""Enables caching request-wide for all cachable calls.
|
||||||
|
In choosing the backend used for caching, it will try _SqliteCacheBackend first if
|
||||||
|
the module sqlite3 is present. If not, it will fallback to _ShelfCacheBackend which uses shelve.Shelf objects.
|
||||||
|
|
||||||
* file_path: A file path for the backend storage file. If
|
* file_path: A file path for the backend storage file. If
|
||||||
None set, a temp file would probably be created, according the backend.
|
None set, a temp file would probably be created, according the backend.
|
||||||
|
@ -1150,9 +1183,8 @@ class Album(_BaseObject, _Taggable):
|
||||||
|
|
||||||
title = None
|
title = None
|
||||||
artist = None
|
artist = None
|
||||||
username = None
|
|
||||||
|
|
||||||
def __init__(self, artist, title, network, username=None):
|
def __init__(self, artist, title, network):
|
||||||
"""
|
"""
|
||||||
Create an album instance.
|
Create an album instance.
|
||||||
# Parameters:
|
# Parameters:
|
||||||
|
@ -1169,7 +1201,6 @@ class Album(_BaseObject, _Taggable):
|
||||||
self.artist = Artist(artist, self.network)
|
self.artist = Artist(artist, self.network)
|
||||||
|
|
||||||
self.title = title
|
self.title = title
|
||||||
self.username = username
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.Album(%s, %s, %s)" %(repr(self.artist.name), repr(self.title), repr(self.network))
|
return "pylast.Album(%s, %s, %s)" %(repr(self.artist.name), repr(self.title), repr(self.network))
|
||||||
|
@ -1229,16 +1260,6 @@ class Album(_BaseObject, _Taggable):
|
||||||
|
|
||||||
return _number(_extract(self._request("album.getInfo", cacheable = True), "playcount"))
|
return _number(_extract(self._request("album.getInfo", cacheable = True), "playcount"))
|
||||||
|
|
||||||
def get_userplaycount(self):
|
|
||||||
"""Returns the number of plays by a given username"""
|
|
||||||
|
|
||||||
if not self.username: return
|
|
||||||
|
|
||||||
params = self._get_params()
|
|
||||||
params['username'] = self.username
|
|
||||||
|
|
||||||
return _number(_extract(self._request("album.getInfo", True, params), "userplaycount"))
|
|
||||||
|
|
||||||
def get_listener_count(self):
|
def get_listener_count(self):
|
||||||
"""Returns the number of liteners on the network"""
|
"""Returns the number of liteners on the network"""
|
||||||
|
|
||||||
|
@ -1334,9 +1355,8 @@ class Artist(_BaseObject, _Taggable):
|
||||||
"""An artist."""
|
"""An artist."""
|
||||||
|
|
||||||
name = None
|
name = None
|
||||||
username = None
|
|
||||||
|
|
||||||
def __init__(self, name, network, username=None):
|
def __init__(self, name, network):
|
||||||
"""Create an artist object.
|
"""Create an artist object.
|
||||||
# Parameters:
|
# Parameters:
|
||||||
* name str: The artist's name.
|
* name str: The artist's name.
|
||||||
|
@ -1346,7 +1366,6 @@ class Artist(_BaseObject, _Taggable):
|
||||||
_Taggable.__init__(self, 'artist')
|
_Taggable.__init__(self, 'artist')
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.username = username
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.Artist(%s, %s)" %(repr(self.get_name()), repr(self.network))
|
return "pylast.Artist(%s, %s)" %(repr(self.get_name()), repr(self.network))
|
||||||
|
@ -1392,16 +1411,6 @@ class Artist(_BaseObject, _Taggable):
|
||||||
|
|
||||||
return _number(_extract(self._request("artist.getInfo", True), "playcount"))
|
return _number(_extract(self._request("artist.getInfo", True), "playcount"))
|
||||||
|
|
||||||
def get_userplaycount(self):
|
|
||||||
"""Returns the number of plays by a given username"""
|
|
||||||
|
|
||||||
if not self.username: return
|
|
||||||
|
|
||||||
params = self._get_params()
|
|
||||||
params['username'] = self.username
|
|
||||||
|
|
||||||
return _number(_extract(self._request("artist.getInfo", True, params), "userplaycount"))
|
|
||||||
|
|
||||||
def get_mbid(self):
|
def get_mbid(self):
|
||||||
"""Returns the MusicBrainz ID of this artist."""
|
"""Returns the MusicBrainz ID of this artist."""
|
||||||
|
|
||||||
|
@ -2344,9 +2353,8 @@ class Track(_BaseObject, _Taggable):
|
||||||
|
|
||||||
artist = None
|
artist = None
|
||||||
title = None
|
title = None
|
||||||
username = None
|
|
||||||
|
|
||||||
def __init__(self, artist, title, network, username=None):
|
def __init__(self, artist, title, network):
|
||||||
_BaseObject.__init__(self, network)
|
_BaseObject.__init__(self, network)
|
||||||
_Taggable.__init__(self, 'track')
|
_Taggable.__init__(self, 'track')
|
||||||
|
|
||||||
|
@ -2357,8 +2365,6 @@ class Track(_BaseObject, _Taggable):
|
||||||
|
|
||||||
self.title = title
|
self.title = title
|
||||||
|
|
||||||
self.username = username
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.Track(%s, %s, %s)" %(repr(self.artist.name), repr(self.title), repr(self.network))
|
return "pylast.Track(%s, %s, %s)" %(repr(self.artist.name), repr(self.title), repr(self.network))
|
||||||
|
|
||||||
|
@ -2430,17 +2436,6 @@ class Track(_BaseObject, _Taggable):
|
||||||
doc = self._request("track.getInfo", True)
|
doc = self._request("track.getInfo", True)
|
||||||
return _number(_extract(doc, "playcount"))
|
return _number(_extract(doc, "playcount"))
|
||||||
|
|
||||||
def get_userplaycount(self):
|
|
||||||
"""Returns the number of plays by a given username"""
|
|
||||||
|
|
||||||
if not self.username: return
|
|
||||||
|
|
||||||
params = self._get_params()
|
|
||||||
params['username'] = self.username
|
|
||||||
|
|
||||||
doc = self._request("track.getInfo", True, params)
|
|
||||||
return _number(_extract(doc, "userplaycount"))
|
|
||||||
|
|
||||||
def is_streamable(self):
|
def is_streamable(self):
|
||||||
"""Returns True if the track is available at Last.fm."""
|
"""Returns True if the track is available at Last.fm."""
|
||||||
|
|
||||||
|
@ -2835,24 +2830,6 @@ class User(_BaseObject):
|
||||||
|
|
||||||
return events
|
return events
|
||||||
|
|
||||||
def get_artist_tracks(self, artist):
|
|
||||||
"""Get a list of tracks by a given artist scrobbled by this user, including scrobble time."""
|
|
||||||
# Not implemented: "Can be limited to specific timeranges, defaults to all time."
|
|
||||||
|
|
||||||
params = self._get_params()
|
|
||||||
params['artist'] = artist
|
|
||||||
|
|
||||||
seq = []
|
|
||||||
for track in _collect_nodes(None, self, "user.getArtistTracks", False, params):
|
|
||||||
title = _extract(track, "name")
|
|
||||||
artist = _extract(track, "artist")
|
|
||||||
date = _extract(track, "date")
|
|
||||||
timestamp = track.getElementsByTagName("date")[0].getAttribute("uts")
|
|
||||||
|
|
||||||
seq.append(PlayedTrack(Track(artist, title, self.network), date, timestamp))
|
|
||||||
|
|
||||||
return seq
|
|
||||||
|
|
||||||
def get_friends(self, limit = 50):
|
def get_friends(self, limit = 50):
|
||||||
"""Returns a list of the user's friends. """
|
"""Returns a list of the user's friends. """
|
||||||
|
|
||||||
|
@ -2946,7 +2923,7 @@ class User(_BaseObject):
|
||||||
artist = _extract(e, 'artist')
|
artist = _extract(e, 'artist')
|
||||||
title = _extract(e, 'name')
|
title = _extract(e, 'name')
|
||||||
|
|
||||||
return Track(artist, title, self.network, self.name)
|
return Track(artist, title, self.network)
|
||||||
|
|
||||||
|
|
||||||
def get_recent_tracks(self, limit = 10):
|
def get_recent_tracks(self, limit = 10):
|
||||||
|
@ -3552,7 +3529,7 @@ def _string(text):
|
||||||
|
|
||||||
def _collect_nodes(limit, sender, method_name, cacheable, params=None):
|
def _collect_nodes(limit, sender, method_name, cacheable, params=None):
|
||||||
"""
|
"""
|
||||||
Returns a sequence of dom.Node objects about as close to
|
Returns a sequqnce of dom.Node objects about as close to
|
||||||
limit as possible
|
limit as possible
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -3577,7 +3554,7 @@ def _collect_nodes(limit, sender, method_name, cacheable, params=None):
|
||||||
raise Exception("No total pages attribute")
|
raise Exception("No total pages attribute")
|
||||||
|
|
||||||
for node in main.childNodes:
|
for node in main.childNodes:
|
||||||
if not node.nodeType == xml.dom.Node.TEXT_NODE and (not limit or (len(nodes) < limit)):
|
if not node.nodeType == xml.dom.Node.TEXT_NODE and len(nodes) < limit:
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
|
||||||
if page >= total_pages:
|
if page >= total_pages:
|
||||||
|
@ -3594,7 +3571,7 @@ def _extract(node, name, index = 0):
|
||||||
|
|
||||||
if len(nodes):
|
if len(nodes):
|
||||||
if nodes[index].firstChild:
|
if nodes[index].firstChild:
|
||||||
return _unescape_htmlentity(nodes[index].firstChild.data.strip())
|
return _unescape_htmlentity(nodes[index].firstChild.wholeText.strip())
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
7
setup.py
Executable file → Normal file
7
setup.py
Executable file → Normal file
|
@ -1,5 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
try:
|
||||||
|
from setuptools import setup
|
||||||
|
except:
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -22,11 +25,11 @@ def get_build():
|
||||||
return str(build)
|
return str(build)
|
||||||
|
|
||||||
setup(name = "pylast",
|
setup(name = "pylast",
|
||||||
version = "0.1+0.5." + get_build(),
|
version = "0.5." + get_build(),
|
||||||
author = "Amr Hassan <amr.hassan@gmail.com>",
|
author = "Amr Hassan <amr.hassan@gmail.com>",
|
||||||
description = "A Python interface to Last.fm (and other API compatible social networks)",
|
description = "A Python interface to Last.fm (and other API compatible social networks)",
|
||||||
author_email = "amr.hassan@gmail.com",
|
author_email = "amr.hassan@gmail.com",
|
||||||
url = "https://github.com/Elizacat/",
|
url = "http://code.google.com/p/pylast/",
|
||||||
py_modules = ("pylast",),
|
py_modules = ("pylast",),
|
||||||
license = "Apache2"
|
license = "Apache2"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue