Merge pull request #228 from pylast/no-skipping-broken-last.fm
No more skipping broken Last.fm and remove more dead Last.fm stuff
This commit is contained in:
commit
3607deae80
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
from xml.dom import minidom, Node
|
from xml.dom import minidom, Node
|
||||||
import collections
|
import collections
|
||||||
import re
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import shelve
|
import shelve
|
||||||
import six
|
import six
|
||||||
|
@ -108,18 +107,6 @@ SCROBBLE_MODE_LOVED = "L"
|
||||||
SCROBBLE_MODE_BANNED = "B"
|
SCROBBLE_MODE_BANNED = "B"
|
||||||
SCROBBLE_MODE_SKIPPED = "S"
|
SCROBBLE_MODE_SKIPPED = "S"
|
||||||
|
|
||||||
# From http://boodebr.org/main/python/all-about-python-and-unicode#UNI_XML
|
|
||||||
RE_XML_ILLEGAL = (u'([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])' +
|
|
||||||
u'|' +
|
|
||||||
u'([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])'
|
|
||||||
%
|
|
||||||
(unichr(0xd800), unichr(0xdbff), unichr(0xdc00),
|
|
||||||
unichr(0xdfff), unichr(0xd800), unichr(0xdbff),
|
|
||||||
unichr(0xdc00), unichr(0xdfff), unichr(0xd800),
|
|
||||||
unichr(0xdbff), unichr(0xdc00), unichr(0xdfff)))
|
|
||||||
|
|
||||||
XML_ILLEGAL = re.compile(RE_XML_ILLEGAL)
|
|
||||||
|
|
||||||
# Python >3.4 and >2.7.9 has sane defaults
|
# Python >3.4 and >2.7.9 has sane defaults
|
||||||
SSL_CONTEXT = ssl.create_default_context()
|
SSL_CONTEXT = ssl.create_default_context()
|
||||||
|
|
||||||
|
@ -862,8 +849,6 @@ class _Request(object):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise MalformedResponseError(self.network, e)
|
raise MalformedResponseError(self.network, e)
|
||||||
|
|
||||||
response_text = XML_ILLEGAL.sub("?", response_text)
|
|
||||||
|
|
||||||
self._check_response_for_errors(response_text)
|
self._check_response_for_errors(response_text)
|
||||||
conn.close()
|
conn.close()
|
||||||
return response_text
|
return response_text
|
||||||
|
@ -1429,12 +1414,6 @@ class _Opus(_BaseObject, _Taggable):
|
||||||
|
|
||||||
return self.get_title(properly_capitalized)
|
return self.get_title(properly_capitalized)
|
||||||
|
|
||||||
def get_id(self):
|
|
||||||
"""Returns the ID on the network."""
|
|
||||||
|
|
||||||
return _extract(
|
|
||||||
self._request(self.ws_prefix + ".getInfo", cacheable=True), "id")
|
|
||||||
|
|
||||||
def get_playcount(self):
|
def get_playcount(self):
|
||||||
"""Returns the number of plays on the network"""
|
"""Returns the number of plays on the network"""
|
||||||
|
|
||||||
|
@ -1738,17 +1717,6 @@ class Artist(_BaseObject, _Taggable):
|
||||||
return self.network._get_url(
|
return self.network._get_url(
|
||||||
domain_name, "artist") % {'artist': artist}
|
domain_name, "artist") % {'artist': artist}
|
||||||
|
|
||||||
def get_band_members(self):
|
|
||||||
"""Returns a list of band members or None if unknown."""
|
|
||||||
|
|
||||||
names = None
|
|
||||||
doc = self._request(self.ws_prefix + ".getInfo", True)
|
|
||||||
|
|
||||||
for node in doc.getElementsByTagName("bandmembers"):
|
|
||||||
names = _extract_all(node, "name")
|
|
||||||
|
|
||||||
return names
|
|
||||||
|
|
||||||
|
|
||||||
class Country(_BaseObject):
|
class Country(_BaseObject):
|
||||||
"""A country at Last.fm."""
|
"""A country at Last.fm."""
|
||||||
|
@ -1915,18 +1883,6 @@ class Tag(_BaseObject, _Chartable):
|
||||||
|
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def get_similar(self):
|
|
||||||
"""Returns the tags similar to this one, ordered by similarity. """
|
|
||||||
|
|
||||||
doc = self._request(self.ws_prefix + '.getSimilar', True)
|
|
||||||
|
|
||||||
seq = []
|
|
||||||
names = _extract_all(doc, 'name')
|
|
||||||
for name in names:
|
|
||||||
seq.append(Tag(name, self.network))
|
|
||||||
|
|
||||||
return seq
|
|
||||||
|
|
||||||
def get_top_albums(self, limit=None, cacheable=True):
|
def get_top_albums(self, limit=None, cacheable=True):
|
||||||
"""Returns a list of the top albums."""
|
"""Returns a list of the top albums."""
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
|
|
|
@ -52,11 +52,6 @@ class PyLastTestCase(unittest.TestCase):
|
||||||
api_key=API_KEY, api_secret=API_SECRET,
|
api_key=API_KEY, api_secret=API_SECRET,
|
||||||
username=self.username, password_hash=password_hash)
|
username=self.username, password_hash=password_hash)
|
||||||
|
|
||||||
def skip_if_lastfm_api_broken(self, value):
|
|
||||||
"""Skip things not yet restored in Last.fm's broken API"""
|
|
||||||
if value is None or len(value) == 0:
|
|
||||||
pytest.skip("Last.fm API is broken.")
|
|
||||||
|
|
||||||
def helper_is_thing_hashable(self, thing):
|
def helper_is_thing_hashable(self, thing):
|
||||||
# Arrange
|
# Arrange
|
||||||
things = set()
|
things = set()
|
||||||
|
|
|
@ -237,27 +237,6 @@ class TestPyLastArtist(PyLastTestCase):
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertTrue(artist1 != artist2)
|
self.assertTrue(artist1 != artist2)
|
||||||
|
|
||||||
def test_band_members(self):
|
|
||||||
# Arrange
|
|
||||||
artist = pylast.Artist("The Beatles", self.network)
|
|
||||||
|
|
||||||
# Act
|
|
||||||
band_members = artist.get_band_members()
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
self.skip_if_lastfm_api_broken(band_members)
|
|
||||||
self.assertGreaterEqual(len(band_members), 4)
|
|
||||||
|
|
||||||
def test_no_band_members(self):
|
|
||||||
# Arrange
|
|
||||||
artist = pylast.Artist("John Lennon", self.network)
|
|
||||||
|
|
||||||
# Act
|
|
||||||
band_members = artist.get_band_members()
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
self.assertIsNone(band_members)
|
|
||||||
|
|
||||||
def test_artist_get_correction(self):
|
def test_artist_get_correction(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
artist = pylast.Artist("guns and roses", self.network)
|
artist = pylast.Artist("guns and roses", self.network)
|
||||||
|
|
|
@ -47,20 +47,6 @@ class TestPyLastNetwork(PyLastTestCase):
|
||||||
self.assertEqual(str(current_track.title), "test title")
|
self.assertEqual(str(current_track.title), "test title")
|
||||||
self.assertEqual(str(current_track.artist), "Test Artist")
|
self.assertEqual(str(current_track.artist), "Test Artist")
|
||||||
|
|
||||||
def test_invalid_xml(self):
|
|
||||||
# Arrange
|
|
||||||
# Currently causes PCDATA invalid Char value 25
|
|
||||||
artist = "Blind Willie Johnson"
|
|
||||||
title = "It's nobody's fault but mine"
|
|
||||||
|
|
||||||
# Act
|
|
||||||
search = self.network.search_for_track(artist, title)
|
|
||||||
total = search.get_total_result_count()
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
self.skip_if_lastfm_api_broken(total)
|
|
||||||
self.assertGreaterEqual(int(total), 0)
|
|
||||||
|
|
||||||
def test_enable_rate_limiting(self):
|
def test_enable_rate_limiting(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
self.assertFalse(self.network.is_rate_limited())
|
self.assertFalse(self.network.is_rate_limited())
|
||||||
|
|
|
@ -58,22 +58,6 @@ class TestPyLastTag(PyLastTestCase):
|
||||||
self.assertTrue(tag1 != tag2)
|
self.assertTrue(tag1 != tag2)
|
||||||
self.assertEqual(url, "https://www.last.fm/tag/blues")
|
self.assertEqual(url, "https://www.last.fm/tag/blues")
|
||||||
|
|
||||||
def test_tags_similar(self):
|
|
||||||
# Arrange
|
|
||||||
tag = self.network.get_tag("blues")
|
|
||||||
|
|
||||||
# Act
|
|
||||||
similar = tag.get_similar()
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
self.skip_if_lastfm_api_broken(similar)
|
|
||||||
found = False
|
|
||||||
for tag in similar:
|
|
||||||
if tag.name == "delta blues":
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
self.assertTrue(found)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(failfast=True)
|
unittest.main(failfast=True)
|
||||||
|
|
|
@ -5,8 +5,6 @@ Integration (not unit) tests for pylast.py
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
import pylast
|
import pylast
|
||||||
|
|
||||||
from .test_pylast import PyLastTestCase
|
from .test_pylast import PyLastTestCase
|
||||||
|
@ -72,10 +70,11 @@ class TestPyLastUser(PyLastTestCase):
|
||||||
registered = user.get_registered()
|
registered = user.get_registered()
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
# Last.fm API broken? Should be yyyy-mm-dd not Unix timestamp
|
|
||||||
if int(registered):
|
if int(registered):
|
||||||
pytest.skip("Last.fm API is broken.")
|
# Last.fm API broken? Used to be yyyy-mm-dd not Unix timestamp
|
||||||
|
self.assertEqual(registered, "1037793040")
|
||||||
|
else:
|
||||||
|
# Old way
|
||||||
# Just check date because of timezones
|
# Just check date because of timezones
|
||||||
self.assertIn(u"2002-11-20 ", registered)
|
self.assertIn(u"2002-11-20 ", registered)
|
||||||
|
|
||||||
|
@ -219,7 +218,6 @@ class TestPyLastUser(PyLastTestCase):
|
||||||
tags = user.get_top_tags(limit=1)
|
tags = user.get_top_tags(limit=1)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.skip_if_lastfm_api_broken(tags)
|
|
||||||
self.helper_only_one_thing_in_top_list(tags, pylast.Tag)
|
self.helper_only_one_thing_in_top_list(tags, pylast.Tag)
|
||||||
|
|
||||||
def test_user_top_tracks(self):
|
def test_user_top_tracks(self):
|
||||||
|
@ -392,17 +390,6 @@ class TestPyLastUser(PyLastTestCase):
|
||||||
# Assert
|
# Assert
|
||||||
self.assertNotEqual(track1, track2)
|
self.assertNotEqual(track1, track2)
|
||||||
|
|
||||||
def test_track_id(self):
|
|
||||||
# Arrange
|
|
||||||
track = pylast.Track("Test Artist", "test title", self.network)
|
|
||||||
|
|
||||||
# Act
|
|
||||||
id = track.get_id()
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
self.skip_if_lastfm_api_broken(id)
|
|
||||||
self.assertEqual(id, "14053327")
|
|
||||||
|
|
||||||
def test_track_title_prop_caps(self):
|
def test_track_title_prop_caps(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
track = pylast.Track("test artist", "test title", self.network)
|
track = pylast.Track("test artist", "test title", self.network)
|
||||||
|
|
Loading…
Reference in a new issue