From eb741a2b9ddaa84344315df1bc62d6502c086dfe Mon Sep 17 00:00:00 2001 From: Il'ya Date: Thu, 22 Aug 2019 21:56:02 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BD=D0=B8=D1=86=D0=B8=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B8=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=20=D1=81=20=D0=BA=D0=BB=D0=B8=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=BE=D0=BC=20=D0=B1=D0=B5=D0=B7=20=D0=B0=D0=B2?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлена возможность инициализации и работы с клиентом без авторизации (https://github.com/MarshalX/yandex-music-api/issues/14). Авторизация через логин и пароль доступна через метод from_credentials у Client'a. Многие поля в account стали необязательными в связи с поддержкой клиентов без авторизации. Исправлен баг в request связанный с одинаковыми заголовками при разных объектах. Обновлена документация к методам. * Обновлена версия. --- setup.py | 2 +- yandex_music/client.py | 37 +++++++++++++++++++++--------- yandex_music/status/account.py | 42 ++++++++++++++++++---------------- yandex_music/status/status.py | 4 ++-- yandex_music/utils/request.py | 2 +- 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/setup.py b/setup.py index f224b5b..185c7a7 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ packages = find_packages(exclude=['tests*']) with open('README.rst', 'r', encoding='utf-8') as f: setup(name='yandex-music', - version='0.0.8', + version='0.0.9', author='Il`ya Semyonov', author_email='Ilya@marshal.by', license='LGPLv3', diff --git a/yandex_music/client.py b/yandex_music/client.py index 3403cfa..8fbb573 100644 --- a/yandex_music/client.py +++ b/yandex_music/client.py @@ -37,8 +37,6 @@ class Client(YandexMusicObject): информацию об аккаунте. Args: - username (:obj:`str`): Логин клиента (идентификатор). - password (:obj:`str`): Пароль клиента (аутентификатор). token (:obj:`str`, optional): Уникальный ключ для аутентификации. base_url (:obj:`str`, optional): Ссылка на API Yandex Music. oauth_url (:obj:`str`, optional): Ссылка на OAuth Yandex Music. @@ -46,7 +44,7 @@ class Client(YandexMusicObject): :class:`yandex_music.utils.request.Request`. """ - def __init__(self, username, password, token=None, base_url=None, oauth_url=None, request=None): + def __init__(self, token=None, base_url=None, oauth_url=None, request=None): self.logger = logging.getLogger(__name__) self.token = token @@ -60,24 +58,41 @@ class Client(YandexMusicObject): self._request = request or Request(self) - if self.token is None: - self.token = self.generate_token_by_username_and_password(username, password) - self.request.set_authorization(self.token) - self.account = self.account_status().account @classmethod - def from_token(cls, token): - """Сокращение для авторизации по токену. + def from_credentials(cls, username, password, *args, **kwargs): + """Инициализция клиента по логину и паролю. + + Данный метод получает токен каждый раз при вызове. Рекомендуется сгенерировать его самостоятельно, сохранить и + использовать при следующих инициализациях клиента. Не храните логины и пароли! Args: - token (:obj:`str`, optional): Уникальный ключ для аутентификации. + username (:obj:`str`): Логин клиента (идентификатор). + password (:obj:`str`): Пароль клиента (аутентификатор). + **kwargs (:obj:`dict`, optional): Аргументы для конструктора клиента. Returns: :obj:`yandex_music.Client`. """ - return cls(username=None, password=None, token=token) + return cls(cls().generate_token_by_username_and_password(username, password), *args, **kwargs) + + @classmethod + def from_token(cls, token, *args, **kwargs): + """Инициализция клиента по токену. + + Ничем не отличается от Client(token). Так исторически сложилось. + + Args: + token (:obj:`str`, optional): Уникальный ключ для аутентификации. + **kwargs (:obj:`dict`, optional): Аргументы для конструктора клиента. + + Returns: + :obj:`yandex_music.Client`. + """ + + return cls(token=token, *args, **kwargs) def generate_token_by_username_and_password(self, username, password, grant_type='password', timeout=None, *args, **kwargs): diff --git a/yandex_music/status/account.py b/yandex_music/status/account.py index 3b504c7..0dab85f 100644 --- a/yandex_music/status/account.py +++ b/yandex_music/status/account.py @@ -27,16 +27,16 @@ class Account(YandexMusicObject): Args: now (:obj:`str`): Текущая дата и время. - uid (:obj:`int`): Уникальный идентификатор. - login (:obj:`str`): Виртуальное имя (обычно e-mail). - full_name (:obj:`str`): Полное имя (имя и фамилия). - second_name (:obj:`str`): Фамилия. - first_name (:obj:`str`): Имя. - display_name (:obj:`str`): Отображаемое имя. + uid (:obj:`int`, optional): Уникальный идентификатор. + login (:obj:`str`, optional): Виртуальное имя (обычно e-mail). + full_name (:obj:`str`, optional): Полное имя (имя и фамилия). + second_name (:obj:`str`, optional): Фамилия. + first_name (:obj:`str`, optional): Имя. + display_name (:obj:`str`, optional): Отображаемое имя. service_available (:obj:`bool`): Доступен ли сервис. - hosted_user (:obj:`bool`): Является ли пользователем чьим-то другим. + hosted_user (:obj:`bool`, optional): Является ли пользователем чьим-то другим. birthday (:obj:`str`, optional): Дата рождения. - region (:obj:`int`, optional): Регион. + region (:obj:`int`): Регион. passport_phones (:obj:`list` из :obj:`yandex_music.PassportPhone`): Список объектов класса :class:`yandex_music.PassportPhone` представляющие мобильные номера. registered_at (:obj:`str`, optional): Дата создания учётной записи. @@ -48,39 +48,41 @@ class Account(YandexMusicObject): def __init__(self, now, - uid, - login, - full_name, - second_name, - first_name, - display_name, + region, service_available, - hosted_user, + uid=None, + login=None, + full_name=None, + second_name=None, + first_name=None, + display_name=None, + hosted_user=None, birthday=None, - region=None, passport_phones=None, registered_at=None, has_info_for_app_metrica=False, client=None, **kwargs): self.now = datetime.fromisoformat(now) + self.region = region + self.service_available = service_available + self.uid = uid self.login = login - self.region = region self.full_name = full_name self.second_name = second_name self.first_name = first_name self.display_name = display_name - self.service_available = service_available self.hosted_user = hosted_user self.passport_phones = passport_phones - self.birthday = datetime.fromisoformat(birthday) if birthday else None self.registered_at = datetime.fromisoformat(registered_at) if registered_at else registered_at self.has_info_for_app_metrica = has_info_for_app_metrica self.client = client - self._id_attrs = (self.uid,) + + if self.uid: + self._id_attrs = (self.uid,) def download_avatar(self, filename, format='normal'): """Загрузка изображения пользователя. diff --git a/yandex_music/status/status.py b/yandex_music/status/status.py index aa0818f..90b05bd 100644 --- a/yandex_music/status/status.py +++ b/yandex_music/status/status.py @@ -47,7 +47,7 @@ class Status(YandexMusicObject): def __init__(self, account, permissions, - subscription, + subscription=None, cache_limit=None, subeditor=None, subeditor_level=None, @@ -60,8 +60,8 @@ class Status(YandexMusicObject): **kwargs): self.account = account self.permissions = permissions - self.subscription = subscription + self.subscription = subscription self.cache_limit = cache_limit self.subeditor = subeditor self.subeditor_level = subeditor_level diff --git a/yandex_music/utils/request.py b/yandex_music/utils/request.py index 8f1f51a..5f3a71b 100644 --- a/yandex_music/utils/request.py +++ b/yandex_music/utils/request.py @@ -35,7 +35,7 @@ class Request: self.client = client - self.headers = headers or HEADERS + self.headers = headers or HEADERS.copy() if self.client.token: self.set_authorization(self.client.token)