diff --git a/pylast.py b/pylast.py index 02ea3c1..e60ae42 100644 --- a/pylast.py +++ b/pylast.py @@ -226,6 +226,13 @@ class _Network(object): return Country(country_name, self) + def get_metro(self, metro_name, country_name): + """ + Returns a metro object + """ + + return Metro(metro_name, country_name, self) + def get_group(self, name): """ Returns a Group object @@ -412,8 +419,28 @@ class _Network(object): # geo.getMetroUniqueArtistChart # geo.getMetroUniqueTrackChart # geo.getMetroWeeklyChartlist - # geo.getMetros - # geo.getTopArtists + def get_metros(self, country=None, cacheable=True): + """Get a list of valid countries and metros for use in the other webservices. + Parameters: + country (Optional) : Optionally restrict the results to those Metros from a particular country, as defined by the ISO 3166-1 country names standard + """ + params = {} + + if country: params["country"] = country + + doc = _Request(self, "geo.getMetros", params).execute(cacheable) + + metros = doc.getElementsByTagName("metro") + seq = [] + + for metro in metros: + name = _extract(metro, "name") + country = _extract(metro, "country") + + seq.append(Metro(name, country, self)) + + return seq + def get_geo_top_artists(self, country, limit=None, cacheable=True): """Get the most popular artists on Last.fm by country. @@ -464,9 +491,6 @@ class _Network(object): return seq - # TODO? - # geo.getTopTracks - def enable_proxy(self, host, port): """Enable a default web proxy""" @@ -2089,6 +2113,48 @@ class Country(_BaseObject): return self.network._get_url(domain_name, "country") %{'country_name': country_name} +class Metro(_BaseObject): + """A metro at Last.fm.""" + + name = None + country = None + + __hash__ = _BaseObject.__hash__ + + def __init__(self, name, country, network): + _BaseObject.__init__(self, network) + + self.name = name + self.country = country + + def __repr__(self): + return "pylast.Metro(%s, %s, %s)" %(repr(self.name), repr(self.country), repr(self.network)) + + @_string_output + def __str__(self): + return self.get_name() + ", " + self.get_country() + + def __eq__(self, other): + return self.get_name().lower() == other.get_name().lower() and \ + self.get_country().lower() == other.get_country().lower() + + def __ne__(self, other): + return self.get_name() != other.get_name() or \ + self.get_country().lower() != other.get_country().lower() + + def _get_params(self): + return {'name': self.get_name(), 'country': self.get_country()} + + def get_name(self): + """Returns the metro name.""" + + return self.name + + def get_country(self): + """Returns the metro country.""" + + return self.country + class Library(_BaseObject): """A user's Last.fm library.""" diff --git a/test_pylast.py b/test_pylast.py index e8d84dd..e1cdc9b 100755 --- a/test_pylast.py +++ b/test_pylast.py @@ -396,6 +396,14 @@ class TestPyLast(unittest.TestCase): self.helper_is_thing_hashable(country) + def test_country_is_hashable(self): + # Arrange + metro = self.network.get_metro("Helsinki", "Finland") + + # Act/Assert + self.helper_is_thing_hashable(metro) + + def test_event_is_hashable(self): # Arrange user = self.network.get_user("RJ") @@ -896,6 +904,16 @@ class TestPyLast(unittest.TestCase): self.assertEqual(event.get_venue().location['city'], "Reading") + def test_geo_get_metros(self): + # Arrange + # Act + metros = self.network.get_metros(country = "Poland") + + # Assert + self.assertGreaterEqual(len(metros), 1) + self.assertEqual(type(metros[0]), pylast.Metro) + + def test_geo_get_top_artists(self): # Arrange # Act @@ -918,6 +936,19 @@ class TestPyLast(unittest.TestCase): self.assertEqual(type(tracks[0].item), pylast.Track) + def test_metro_class(self): + # Arrange + # Act + metro = self.network.get_metro("Bergen", "Norway") + + # Assert + self.assertEqual(metro.get_name(), "Bergen") + self.assertEqual(metro.get_country(), "Norway") + self.assertEqual(str(metro), "Bergen, Norway") + self.assertEqual(metro, pylast.Metro("Bergen", "Norway", self.network)) + self.assertNotEqual(metro, pylast.Metro("Wellington", "New Zealand", self.network)) + + if __name__ == '__main__': # For quick testing of a single case (eg. test = "test_scrobble")