Инициализации и работа с клиентом без авторизации (#15)

* Добавлена возможность инициализации и работы с клиентом без авторизации (https://github.com/MarshalX/yandex-music-api/issues/14).
Авторизация через логин и пароль доступна через метод from_credentials у Client'a.
Многие поля в account стали необязательными в связи с поддержкой клиентов без авторизации.
Исправлен баг в request связанный с одинаковыми заголовками при разных объектах.
Обновлена документация к методам.

* Обновлена версия.
このコミットが含まれているのは:
Il'ya 2019-08-22 21:56:02 +03:00 committed by GitHub
コミット eb741a2b9d
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
5個のファイルの変更52行の追加35行の削除

ファイルの表示

@ -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',

ファイルの表示

@ -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):

ファイルの表示

@ -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'):
"""Загрузка изображения пользователя.

ファイルの表示

@ -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

ファイルの表示

@ -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)