Merge pull request #167 from MarshalX/issue-120

Тайп хинты
このコミットが含まれているのは:
Il'ya 2019-12-27 00:05:58 +03:00 committed by GitHub
コミット 53c81513df
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
16個のファイルの変更286行の追加177行の削除

ファイルの表示

@ -1,3 +1,5 @@
from __future__ import annotations
from .base import YandexMusicObject
from .settings import Settings

ファイルの表示

@ -1,8 +1,9 @@
from abc import ABCMeta
from typing import Optional
import builtins
ujson = False
ujson: bool = False
try:
import ujson as json
ujson = True
@ -14,19 +15,19 @@ reserved_names = [name.lower() for name in dir(builtins)]
class YandexMusicObject:
__metaclass__ = ABCMeta
_id_attrs = ()
_id_attrs: tuple = ()
def __str__(self):
def __str__(self) -> str:
return str(self.to_dict())
def __repr__(self):
def __repr__(self) -> str:
return str(self)
def __getitem__(self, item):
return self.__dict__[item]
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client) -> Optional[dict]:
if not data:
return None
@ -34,10 +35,10 @@ class YandexMusicObject:
return data
def to_json(self):
def to_json(self) -> str:
return json.dumps(self.to_dict(), ensure_ascii=not ujson)
def to_dict(self):
def to_dict(self) -> dict:
def parse(val):
if hasattr(val, 'to_dict'):
return val.to_dict()
@ -59,7 +60,7 @@ class YandexMusicObject:
return parse(data)
def __eq__(self, other):
def __eq__(self, other) -> bool:
if isinstance(other, self.__class__):
return self._id_attrs == other._id_attrs
return super(YandexMusicObject, self).__eq__(other)

ファイルの表示

@ -1,6 +1,7 @@
import logging
import functools
from datetime import datetime
from typing import Callable, Union, List
from yandex_music import YandexMusicObject, Status, Settings, PermissionAlerts, Experiments, Artist, Album, Playlist, \
TracksList, Track, AlbumsLikes, ArtistsLikes, PlaylistsLikes, Feed, PromoCodeStatus, DownloadInfo, Search, \
@ -69,7 +70,8 @@ class Client(YandexMusicObject):
:class:`yandex_music.utils.request.Request`.
"""
def __init__(self, token=None, fetch_account_status=True, base_url=None, oauth_url=None, request=None):
def __init__(self, token: str = None, fetch_account_status: bool = True, base_url: str = None,
oauth_url: str = None, request: Request = None) -> None:
self.logger = logging.getLogger(__name__)
self.token = token
@ -92,8 +94,8 @@ class Client(YandexMusicObject):
self.me = self.account_status()
@classmethod
def from_credentials(cls, username, password, x_captcha_answer=None, x_captcha_key=None, captcha_callback=None,
*args, **kwargs):
def from_credentials(cls, username: str, password: str, x_captcha_answer: str = None, x_captcha_key: str = None,
captcha_callback: Callable[[Captcha], str] = None, *args, **kwargs) -> 'Client':
"""Инициализция клиента по логину и паролю.
Note:
@ -132,7 +134,7 @@ class Client(YandexMusicObject):
return cls(token, *args, **kwargs)
@classmethod
def from_token(cls, token, *args, **kwargs):
def from_token(cls, token: str, *args, **kwargs) -> 'Client':
"""Инициализция клиента по токену.
Ничем не отличается от Client(token). Так исторически сложилось.
@ -148,8 +150,9 @@ class Client(YandexMusicObject):
return cls(token, *args, **kwargs)
@log
def generate_token_by_username_and_password(self, username, password, grant_type='password', x_captcha_answer=None,
x_captcha_key=None, timeout=None, *args, **kwargs):
def generate_token_by_username_and_password(self, username: str, password: str, grant_type: str = 'password',
x_captcha_answer: str = None, x_captcha_key: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> str:
"""Метод получения OAuth токена по логину и паролю.
Args:
@ -187,7 +190,7 @@ class Client(YandexMusicObject):
return result.get('access_token')
@staticmethod
def _validate_token(token: str):
def _validate_token(token: str) -> str:
"""Примитивная валидация токена.
Args:
@ -209,12 +212,12 @@ class Client(YandexMusicObject):
return token
@property
def request(self):
def request(self) -> Request:
""":obj:`yandex_music.utils.request.Request`: Объект вспомогательного класса для отправки запросов."""
return self._request
@log
def account_status(self, timeout=None, *args, **kwargs):
def account_status(self, timeout: Union[int, float] = None, *args, **kwargs) -> Status:
"""Получение статуса аккаунта. Нет обязательных параметров.
Args:
@ -237,7 +240,7 @@ class Client(YandexMusicObject):
return Status.de_json(result, self)
@log
def settings(self, timeout=None, *args, **kwargs):
def settings(self, timeout: Union[int, float] = None, *args, **kwargs) -> Settings:
"""Получение предложений по покупке. Нет обязательных параметров.
Args:
@ -260,7 +263,7 @@ class Client(YandexMusicObject):
return Settings.de_json(result, self)
@log
def permission_alerts(self, timeout=None, *args, **kwargs):
def permission_alerts(self, timeout: Union[int, float] = None, *args, **kwargs) -> PermissionAlerts:
"""Получение оповещений. Нет обязательных параметров.
Args:
@ -283,7 +286,7 @@ class Client(YandexMusicObject):
return PermissionAlerts.de_json(result, self)
@log
def account_experiments(self, timeout=None, *args, **kwargs):
def account_experiments(self, timeout: Union[int, float] = None, *args, **kwargs) -> Experiments:
"""Получение значений экспериментальных функций аккаунта.
Args:
@ -306,7 +309,8 @@ class Client(YandexMusicObject):
return Experiments.de_json(result, self)
@log
def consume_promo_code(self, code: str, language: str = 'en', timeout=None, *args, **kwargs):
def consume_promo_code(self, code: str, language: str = 'en', timeout: Union[int, float] = None,
*args, **kwargs) -> PromoCodeStatus:
"""Активация промо-кода.
Args:
@ -331,7 +335,7 @@ class Client(YandexMusicObject):
return PromoCodeStatus.de_json(result, self)
@log
def feed(self, timeout=None, *args, **kwargs):
def feed(self, timeout: Union[int, float] = None, *args, **kwargs) -> Feed:
"""Получение потока информации (фида) подобранного под пользователя. Содержит умные плейлисты.
Args:
@ -354,7 +358,7 @@ class Client(YandexMusicObject):
return Feed.de_json(result, self)
@log
def feed_wizard_is_passed(self, timeout=None, *args, **kwargs):
def feed_wizard_is_passed(self, timeout: Union[int, float] = None, *args, **kwargs) -> bool:
url = f'{self.base_url}/feed/wizard/is-passed'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -362,7 +366,7 @@ class Client(YandexMusicObject):
return result.get('is_wizard_passed') or False
@log
def landing(self, blocks: str or list, timeout=None, *args, **kwargs):
def landing(self, blocks: Union[str, List[str]], timeout: Union[int, float] = None, *args, **kwargs) -> Landing:
"""Получение лендинг-страницы содержащий блоки с новыми релизами, чартами, плейлистами с новинками и т.д.
Поддерживаемые типы блоков: personalplaylists, promotions, new-releases, new-playlists, mixes,c hart, artists,
@ -389,7 +393,7 @@ class Client(YandexMusicObject):
return Landing.de_json(result, self)
@log
def genres(self, timeout=None, *args, **kwargs):
def genres(self, timeout: Union[int, float] = None, *args, **kwargs) -> List[Genre]:
"""Получение жанров музыки.
Args:
@ -412,7 +416,8 @@ class Client(YandexMusicObject):
return Genre.de_list(result, self)
@log
def tracks_download_info(self, track_id: str or int, get_direct_links: bool = False, timeout=None, *args, **kwargs):
def tracks_download_info(self, track_id: Union[str, int], get_direct_links: bool = False,
timeout: Union[int, float] = None, *args, **kwargs) -> List[DownloadInfo]:
"""Получение информации о доступных вариантах загрузки трека.
Args:
@ -437,7 +442,8 @@ class Client(YandexMusicObject):
return DownloadInfo.de_list(result, self, get_direct_links)
@log
def track_supplement(self, track_id: str or int, timeout=None, *args, **kwargs):
def track_supplement(self, track_id: Union[str, int], timeout: Union[int, float] = None,
*args, **kwargs) -> Supplement:
"""Получение дополнительной информации о треке.
Args:
@ -460,9 +466,9 @@ class Client(YandexMusicObject):
@log
def play_audio(self,
track_id: str or int,
track_id: Union[str, int],
from_: str,
album_id: str or int,
album_id: Union[str, int],
playlist_id: str = None,
from_cache: bool = False,
play_id: str = None,
@ -472,8 +478,8 @@ class Client(YandexMusicObject):
total_played_seconds: int = 0,
end_position_seconds: int = 0,
client_now: str = None,
timeout=None,
*args, **kwargs):
timeout: Union[int, float] = None,
*args, **kwargs) -> bool:
"""Метод для отправки текущего состояния прослушиваемого трека.
Args:
@ -524,7 +530,8 @@ class Client(YandexMusicObject):
return result == 'ok'
def albums_with_tracks(self, album_id: str or int, timeout=None, *args, **kwargs):
def albums_with_tracks(self, album_id: Union[str, int], timeout: Union[int, float] = None,
*args, **kwargs) -> Album:
"""Получение альбома по его уникальному идентификатору вместе с треками.
Args:
@ -554,8 +561,8 @@ class Client(YandexMusicObject):
type_: str = 'all',
page: int = 0,
playlist_in_best: bool = True,
timeout=None,
*args, **kwargs):
timeout: Union[int, float] = None,
*args, **kwargs) -> Search:
"""Осуществление поиска по запросу и типу, получение результатов.
Args:
@ -591,7 +598,7 @@ class Client(YandexMusicObject):
return Search.de_json(result, self)
@log
def search_suggest(self, part: str, timeout=None, *args, **kwargs):
def search_suggest(self, part: str, timeout: Union[int, float] = None, *args, **kwargs) -> Suggestions:
"""Получение подсказок по введенной части поискового запроса.
Args:
@ -615,7 +622,8 @@ class Client(YandexMusicObject):
return Suggestions.de_json(result, self)
@log
def users_playlists(self, kind: str or int or list, user_id: str = None, timeout=None, *args, **kwargs):
def users_playlists(self, kind: Union[List[Union[str, int]], str, int], user_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> List[Playlist]:
"""Получение плейлиста или списка плейлистов по уникальным идентификаторам.
Args:
@ -649,7 +657,7 @@ class Client(YandexMusicObject):
@log
def users_playlists_create(self, title: str, visibility: str = 'public', user_id: str = None,
timeout=None, *args, **kwargs):
timeout: Union[int, float] = None, *args, **kwargs) -> Playlist:
"""Создание плейлиста.
Args:
@ -683,8 +691,8 @@ class Client(YandexMusicObject):
return Playlist.de_json(result, self)
@log
def users_playlists_delete(self, kind: str or int, user_id: str = None,
timeout=None, *args, **kwargs):
def users_playlists_delete(self, kind: Union[str, int], user_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
"""Удаление плейлиста.
Args:
@ -711,7 +719,8 @@ class Client(YandexMusicObject):
return result == 'ok'
@log
def users_playlists_name(self, kind: str or int, name: str, user_id: str = None, timeout=None, *args, **kwargs):
def users_playlists_name(self, kind: Union[str, int], name: str, user_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> Playlist:
"""Изменение названия плейлиста.
Args:
@ -740,8 +749,8 @@ class Client(YandexMusicObject):
return Playlist.de_json(result, self)
@log
def users_playlists_change(self, kind: str or int, diff: str, revision: int = 1, user_id: str = None,
timeout=None, *args, **kwargs):
def users_playlists_change(self, kind: Union[str, int], diff: str, revision: int = 1, user_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> Playlist:
"""Изменение плейлиста.
Для получения отличий есть вспомогательный класс :class:`from yandex_music.utils.difference.Difference`.
@ -780,8 +789,9 @@ class Client(YandexMusicObject):
return Playlist.de_json(result, self)
@log
def users_playlists_insert_track(self, kind: str or int, track_id: str or int, album_id: str or int, at: int = 0,
revision: int = 1, user_id: str = None, timeout=None, *args, **kwargs):
def users_playlists_insert_track(self, kind: Union[str, int], track_id: Union[str, int], album_id: Union[str, int],
at: int = 0, revision: int = 1, user_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> Playlist:
"""Добавление трека в плейлист.
Трек можно вставить с любое место плейлиста задав индекс вставки (аргумент at).
@ -813,8 +823,9 @@ class Client(YandexMusicObject):
return self.users_playlists_change(kind, diff.to_json(), revision, user_id, timeout, *args, **kwargs)
@log
def users_playlists_delete_track(self, kind: str or int, from_: int, to: int, revision: int = 1,
user_id: str = None, timeout=None, *args, **kwargs):
def users_playlists_delete_track(self, kind: Union[str, int], from_: int, to: int, revision: int = 1,
user_id: str = None, timeout: Union[int, float] = None,
*args, **kwargs) -> Playlist:
"""Удаление треков из плейлиста.
Для удаление необходимо указать границы с какого по какой элемент (трек) удалить.
@ -845,7 +856,7 @@ class Client(YandexMusicObject):
return self.users_playlists_change(kind, diff.to_json(), revision, user_id, timeout, *args, **kwargs)
@log
def rotor_account_status(self, timeout=None, *args, **kwargs):
def rotor_account_status(self, timeout: Union[int, float] = None, *args, **kwargs) -> Status:
url = f'{self.base_url}/rotor/account/status'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -853,7 +864,7 @@ class Client(YandexMusicObject):
return Status.de_json(result, self)
@log
def rotor_stations_dashboard(self, timeout=None, *args, **kwargs):
def rotor_stations_dashboard(self, timeout: Union[int, float] = None, *args, **kwargs) -> Dashboard:
url = f'{self.base_url}/rotor/stations/dashboard'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -861,7 +872,8 @@ class Client(YandexMusicObject):
return Dashboard.de_json(result, self)
@log
def rotor_stations_list(self, language: str = 'en', timeout=None, *args, **kwargs):
def rotor_stations_list(self, language: str = 'en', timeout: Union[int, float] = None,
*args, **kwargs) -> List[StationResult]:
url = f'{self.base_url}/rotor/stations/list'
result = self._request.get(url, {'language': language}, timeout=timeout, *args, **kwargs)
@ -869,8 +881,9 @@ class Client(YandexMusicObject):
return StationResult.de_list(result, self)
@log
def rotor_station_genre_feedback(self, genre: str, type_: str, timestamp=None, from_: str = None,
batch_id: str or int = None, track_id: str = None, timeout=None, *args, **kwargs):
def rotor_station_genre_feedback(self, genre: str, type_: str, timestamp: int = None, from_: str = None,
batch_id: Union[str, int] = None, track_id: str = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
if timestamp is None:
timestamp = datetime.now().timestamp()
@ -894,18 +907,20 @@ class Client(YandexMusicObject):
return result == 'ok'
@log
def rotor_station_genre_feedback_radio_started(self, genre: str, from_: str, timestamp=None,
timeout=None, *args, **kwargs):
def rotor_station_genre_feedback_radio_started(self, genre: str, from_: str, timestamp: int = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self.rotor_station_genre_feedback(genre, 'radioStarted', timestamp, from_, timeout, *args, **kwargs)
@log
def rotor_station_genre_feedback_track_started(self, genre: str, track_id: str, batch_id: str or int,
timestamp=None, timeout=None, *args, **kwargs):
def rotor_station_genre_feedback_track_started(self, genre: str, track_id: str, batch_id: Union[str, int],
timestamp: int = None, timeout: Union[int, float] = None,
*args, **kwargs) -> bool:
return self.rotor_station_genre_feedback(genre, 'trackStarted', timestamp, track_id=track_id, batch_id=batch_id,
timeout=timeout, *args, **kwargs)
@log
def rotor_station_genre_info(self, genre: str, timeout=None, *args, **kwargs):
def rotor_station_genre_info(self, genre: str, timeout: Union[int, float] = None,
*args, **kwargs) -> List[StationResult]:
url = f'{self.base_url}/rotor/station/genre:{genre}/info'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -913,7 +928,8 @@ class Client(YandexMusicObject):
return StationResult.de_list(result, self)
@log
def rotor_station_genre_tracks(self, genre: str, timeout=None, *args, **kwargs):
def rotor_station_genre_tracks(self, genre: str, timeout: Union[int, float] = None,
*args, **kwargs) -> StationTracksResult:
url = f'{self.base_url}/rotor/station/genre:{genre}/tracks'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -921,7 +937,8 @@ class Client(YandexMusicObject):
return StationTracksResult.de_json(result, self)
@log
def artists_brief_info(self, artist_id: str or int, timeout=None, *args, **kwargs):
def artists_brief_info(self, artist_id: Union[str, int], timeout: Union[int, float] = None,
*args, **kwargs) -> BriefInfo:
url = f'{self.base_url}/artists/{artist_id}/brief-info'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
@ -929,7 +946,8 @@ class Client(YandexMusicObject):
return BriefInfo.de_json(result, self)
@log
def artists_tracks(self, artist_id: str or int, page=0, page_size=20, timeout=None, *args, **kwargs):
def artists_tracks(self, artist_id: Union[str, int], page: int = 0, page_size: int = 20,
timeout: Union[int, float] = None, *args, **kwargs) -> ArtistTracks:
"""Получение треков артиста.
Args:
@ -960,8 +978,9 @@ class Client(YandexMusicObject):
return ArtistTracks.de_json(result, self)
@log
def artists_direct_albums(self, artist_id: str or int, page=0, page_size=20, sort_by='year',
timeout=None, *args, **kwargs):
def artists_direct_albums(self, artist_id: Union[str, int], page: int = 0, page_size: int = 20,
sort_by: str = 'year', timeout: Union[int, float] = None,
*args, **kwargs) -> ArtistAlbums:
"""Получение альбомов артиста.
Известные значения для sort_by: year, rating.
@ -995,8 +1014,8 @@ class Client(YandexMusicObject):
return ArtistAlbums.de_json(result, self)
def _like_action(self, object_type: str, ids: str or int or list, remove: bool = False, user_id: str or int = None,
timeout=None, *args, **kwargs):
def _like_action(self, object_type: str, ids: Union[List[Union[str, int]], str, int], remove: bool = False,
user_id: Union[str, int] = None, timeout: Union[int, float] = None, *args, **kwargs) -> bool:
if user_id is None and self.me is not None:
user_id = self.me.account.uid
@ -1011,45 +1030,53 @@ class Client(YandexMusicObject):
return result == 'ok'
@log
def users_likes_tracks_add(self, track_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_tracks_add(self, track_ids: Union[List[Union[str, int]], str, int], user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('track', track_ids, False, user_id, timeout, *args, **kwargs)
@log
def users_likes_tracks_remove(self, track_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_tracks_remove(self, track_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('track', track_ids, True, user_id, timeout, *args, **kwargs)
@log
def users_likes_artists_add(self, artist_ids: str or int or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_artists_add(self, artist_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('artist', artist_ids, False, user_id, timeout, *args, **kwargs)
def users_likes_artists_remove(self, artist_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_artists_remove(self, artist_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('artist', artist_ids, True, user_id, timeout, *args, **kwargs)
@log
def users_likes_playlists_add(self, playlist_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_playlists_add(self, playlist_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('playlist', playlist_ids, False, user_id, timeout, *args, **kwargs)
@log
def users_likes_playlists_remove(self, playlist_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_playlists_remove(self, playlist_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('playlist', playlist_ids, True, user_id, timeout, *args, **kwargs)
@log
def users_likes_albums_add(self, album_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_albums_add(self, album_ids: Union[List[Union[str, int]], str, int], user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('album', album_ids, False, user_id, timeout, *args, **kwargs)
@log
def users_likes_albums_remove(self, album_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_likes_albums_remove(self, album_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._like_action('album', album_ids, True, user_id, timeout, *args, **kwargs)
def _get_list(self, object_type: str, ids: list or int or str, params=None, timeout=None, *args, **kwargs):
def _get_list(self, object_type: str, ids: Union[List[Union[str, int]], int, str],
params: dict = None, timeout: Union[int, float] = None,
*args, **kwargs) -> List[Union[Artist, Album, Track, Playlist]]:
if params is None:
params = {}
params.update({f'{object_type}-ids': ids})
@ -1061,23 +1088,28 @@ class Client(YandexMusicObject):
return de_list.get(object_type)(result, self)
@log
def artists(self, artist_ids: list or int or str, timeout=None, *args, **kwargs):
return self._get_list('artist', artist_ids, timeout, *args, **kwargs)
def artists(self, artist_ids: Union[List[Union[str, int]], int, str], timeout: Union[int, float] = None,
*args, **kwargs) -> List[Artist]:
return self._get_list('artist', artist_ids, timeout=timeout, *args, **kwargs)
@log
def albums(self, album_ids: list or int or str, timeout=None, *args, **kwargs):
return self._get_list('album', album_ids, timeout, *args, **kwargs)
def albums(self, album_ids: Union[List[Union[str, int]], int, str], timeout: Union[int, float] = None,
*args, **kwargs) -> List[Album]:
return self._get_list('album', album_ids, timeout=timeout, *args, **kwargs)
@log
def tracks(self, track_ids: int or str, with_positions=True, timeout=None, *args, **kwargs):
def tracks(self, track_ids: Union[List[Union[str, int]], int, str], with_positions: bool = True,
timeout: Union[int, float] = None, *args, **kwargs) -> List[Track]:
return self._get_list('track', track_ids, {'with-positions': with_positions}, timeout, *args, **kwargs)
@log
def playlists_list(self, playlist_ids: list or int or str, timeout=None, *args, **kwargs):
return self._get_list('playlist', playlist_ids, timeout, *args, **kwargs)
def playlists_list(self, playlist_ids: Union[List[Union[str, int]], int, str], timeout: Union[int, float] = None,
*args, **kwargs) -> List[Playlist]:
return self._get_list('playlist', playlist_ids, timeout=timeout, *args, **kwargs)
@log
def users_playlists_list(self, user_id: int or str = None, timeout=None, *args, **kwargs):
def users_playlists_list(self, user_id: Union[str, int] = None, timeout: Union[int, float] = None,
*args, **kwargs) -> List[Playlist]:
if user_id is None and self.me is not None:
user_id = self.me.account.uid
@ -1087,7 +1119,9 @@ class Client(YandexMusicObject):
return Playlist.de_list(result, self)
def _get_likes(self, object_type, user_id: int or str = None, params=None, timeout=None, *args, **kwargs):
def _get_likes(self, object_type: str, user_id: Union[str, int] = None, params: dict = None,
timeout: Union[int, float] = None, *args, **kwargs) \
-> Union[List[ArtistsLikes], List[AlbumsLikes], List[PlaylistsLikes], TracksList]:
if user_id is None and self.me is not None:
user_id = self.me.account.uid
@ -1101,26 +1135,29 @@ class Client(YandexMusicObject):
return de_list_likes.get(object_type)(result, self)
@log
def users_likes_tracks(self, user_id: int or str = None, if_modified_since_revision=0, timeout=None,
*args, **kwargs):
def users_likes_tracks(self, user_id: Union[str, int] = None, if_modified_since_revision: int = 0,
timeout: Union[int, float] = None, *args, **kwargs) -> TracksList:
return self._get_likes('track', user_id, {'if-modified-since-revision': if_modified_since_revision}, timeout,
*args, **kwargs)
@log
def users_likes_albums(self, user_id: int or str = None, rich=True, timeout=None, *args, **kwargs):
def users_likes_albums(self, user_id: Union[str, int] = None, rich: bool = True, timeout: Union[int, float] = None,
*args, **kwargs) -> List[AlbumsLikes]:
return self._get_likes('album', user_id, {'rich': rich}, timeout, *args, **kwargs)
@log
def users_likes_artists(self, user_id: int or str = None, with_timestamps=True, timeout=None, *args, **kwargs):
def users_likes_artists(self, user_id: Union[str, int] = None, with_timestamps: bool = True,
timeout: Union[int, float] = None, *args, **kwargs) -> List[ArtistsLikes]:
return self._get_likes('artist', user_id, {'with-timestamps': with_timestamps}, timeout, *args, **kwargs)
@log
def users_likes_playlists(self, user_id: int or str = None, timeout=None, *args, **kwargs):
def users_likes_playlists(self, user_id: Union[str, int] = None, timeout: Union[int, float] = None,
*args, **kwargs) -> List[PlaylistsLikes]:
return self._get_likes('playlist', user_id, timeout=timeout, *args, **kwargs)
@log
def users_dislikes_tracks(self, user_id: int or str = None, if_modified_since_revision=0,
timeout=None, *args, **kwargs):
def users_dislikes_tracks(self, user_id: Union[str, int] = None, if_modified_since_revision: int = 0,
timeout: Union[int, float] = None, *args, **kwargs) -> TracksList:
if user_id is None and self.me is not None:
user_id = self.me.account.uid
@ -1131,8 +1168,8 @@ class Client(YandexMusicObject):
return TracksList.de_json(result.get('library'), self)
def _dislike_action(self, ids: str or int or list, remove: bool = False, user_id: str or int = None,
timeout=None, *args, **kwargs):
def _dislike_action(self, ids: Union[List[Union[str, int]], str, int], remove: bool = False,
user_id: Union[str, int] = None, timeout: Union[int, float] = None, *args, **kwargs) -> bool:
if user_id is None and self.me is not None:
user_id = self.me.account.uid
@ -1144,13 +1181,15 @@ class Client(YandexMusicObject):
return 'revision' in result
@log
def users_dislikes_tracks_add(self, track_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_dislikes_tracks_add(self, track_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._dislike_action(track_ids, False, user_id, timeout, *args, **kwargs)
@log
def users_dislikes_tracks_remove(self, track_ids: str or list, user_id: str or int = None,
timeout=None, *args, **kwargs):
def users_dislikes_tracks_remove(self, track_ids: Union[List[Union[str, int]], str, int],
user_id: Union[str, int] = None,
timeout: Union[int, float] = None, *args, **kwargs) -> bool:
return self._dislike_action(track_ids, True, user_id, timeout, *args, **kwargs)
# camelCase псевдонимы

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional, List
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -31,15 +36,15 @@ class Cover(YandexMusicObject):
"""
def __init__(self,
type_=None,
uri=None,
items_uri=None,
dir_=None,
version=None,
custom=None,
prefix=None,
error=None,
client=None,
type_: Optional[str] = None,
uri: Optional[str] = None,
items_uri: Optional[str] = None,
dir_: Optional[str] = None,
version: Optional[str] = None,
custom: Optional[bool] = None,
prefix: Optional[str] = None,
error: Optional[str] = None,
client: Optional['Client'] = None,
**kwargs):
self.type = type_
self.uri = uri
@ -53,7 +58,7 @@ class Cover(YandexMusicObject):
self.client = client
self._id_attrs = (self.prefix, self.version, self.uri, self.items_uri)
def download(self, filename, index=0, size='200x200'):
def download(self, filename: str, index: int = 0, size: str = '200x200') -> None:
"""Загрузка обложки.
Args:
@ -67,7 +72,7 @@ class Cover(YandexMusicObject):
self.client.request.download(f'https://{uri.replace("%%", size)}', filename)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Cover']:
"""Десериализация объекта.
Args:
@ -86,7 +91,7 @@ class Cover(YandexMusicObject):
return cls(client=client, **data)
@classmethod
def de_list(cls, data, client):
def de_list(cls, data: dict, client: 'Client') -> List['Cover']:
"""Десериализация списка объектов.
Args:

ファイルの表示

@ -1,3 +1,9 @@
from typing import TYPE_CHECKING, Optional, List
if TYPE_CHECKING:
from yandex_music import Client
from xml.dom.minicompat import NodeList
from hashlib import md5
import xml.dom.minidom as minidom
@ -29,12 +35,12 @@ class DownloadInfo(YandexMusicObject):
"""
def __init__(self,
codec,
bitrate_in_kbps,
gain,
preview,
download_info_url,
client=None,
codec: str,
bitrate_in_kbps: int,
gain: bool,
preview: bool,
download_info_url: str,
client: Optional['Client'] = None,
**kwargs):
self.codec = codec
self.bitrate_in_kbps = bitrate_in_kbps
@ -48,7 +54,7 @@ class DownloadInfo(YandexMusicObject):
self._id_attrs = (self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url)
@staticmethod
def _get_text_node_data(elements):
def _get_text_node_data(elements: 'NodeList') -> str:
""":obj:`str`: Получение текстовой информации из узлов XML элемента."""
for element in elements:
nodes = element.childNodes
@ -56,7 +62,7 @@ class DownloadInfo(YandexMusicObject):
if node.nodeType == node.TEXT_NODE:
return node.data
def get_direct_link(self):
def get_direct_link(self) -> str:
"""Получение прямой ссылки на загрузку из XML ответа.
Метод доступен только одну минуту с момента получения информации о загрузке, иначе 410 ошибка!
@ -80,7 +86,7 @@ class DownloadInfo(YandexMusicObject):
return self.direct_link
def download(self, filename):
def download(self, filename: str) -> None:
"""Загрузка трека.
Args:
@ -93,7 +99,7 @@ class DownloadInfo(YandexMusicObject):
self.client.request.download(self.direct_link, filename)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['DownloadInfo']:
"""Десериализация объекта.
Args:
@ -112,7 +118,7 @@ class DownloadInfo(YandexMusicObject):
return cls(client=client, **data)
@classmethod
def de_list(cls, data, client, get_direct_links=False):
def de_list(cls, data: dict, client: 'Client', get_direct_links: bool = False) -> List['DownloadInfo']:
"""Десериализация списка объектов.
Args:

ファイルの表示

@ -1,3 +1,9 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from yandex_music.utils.captcha_response import CaptchaResponse
class YandexMusicError(Exception):
"""Базовый класс, представляющий исключения общего характера. """
@ -33,7 +39,7 @@ class Captcha(YandexMusicError):
:class:`yandex_music.utils.captcha_response.CaptchaResponse` представляющий капчу.
"""
def __init__(self, msg, captcha, *args, **kwargs):
def __init__(self, msg: str, captcha: 'CaptchaResponse', *args, **kwargs):
self.captcha = captcha
super().__init__(msg, *args, **kwargs)

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -16,14 +21,14 @@ class Experiments(YandexMusicObject):
"""
def __init__(self,
client=None,
client: Optional['Client'] = None,
**kwargs):
self.__dict__.update(kwargs)
self.client = client
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Experiments']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -19,9 +24,9 @@ class Icon(YandexMusicObject):
"""
def __init__(self,
background_color,
image_url,
client=None,
background_color: str,
image_url: str,
client: Optional['Client'] = None,
**kwargs):
self.background_color = background_color
self.image_url = image_url
@ -29,7 +34,7 @@ class Icon(YandexMusicObject):
self.client = client
self._id_attrs = (self.background_color, self.image_url)
def download(self, filename, size='200x200'):
def download(self, filename: str, size: str = '200x200'):
"""Загрузка иконки.
Args:
@ -40,7 +45,7 @@ class Icon(YandexMusicObject):
self.client.request.download(f'https://{self.image_url.replace("%%", size)}', filename)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Icon']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -21,10 +26,10 @@ class InvocationInfo(YandexMusicObject):
"""
def __init__(self,
hostname,
req_id,
exec_duration_millis=None,
client=None,
hostname: str,
req_id: str,
exec_duration_millis: Optional[str] = None,
client: Optional['Client'] = None,
**kwargs):
self.hostname = hostname
self.req_id = req_id
@ -35,7 +40,7 @@ class InvocationInfo(YandexMusicObject):
self._id_attrs = (self.hostname, self.req_id)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['InvocationInfo']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -21,10 +26,10 @@ class Pager(YandexMusicObject):
"""
def __init__(self,
total,
page,
per_page,
client=None,
total: int,
page: int,
per_page: int,
client: Optional['Client'] = None,
**kwargs):
self.total = total
self.page = page
@ -34,7 +39,7 @@ class Pager(YandexMusicObject):
self._id_attrs = (self.total, self.page, self.per_page)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Pager']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -18,14 +23,14 @@ class PermissionAlerts(YandexMusicObject):
def __init__(self,
alerts,
client=None,
client: Optional['Client'] = None,
**kwargs):
self.alerts = alerts
self.client = client
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['PermissionAlerts']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
from yandex_music import Client, Status
from yandex_music import YandexMusicObject
@ -23,10 +28,10 @@ class PromoCodeStatus(YandexMusicObject):
"""
def __init__(self,
status,
status_desc,
account_status,
client=None,
status: str,
status_desc: str,
account_status: 'Status',
client: Optional['Client'] = None,
**kwargs):
self.status = status
self.status_desc = status_desc
@ -36,7 +41,7 @@ class PromoCodeStatus(YandexMusicObject):
self._id_attrs = (self.status, self.status_desc, self.account_status)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['PromoCodeStatus']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional, List
if TYPE_CHECKING:
from yandex_music import Client, Product, Price
from yandex_music import YandexMusicObject
@ -7,7 +12,7 @@ class Settings(YandexMusicObject):
Attributes:
in_app_products (:obj:`list` из :obj:`yandex_music.Product`): Список объектов класса
:class:`yandex_music.Product` представляющий продаваемые продукты внутри приложения.
native_products (:obj:`list`) из :obj:`yandex_music.Product`: Список объектов класса
native_products (:obj:`list` из :obj:`yandex_music.Product`): Список объектов класса
:class:`yandex_music.Product` представляющий продаваемые продукты всплывающими окнами.
web_payment_url (:obj:`str`): Ссылка для осуществления платежа.
web_payment_month_product_price (:obj:`yandex_music.Price`): Объект класса :class:`yandex_music.Price`
@ -31,12 +36,12 @@ class Settings(YandexMusicObject):
"""
def __init__(self,
in_app_products,
native_products,
web_payment_url,
promo_codes_enabled,
web_payment_month_product_price=None,
client=None,
in_app_products: List['Product'],
native_products: List['Product'],
web_payment_url: str,
promo_codes_enabled: bool,
web_payment_month_product_price: Optional['Price'] = None,
client: Optional['Client'] = None,
**kwargs):
self.in_app_products = in_app_products
self.native_products = native_products
@ -48,7 +53,7 @@ class Settings(YandexMusicObject):
self._id_attrs = (self.in_app_products, self.native_products, self.web_payment_url, self.promo_codes_enabled)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Settings']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional, List
if TYPE_CHECKING:
from yandex_music import Client, Track
from yandex_music import YandexMusicObject
@ -21,10 +26,10 @@ class TrackShort(YandexMusicObject):
"""
def __init__(self,
id_,
timestamp,
album_id=None,
client=None,
id_: str,
timestamp: str,
album_id: Optional[str] = None,
client: Optional['Client'] = None,
**kwargs):
self.id = id_
self.timestamp = timestamp
@ -37,7 +42,7 @@ class TrackShort(YandexMusicObject):
self._id_attrs = (self.id, self.album_id)
@property
def track(self):
def track(self) -> 'Track':
""":obj:`yandex_music.Track`: Объект класса :class:`yandex_music.Track` представляющий полную версию трека."""
if self._track:
return self._track
@ -47,7 +52,7 @@ class TrackShort(YandexMusicObject):
return self._track
@property
def track_id(self):
def track_id(self) -> str:
""":obj:`str`: Уникальный идентификатор трека состоящий из его номера и номера альбома или просто из номера."""
if self.album_id:
@ -56,7 +61,7 @@ class TrackShort(YandexMusicObject):
return f'{self.id}'
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['TrackShort']:
"""Десериализация объекта.
Args:
@ -75,7 +80,7 @@ class TrackShort(YandexMusicObject):
return cls(client=client, **data)
@classmethod
def de_list(cls, data, client):
def de_list(cls, data: dict, client: 'Client') -> List['TrackShort']:
"""Десериализация списка объектов.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional, List, Iterator
if TYPE_CHECKING:
from yandex_music import Client, TrackShort
from yandex_music import YandexMusicObject
@ -21,10 +26,10 @@ class TracksList(YandexMusicObject):
"""
def __init__(self,
uid,
revision,
tracks,
client=None,
uid: int,
revision: int,
tracks: List['TrackShort'],
client: Optional['Client'] = None,
**kwargs):
self.uid = uid
self.revision = revision
@ -33,19 +38,19 @@ class TracksList(YandexMusicObject):
self.client = client
self._id_attrs = (self.uid, self.tracks)
def __getitem__(self, item):
def __getitem__(self, item) -> 'TrackShort':
return self.tracks[item]
def __iter__(self):
def __iter__(self) -> Iterator['TrackShort']:
return iter(self.tracks)
@property
def tracks_ids(self):
def tracks_ids(self) -> List[str]:
""":obj:`list` из :obj:`str`: Список уникальных идентификаторов треков."""
return [track.track_id for track in self.tracks]
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['TracksList']:
"""Десериализация объекта.
Args:

ファイルの表示

@ -1,3 +1,8 @@
from typing import TYPE_CHECKING, Optional, List
if TYPE_CHECKING:
from yandex_music import Client
from yandex_music import YandexMusicObject
@ -14,7 +19,7 @@ class Video(YandexMusicObject):
text=None,
html_auto_play_video_player=None,
regions=None,
client=None,
client: Optional['Client'] = None,
**kwargs):
self.title = title
@ -36,7 +41,7 @@ class Video(YandexMusicObject):
self._id_attrs = (self.provider_video_id, self.youtube_url, self.title)
@classmethod
def de_json(cls, data, client):
def de_json(cls, data: dict, client: 'Client') -> Optional['Video']:
if not data:
return None
@ -45,7 +50,7 @@ class Video(YandexMusicObject):
return cls(client=client, **data)
@classmethod
def de_list(cls, data, client):
def de_list(cls, data: dict, client: 'Client') -> List['Video']:
if not data:
return []