diff --git a/src/pylast/__init__.py b/src/pylast/__init__.py index 3065e7d..e152c31 100644 --- a/src/pylast/__init__.py +++ b/src/pylast/__init__.py @@ -41,7 +41,7 @@ try: import importlib.metadata as importlib_metadata except ImportError: # Python 3.7 and lower - import importlib_metadata + import importlib_metadata # type: ignore __author__ = "Amr Hassan, hugovk, Mice Pápai" __copyright__ = "Copyright (C) 2008-2010 Amr Hassan, 2013-2021 hugovk, 2017 Mice Pápai" @@ -156,7 +156,7 @@ class _Network: domain_names, urls, token=None, - ): + ) -> None: """ name: the name of the network homepage: the homepage URL @@ -196,7 +196,7 @@ class _Network: self.cache_backend = None self.proxy = None - self.last_call_time = 0 + self.last_call_time: float = 0.0 self.limit_rate = False # Load session_key and username from authentication token if provided @@ -215,8 +215,8 @@ class _Network: sk_gen = SessionKeyGenerator(self) self.session_key = sk_gen.get_session_key(self.username, self.password_hash) - def __str__(self): - return "%s Network" % self.name + def __str__(self) -> str: + return f"{self.name} Network" def get_artist(self, artist_name): """ @@ -275,10 +275,8 @@ class _Network: if domain_language in self.domain_names: return self.domain_names[domain_language] - def _get_url(self, domain, url_type): - return "https://{}/{}".format( - self._get_language_domain(domain), self.urls[url_type] - ) + def _get_url(self, domain, url_type) -> str: + return f"https://{self._get_language_domain(domain)}/{self.urls[url_type]}" def _get_ws_auth(self): """ @@ -286,7 +284,7 @@ class _Network: """ return self.api_key, self.api_secret, self.session_key - def _delay_call(self): + def _delay_call(self) -> None: """ Makes sure that web service calls are at least 0.2 seconds apart. """ @@ -299,7 +297,7 @@ class _Network: self.last_call_time = now - def get_top_artists(self, limit=None, cacheable=True): + def get_top_artists(self, limit=None, cacheable: bool = True): """Returns the most played artists as a sequence of TopItem objects.""" params = {} @@ -310,7 +308,7 @@ class _Network: return _extract_top_artists(doc, self) - def get_top_tracks(self, limit=None, cacheable=True): + def get_top_tracks(self, limit=None, cacheable: bool = True): """Returns the most played tracks as a sequence of TopItem objects.""" params = {} @@ -329,14 +327,14 @@ class _Network: return seq - def get_top_tags(self, limit=None, cacheable=True): + def get_top_tags(self, limit=None, cacheable: bool = True): """Returns the most used tags as a sequence of TopItem objects.""" # Last.fm has no "limit" parameter for tag.getTopTags # so we need to get all (250) and then limit locally doc = _Request(self, "tag.getTopTags").execute(cacheable) - seq = [] + seq: list[TopItem] = [] for node in doc.getElementsByTagName("tag"): if limit and len(seq) >= limit: break @@ -346,7 +344,7 @@ class _Network: return seq - def get_geo_top_artists(self, country, limit=None, cacheable=True): + def get_geo_top_artists(self, country, limit=None, cacheable: bool = True): """Get the most popular artists on Last.fm by country. Parameters: country (Required) : A country name, as defined by the ISO 3166-1 @@ -363,7 +361,9 @@ class _Network: return _extract_top_artists(doc, self) - def get_geo_top_tracks(self, country, location=None, limit=None, cacheable=True): + def get_geo_top_tracks( + self, country, location=None, limit=None, cacheable: bool = True + ): """Get the most popular tracks on Last.fm last week by country. Parameters: country (Required) : A country name, as defined by the ISO 3166-1 @@ -409,59 +409,52 @@ class _Network: """Returns True if web proxy is enabled.""" return self.proxy is not None - def enable_rate_limit(self): + def enable_rate_limit(self) -> None: """Enables rate limiting for this network""" self.limit_rate = True - def disable_rate_limit(self): + def disable_rate_limit(self) -> None: """Disables rate limiting for this network""" self.limit_rate = False - def is_rate_limited(self): + def is_rate_limited(self) -> bool: """Return True if web service calls are rate limited""" return self.limit_rate - def enable_caching(self, file_path=None): + def enable_caching(self, file_path=None) -> None: """Enables caching request-wide for all cacheable calls. * file_path: A file path for the backend storage file. If None set, a temp file would probably be created, according the backend. """ - if not file_path: self.cache_backend = _ShelfCacheBackend.create_shelf() return self.cache_backend = _ShelfCacheBackend(file_path) - def disable_caching(self): + def disable_caching(self) -> None: """Disables all caching features.""" - self.cache_backend = None - def is_caching_enabled(self): + def is_caching_enabled(self) -> bool: """Returns True if caching is enabled.""" - - return not (self.cache_backend is None) - - def _get_cache_backend(self): - - return self.cache_backend + return self.cache_backend is not None def search_for_album(self, album_name): - """Searches for an album by its name. Returns a AlbumSearch object. + """Searches for an album by its name. Returns an AlbumSearch object. Use get_next_page() to retrieve sequences of results.""" return AlbumSearch(album_name, self) def search_for_artist(self, artist_name): - """Searches of an artist by its name. Returns a ArtistSearch object. + """Searches for an artist by its name. Returns an ArtistSearch object. Use get_next_page() to retrieve sequences of results.""" return ArtistSearch(artist_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 + """Searches for a track by its name and its artist. Set artist to an empty string if not available. Returns a TrackSearch object. Use get_next_page() to retrieve sequences of results.""" @@ -505,7 +498,7 @@ class _Network: track_number=None, mbid=None, context=None, - ): + ) -> None: """ Used to notify Last.fm that a user has started listening to a track. @@ -592,7 +585,7 @@ class _Network: ) ) - def scrobble_many(self, tracks): + def scrobble_many(self, tracks) -> None: """ Used to scrobble a batch of tracks at once. The parameter tracks is a sequence of dicts per track containing the keyword arguments as if @@ -608,8 +601,8 @@ class _Network: params = {} for i in range(len(tracks_to_scrobble)): - params["artist[%d]" % i] = tracks_to_scrobble[i]["artist"] - params["track[%d]" % i] = tracks_to_scrobble[i]["title"] + params[f"artist[{i}]"] = tracks_to_scrobble[i]["artist"] + params[f"track[{i}]"] = tracks_to_scrobble[i]["title"] additional_args = ( "timestamp", @@ -635,7 +628,7 @@ class _Network: else: maps_to = arg - params["%s[%d]" % (maps_to, i)] = tracks_to_scrobble[i][arg] + params[f"{maps_to}[{i}]"] = tracks_to_scrobble[i][arg] _Request(self, "track.scrobble", params).execute() @@ -667,13 +660,13 @@ class LastFMNetwork(_Network): def __init__( self, - api_key="", - api_secret="", - session_key="", - username="", - password_hash="", - token="", - ): + api_key: str = "", + api_secret: str = "", + session_key: str = "", + username: str = "", + password_hash: str = "", + token: str = "", + ) -> None: super().__init__( name="Last.fm", homepage="https://www.last.fm", @@ -708,17 +701,15 @@ class LastFMNetwork(_Network): }, ) - def __repr__(self): - return "pylast.LastFMNetwork(%s)" % ( - ", ".join( - ( - "'%s'" % self.api_key, - "'%s'" % self.api_secret, - "'%s'" % self.session_key, - "'%s'" % self.username, - "'%s'" % self.password_hash, - ) - ) + def __repr__(self) -> str: + return ( + "pylast.LastFMNetwork(" + f"'{self.api_key}', " + f"'{self.api_secret}', " + f"'{self.session_key}', " + f"'{self.username}', " + f"'{self.password_hash}'" + ")" ) @@ -738,8 +729,13 @@ class LibreFMNetwork(_Network): """ def __init__( - self, api_key="", api_secret="", session_key="", username="", password_hash="" - ): + self, + api_key: str = "", + api_secret: str = "", + session_key: str = "", + username: str = "", + password_hash: str = "", + ) -> None: super().__init__( name="Libre.fm", @@ -774,31 +770,29 @@ class LibreFMNetwork(_Network): }, ) - def __repr__(self): - return "pylast.LibreFMNetwork(%s)" % ( - ", ".join( - ( - "'%s'" % self.api_key, - "'%s'" % self.api_secret, - "'%s'" % self.session_key, - "'%s'" % self.username, - "'%s'" % self.password_hash, - ) - ) + def __repr__(self) -> str: + return ( + "pylast.LibreFMNetwork(" + f"'{self.api_key}', " + f"'{self.api_secret}', " + f"'{self.session_key}', " + f"'{self.username}', " + f"'{self.password_hash}'" + ")" ) class _ShelfCacheBackend: """Used as a backend for caching cacheable requests.""" - def __init__(self, file_path=None, flag=None): + def __init__(self, file_path=None, flag=None) -> None: if flag is not None: self.shelf = shelve.open(file_path, flag=flag) else: self.shelf = shelve.open(file_path) self.cache_keys = set(self.shelf.keys()) - def __contains__(self, key): + def __contains__(self, key) -> bool: return key in self.cache_keys def __iter__(self): @@ -807,7 +801,7 @@ class _ShelfCacheBackend: def get_xml(self, key): return self.shelf[key] - def set_xml(self, key, xml_string): + def set_xml(self, key, xml_string) -> None: self.cache_keys.add(key) self.shelf[key] = xml_string @@ -821,7 +815,7 @@ class _ShelfCacheBackend: class _Request: """Representing an abstract web service operation.""" - def __init__(self, network, method_name, params=None): + def __init__(self, network, method_name, params=None) -> None: logger.info(method_name) if params is None: @@ -839,13 +833,13 @@ class _Request: self.params["method"] = method_name if network.is_caching_enabled(): - self.cache = network._get_cache_backend() + self.cache = network.cache_backend if self.session_key: self.params["sk"] = self.session_key self.sign_it() - def sign_it(self): + def sign_it(self) -> None: """Sign this request.""" if "api_sig" not in self.params.keys(): @@ -961,13 +955,13 @@ class _Request: except Exception as e: raise MalformedResponseError(self.network, e) from e - e = doc.getElementsByTagName("lfm")[0] + element = doc.getElementsByTagName("lfm")[0] logger.debug(doc.toprettyxml()) - if e.getAttribute("status") != "ok": - e = doc.getElementsByTagName("error")[0] - status = e.getAttribute("code") - details = e.firstChild.data.strip() + if element.getAttribute("status") != "ok": + element = doc.getElementsByTagName("error")[0] + status = element.getAttribute("code") + details = element.firstChild.data.strip() raise WSError(self.network, status, details) @@ -989,13 +983,13 @@ class SessionKeyGenerator: A session key's lifetime is infinite, unless the user revokes the rights of the given API Key. - If you create a Network object with just a API_KEY and API_SECRET and a + If you create a Network object with just an API_KEY and API_SECRET and a username and a password_hash, a SESSION_KEY will be automatically generated for that network and stored in it so you don't have to do this manually, unless you want to. """ - def __init__(self, network): + def __init__(self, network) -> None: self.network = network self.web_auth_tokens = {} @@ -1025,15 +1019,17 @@ class SessionKeyGenerator: token = self._get_web_auth_token() - url = "{homepage}/api/auth/?api_key={api}&token={token}".format( - homepage=self.network.homepage, api=self.network.api_key, token=token + url = ( + f"{self.network.homepage}/api/auth/" + f"?api_key={self.network.api_key}" + f"&token={token}" ) self.web_auth_tokens[url] = token return url - def get_web_auth_session_key_username(self, url, token=""): + def get_web_auth_session_key_username(self, url, token: str = ""): """ Retrieves the session key/username of a web authorization process by its URL. """ @@ -1053,7 +1049,7 @@ class SessionKeyGenerator: username = doc.getElementsByTagName("name")[0].firstChild.data return session_key, username - def get_web_auth_session_key(self, url, token=""): + def get_web_auth_session_key(self, url, token: str = ""): """ Retrieves the session key of a web authorization process by its URL. """ @@ -1105,11 +1101,11 @@ class _BaseObject: network = None - def __init__(self, network, ws_prefix): + def __init__(self, network, ws_prefix) -> None: self.network = network self.ws_prefix = ws_prefix - def _request(self, method_name, cacheable=False, params=None): + def _request(self, method_name, cacheable: bool = False, params=None): if not params: params = self._get_params() @@ -1140,7 +1136,12 @@ class _BaseObject: return first_child.wholeText.strip() def _get_things( - self, method, thing_type, params=None, cacheable=True, stream=False + self, + method, + thing_type, + params=None, + cacheable: bool = True, + stream: bool = False, ): """Returns a list of the most played thing_types by this thing.""" @@ -1205,7 +1206,7 @@ class _BaseObject: class _Chartable(_BaseObject): """Common functions for classes with charts.""" - def __init__(self, network, ws_prefix): + def __init__(self, network, ws_prefix) -> None: super().__init__(network=network, ws_prefix=ws_prefix) def get_weekly_chart_dates(self): @@ -1276,10 +1277,10 @@ class _Chartable(_BaseObject): class _Taggable(_BaseObject): """Common functions for classes with tags.""" - def __init__(self, network, ws_prefix): + def __init__(self, network, ws_prefix) -> None: super().__init__(network=network, ws_prefix=ws_prefix) - def add_tags(self, tags): + def add_tags(self, tags) -> None: """Adds one or several tags. * tags: A sequence of tag names or Tag objects. """ @@ -1287,7 +1288,7 @@ class _Taggable(_BaseObject): for tag in tags: self.add_tag(tag) - def add_tag(self, tag): + def add_tag(self, tag) -> None: """Adds one tag. * tag: a tag name or a Tag object. """ @@ -1300,7 +1301,7 @@ class _Taggable(_BaseObject): self._request(self.ws_prefix + ".addTags", False, params) - def remove_tag(self, tag): + def remove_tag(self, tag) -> None: """Remove a user's tag from this object.""" if isinstance(tag, Tag): @@ -1325,7 +1326,7 @@ class _Taggable(_BaseObject): return tags - def remove_tags(self, tags): + def remove_tags(self, tags) -> None: """Removes one or several tags from this object. * tags: a sequence of tag names or Tag objects. """ @@ -1333,12 +1334,12 @@ class _Taggable(_BaseObject): for tag in tags: self.remove_tag(tag) - def clear_tags(self): + def clear_tags(self) -> None: """Clears all the user-set tags.""" self.remove_tags(*(self.get_tags())) - def set_tags(self, tags): + def set_tags(self, tags) -> None: """Sets this object's tags to only those tags. * tags: a sequence of tag names or Tag objects. """ @@ -1401,13 +1402,13 @@ class PyLastError(Exception): class WSError(PyLastError): """Exception related to the Network web service""" - def __init__(self, network, status, details): + def __init__(self, network, status, details) -> None: self.status = status self.details = details self.network = network @_string_output - def __str__(self): + def __str__(self) -> str: return self.details def get_id(self): @@ -1445,25 +1446,26 @@ class WSError(PyLastError): class MalformedResponseError(PyLastError): """Exception conveying a malformed response from the music network.""" - def __init__(self, network, underlying_error): + def __init__(self, network, underlying_error) -> None: self.network = network self.underlying_error = underlying_error - def __str__(self): - return "Malformed response from {}. Underlying error: {}".format( - self.network.name, str(self.underlying_error) + def __str__(self) -> str: + return ( + f"Malformed response from {self.network.name}. " + f"Underlying error: {self.underlying_error}" ) class NetworkError(PyLastError): """Exception conveying a problem in sending a request to Last.fm""" - def __init__(self, network, underlying_error): + def __init__(self, network, underlying_error) -> None: self.network = network self.underlying_error = underlying_error - def __str__(self): - return "NetworkError: %s" % str(self.underlying_error) + def __str__(self) -> str: + return f"NetworkError: {self.underlying_error}" class _Opus(_Taggable): @@ -1475,7 +1477,9 @@ class _Opus(_Taggable): __hash__ = _BaseObject.__hash__ - def __init__(self, artist, title, network, ws_prefix, username=None, info=None): + def __init__( + self, artist, title, network, ws_prefix, username=None, info=None + ) -> None: """ Create an opus instance. # Parameters: @@ -1500,17 +1504,15 @@ class _Opus(_Taggable): ) # Default to current user self.info = info - def __repr__(self): - return "pylast.{}({}, {}, {})".format( - self.ws_prefix.title(), - repr(self.artist.name), - repr(self.title), - repr(self.network), + def __repr__(self) -> str: + return ( + f"pylast.{self.ws_prefix.title()}" + f"({repr(self.artist.name)}, {repr(self.title)}, {repr(self.network)})" ) @_string_output - def __str__(self): - return _unicode("%s - %s") % (self.get_artist().get_name(), self.get_title()) + def __str__(self) -> str: + return f"{self.get_artist().get_name()} - {self.get_title()}" def __eq__(self, other): if type(self) != type(other): @@ -1550,7 +1552,7 @@ class _Opus(_Taggable): ) return self.info["image"][size] - def get_title(self, properly_capitalized=False): + def get_title(self, properly_capitalized: bool = False): """Returns the artist or track title.""" if properly_capitalized: self.title = _extract( @@ -1559,7 +1561,7 @@ class _Opus(_Taggable): return self.title - def get_name(self, properly_capitalized=False): + def get_name(self, properly_capitalized: bool = False): """Returns the album or track title (alias to get_title()).""" return self.get_title(properly_capitalized) @@ -1620,7 +1622,7 @@ class Album(_Opus): __hash__ = _Opus.__hash__ - def __init__(self, artist, title, network, username=None, info=None): + def __init__(self, artist, title, network, username=None, info=None) -> None: super().__init__(artist, title, network, "album", username, info) def get_tracks(self): @@ -1665,7 +1667,7 @@ class Artist(_Taggable): __hash__ = _BaseObject.__hash__ - def __init__(self, name, network, username=None, info=None): + def __init__(self, name, network, username=None, info=None) -> None: """Create an artist object. # Parameters: * name str: The artist's name. @@ -1680,14 +1682,14 @@ class Artist(_Taggable): self.username = username self.info = info - def __repr__(self): + def __repr__(self) -> str: return f"pylast.Artist({repr(self.get_name())}, {repr(self.network)})" def __unicode__(self): return str(self.get_name()) @_string_output - def __str__(self): + def __str__(self) -> str: return self.__unicode__() def __eq__(self, other): @@ -1702,7 +1704,7 @@ class Artist(_Taggable): def _get_params(self): return {self.ws_prefix: self.get_name()} - def get_name(self, properly_capitalized=False): + def get_name(self, properly_capitalized: bool = False): """Returns the name of the artist. If properly_capitalized was asserted then the name would be downloaded overwriting the given one.""" @@ -1809,7 +1811,7 @@ class Artist(_Taggable): return artists - def get_top_albums(self, limit=None, cacheable=True, stream=False): + def get_top_albums(self, limit=None, cacheable: bool = True, stream: bool = False): """Returns a list of the top albums.""" params = self._get_params() if limit: @@ -1817,7 +1819,7 @@ class Artist(_Taggable): return self._get_things("getTopAlbums", Album, params, cacheable, stream=stream) - def get_top_tracks(self, limit=None, cacheable=True, stream=False): + def get_top_tracks(self, limit=None, cacheable: bool = True, stream: bool = False): """Returns a list of the most played Tracks by this artist.""" params = self._get_params() if limit: @@ -1855,16 +1857,16 @@ class Country(_BaseObject): __hash__ = _BaseObject.__hash__ - def __init__(self, name, network): + def __init__(self, name, network) -> None: super().__init__(network=network, ws_prefix="geo") self.name = name - def __repr__(self): + def __repr__(self) -> str: return f"pylast.Country({repr(self.name)}, {repr(self.network)})" @_string_output - def __str__(self): + def __str__(self) -> str: return self.get_name() def __eq__(self, other): @@ -1881,7 +1883,7 @@ class Country(_BaseObject): return self.name - def get_top_artists(self, limit=None, cacheable=True): + def get_top_artists(self, limit=None, cacheable: bool = True): """Returns a sequence of the most played artists.""" params = self._get_params() if limit: @@ -1891,7 +1893,7 @@ class Country(_BaseObject): return _extract_top_artists(doc, self) - def get_top_tracks(self, limit=None, cacheable=True, stream=False): + def get_top_tracks(self, limit=None, cacheable: bool = True, stream: bool = False): """Returns a sequence of the most played tracks""" params = self._get_params() if limit: @@ -1930,7 +1932,7 @@ class Library(_BaseObject): __hash__ = _BaseObject.__hash__ - def __init__(self, user, network): + def __init__(self, user, network) -> None: super().__init__(network=network, ws_prefix="library") if isinstance(user, User): @@ -1938,11 +1940,11 @@ class Library(_BaseObject): else: self.user = User(user, self.network) - def __repr__(self): + def __repr__(self) -> str: return f"pylast.Library({repr(self.user)}, {repr(self.network)})" @_string_output - def __str__(self): + def __str__(self) -> str: return repr(self.get_user()) + "'s Library" def _get_params(self): @@ -1952,7 +1954,9 @@ class Library(_BaseObject): """Returns the user who owns this library.""" return self.user - def get_artists(self, limit=50, cacheable=True, stream=False): + def get_artists( + self, limit: int = 50, cacheable: bool = True, stream: bool = False + ): """ Returns a sequence of Album objects if limit==None it will return all (may take a while) @@ -1979,16 +1983,16 @@ class Tag(_Chartable): __hash__ = _BaseObject.__hash__ - def __init__(self, name, network): + def __init__(self, name, network) -> None: super().__init__(network=network, ws_prefix="tag") self.name = name - def __repr__(self): + def __repr__(self) -> str: return f"pylast.Tag({repr(self.name)}, {repr(self.network)})" @_string_output - def __str__(self): + def __str__(self) -> str: return self.get_name() def __eq__(self, other): @@ -2000,7 +2004,7 @@ class Tag(_Chartable): def _get_params(self): return {self.ws_prefix: self.get_name()} - def get_name(self, properly_capitalized=False): + def get_name(self, properly_capitalized: bool = False): """Returns the name of the tag.""" if properly_capitalized: @@ -2010,7 +2014,7 @@ class Tag(_Chartable): return self.name - def get_top_albums(self, limit=None, cacheable=True): + def get_top_albums(self, limit=None, cacheable: bool = True): """Returns a list of the top albums.""" params = self._get_params() if limit: @@ -2020,7 +2024,7 @@ class Tag(_Chartable): return _extract_top_albums(doc, self.network) - def get_top_tracks(self, limit=None, cacheable=True, stream=False): + def get_top_tracks(self, limit=None, cacheable: bool = True, stream: bool = False): """Returns a list of the most played Tracks for this tag.""" params = self._get_params() if limit: @@ -2028,7 +2032,7 @@ class Tag(_Chartable): return self._get_things("getTopTracks", Track, params, cacheable, stream=stream) - def get_top_artists(self, limit=None, cacheable=True): + def get_top_artists(self, limit=None, cacheable: bool = True): """Returns a sequence of the most played artists.""" params = self._get_params() @@ -2066,7 +2070,7 @@ class Track(_Opus): __hash__ = _Opus.__hash__ - def __init__(self, artist, title, network, username=None, info=None): + def __init__(self, artist, title, network, username=None, info=None) -> None: super().__init__(artist, title, network, "track", username, info) def get_correction(self): @@ -2109,12 +2113,12 @@ class Track(_Opus): node = doc.getElementsByTagName("album")[0] return Album(_extract(node, "artist"), _extract(node, "title"), self.network) - def love(self): + def love(self) -> None: """Adds the track to the user's loved tracks.""" self._request(self.ws_prefix + ".love") - def unlove(self): + def unlove(self) -> None: """Remove the track to the user's loved tracks.""" self._request(self.ws_prefix + ".unlove") @@ -2175,16 +2179,16 @@ class User(_Chartable): __hash__ = _BaseObject.__hash__ - def __init__(self, user_name, network): + def __init__(self, user_name, network) -> None: super().__init__(network=network, ws_prefix="user") self.name = user_name - def __repr__(self): + def __repr__(self) -> str: return f"pylast.User({repr(self.name)}, {repr(self.network)})" @_string_output - def __str__(self): + def __str__(self) -> str: return self.get_name() def __eq__(self, other): @@ -2209,7 +2213,7 @@ class User(_Chartable): Track(track_artist, title, self.network), album, date, timestamp ) - def get_name(self, properly_capitalized=False): + def get_name(self, properly_capitalized: bool = False): """Returns the user name.""" if properly_capitalized: @@ -2219,7 +2223,9 @@ class User(_Chartable): return self.name - def get_friends(self, limit=50, cacheable=False, stream=False): + def get_friends( + self, limit: int = 50, cacheable: bool = False, stream: bool = False + ): """Returns a list of the user's friends.""" def _get_friends(): @@ -2230,7 +2236,9 @@ class User(_Chartable): return _get_friends() if stream else list(_get_friends()) - def get_loved_tracks(self, limit=50, cacheable=True, stream=False): + def get_loved_tracks( + self, limit: int = 50, cacheable: bool = True, stream: bool = False + ): """ Returns this user's loved track as a sequence of LovedTrack objects in reverse order of their timestamp, all the way back to the first track. @@ -2295,12 +2303,12 @@ class User(_Chartable): def get_recent_tracks( self, - limit=10, - cacheable=True, + limit: int = 10, + cacheable: bool = True, time_from=None, time_to=None, - stream=False, - now_playing=False, + stream: bool = False, + now_playing: bool = False, ): """ Returns this user's played track as a sequence of PlayedTrack objects @@ -2390,7 +2398,7 @@ class User(_Chartable): return int(doc.getElementsByTagName("registered")[0].getAttribute("unixtime")) - def get_tagged_albums(self, tag, limit=None, cacheable=True): + def get_tagged_albums(self, tag, limit=None, cacheable: bool = True): """Returns the albums tagged by a user.""" params = self._get_params() @@ -2412,7 +2420,7 @@ class User(_Chartable): doc = self._request(self.ws_prefix + ".getpersonaltags", True, params) return _extract_artists(doc, self.network) - def get_tagged_tracks(self, tag, limit=None, cacheable=True): + def get_tagged_tracks(self, tag, limit=None, cacheable: bool = True): """Returns the tracks tagged by a user.""" params = self._get_params() @@ -2423,7 +2431,7 @@ class User(_Chartable): doc = self._request(self.ws_prefix + ".getpersonaltags", cacheable, params) return _extract_tracks(doc, self.network) - def get_top_albums(self, period=PERIOD_OVERALL, limit=None, cacheable=True): + def get_top_albums(self, period=PERIOD_OVERALL, limit=None, cacheable: bool = True): """Returns the top albums played by a user. * period: The period of time. Possible values: o PERIOD_OVERALL @@ -2463,7 +2471,7 @@ class User(_Chartable): return _extract_top_artists(doc, self.network) - def get_top_tags(self, limit=None, cacheable=True): + def get_top_tags(self, limit=None, cacheable: bool = True): """ Returns a sequence of the top tags used by this user with their counts as TopItem objects. @@ -2488,7 +2496,11 @@ class User(_Chartable): return seq def get_top_tracks( - self, period=PERIOD_OVERALL, limit=None, cacheable=True, stream=False + self, + period=PERIOD_OVERALL, + limit=None, + cacheable: bool = True, + stream: bool = False, ): """Returns the top tracks played by a user. * period: The period of time. Possible values: @@ -2506,7 +2518,9 @@ class User(_Chartable): return self._get_things("getTopTracks", Track, params, cacheable, stream=stream) - def get_track_scrobbles(self, artist, track, cacheable=False, stream=False): + def get_track_scrobbles( + self, artist, track, cacheable: bool = False, stream: bool = False + ): """ Get a list of this user's scrobbles of this artist's track, including scrobble time. @@ -2570,13 +2584,13 @@ class User(_Chartable): class AuthenticatedUser(User): - def __init__(self, network): + def __init__(self, network) -> None: super().__init__(user_name=network.username, network=network) def _get_params(self): return {"user": self.get_name()} - def get_name(self, properly_capitalized=False): + def get_name(self, properly_capitalized: bool = False): """Returns the name of the authenticated user.""" return super().get_name(properly_capitalized=properly_capitalized) @@ -2584,7 +2598,7 @@ class AuthenticatedUser(User): class _Search(_BaseObject): """An abstract class. Use one of its derivatives.""" - def __init__(self, ws_prefix, search_terms, network): + def __init__(self, ws_prefix, search_terms, network) -> None: super().__init__(network, ws_prefix) self._ws_prefix = ws_prefix @@ -2624,7 +2638,7 @@ class _Search(_BaseObject): class AlbumSearch(_Search): """Search for an album by name.""" - def __init__(self, album_name, network): + def __init__(self, album_name, network) -> None: super().__init__( ws_prefix="album", search_terms={"album": album_name}, network=network ) @@ -2651,7 +2665,7 @@ class AlbumSearch(_Search): class ArtistSearch(_Search): """Search for an artist by artist name.""" - def __init__(self, artist_name, network): + def __init__(self, artist_name, network) -> None: super().__init__( ws_prefix="artist", search_terms={"artist": artist_name}, network=network ) @@ -2680,7 +2694,7 @@ class TrackSearch(_Search): down by specifying the artist name, set it to empty string. """ - def __init__(self, artist_name, track_title, network): + def __init__(self, artist_name, track_title, network) -> None: super().__init__( ws_prefix="track", search_terms={"track": track_title, "artist": artist_name}, @@ -2732,7 +2746,9 @@ def cleanup_nodes(doc): return doc -def _collect_nodes(limit, sender, method_name, cacheable, params=None, stream=False): +def _collect_nodes( + limit, sender, method_name, cacheable, params=None, stream: bool = False +): """ Returns a sequence of dom.Node objects about as close to limit as possible """ @@ -2787,7 +2803,7 @@ def _collect_nodes(limit, sender, method_name, cacheable, params=None, stream=Fa return _stream_collect_nodes() if stream else list(_stream_collect_nodes()) -def _extract(node, name, index=0): +def _extract(node, name, index: int = 0): """Extracts a value from the xml string""" nodes = node.getElementsByTagName(name) @@ -2888,7 +2904,7 @@ def _number(string): def _unescape_htmlentity(string): mapping = html.entities.name2codepoint for key in mapping: - string = string.replace("&%s;" % key, chr(mapping[key])) + string = string.replace(f"&{key};", chr(mapping[key])) return string diff --git a/tests/test_album.py b/tests/test_album.py index 56c469b..ae2c1a0 100755 --- a/tests/test_album.py +++ b/tests/test_album.py @@ -8,7 +8,7 @@ from .test_pylast import TestPyLastWithLastFm class TestPyLastAlbum(TestPyLastWithLastFm): - def test_album_tags_are_topitems(self): + def test_album_tags_are_topitems(self) -> None: # Arrange album = self.network.get_album("Test Artist", "Test Album") @@ -19,14 +19,14 @@ class TestPyLastAlbum(TestPyLastWithLastFm): assert len(tags) > 0 assert isinstance(tags[0], pylast.TopItem) - def test_album_is_hashable(self): + def test_album_is_hashable(self) -> None: # Arrange album = self.network.get_album("Test Artist", "Test Album") # Act/Assert self.helper_is_thing_hashable(album) - def test_album_in_recent_tracks(self): + def test_album_in_recent_tracks(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) @@ -37,7 +37,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): # Assert assert hasattr(track, "album") - def test_album_wiki_content(self): + def test_album_wiki_content(self) -> None: # Arrange album = pylast.Album("Test Artist", "Test Album", self.network) @@ -48,7 +48,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): assert wiki is not None assert len(wiki) >= 1 - def test_album_wiki_published_date(self): + def test_album_wiki_published_date(self) -> None: # Arrange album = pylast.Album("Test Artist", "Test Album", self.network) @@ -59,7 +59,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): assert wiki is not None assert len(wiki) >= 1 - def test_album_wiki_summary(self): + def test_album_wiki_summary(self) -> None: # Arrange album = pylast.Album("Test Artist", "Test Album", self.network) @@ -70,7 +70,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): assert wiki is not None assert len(wiki) >= 1 - def test_album_eq_none_is_false(self): + def test_album_eq_none_is_false(self) -> None: # Arrange album1 = None album2 = pylast.Album("Test Artist", "Test Album", self.network) @@ -78,7 +78,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): # Act / Assert assert album1 != album2 - def test_album_ne_none_is_true(self): + def test_album_ne_none_is_true(self) -> None: # Arrange album1 = None album2 = pylast.Album("Test Artist", "Test Album", self.network) @@ -86,7 +86,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): # Act / Assert assert album1 != album2 - def test_get_cover_image(self): + def test_get_cover_image(self) -> None: # Arrange album = self.network.get_album("Test Artist", "Test Album") @@ -97,7 +97,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): self.assert_startswith(image, "https://") self.assert_endswith(image, ".gif") - def test_mbid(self): + def test_mbid(self) -> None: # Arrange album = self.network.get_album("Radiohead", "OK Computer") @@ -107,7 +107,7 @@ class TestPyLastAlbum(TestPyLastWithLastFm): # Assert assert mbid == "0b6b4ba0-d36f-47bd-b4ea-6a5b91842d29" - def test_no_mbid(self): + def test_no_mbid(self) -> None: # Arrange album = self.network.get_album("Test Artist", "Test Album") diff --git a/tests/test_artist.py b/tests/test_artist.py index 44bacfd..e72474e 100755 --- a/tests/test_artist.py +++ b/tests/test_artist.py @@ -10,7 +10,7 @@ from .test_pylast import WRITE_TEST, TestPyLastWithLastFm class TestPyLastArtist(TestPyLastWithLastFm): - def test_repr(self): + def test_repr(self) -> None: # Arrange artist = pylast.Artist("Test Artist", self.network) @@ -20,7 +20,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert representation.startswith("pylast.Artist('Test Artist',") - def test_artist_is_hashable(self): + def test_artist_is_hashable(self) -> None: # Arrange test_artist = self.network.get_artist("Radiohead") artist = test_artist.get_similar(limit=2)[0].item @@ -29,7 +29,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Act/Assert self.helper_is_thing_hashable(artist) - def test_bio_published_date(self): + def test_bio_published_date(self) -> None: # Arrange artist = pylast.Artist("Test Artist", self.network) @@ -40,7 +40,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert bio is not None assert len(bio) >= 1 - def test_bio_content(self): + def test_bio_content(self) -> None: # Arrange artist = pylast.Artist("Test Artist", self.network) @@ -51,7 +51,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert bio is not None assert len(bio) >= 1 - def test_bio_content_none(self): + def test_bio_content_none(self) -> None: # Arrange # An artist with no biography, with "" in the API XML artist = pylast.Artist("Mr Sizef + Unquote", self.network) @@ -62,7 +62,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert bio is None - def test_bio_summary(self): + def test_bio_summary(self) -> None: # Arrange artist = pylast.Artist("Test Artist", self.network) @@ -73,7 +73,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert bio is not None assert len(bio) >= 1 - def test_artist_top_tracks(self): + def test_artist_top_tracks(self) -> None: # Arrange # Pick an artist with plenty of plays artist = self.network.get_top_artists(limit=1)[0].item @@ -84,7 +84,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert self.helper_two_different_things_in_top_list(things, pylast.Track) - def test_artist_top_albums(self): + def test_artist_top_albums(self) -> None: # Arrange # Pick an artist with plenty of plays artist = self.network.get_top_artists(limit=1)[0].item @@ -107,7 +107,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert len(things) == test_limit - def test_artist_top_albums_limit_default(self): + def test_artist_top_albums_limit_default(self) -> None: # Arrange # Pick an artist with plenty of plays artist = self.network.get_top_artists(limit=1)[0].item @@ -118,7 +118,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert len(things) == 50 - def test_artist_listener_count(self): + def test_artist_listener_count(self) -> None: # Arrange artist = self.network.get_artist("Test Artist") @@ -130,7 +130,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert count > 0 @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_tag_artist(self): + def test_tag_artist(self) -> None: # Arrange artist = self.network.get_artist("Test Artist") # artist.clear_tags() @@ -145,7 +145,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert found @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_remove_tag_of_type_text(self): + def test_remove_tag_of_type_text(self) -> None: # Arrange tag = "testing" # text artist = self.network.get_artist("Test Artist") @@ -160,7 +160,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert not found @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_remove_tag_of_type_tag(self): + def test_remove_tag_of_type_tag(self) -> None: # Arrange tag = pylast.Tag("testing", self.network) # Tag artist = self.network.get_artist("Test Artist") @@ -175,7 +175,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert not found @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_remove_tags(self): + def test_remove_tags(self) -> None: # Arrange tags = ["removetag1", "removetag2"] artist = self.network.get_artist("Test Artist") @@ -195,7 +195,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert not found2 @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_set_tags(self): + def test_set_tags(self) -> None: # Arrange tags = ["sometag1", "sometag2"] artist = self.network.get_artist("Test Artist 2") @@ -219,7 +219,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert found1 assert found2 - def test_artists(self): + def test_artists(self) -> None: # Arrange artist1 = self.network.get_artist("Radiohead") artist2 = self.network.get_artist("Portishead") @@ -239,7 +239,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): assert url == "https://www.last.fm/music/radiohead" assert mbid == "a74b1b7f-71a5-4011-9441-d0b5e4122711" - def test_artist_eq_none_is_false(self): + def test_artist_eq_none_is_false(self) -> None: # Arrange artist1 = None artist2 = pylast.Artist("Test Artist", self.network) @@ -247,7 +247,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Act / Assert assert artist1 != artist2 - def test_artist_ne_none_is_true(self): + def test_artist_ne_none_is_true(self) -> None: # Arrange artist1 = None artist2 = pylast.Artist("Test Artist", self.network) @@ -255,7 +255,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Act / Assert assert artist1 != artist2 - def test_artist_get_correction(self): + def test_artist_get_correction(self) -> None: # Arrange artist = pylast.Artist("guns and roses", self.network) @@ -265,7 +265,7 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert corrected_artist_name == "Guns N' Roses" - def test_get_userplaycount(self): + def test_get_userplaycount(self) -> None: # Arrange artist = pylast.Artist("John Lennon", self.network, username=self.username) diff --git a/tests/test_country.py b/tests/test_country.py index 4561d82..6d36ef3 100755 --- a/tests/test_country.py +++ b/tests/test_country.py @@ -8,14 +8,14 @@ from .test_pylast import TestPyLastWithLastFm class TestPyLastCountry(TestPyLastWithLastFm): - def test_country_is_hashable(self): + def test_country_is_hashable(self) -> None: # Arrange country = self.network.get_country("Italy") # Act/Assert self.helper_is_thing_hashable(country) - def test_countries(self): + def test_countries(self) -> None: # Arrange country1 = pylast.Country("Italy", self.network) country2 = pylast.Country("Finland", self.network) diff --git a/tests/test_library.py b/tests/test_library.py index dea876d..e37b771 100755 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -8,7 +8,7 @@ from .test_pylast import TestPyLastWithLastFm class TestPyLastLibrary(TestPyLastWithLastFm): - def test_repr(self): + def test_repr(self) -> None: # Arrange library = pylast.Library(user=self.username, network=self.network) @@ -18,7 +18,7 @@ class TestPyLastLibrary(TestPyLastWithLastFm): # Assert self.assert_startswith(representation, "pylast.Library(") - def test_str(self): + def test_str(self) -> None: # Arrange library = pylast.Library(user=self.username, network=self.network) @@ -28,21 +28,21 @@ class TestPyLastLibrary(TestPyLastWithLastFm): # Assert self.assert_endswith(string, "'s Library") - def test_library_is_hashable(self): + def test_library_is_hashable(self) -> None: # Arrange library = pylast.Library(user=self.username, network=self.network) # Act/Assert self.helper_is_thing_hashable(library) - def test_cacheable_library(self): + def test_cacheable_library(self) -> None: # Arrange library = pylast.Library(self.username, self.network) # Act/Assert self.helper_validate_cacheable(library, "get_artists") - def test_get_user(self): + def test_get_user(self) -> None: # Arrange library = pylast.Library(user=self.username, network=self.network) user_to_get = self.network.get_user(self.username) diff --git a/tests/test_librefm.py b/tests/test_librefm.py index 6b0f3dd..0647976 100755 --- a/tests/test_librefm.py +++ b/tests/test_librefm.py @@ -13,7 +13,7 @@ from .test_pylast import PyLastTestCase, load_secrets class TestPyLastWithLibreFm(PyLastTestCase): """Own class for Libre.fm because we don't need the Last.fm setUp""" - def test_libre_fm(self): + def test_libre_fm(self) -> None: # Arrange secrets = load_secrets() username = secrets["username"] @@ -27,7 +27,7 @@ class TestPyLastWithLibreFm(PyLastTestCase): # Assert assert name == "Radiohead" - def test_repr(self): + def test_repr(self) -> None: # Arrange secrets = load_secrets() username = secrets["username"] diff --git a/tests/test_network.py b/tests/test_network.py index 8937c53..d10cc66 100755 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -13,7 +13,7 @@ from .test_pylast import WRITE_TEST, TestPyLastWithLastFm class TestPyLastNetwork(TestPyLastWithLastFm): @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_scrobble(self): + def test_scrobble(self) -> None: # Arrange artist = "test artist" title = "test title" @@ -31,7 +31,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert str(last_scrobble.track.title).lower() == title @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_update_now_playing(self): + def test_update_now_playing(self) -> None: # Arrange artist = "Test Artist" title = "test title" @@ -55,7 +55,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert len(current_track.info["image"]) assert re.search(r"^http.+$", current_track.info["image"][pylast.SIZE_LARGE]) - def test_enable_rate_limiting(self): + def test_enable_rate_limiting(self) -> None: # Arrange assert not self.network.is_rate_limited() @@ -72,7 +72,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert self.network.is_rate_limited() assert now - then >= 0.2 - def test_disable_rate_limiting(self): + def test_disable_rate_limiting(self) -> None: # Arrange self.network.enable_rate_limit() assert self.network.is_rate_limited() @@ -87,14 +87,14 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert assert not self.network.is_rate_limited() - def test_lastfm_network_name(self): + def test_lastfm_network_name(self) -> None: # Act name = str(self.network) # Assert assert name == "Last.fm Network" - def test_geo_get_top_artists(self): + def test_geo_get_top_artists(self) -> None: # Arrange # Act artists = self.network.get_geo_top_artists(country="United Kingdom", limit=1) @@ -104,7 +104,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(artists[0], pylast.TopItem) assert isinstance(artists[0].item, pylast.Artist) - def test_geo_get_top_tracks(self): + def test_geo_get_top_tracks(self) -> None: # Arrange # Act tracks = self.network.get_geo_top_tracks( @@ -116,7 +116,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(tracks[0], pylast.TopItem) assert isinstance(tracks[0].item, pylast.Track) - def test_network_get_top_artists_with_limit(self): + def test_network_get_top_artists_with_limit(self) -> None: # Arrange # Act artists = self.network.get_top_artists(limit=1) @@ -124,7 +124,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(artists, pylast.Artist) - def test_network_get_top_tags_with_limit(self): + def test_network_get_top_tags_with_limit(self) -> None: # Arrange # Act tags = self.network.get_top_tags(limit=1) @@ -132,7 +132,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(tags, pylast.Tag) - def test_network_get_top_tags_with_no_limit(self): + def test_network_get_top_tags_with_no_limit(self) -> None: # Arrange # Act tags = self.network.get_top_tags() @@ -140,7 +140,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_at_least_one_thing_in_top_list(tags, pylast.Tag) - def test_network_get_top_tracks_with_limit(self): + def test_network_get_top_tracks_with_limit(self) -> None: # Arrange # Act tracks = self.network.get_top_tracks(limit=1) @@ -148,7 +148,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(tracks, pylast.Track) - def test_country_top_tracks(self): + def test_country_top_tracks(self) -> None: # Arrange country = self.network.get_country("Croatia") @@ -158,7 +158,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_two_different_things_in_top_list(things, pylast.Track) - def test_country_network_top_tracks(self): + def test_country_network_top_tracks(self) -> None: # Arrange # Act things = self.network.get_geo_top_tracks("Croatia", limit=2) @@ -166,7 +166,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_two_different_things_in_top_list(things, pylast.Track) - def test_tag_top_tracks(self): + def test_tag_top_tracks(self) -> None: # Arrange tag = self.network.get_tag("blues") @@ -176,7 +176,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_two_different_things_in_top_list(things, pylast.Track) - def test_album_data(self): + def test_album_data(self) -> None: # Arrange thing = self.network.get_album("Test Artist", "Test Album") @@ -196,7 +196,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert playcount > 1 assert "https://www.last.fm/music/test%2bartist/test%2balbum" == url - def test_track_data(self): + def test_track_data(self) -> None: # Arrange thing = self.network.get_track("Test Artist", "test title") @@ -217,7 +217,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert playcount > 1 assert "https://www.last.fm/fr/music/test%2bartist/_/test%2btitle" == url - def test_country_top_artists(self): + def test_country_top_artists(self) -> None: # Arrange country = self.network.get_country("Ukraine") @@ -227,7 +227,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(artists, pylast.Artist) - def test_caching(self): + def test_caching(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -242,7 +242,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): self.network.disable_caching() assert not self.network.is_caching_enabled() - def test_album_mbid(self): + def test_album_mbid(self) -> None: # Arrange mbid = "03c91c40-49a6-44a7-90e7-a700edf97a62" @@ -255,7 +255,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert album.title == "Believe" assert album_mbid == mbid - def test_artist_mbid(self): + def test_artist_mbid(self) -> None: # Arrange mbid = "7e84f845-ac16-41fe-9ff8-df12eb32af55" @@ -266,7 +266,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(artist, pylast.Artist) assert artist.name in ("MusicBrainz Test Artist", "MusicBrainzz Test Artist") - def test_track_mbid(self): + def test_track_mbid(self) -> None: # Arrange mbid = "ebc037b1-cc9c-44f2-a21f-83c219f0e1e0" @@ -279,7 +279,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert track.title == "first" assert track_mbid == mbid - def test_init_with_token(self): + def test_init_with_token(self) -> None: # Arrange/Act msg = None try: @@ -294,7 +294,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): # Assert assert msg == "Unauthorized Token - This token has not been issued" - def test_proxy(self): + def test_proxy(self) -> None: # Arrange proxy = "http://example.com:1234" @@ -306,7 +306,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): self.network.disable_proxy() assert not self.network.is_proxy_enabled() - def test_album_search(self): + def test_album_search(self) -> None: # Arrange album = "Nevermind" @@ -318,7 +318,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(results, list) assert isinstance(results[0], pylast.Album) - def test_album_search_images(self): + def test_album_search_images(self) -> None: # Arrange album = "Nevermind" search = self.network.search_for_album(album) @@ -338,7 +338,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png") assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE] - def test_artist_search(self): + def test_artist_search(self) -> None: # Arrange artist = "Nirvana" @@ -350,7 +350,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(results, list) assert isinstance(results[0], pylast.Artist) - def test_artist_search_images(self): + def test_artist_search_images(self) -> None: # Arrange artist = "Nirvana" search = self.network.search_for_artist(artist) @@ -370,7 +370,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png") assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE] - def test_track_search(self): + def test_track_search(self) -> None: # Arrange artist = "Nirvana" track = "Smells Like Teen Spirit" @@ -383,7 +383,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(results, list) assert isinstance(results[0], pylast.Track) - def test_track_search_images(self): + def test_track_search_images(self) -> None: # Arrange artist = "Nirvana" track = "Smells Like Teen Spirit" @@ -404,7 +404,7 @@ class TestPyLastNetwork(TestPyLastWithLastFm): self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png") assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE] - def test_search_get_total_result_count(self): + def test_search_get_total_result_count(self) -> None: # Arrange artist = "Nirvana" track = "Smells Like Teen Spirit" diff --git a/tests/test_pylast.py b/tests/test_pylast.py index c7cd7b3..7125413 100755 --- a/tests/test_pylast.py +++ b/tests/test_pylast.py @@ -33,14 +33,14 @@ def load_secrets(): # pragma: no cover class PyLastTestCase: - def assert_startswith(self, s, prefix, start=None, end=None): + def assert_startswith(self, s, prefix, start=None, end=None) -> None: assert s.startswith(prefix, start, end) - def assert_endswith(self, s, suffix, start=None, end=None): + def assert_endswith(self, s, suffix, start=None, end=None) -> None: assert s.endswith(suffix, start, end) -def _no_xfail_rerun_filter(err, name, test, plugin): +def _no_xfail_rerun_filter(err, name, test, plugin) -> bool: for _ in test.iter_markers(name="xfail"): return False @@ -54,7 +54,7 @@ class TestPyLastWithLastFm(PyLastTestCase): return int(time.time()) @classmethod - def setup_class(cls): + def setup_class(cls) -> None: if cls.secrets is None: cls.secrets = load_secrets() @@ -71,7 +71,7 @@ class TestPyLastWithLastFm(PyLastTestCase): password_hash=password_hash, ) - def helper_is_thing_hashable(self, thing): + def helper_is_thing_hashable(self, thing) -> None: # Arrange things = set() @@ -82,7 +82,7 @@ class TestPyLastWithLastFm(PyLastTestCase): assert thing is not None assert len(things) == 1 - def helper_validate_results(self, a, b, c): + def helper_validate_results(self, a, b, c) -> None: # Assert assert a is not None assert b is not None @@ -93,7 +93,7 @@ class TestPyLastWithLastFm(PyLastTestCase): assert a == b assert b == c - def helper_validate_cacheable(self, thing, function_name): + def helper_validate_cacheable(self, thing, function_name) -> None: # Arrange # get thing.function_name() func = getattr(thing, function_name, None) @@ -106,27 +106,27 @@ class TestPyLastWithLastFm(PyLastTestCase): # Assert self.helper_validate_results(result1, result2, result3) - def helper_at_least_one_thing_in_top_list(self, things, expected_type): + def helper_at_least_one_thing_in_top_list(self, things, expected_type) -> None: # Assert assert len(things) > 1 assert isinstance(things, list) assert isinstance(things[0], pylast.TopItem) assert isinstance(things[0].item, expected_type) - def helper_only_one_thing_in_top_list(self, things, expected_type): + def helper_only_one_thing_in_top_list(self, things, expected_type) -> None: # Assert assert len(things) == 1 assert isinstance(things, list) assert isinstance(things[0], pylast.TopItem) assert isinstance(things[0].item, expected_type) - def helper_only_one_thing_in_list(self, things, expected_type): + def helper_only_one_thing_in_list(self, things, expected_type) -> None: # Assert assert len(things) == 1 assert isinstance(things, list) assert isinstance(things[0], expected_type) - def helper_two_different_things_in_top_list(self, things, expected_type): + def helper_two_different_things_in_top_list(self, things, expected_type) -> None: # Assert assert len(things) == 2 thing1 = things[0] diff --git a/tests/test_tag.py b/tests/test_tag.py index 65544e0..89080f6 100755 --- a/tests/test_tag.py +++ b/tests/test_tag.py @@ -8,14 +8,14 @@ from .test_pylast import TestPyLastWithLastFm class TestPyLastTag(TestPyLastWithLastFm): - def test_tag_is_hashable(self): + def test_tag_is_hashable(self) -> None: # Arrange tag = self.network.get_top_tags(limit=1)[0] # Act/Assert self.helper_is_thing_hashable(tag) - def test_tag_top_artists(self): + def test_tag_top_artists(self) -> None: # Arrange tag = self.network.get_tag("blues") @@ -25,7 +25,7 @@ class TestPyLastTag(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(artists, pylast.Artist) - def test_tag_top_albums(self): + def test_tag_top_albums(self) -> None: # Arrange tag = self.network.get_tag("blues") @@ -35,7 +35,7 @@ class TestPyLastTag(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(albums, pylast.Album) - def test_tags(self): + def test_tags(self) -> None: # Arrange tag1 = self.network.get_tag("blues") tag2 = self.network.get_tag("rock") diff --git a/tests/test_track.py b/tests/test_track.py index 18f1d87..3430e29 100755 --- a/tests/test_track.py +++ b/tests/test_track.py @@ -13,7 +13,7 @@ from .test_pylast import WRITE_TEST, TestPyLastWithLastFm class TestPyLastTrack(TestPyLastWithLastFm): @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_love(self): + def test_love(self) -> None: # Arrange artist = "Test Artist" title = "test title" @@ -29,7 +29,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert str(loved[0].track.title).lower() == "test title" @pytest.mark.skipif(not WRITE_TEST, reason="Only test once to avoid collisions") - def test_unlove(self): + def test_unlove(self) -> None: # Arrange artist = pylast.Artist("Test Artist", self.network) title = "test title" @@ -47,7 +47,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert str(loved[0].track.artist) != "Test Artist" assert str(loved[0].track.title) != "test title" - def test_user_play_count_in_track_info(self): + def test_user_play_count_in_track_info(self) -> None: # Arrange artist = "Test Artist" title = "test title" @@ -61,7 +61,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert count >= 0 - def test_user_loved_in_track_info(self): + def test_user_loved_in_track_info(self) -> None: # Arrange artist = "Test Artist" title = "test title" @@ -77,7 +77,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert isinstance(loved, bool) assert not isinstance(loved, str) - def test_track_is_hashable(self): + def test_track_is_hashable(self) -> None: # Arrange artist = self.network.get_artist("Test Artist") track = artist.get_top_tracks(stream=False)[0].item @@ -86,7 +86,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Act/Assert self.helper_is_thing_hashable(track) - def test_track_wiki_content(self): + def test_track_wiki_content(self) -> None: # Arrange track = pylast.Track("Test Artist", "test title", self.network) @@ -97,7 +97,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert wiki is not None assert len(wiki) >= 1 - def test_track_wiki_summary(self): + def test_track_wiki_summary(self) -> None: # Arrange track = pylast.Track("Test Artist", "test title", self.network) @@ -108,7 +108,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert wiki is not None assert len(wiki) >= 1 - def test_track_get_duration(self): + def test_track_get_duration(self) -> None: # Arrange track = pylast.Track("Cher", "Believe", self.network) @@ -118,7 +118,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert duration >= 200000 - def test_track_get_album(self): + def test_track_get_album(self) -> None: # Arrange track = pylast.Track("Nirvana", "Lithium", self.network) @@ -128,7 +128,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert str(album) == "Nirvana - Nevermind" - def test_track_get_similar(self): + def test_track_get_similar(self) -> None: # Arrange track = pylast.Track("Cher", "Believe", self.network) @@ -143,7 +143,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): break assert found - def test_track_get_similar_limits(self): + def test_track_get_similar_limits(self) -> None: # Arrange track = pylast.Track("Cher", "Believe", self.network) @@ -153,7 +153,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert len(track.get_similar(limit=None)) >= 23 assert len(track.get_similar(limit=0)) >= 23 - def test_tracks_notequal(self): + def test_tracks_notequal(self) -> None: # Arrange track1 = pylast.Track("Test Artist", "test title", self.network) track2 = pylast.Track("Test Artist", "Test Track", self.network) @@ -162,7 +162,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert track1 != track2 - def test_track_title_prop_caps(self): + def test_track_title_prop_caps(self) -> None: # Arrange track = pylast.Track("test artist", "test title", self.network) @@ -172,7 +172,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert title == "Test Title" - def test_track_listener_count(self): + def test_track_listener_count(self) -> None: # Arrange track = pylast.Track("test artist", "test title", self.network) @@ -182,7 +182,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert count > 21 - def test_album_tracks(self): + def test_album_tracks(self) -> None: # Arrange album = pylast.Album("Test Artist", "Test", self.network) @@ -196,7 +196,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): assert len(tracks) == 1 assert url.startswith("https://www.last.fm/music/test") - def test_track_eq_none_is_false(self): + def test_track_eq_none_is_false(self) -> None: # Arrange track1 = None track2 = pylast.Track("Test Artist", "test title", self.network) @@ -204,7 +204,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Act / Assert assert track1 != track2 - def test_track_ne_none_is_true(self): + def test_track_ne_none_is_true(self) -> None: # Arrange track1 = None track2 = pylast.Track("Test Artist", "test title", self.network) @@ -212,7 +212,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Act / Assert assert track1 != track2 - def test_track_get_correction(self): + def test_track_get_correction(self) -> None: # Arrange track = pylast.Track("Guns N' Roses", "mrbrownstone", self.network) @@ -222,7 +222,7 @@ class TestPyLastTrack(TestPyLastWithLastFm): # Assert assert corrected_track_name == "Mr. Brownstone" - def test_track_with_no_mbid(self): + def test_track_with_no_mbid(self) -> None: # Arrange track = pylast.Track("Static-X", "Set It Off", self.network) diff --git a/tests/test_user.py b/tests/test_user.py index 5f68262..6e0f3ba 100755 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -16,7 +16,7 @@ from .test_pylast import TestPyLastWithLastFm class TestPyLastUser(TestPyLastWithLastFm): - def test_repr(self): + def test_repr(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -26,7 +26,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.assert_startswith(representation, "pylast.User('RJ',") - def test_str(self): + def test_str(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -36,7 +36,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert string == "RJ" - def test_equality(self): + def test_equality(self) -> None: # Arrange user_1a = self.network.get_user("RJ") user_1b = self.network.get_user("RJ") @@ -48,7 +48,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert user_1a != user_2 assert user_1a != not_a_user - def test_get_name(self): + def test_get_name(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -58,7 +58,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert name == "RJ" - def test_get_user_registration(self): + def test_get_user_registration(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -74,7 +74,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Just check date because of timezones assert "2002-11-20 " in registered - def test_get_user_unixtime_registration(self): + def test_get_user_unixtime_registration(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -85,7 +85,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Just check date because of timezones assert unixtime_registered == 1037793040 - def test_get_countryless_user(self): + def test_get_countryless_user(self) -> None: # Arrange # Currently test_user has no country set: lastfm_user = self.network.get_user("test_user") @@ -96,7 +96,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert country is None - def test_user_get_country(self): + def test_user_get_country(self) -> None: # Arrange lastfm_user = self.network.get_user("RJ") @@ -106,7 +106,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert str(country) == "United Kingdom" - def test_user_equals_none(self): + def test_user_equals_none(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) @@ -116,7 +116,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert not value - def test_user_not_equal_to_none(self): + def test_user_not_equal_to_none(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) @@ -126,7 +126,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert value - def test_now_playing_user_with_no_scrobbles(self): + def test_now_playing_user_with_no_scrobbles(self) -> None: # Arrange # Currently test-account has no scrobbles: user = self.network.get_user("test-account") @@ -137,7 +137,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert current_track is None - def test_love_limits(self): + def test_love_limits(self) -> None: # Arrange # Currently test-account has at least 23 loved tracks: user = self.network.get_user("test-user") @@ -148,7 +148,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert len(user.get_loved_tracks(limit=None)) >= 23 assert len(user.get_loved_tracks(limit=0)) >= 23 - def test_user_is_hashable(self): + def test_user_is_hashable(self) -> None: # Arrange user = self.network.get_user(self.username) @@ -169,7 +169,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # # Assert # self.assertGreaterEqual(len(tracks), 0) - def test_pickle(self): + def test_pickle(self) -> None: # Arrange import pickle @@ -187,7 +187,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert lastfm_user == loaded_user @pytest.mark.xfail - def test_cacheable_user(self): + def test_cacheable_user(self) -> None: # Arrange lastfm_user = self.network.get_authenticated_user() @@ -201,7 +201,7 @@ class TestPyLastUser(TestPyLastWithLastFm): lastfm_user, "get_recent_tracks" ) - def test_user_get_top_tags_with_limit(self): + def test_user_get_top_tags_with_limit(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -211,7 +211,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(tags, pylast.Tag) - def test_user_top_tracks(self): + def test_user_top_tracks(self) -> None: # Arrange lastfm_user = self.network.get_user("RJ") @@ -221,14 +221,14 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_two_different_things_in_top_list(things, pylast.Track) - def helper_assert_chart(self, chart, expected_type): + def helper_assert_chart(self, chart, expected_type) -> None: # Assert assert chart is not None assert len(chart) > 0 assert isinstance(chart[0], pylast.TopItem) assert isinstance(chart[0].item, expected_type) - def helper_get_assert_charts(self, thing, date): + def helper_get_assert_charts(self, thing, date) -> None: # Arrange album_chart, track_chart = None, None (from_date, to_date) = date @@ -245,14 +245,14 @@ class TestPyLastUser(TestPyLastWithLastFm): self.helper_assert_chart(album_chart, pylast.Album) self.helper_assert_chart(track_chart, pylast.Track) - def helper_dates_valid(self, dates): + def helper_dates_valid(self, dates) -> None: # Assert assert len(dates) >= 1 assert isinstance(dates[0], tuple) (start, end) = dates[0] assert start < end - def test_user_charts(self): + def test_user_charts(self) -> None: # Arrange lastfm_user = self.network.get_user("RJ") dates = lastfm_user.get_weekly_chart_dates() @@ -261,7 +261,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Act/Assert self.helper_get_assert_charts(lastfm_user, dates[0]) - def test_user_top_artists(self): + def test_user_top_artists(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) @@ -271,7 +271,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_top_list(artists, pylast.Artist) - def test_user_top_albums(self): + def test_user_top_albums(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -285,7 +285,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert len(top_album.info["image"]) assert re.search(r"^http.+$", top_album.info["image"][pylast.SIZE_LARGE]) - def test_user_tagged_artists(self): + def test_user_tagged_artists(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) tags = ["artisttagola"] @@ -298,7 +298,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_list(artists, pylast.Artist) - def test_user_tagged_albums(self): + def test_user_tagged_albums(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) tags = ["albumtagola"] @@ -311,7 +311,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_list(albums, pylast.Album) - def test_user_tagged_tracks(self): + def test_user_tagged_tracks(self) -> None: # Arrange lastfm_user = self.network.get_user(self.username) tags = ["tracktagola"] @@ -324,7 +324,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.helper_only_one_thing_in_list(tracks, pylast.Track) - def test_user_subscriber(self): + def test_user_subscriber(self) -> None: # Arrange subscriber = self.network.get_user("RJ") non_subscriber = self.network.get_user("Test User") @@ -337,7 +337,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert subscriber_is_subscriber assert not non_subscriber_is_subscriber - def test_user_get_image(self): + def test_user_get_image(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -347,7 +347,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert self.assert_startswith(url, "https://") - def test_user_get_library(self): + def test_user_get_library(self) -> None: # Arrange user = self.network.get_user(self.username) @@ -357,7 +357,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert isinstance(library, pylast.Library) - def test_get_recent_tracks_from_to(self): + def test_get_recent_tracks_from_to(self) -> None: # Arrange lastfm_user = self.network.get_user("RJ") start = dt.datetime(2011, 7, 21, 15, 10) @@ -374,7 +374,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert str(tracks[0].track.artist) == "Johnny Cash" assert str(tracks[0].track.title) == "Ring of Fire" - def test_get_recent_tracks_limit_none(self): + def test_get_recent_tracks_limit_none(self) -> None: # Arrange lastfm_user = self.network.get_user("bbc6music") start = dt.datetime(2020, 2, 15, 15, 00) @@ -393,7 +393,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert str(tracks[0].track.artist) == "Seun Kuti & Egypt 80" assert str(tracks[0].track.title) == "Struggles Sounds" - def test_get_recent_tracks_is_streamable(self): + def test_get_recent_tracks_is_streamable(self) -> None: # Arrange lastfm_user = self.network.get_user("bbc6music") start = dt.datetime(2020, 2, 15, 15, 00) @@ -410,7 +410,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert inspect.isgenerator(tracks) - def test_get_playcount(self): + def test_get_playcount(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -420,7 +420,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert playcount >= 128387 - def test_get_image(self): + def test_get_image(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -431,7 +431,7 @@ class TestPyLastUser(TestPyLastWithLastFm): self.assert_startswith(image, "https://") self.assert_endswith(image, ".png") - def test_get_url(self): + def test_get_url(self) -> None: # Arrange user = self.network.get_user("RJ") @@ -441,7 +441,7 @@ class TestPyLastUser(TestPyLastWithLastFm): # Assert assert url == "https://www.last.fm/user/rj" - def test_get_weekly_artist_charts(self): + def test_get_weekly_artist_charts(self) -> None: # Arrange user = self.network.get_user("bbc6music") @@ -453,7 +453,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert artist is not None assert isinstance(artist.network, pylast.LastFMNetwork) - def test_get_weekly_track_charts(self): + def test_get_weekly_track_charts(self) -> None: # Arrange user = self.network.get_user("bbc6music") @@ -465,7 +465,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert track is not None assert isinstance(track.network, pylast.LastFMNetwork) - def test_user_get_track_scrobbles(self): + def test_user_get_track_scrobbles(self) -> None: # Arrange artist = "France Gall" title = "Laisse Tomber Les Filles" @@ -479,7 +479,7 @@ class TestPyLastUser(TestPyLastWithLastFm): assert str(scrobbles[0].track.artist) == "France Gall" assert scrobbles[0].track.title == "Laisse Tomber Les Filles" - def test_cacheable_user_get_track_scrobbles(self): + def test_cacheable_user_get_track_scrobbles(self) -> None: # Arrange artist = "France Gall" title = "Laisse Tomber Les Filles" diff --git a/tests/unicode_test.py b/tests/unicode_test.py index 350256c..bc93dfa 100644 --- a/tests/unicode_test.py +++ b/tests/unicode_test.py @@ -18,13 +18,13 @@ def mock_network(): "fdasfdsafsaf not unicode", ], ) -def test_get_cache_key(artist): +def test_get_cache_key(artist) -> None: request = pylast._Request(mock_network(), "some_method", params={"artist": artist}) request._get_cache_key() @pytest.mark.parametrize("obj", [pylast.Artist("B\xe9l", mock_network())]) -def test_cast_and_hash(obj): +def test_cast_and_hash(obj) -> None: assert type(str(obj)) is str assert isinstance(hash(obj), int)