From 58b93c847e0e3ec71b1eff0b63a7d45e94005bc3 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 18 Oct 2017 08:57:39 +0300 Subject: [PATCH 1/9] WIP: More tests --- tests/test_pylast_network.py | 63 ++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/test_pylast_network.py b/tests/test_pylast_network.py index 553a7aa..04037f4 100755 --- a/tests/test_pylast_network.py +++ b/tests/test_pylast_network.py @@ -302,6 +302,69 @@ class TestPyLastNetwork(PyLastTestCase): self.assertEqual(msg, "Unauthorized Token - This token has not been issued") + def test_proxy(self): + # Arrange + host = "https://example.com" + port = 1234 + + # Act / Assert + self.network.enable_proxy(host, port) + self.assertTrue(self.network.is_proxy_enabled()) + self.assertEqual(self.network._get_proxy(), + ["https://example.com", 1234]) + + self.network.disable_proxy() + self.assertFalse(self.network.is_proxy_enabled()) + + def test_album_search(self): + # Arrange + album = "Nevermind" + + # Act + search = self.network.search_for_album(album) + results = search.get_next_page() + + # Assert + self.assertIsInstance(results, list) + self.assertIsInstance(results[0], pylast.Album) + + def test_artist_search(self): + # Arrange + artist = "Nirvana" + + # Act + search = self.network.search_for_artist(artist) + results = search.get_next_page() + + # Assert + self.assertIsInstance(results, list) + self.assertIsInstance(results[0], pylast.Artist) + + def test_tag_search(self): + # Arrange + tag = "rock" + + # Act + search = self.network.search_for_tag(tag) + results = search.get_next_page() + + # Assert + self.assertIsInstance(results, list) + self.assertIsInstance(results[0], pylast.Tag) + + def test_track_search(self): + # Arrange + artist = "Nirvana" + track = "Smells Like Teen Spirit" + + # Act + search = self.network.search_for_track(artist, track) + results = search.get_next_page() + + # Assert + self.assertIsInstance(results, list) + self.assertIsInstance(results[0], pylast.Track) + if __name__ == '__main__': unittest.main(failfast=True) From f70254b9473bc133e4138e1c4680df6c4ed3a72d Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 18 Oct 2017 22:31:15 +0300 Subject: [PATCH 2/9] Remove dead Last.fm tag search --- pylast/__init__.py | 27 --------------------------- tests/test_pylast_network.py | 12 ------------ 2 files changed, 39 deletions(-) diff --git a/pylast/__init__.py b/pylast/__init__.py index 333768b..0470a17 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -445,12 +445,6 @@ class _Network(object): return ArtistSearch(artist_name, self) - def search_for_tag(self, tag_name): - """Searches of a tag by its name. Returns a TagSearch object. - Use get_next_page() to retrieve sequences of results.""" - - return TagSearch(tag_name, self) - def search_for_track(self, artist_name, track_name): """Searches of a track by its name and its artist. Set artist to an empty string if not available. @@ -2729,27 +2723,6 @@ class ArtistSearch(_Search): return seq -class TagSearch(_Search): - """Search for a tag by tag name.""" - - def __init__(self, tag_name, network): - - _Search.__init__(self, "tag", {"tag": tag_name}, network) - - def get_next_page(self): - """Returns the next page of results as a sequence of Tag objects.""" - - master_node = self._retrieve_next_page() - - seq = [] - for node in master_node.getElementsByTagName("tag"): - tag = Tag(_extract(node, "name"), self.network) - tag.tag_count = _number(_extract(node, "count")) - seq.append(tag) - - return seq - - class TrackSearch(_Search): """ Search for a track by track title. If you don't want to narrow the results diff --git a/tests/test_pylast_network.py b/tests/test_pylast_network.py index 04037f4..7ea6432 100755 --- a/tests/test_pylast_network.py +++ b/tests/test_pylast_network.py @@ -340,18 +340,6 @@ class TestPyLastNetwork(PyLastTestCase): self.assertIsInstance(results, list) self.assertIsInstance(results[0], pylast.Artist) - def test_tag_search(self): - # Arrange - tag = "rock" - - # Act - search = self.network.search_for_tag(tag) - results = search.get_next_page() - - # Assert - self.assertIsInstance(results, list) - self.assertIsInstance(results[0], pylast.Tag) - def test_track_search(self): # Arrange artist = "Nirvana" From f2b699a11f37e4dda26da4281e9ce9379ff1b1b4 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 18 Oct 2017 23:48:02 +0300 Subject: [PATCH 3/9] More tests --- tests/test_pylast_library.py | 31 ++++++++++++++++++++++++++ tests/test_pylast_librefm.py | 14 ++++++++++++ tests/test_pylast_user.py | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/tests/test_pylast_library.py b/tests/test_pylast_library.py index 0df22da..1e437f1 100755 --- a/tests/test_pylast_library.py +++ b/tests/test_pylast_library.py @@ -11,6 +11,26 @@ from .test_pylast import PyLastTestCase class TestPyLastLibrary(PyLastTestCase): + def test_repr(self): + # Arrange + library = pylast.Library(user=self.username, network=self.network) + + # Act + representation = repr(library) + + # Assert + self.assertTrue(representation.startswith("pylast.Library(")) + + def test_str(self): + # Arrange + library = pylast.Library(user=self.username, network=self.network) + + # Act + string = str(library) + + # Assert + self.assertTrue(string.endswith("'s Library")) + def test_library_is_hashable(self): # Arrange library = pylast.Library(user=self.username, network=self.network) @@ -25,6 +45,17 @@ class TestPyLastLibrary(PyLastTestCase): # Act/Assert self.helper_validate_cacheable(library, "get_artists") + def test_get_user(self): + # Arrange + library = pylast.Library(user=self.username, network=self.network) + user_to_get = self.network.get_user(self.username) + + # Act + library_user = library.get_user() + + # Assert + self.assertEqual(library_user, user_to_get) + if __name__ == '__main__': unittest.main(failfast=True) diff --git a/tests/test_pylast_librefm.py b/tests/test_pylast_librefm.py index c403e2b..7c958cb 100755 --- a/tests/test_pylast_librefm.py +++ b/tests/test_pylast_librefm.py @@ -30,6 +30,20 @@ class TestPyLastWithLibreFm(unittest.TestCase): # Assert self.assertEqual(name, "Radiohead") + def test_repr(self): + # Arrange + secrets = load_secrets() + username = secrets["username"] + password_hash = secrets["password_hash"] + network = pylast.LibreFMNetwork( + password_hash=password_hash, username=username) + + # Act + representation = repr(network) + + # Assert + self.assertTrue(representation.startswith("pylast.LibreFMNetwork(")) + if __name__ == '__main__': unittest.main(failfast=True) diff --git a/tests/test_pylast_user.py b/tests/test_pylast_user.py index 3f24baa..36ef7bd 100755 --- a/tests/test_pylast_user.py +++ b/tests/test_pylast_user.py @@ -14,6 +14,49 @@ from .test_pylast import PyLastTestCase class TestPyLastUser(PyLastTestCase): + def test_repr(self): + # Arrange + username = "RJ" + user = self.network.get_user(username) + + # Act + representation = repr(user) + + # Assert + self.assertTrue( + representation.startswith(representation), "pylast.User('RJ',") + + def test_str(self): + # Arrange + username = "RJ" + user = self.network.get_user(username) + + # Act + string = str(user) + + # Assert + self.assertEqual(string, "RJ") + + def test_equality(self): + # Arrange + username = "RJ" + user = self.network.get_user(username) + not_a_user = self.network + + # Act / Assert + self.assertNotEqual(user, not_a_user) + + def test_get_name(self): + # Arrange + username = "RJ" + user = self.network.get_user(username) + + # Act + name = user.get_name(properly_capitalized=True) + + # Assert + self.assertEqual(name, "RJ") + def test_get_user_registration(self): # Arrange username = "RJ" From 2ef88dfd4c0c26b3af042d090352e07be0644f1b Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 00:22:06 +0300 Subject: [PATCH 4/9] Remove dead or broken Last.fm user functions --- pylast/__init__.py | 56 ---------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/pylast/__init__.py b/pylast/__init__.py index 0470a17..270ae69 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -97,9 +97,6 @@ IMAGES_ORDER_POPULARITY = "popularity" IMAGES_ORDER_DATE = "dateadded" -USER_MALE = 'Male' -USER_FEMALE = 'Female' - SCROBBLE_SOURCE_USER = "P" SCROBBLE_SOURCE_NON_PERSONALIZED_BROADCAST = "R" SCROBBLE_SOURCE_PERSONALIZED_BROADCAST = "E" @@ -2255,24 +2252,6 @@ class User(_BaseObject, _Chartable): return seq - def get_neighbours(self, limit=50, cacheable=True): - """Returns a list of the user's friends.""" - - params = self._get_params() - if limit: - params['limit'] = limit - - doc = self._request( - self.ws_prefix + '.getNeighbours', cacheable, params) - - seq = [] - names = _extract_all(doc, 'name') - - for name in names: - seq.append(User(name, self.network)) - - return seq - def get_now_playing(self): """ Returns the currently playing track, or None if nothing is playing. @@ -2350,20 +2329,6 @@ class User(_BaseObject, _Chartable): return seq - def get_id(self): - """Returns the user ID.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - - return _extract(doc, "id") - - def get_language(self): - """Returns the language code of the language used by the user.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - - return _extract(doc, "lang") - def get_country(self): """Returns the name of the country of the user.""" @@ -2376,27 +2341,6 @@ class User(_BaseObject, _Chartable): else: return Country(country, self.network) - def get_age(self): - """Returns the user's age.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - - return _number(_extract(doc, "age")) - - def get_gender(self): - """Returns the user's gender. Either USER_MALE or USER_FEMALE.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - - value = _extract(doc, "gender") - - if value == 'm': - return USER_MALE - elif value == 'f': - return USER_FEMALE - - return None - def is_subscriber(self): """Returns whether the user is a subscriber or not. True or False.""" From 5fd9e4c8c5232c76b4879d26f9a166a105dd4f34 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 00:33:02 +0300 Subject: [PATCH 5/9] Remove dead or broken Last.fm user functions --- pylast/__init__.py | 33 --------------------------------- tests/test_pylast_user.py | 11 ----------- 2 files changed, 44 deletions(-) diff --git a/pylast/__init__.py b/pylast/__init__.py index 270ae69..a1a23d2 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -2489,39 +2489,6 @@ class User(_BaseObject, _Chartable): return self._get_things( "getTopTracks", "track", Track, params, cacheable) - def compare_with_user(self, user, shared_artists_limit=None): - """ - Compare this user with another Last.fm user. - Returns a sequence: - (tasteometer_score, (shared_artist1, shared_artist2, ...)) - user: A User object or a username string/unicode object. - """ - - if isinstance(user, User): - user = user.get_name() - - params = self._get_params() - if shared_artists_limit: - params['limit'] = shared_artists_limit - params['type1'] = 'user' - params['type2'] = 'user' - params['value1'] = self.get_name() - params['value2'] = user - - doc = self._request('tasteometer.compare', False, params) - - score = _extract(doc, 'score') - - artists = doc.getElementsByTagName('artists')[0] - shared_artists_names = _extract_all(artists, 'name') - - shared_artists_seq = [] - - for name in shared_artists_names: - shared_artists_seq.append(Artist(name, self.network)) - - return (score, shared_artists_seq) - def get_image(self): """Returns the user's avatar.""" diff --git a/tests/test_pylast_user.py b/tests/test_pylast_user.py index 36ef7bd..9121dbe 100755 --- a/tests/test_pylast_user.py +++ b/tests/test_pylast_user.py @@ -85,17 +85,6 @@ class TestPyLastUser(PyLastTestCase): # Just check date because of timezones self.assertEqual(unixtime_registered, u"1037793040") - def test_get_genderless_user(self): - # Arrange - # Currently test_user has no gender set: - lastfm_user = self.network.get_user("test_user") - - # Act - gender = lastfm_user.get_gender() - - # Assert - self.assertIsNone(gender) - def test_get_countryless_user(self): # Arrange # Currently test_user has no country set: From ebc5b29f5cdf719c1a35b4c48deb064a793874b6 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 00:46:23 +0300 Subject: [PATCH 6/9] Remove dead or broken Last.fm user functions --- pylast/__init__.py | 44 --------------------------------------- tests/test_pylast_user.py | 17 --------------- 2 files changed, 61 deletions(-) diff --git a/pylast/__init__.py b/pylast/__init__.py index a1a23d2..e74c247 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -1074,37 +1074,6 @@ class _BaseObject(object): return seq - def share(self, users, message=None): - """ - Shares this (sends out recommendations). - Parameters: - * users [User|str,]: A list that can contain usernames, emails, - User objects, or all of them. - * message str: A message to include in the recommendation message. - Only for Artist/Track. - """ - - # Last.fm currently accepts a max of 10 recipient at a time - while len(users) > 10: - section = users[0:9] - users = users[9:] - self.share(section, message) - - user_names = [] - for user in users: - if isinstance(user, User): - user_names.append(user.get_name()) - else: - user_names.append(user) - - params = self._get_params() - recipients = ','.join(user_names) - params['recipient'] = recipients - if message: - params['message'] = message - - self._request(self.ws_prefix + '.share', False, params) - def get_wiki_published_date(self): """ Returns the summary of the wiki. @@ -2538,19 +2507,6 @@ class AuthenticatedUser(User): self.name = _extract(doc, "name") return self.name - def get_recommended_artists(self, limit=50, cacheable=False): - """ - Returns a sequence of Artist objects - if limit==None it will return all - """ - - seq = [] - for node in _collect_nodes( - limit, self, "user.getRecommendedArtists", cacheable): - seq.append(Artist(_extract(node, "name"), self.network)) - - return seq - class _Search(_BaseObject): """An abstract class. Use one of its derivatives.""" diff --git a/tests/test_pylast_user.py b/tests/test_pylast_user.py index 9121dbe..26876bf 100755 --- a/tests/test_pylast_user.py +++ b/tests/test_pylast_user.py @@ -256,23 +256,6 @@ class TestPyLastUser(PyLastTestCase): # Act/Assert self.helper_get_assert_charts(lastfm_user, dates[0]) - # Commented out to avoid spamming - # def test_share_spam(self): - # # Arrange - # users_to_spam = [TODO_ENTER_SPAMEES_HERE] - # spam_message = "Dig the krazee sound!" - # artist = self.network.get_top_artists(limit=1)[0].item - # track = artist.get_top_tracks(limit=1)[0].item - - # # Act - # artist.share(users_to_spam, spam_message) - # track.share(users_to_spam, spam_message) - - # Assert - # Check inbox for spam! - - # album/artist/track/user - def test_user_top_artists(self): # Arrange lastfm_user = self.network.get_user(self.username) From f9a8bf3daee5a4fd4fa59dd0318e7172eff9c5f9 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 00:55:20 +0300 Subject: [PATCH 7/9] More tests --- tests/test_pylast_album.py | 11 +++++++ tests/test_pylast_artist.py | 11 +++++++ tests/test_pylast_user.py | 64 ++++++++++++++++++++++++++++--------- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/tests/test_pylast_album.py b/tests/test_pylast_album.py index a93c27d..53581a5 100755 --- a/tests/test_pylast_album.py +++ b/tests/test_pylast_album.py @@ -99,6 +99,17 @@ class TestPyLastAlbum(PyLastTestCase): # Act / Assert self.assertTrue(album1 != album2) + def test_get_cover_image(self): + # Arrange + album = self.network.get_album("Test Artist", "Test Album") + + # Act + image = album.get_cover_image() + + # Assert + self.assertTrue(image.startswith("https://")) + self.assertTrue(image.endswith(".png")) + if __name__ == '__main__': unittest.main(failfast=True) diff --git a/tests/test_pylast_artist.py b/tests/test_pylast_artist.py index 4fe15a2..bec278e 100755 --- a/tests/test_pylast_artist.py +++ b/tests/test_pylast_artist.py @@ -11,6 +11,17 @@ from .test_pylast import PyLastTestCase class TestPyLastArtist(PyLastTestCase): + def test_repr(self): + # Arrange + artist = pylast.Artist("Test Artist", self.network) + + # Act + representation = repr(artist) + + # Assert + self.assertTrue( + representation.startswith("pylast.Artist('Test Artist',")) + def test_artist_is_hashable(self): # Arrange test_artist = self.network.get_artist("Test Artist") diff --git a/tests/test_pylast_user.py b/tests/test_pylast_user.py index 26876bf..7613345 100755 --- a/tests/test_pylast_user.py +++ b/tests/test_pylast_user.py @@ -16,20 +16,17 @@ class TestPyLastUser(PyLastTestCase): def test_repr(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user = self.network.get_user("RJ") # Act representation = repr(user) # Assert - self.assertTrue( - representation.startswith(representation), "pylast.User('RJ',") + self.assertTrue(representation.startswith("pylast.User('RJ',")) def test_str(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user = self.network.get_user("RJ") # Act string = str(user) @@ -39,17 +36,27 @@ class TestPyLastUser(PyLastTestCase): def test_equality(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user_1a = self.network.get_user("RJ") + user_1b = self.network.get_user("RJ") + user_2 = self.network.get_user("Test User") not_a_user = self.network # Act / Assert - self.assertNotEqual(user, not_a_user) + self.assertEqual(user_1a, user_1b) + self.assertTrue(user_1a == user_1b) + self.assertFalse(user_1a != user_1b) + + self.assertNotEqual(user_1a, user_2) + self.assertTrue(user_1a != user_2) + self.assertFalse(user_1a == user_2) + + self.assertNotEqual(user_1a, not_a_user) + self.assertTrue(user_1a != not_a_user) + self.assertFalse(user_1a == not_a_user) def test_get_name(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user = self.network.get_user("RJ") # Act name = user.get_name(properly_capitalized=True) @@ -59,8 +66,7 @@ class TestPyLastUser(PyLastTestCase): def test_get_user_registration(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user = self.network.get_user("RJ") # Act registered = user.get_registered() @@ -75,8 +81,7 @@ class TestPyLastUser(PyLastTestCase): def test_get_user_unixtime_registration(self): # Arrange - username = "RJ" - user = self.network.get_user(username) + user = self.network.get_user("RJ") # Act unixtime_registered = user.get_unixtime_registered() @@ -458,6 +463,35 @@ class TestPyLastUser(PyLastTestCase): # Assert self.assertEqual(mbid, None) + def test_get_playcount(self): + # Arrange + user = self.network.get_user("RJ") + + # Act + playcount = user.get_playcount() + + # Assert + self.assertGreaterEqual(playcount, 128387) + + def test_get_image(self): + # Arrange + user = self.network.get_user("RJ") + + # Act / Assert + image = user.get_image() + + self.assertTrue(image.startswith("https://")) + self.assertTrue(image.endswith(".png")) + + def test_get_url(self): + # Arrange + user = self.network.get_user("RJ") + + # Act / Assert + url = user.get_url() + + self.assertEqual(url, "https://www.last.fm/user/rj") + if __name__ == '__main__': unittest.main(failfast=True) From 85bf9f9928272a0c3c95b964413c4a83677d1ac1 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 23:36:00 +0300 Subject: [PATCH 8/9] Remove dead Last.fm track ban --- pylast/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pylast/__init__.py b/pylast/__init__.py index e74c247..06fe302 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -2052,11 +2052,6 @@ class Track(_Opus): self._request(self.ws_prefix + '.unlove') - def ban(self): - """Ban this track from ever playing on the radio. """ - - self._request(self.ws_prefix + '.ban') - def get_similar(self): """ Returns similar tracks for this track on the network, From 8f3628a6386fe55c1271332010d4a3141a9bf30d Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 19 Oct 2017 23:37:10 +0300 Subject: [PATCH 9/9] More tests --- tests/test_pylast_artist.py | 11 ++++++++ tests/test_pylast_track.py | 56 +++++++++++++++++++++++++++++++++++++ tests/test_pylast_user.py | 10 +++++++ 3 files changed, 77 insertions(+) diff --git a/tests/test_pylast_artist.py b/tests/test_pylast_artist.py index bec278e..75c951d 100755 --- a/tests/test_pylast_artist.py +++ b/tests/test_pylast_artist.py @@ -268,6 +268,17 @@ class TestPyLastArtist(PyLastTestCase): # Assert self.assertEqual(corrected_artist_name, "Guns N' Roses") + def test_get_userplaycount(self): + # Arrange + artist = pylast.Artist("John Lennon", self.network, + username=self.username) + + # Act + playcount = artist.get_userplaycount() + + # Assert + self.assertGreaterEqual(playcount, 0) + if __name__ == '__main__': unittest.main(failfast=True) diff --git a/tests/test_pylast_track.py b/tests/test_pylast_track.py index 9f446da..61ef132 100755 --- a/tests/test_pylast_track.py +++ b/tests/test_pylast_track.py @@ -104,6 +104,62 @@ class TestPyLastTrack(PyLastTestCase): self.assertIsNotNone(wiki) self.assertGreaterEqual(len(wiki), 1) + def test_track_get_duration(self): + # Arrange + track = pylast.Track("Nirvana", "Lithium", self.network) + + # Act + duration = track.get_duration() + + # Assert + self.assertGreaterEqual(duration, 200000) + + def test_track_is_streamable(self): + # Arrange + track = pylast.Track("Nirvana", "Lithium", self.network) + + # Act + streamable = track.is_streamable() + + # Assert + self.assertFalse(streamable) + + def test_track_is_fulltrack_available(self): + # Arrange + track = pylast.Track("Nirvana", "Lithium", self.network) + + # Act + fulltrack_available = track.is_fulltrack_available() + + # Assert + self.assertFalse(fulltrack_available) + + def test_track_get_album(self): + # Arrange + track = pylast.Track("Nirvana", "Lithium", self.network) + + # Act + album = track.get_album() + print(album) + + # Assert + self.assertEqual(str(album), "Nirvana - Nevermind") + + def test_track_get_similar(self): + # Arrange + track = pylast.Track("Cher", "Believe", self.network) + + # Act + similar = track.get_similar() + + # Assert + found = False + for track in similar: + if str(track.item) == "Madonna - Vogue": + found = True + break + self.assertTrue(found) + if __name__ == '__main__': unittest.main(failfast=True) diff --git a/tests/test_pylast_user.py b/tests/test_pylast_user.py index 7613345..b64e0ee 100755 --- a/tests/test_pylast_user.py +++ b/tests/test_pylast_user.py @@ -101,6 +101,16 @@ class TestPyLastUser(PyLastTestCase): # Assert self.assertIsNone(country) + def test_user_get_country(self): + # Arrange + lastfm_user = self.network.get_user("RJ") + + # Act + country = lastfm_user.get_country() + + # Assert + self.assertEqual(str(country), "United Kingdom") + def test_user_equals_none(self): # Arrange lastfm_user = self.network.get_user(self.username)