Merge branch 'development' into pull/325

このコミットが含まれているのは:
Il'ya 2020-05-14 23:39:50 +03:00 committed by GitHub
コミット 65d1584b79
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
21個のファイルの変更681行の追加11行の削除

ファイルの表示

@ -0,0 +1,7 @@
yandex_music.ChartInfo
======================
.. autoclass:: yandex_music.ChartInfo
:members:
:undoc-members:
:show-inheritance:

ファイルの表示

@ -0,0 +1,7 @@
yandex_music.ChartInfoMenu
==========================
.. autoclass:: yandex_music.ChartInfoMenu
:members:
:undoc-members:
:show-inheritance:

ファイルの表示

@ -0,0 +1,7 @@
yandex_music.ChartInfoMenuItem
==============================
.. autoclass:: yandex_music.ChartInfoMenuItem
:members:
:undoc-members:
:show-inheritance:

ファイルの表示

@ -15,3 +15,6 @@
yandex_music.landing.personal_playlists_data yandex_music.landing.personal_playlists_data
yandex_music.landing.promotion yandex_music.landing.promotion
yandex_music.landing.block yandex_music.landing.block
yandex_music.landing.chart_info
yandex_music.landing.chart_info_menu
yandex_music.landing.chart_info_menu_item

ファイルの表示

@ -11,3 +11,5 @@
yandex_music.playlist.case_forms yandex_music.playlist.case_forms
yandex_music.playlist.playlist_id yandex_music.playlist.playlist_id
yandex_music.playlist.playlist_recommendations yandex_music.playlist.playlist_recommendations
yandex_music.playlist.tag_result
yandex_music.playlist.tag

7
docs/source/yandex_music.playlist.tag.rst ノーマルファイル
ファイルの表示

@ -0,0 +1,7 @@
yandex_music.Tag
================
.. autoclass:: yandex_music.Tag
:members:
:undoc-members:
:show-inheritance:

ファイルの表示

@ -0,0 +1,7 @@
yandex_music.TagResult
======================
.. autoclass:: yandex_music.TagResult
:members:
:undoc-members:
:show-inheritance:

ファイルの表示

@ -17,6 +17,9 @@ from .test_description import TestDescription
from .test_discrete_scale import TestDiscreteScale from .test_discrete_scale import TestDiscreteScale
from .test_enum import TestEnum from .test_enum import TestEnum
from .test_event import TestEvent from .test_event import TestEvent
from .test_chart_info_menu_item import TestChartInfoMenuItem
from .test_chart_info_menu import TestChartInfoMenu
from .test_chart_info import TestChartInfo
from .test_generated_playlist import TestGeneratedPlaylist from .test_generated_playlist import TestGeneratedPlaylist
from .test_genre import TestGenre from .test_genre import TestGenre
from .test_icon import TestIcon from .test_icon import TestIcon
@ -74,3 +77,4 @@ from .test_shot_type import TestShotType
from .test_shot_data import TestShotData from .test_shot_data import TestShotData
from .test_shot import TestShot from .test_shot import TestShot
from .test_renewable_remainder import TestRenewableRemainder from .test_renewable_remainder import TestRenewableRemainder
from .test_tag import TestTag

ファイルの表示

@ -7,7 +7,7 @@ from yandex_music import Counts, TrackId, CaseForms, Ratings, Icon, Album, Lyric
PersonalPlaylistsData, RotorSettings, TrackShortOld, PlayContextsData, Status, Settings, StationResult, Enum, \ PersonalPlaylistsData, RotorSettings, TrackShortOld, PlayContextsData, Status, Settings, StationResult, Enum, \
TrackWithAds, VideoSupplement, ArtistEvent, ChartItem, Event, AlbumEvent, Day, PlayContext, Plus, Title, Label, \ TrackWithAds, VideoSupplement, ArtistEvent, ChartItem, Event, AlbumEvent, Day, PlayContext, Plus, Title, Label, \
GeneratedPlaylist, Video, Vinyl, SearchResult, BlockEntity, Block, PlaylistAbsence, ShotType, ShotData, Shot, \ GeneratedPlaylist, Video, Vinyl, SearchResult, BlockEntity, Block, PlaylistAbsence, ShotType, ShotData, Shot, \
RenewableRemainder RenewableRemainder, ChartInfoMenuItem, ChartInfoMenu, ChartInfo, Tag
from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, TestAlbum, TestLyrics, \ from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, TestAlbum, TestLyrics, \
TestTrack, TestInvocationInfo, TestPlaylist, TestAutoRenewable, TestStation, TestNormalization, TestMajor, \ TestTrack, TestInvocationInfo, TestPlaylist, TestAutoRenewable, TestStation, TestNormalization, TestMajor, \
TestTrackPosition, TestBest, TestChart, TestPermissions, TestPlus, TestProduct, TestCover, TestPlayCounter, \ TestTrackPosition, TestBest, TestChart, TestPermissions, TestPlus, TestProduct, TestCover, TestPlayCounter, \
@ -17,7 +17,7 @@ from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, Tes
TestTrackShortOld, TestPager, TestStatus, TestSettings, TestStationResult, TestLabel, TestTrackWithAds, \ TestTrackShortOld, TestPager, TestStatus, TestSettings, TestStationResult, TestLabel, TestTrackWithAds, \
TestVideoSupplement, TestEvent, TestDay, TestPlayContext, TestGeneratedPlaylist, TestVideo, TestVinyl, \ TestVideoSupplement, TestEvent, TestDay, TestPlayContext, TestGeneratedPlaylist, TestVideo, TestVinyl, \
TestSearchResult, TestBlockEntity, TestBlock, TestPlaylistAbsence, TestShot, TestShotData, TestShotType, \ TestSearchResult, TestBlockEntity, TestBlock, TestPlaylistAbsence, TestShot, TestShotData, TestShotType, \
TestRenewableRemainder TestRenewableRemainder, TestChartInfoMenuItem, TestChartInfo, TestTag
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
@ -137,6 +137,11 @@ def client():
return Client() return Client()
@pytest.fixture(scope='session')
def tag():
return Tag(TestTag.id_, TestTag.value, TestTag.name, TestTag.og_description)
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
def track_with_ads(track): def track_with_ads(track):
return TrackWithAds(TestTrackWithAds.type, track) return TrackWithAds(TestTrackWithAds.type, track)
@ -423,6 +428,22 @@ def event(track, artist_event, album_event):
[album_event], TestEvent.message, TestEvent.device, TestEvent.tracks_count) [album_event], TestEvent.message, TestEvent.device, TestEvent.tracks_count)
@pytest.fixture(scope='session')
def chart_info_menu_item():
return ChartInfoMenuItem(TestChartInfoMenuItem.title, TestChartInfoMenuItem.url, TestChartInfoMenuItem.selected)
@pytest.fixture(scope='session')
def chart_info_menu(chart_info_menu_item):
return ChartInfoMenu([chart_info_menu_item])
@pytest.fixture(scope='session')
def chart_info(playlist, chart_info_menu):
return ChartInfo(TestChartInfo.id, TestChartInfo.type, TestChartInfo.type_for_from, TestChartInfo.title,
chart_info_menu, playlist, TestChartInfo.chart_description)
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
def track_id(): def track_id():
return TrackId(TestTrackId.id, TestTrackId.album_id) return TrackId(TestTrackId.id, TestTrackId.album_id)

74
tests/test_chart_info.py ノーマルファイル
ファイルの表示

@ -0,0 +1,74 @@
from yandex_music import ChartInfo
class TestChartInfo:
id = 'KpXst7X4'
type = 'chart'
type_for_from = 'chart'
title = 'Треки, популярные на Яндекс.Музыке прямо сейчас'
chart_description = 'Слушателей за день'
def test_expected_values(self, chart_info, chart_info_menu, playlist):
assert chart_info.id == self.id
assert chart_info.type == self.type
assert chart_info.type_for_from == self.type_for_from
assert chart_info.title == self.title
assert chart_info.chart == playlist
assert chart_info.menu == chart_info_menu
def test_de_json_none(self, client):
assert ChartInfo.de_json({}, client) is None
def test_de_json_required(self, playlist, chart_info_menu, client):
json_dict = {
'id_': self.id,
'type_': self.type,
'type_for_from': self.type_for_from,
'title': self.title,
'chart_description': self.chart_description,
'menu': chart_info_menu.to_dict(),
'chart': playlist.to_dict()
}
chart_info = ChartInfo.de_json(json_dict, client)
assert chart_info.id == self.id
assert chart_info.type == self.type
assert chart_info.type_for_from == self.type_for_from
assert chart_info.title == self.title
assert chart_info.chart_description == self.chart_description
def test_de_json_all(self, client, playlist, chart_info_menu):
json_dict = {
'id_': self.id,
'type_': self.type,
'type_for_from': self.type_for_from,
'title': self.title,
'chart_description': self.chart_description,
'menu': chart_info_menu.to_dict(),
'chart': playlist.to_dict()
}
chart_info = ChartInfo.de_json(json_dict, client)
assert chart_info.id == self.id
assert chart_info.type == self.type
assert chart_info.type_for_from == self.type_for_from
assert chart_info.title == self.title
assert chart_info.chart_description == self.chart_description
assert chart_info.menu == chart_info_menu
assert chart_info.chart == playlist
def test_equality(self, playlist, chart_info_menu):
a = ChartInfo(self.id, self.type, self.type_for_from, self.title, self.chart_description, chart_info_menu,
playlist)
b = ChartInfo("no_id", self.type, self.type_for_from, self.title, self.chart_description, chart_info_menu,
playlist)
c = ChartInfo(self.id, self.type, self.type_for_from, self.title, self.chart_description, chart_info_menu,
playlist)
assert a != b
assert hash(a) != hash(b)
assert a is not b
assert a == c

29
tests/test_chart_info_menu.py ノーマルファイル
ファイルの表示

@ -0,0 +1,29 @@
from yandex_music import ChartInfoMenu, ChartInfoMenuItem
class TestChartInfoMenu:
def test_expected_values(self, chart_info_menu, chart_info_menu_item):
assert chart_info_menu.items == [chart_info_menu_item]
def test_de_json_none(self, client):
assert ChartInfoMenu.de_json({}, client) is None
def test_de_json_required(self, chart_info_menu_item, client):
json_dict = {
'items': [chart_info_menu_item.to_dict()],
}
chart_info_menu = ChartInfoMenu.de_json(json_dict, client)
assert chart_info_menu.items == [chart_info_menu_item]
def test_equality(self, chart_info_menu_item):
a = ChartInfoMenu([chart_info_menu_item])
b = ChartInfoMenu([ChartInfoMenuItem("tt", "no_url")])
c = ChartInfoMenu([chart_info_menu_item])
assert a != b
assert hash(a) != hash(b)
assert a is not b
assert a == c

50
tests/test_chart_info_menu_item.py ノーマルファイル
ファイルの表示

@ -0,0 +1,50 @@
from yandex_music import ChartInfoMenuItem
class TestChartInfoMenuItem:
title = 'Россия'
url = 'russia'
selected = True
def test_expected_values(self, chart_info_menu_item):
assert chart_info_menu_item.title == self.title
assert chart_info_menu_item.url == self.url
assert chart_info_menu_item.selected == self.selected
def test_de_json_none(self, client):
assert ChartInfoMenuItem.de_json({}, client) is None
def test_de_json_required(self, client):
json_dict = {
'title': self.title,
'url': self.url,
}
chart_info_menu_item = ChartInfoMenuItem.de_json(json_dict, client)
assert chart_info_menu_item.title == self.title
assert chart_info_menu_item.url == self.url
def test_de_json_all(self, client):
json_dict = {
'title': self.title,
'url': self.url,
'selected': self.selected,
}
chart_info_menu_item = ChartInfoMenuItem.de_json(json_dict, client)
assert chart_info_menu_item.title == self.title
assert chart_info_menu_item.url == self.url
assert chart_info_menu_item.selected == self.selected
def test_equality(self):
a = ChartInfoMenuItem(self.title, self.url, self.selected)
b = ChartInfoMenuItem(self.title, "no_url", self.selected)
c = ChartInfoMenuItem(self.title, self.url, self.selected)
assert a != b
assert hash(a) != hash(b)
assert a is not b
assert a == c

47
tests/test_tag.py ノーマルファイル
ファイルの表示

@ -0,0 +1,47 @@
from yandex_music import Tag
class TestTag:
id_ = '5795ce8f77d30f7fda41bca0'
value = 'вечные хиты'
name = 'Вечные хиты'
og_description = ''
def test_expected_values(self, tag):
assert tag.id == self.id_
assert tag.value == self.value
assert tag.name == self.name
assert tag.og_description == self.og_description
def test_de_json_none(self, client):
assert Tag.de_json({}, client) is None
def test_de_json_required(self, client):
json_dict = {'id_': self.id_, 'value': self.value, 'name': self.name, 'og_description': self.og_description}
tag = Tag.de_json(json_dict, client)
assert tag.id == self.id_
assert tag.value == self.value
assert tag.name == self.name
assert tag.og_description == self.og_description
def test_de_json_all(self, client):
json_dict = {'id_': self.id_, 'value': self.value, 'name': self.name, 'og_description': self.og_description}
tag = Tag.de_json(json_dict, client)
assert tag.id == self.id_
assert tag.value == self.value
assert tag.name == self.name
assert tag.og_description == self.og_description
def test_equality(self):
a = Tag(self.id_, self.value, self.name, self.og_description)
b = Tag('10b300', self.value, self.name, self.og_description)
c = Tag(self.id_, self.value, '', self.og_description)
d = Tag(self.id_, self.value, self.name, self.og_description)
assert a != b != c
assert hash(a) != hash(b) != hash(c)
assert a is not b is not c
assert a == d

42
tests/test_tag_result.py ノーマルファイル
ファイルの表示

@ -0,0 +1,42 @@
import pytest
from yandex_music import TagResult
@pytest.fixture(scope='class')
def tag_result(tag, playlist_id):
return TagResult(tag, [playlist_id])
class TestTagResult:
def test_expected_values(self, tag_result, tag, playlist_id):
assert tag_result.tag == tag
assert tag_result.ids == [playlist_id]
def test_de_json_none(self, client):
assert TagResult.de_json({}, client) is None
def test_de_json_required(self, client, tag, playlist_id):
json_dict = {'tag': tag.to_dict(), 'ids': [playlist_id.to_dict()]}
tag_result = TagResult.de_json(json_dict, client)
assert tag_result.tag == tag
assert tag_result.ids == [playlist_id]
def test_de_json_all(self, client, tag, playlist_id):
json_dict = {'tag': tag.to_dict(), 'ids': [playlist_id.to_dict()]}
tag_result = TagResult.de_json(json_dict, client)
assert tag_result.tag == tag
assert tag_result.ids == [playlist_id]
def test_equality(self, tag, playlist_id):
a = TagResult(tag, [playlist_id])
b = TagResult(tag, [])
c = TagResult(tag, [playlist_id])
assert a != b
assert hash(a) != hash(b)
assert a is not b
assert a == c

ファイルの表示

@ -34,6 +34,8 @@ from .playlist.made_for import MadeFor
from .playlist.user import User from .playlist.user import User
from .playlist.play_counter import PlayCounter from .playlist.play_counter import PlayCounter
from .playlist.playlist_id import PlaylistId from .playlist.playlist_id import PlaylistId
from .playlist.tag import Tag
from .playlist.tag_result import TagResult
from .playlist.playlist_absence import PlaylistAbsence from .playlist.playlist_absence import PlaylistAbsence
from .playlist.playlist import Playlist from .playlist.playlist import Playlist
from .playlist.playlist_recommendation import PlaylistRecommendations from .playlist.playlist_recommendation import PlaylistRecommendations
@ -74,6 +76,9 @@ from .landing.promotion import Promotion
from .landing.block_entity import BlockEntity from .landing.block_entity import BlockEntity
from .landing.landing import Landing from .landing.landing import Landing
from .landing.block import Block from .landing.block import Block
from .landing.chart_info_menu_item import ChartInfoMenuItem
from .landing.chart_info_menu import ChartInfoMenu
from .landing.chart_info import ChartInfo
from .landing.track_id import TrackId from .landing.track_id import TrackId
from .landing.chart import Chart from .landing.chart import Chart
from .landing.play_contexts_data import PlayContextsData from .landing.play_contexts_data import PlayContextsData
@ -120,4 +125,5 @@ __all__ = ['YandexMusicObject', 'Client', 'Account', 'PassportPhone', 'Invocatio
'Dashboard', 'RotorSettings', 'AdParams', 'Restrictions', 'Value', 'Enum', 'DiscreteScale', 'StationResult', 'Dashboard', 'RotorSettings', 'AdParams', 'Restrictions', 'Value', 'Enum', 'DiscreteScale', 'StationResult',
'Sequence', 'StationTracksResult', 'BriefInfo', 'Description', 'PlaylistId', 'Vinyl', 'Supplement', 'Lyrics', 'Sequence', 'StationTracksResult', 'BriefInfo', 'Description', 'PlaylistId', 'Vinyl', 'Supplement', 'Lyrics',
'VideoSupplement', 'ArtistTracks', 'Pager', 'ArtistAlbums', 'PlaylistAbsence', 'Shot', 'ShotEvent', 'VideoSupplement', 'ArtistTracks', 'Pager', 'ArtistAlbums', 'PlaylistAbsence', 'Shot', 'ShotEvent',
'ShotType', 'ShotData', 'SimilarTracks', 'UserSettings', 'RenewableRemainder', 'PlaylistRecommendations'] 'ShotType', 'ShotData', 'SimilarTracks', 'UserSettings', 'RenewableRemainder', 'ChartInfo', 'ChartInfoMenu',
'ChartInfoMenuItem', 'Tag', 'TagResult', 'PlaylistRecommendations']

ファイルの表示

@ -4,9 +4,9 @@ from datetime import datetime
from typing import Callable, Dict, List, Optional, Union from typing import Callable, Dict, List, Optional, Union
from yandex_music import Album, Artist, ArtistAlbums, ArtistTracks, BriefInfo, Dashboard, DownloadInfo, Experiments, \ from yandex_music import Album, Artist, ArtistAlbums, ArtistTracks, BriefInfo, Dashboard, DownloadInfo, Experiments, \
Feed, Genre, Landing, Like, PermissionAlerts, Playlist, PromoCodeStatus, Search, Settings, ShotEvent, SimilarTracks, \ Feed, Genre, Landing, Like, PermissionAlerts, Playlist, PromoCodeStatus, Search, Settings, ShotEvent, Supplement, \
StationResult, StationTracksResult, Status, Suggestions, Supplement, Track, TracksList, UserSettings, \ StationResult, StationTracksResult, Status, Suggestions, SimilarTracks, Track, TracksList, UserSettings, \
YandexMusicObject, PlaylistRecommendations YandexMusicObject, ChartInfo, TagResult, PlaylistRecommendations
from yandex_music.exceptions import Captcha, InvalidToken from yandex_music.exceptions import Captcha, InvalidToken
from yandex_music.utils.difference import Difference from yandex_music.utils.difference import Difference
from yandex_music.utils.request import Request from yandex_music.utils.request import Request
@ -439,6 +439,36 @@ class Client(YandexMusicObject):
return Landing.de_json(result, self) return Landing.de_json(result, self)
@log
def chart(self, chart_option: str = '', timeout: Union[int, float] = None, *args, **kwargs) -> Optional[ChartInfo]:
"""Получение чарта.
Note:
`chart_option` - это постфикс к запросу из поля `menu` чарта.
Например, на сайте можно выбрать глобальный (world) чарт или российский (russia).
Args:
chart_option (:obj:`str` optional): Параметры чарта.
timeout (:obj:`int` | :obj:`float`, optional): Если это значение указано, используется как время ожидания
ответа от сервера вместо указанного при создании пула.
**kwargs (:obj:`dict`, optional): Произвольные аргументы (будут переданы в запрос).
Returns:
:obj:`yandex_music.ChartInfo`: Чарт.
Raises:
:class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
"""
url = f'{self.base_url}/landing3/chart'
if chart_option:
url = f'{url}/{chart_option}'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
return ChartInfo.de_json(result, self)
@log @log
def genres(self, timeout: Union[int, float] = None, *args, **kwargs) -> List[Genre]: def genres(self, timeout: Union[int, float] = None, *args, **kwargs) -> List[Genre]:
"""Получение жанров музыки. """Получение жанров музыки.
@ -461,6 +491,35 @@ class Client(YandexMusicObject):
return Genre.de_list(result, self) return Genre.de_list(result, self)
@log
def tags(self, tag_id: str, timeout: Union[int, float] = None, *args, **kwargs) -> Optional[TagResult]:
"""Получение тега (подборки).
Note:
Теги есть в `MixLink` у `Landing`, а также плейлистов в `.tags`.
У `MixLink` есть `URL`, но `tag_id` только его последняя часть.
Например, `/tag/belarus/`. `Tag` - `belarus`.
Args:
tag_id (:obj:`str`): Уникальный идентификатор тега.
timeout (:obj:`int` | :obj:`float`, optional): Если это значение указано, используется как время ожидания
ответа от сервера вместо указанного при создании пула.
**kwargs (:obj:`dict`, optional): Произвольные аргументы (будут переданы в запрос).
Returns:
:obj:`list` из :obj:`yandex_music.Genre` | :obj:`None`: Жанры музыки или :obj:`None`.
Raises:
:class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
"""
url = f'{self.base_url}/tags/{tag_id}/playlist-ids'
result = self._request.get(url, timeout=timeout, *args, **kwargs)
return TagResult.de_json(result, self)
@log @log
def tracks_download_info(self, track_id: Union[str, int], get_direct_links: bool = False, def tracks_download_info(self, track_id: Union[str, int], get_direct_links: bool = False,
timeout: Union[int, float] = None, *args, **kwargs) -> List[DownloadInfo]: timeout: Union[int, float] = None, *args, **kwargs) -> List[DownloadInfo]:
@ -1448,7 +1507,7 @@ class Client(YandexMusicObject):
Note: Note:
Типы объектов: `track` - трек, `artist` - исполнитель, `playlist` - плейлист, `album` - альбом. Типы объектов: `track` - трек, `artist` - исполнитель, `playlist` - плейлист, `album` - альбом.
Идентификатор плейлиста указывается в формате `playlist_id:owner_id`. Где `playlist_id` - идентификатор Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
Args: Args:
@ -1581,7 +1640,7 @@ class Client(YandexMusicObject):
"""Поставить отметку "Мне нравится" плейлисту/плейлистам. """Поставить отметку "Мне нравится" плейлисту/плейлистам.
Note: Note:
Идентификатор плейлиста указывается в формате `playlist_id:owner_id`. Где `playlist_id` - идентификатор Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
Args: Args:
@ -1608,7 +1667,7 @@ class Client(YandexMusicObject):
"""Снять отметку "Мне нравится" у плейлиста/плейлистов. """Снять отметку "Мне нравится" у плейлиста/плейлистов.
Note: Note:
Идентификатор плейлиста указывается в формате `playlist_id:owner_id`. Где `playlist_id` - идентификатор Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
Args: Args:
@ -1772,7 +1831,7 @@ class Client(YandexMusicObject):
"""Получение плейлиста/плейлистов. """Получение плейлиста/плейлистов.
Note: Note:
Идентификатор плейлиста указывается в формате `playlist_id:owner_id`. Где `playlist_id` - идентификатор Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
Args: Args:
@ -1915,7 +1974,7 @@ class Client(YandexMusicObject):
@log @log
def users_likes_playlists(self, user_id: Union[str, int] = None, timeout: Union[int, float] = None, def users_likes_playlists(self, user_id: Union[str, int] = None, timeout: Union[int, float] = None,
*args, **kwargs) -> List[Like]: *args, **kwargs) -> List[Like]:
"""Получение артистов с отметкой "Мне нравится". """Получение плейлистов с отметкой "Мне нравится".
Args: Args:
user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан

72
yandex_music/landing/chart_info.py ノーマルファイル
ファイルの表示

@ -0,0 +1,72 @@
from typing import TYPE_CHECKING, Optional
from yandex_music import YandexMusicObject, Playlist, ChartInfoMenu
if TYPE_CHECKING:
from yandex_music import Client
class ChartInfo(YandexMusicObject):
"""Класс, представляющий чарт.
Attributes:
id (:obj:`str`): Уникальный идентификатор блока.
type (:obj:`str`): Тип блока.
type_for_from (:obj:`str`): Откуда получен блок (как к нему пришли).
title (:obj:`str`): Заголовок.
menu (:obj:`yandex_music.ChartInfoMenu` | :obj:`None`): Меню TODO.
chart (:obj:`yandex_music.Playlist` | :obj:`None`): Плейлист.
chart_description (:obj:`str`): Описание.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
id_ (:obj:`str`): Уникальный идентификатор блока.
type_ (:obj:`str`): Тип блока.
type_for_from (:obj:`str`): Откуда получен блок (как к нему пришли).
title (:obj:`str`): Заголовок.
menu (:obj:`yandex_music.ChartInfoMenu`, optional): Меню TODO.
chart (:obj:`yandex_music.Playlist`, optional): Плейлист.
chart_description (:obj:`str`, optional): Описание.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
"""
def __init__(self,
id_: str,
type_: str,
type_for_from: str,
title: str,
menu: Optional['ChartInfoMenu'],
chart: Optional['Playlist'],
chart_description: Optional[str] = None,
client: Optional['Client'] = None):
self.id = id_
self.type = type_
self.type_for_from = type_for_from
self.title = title
self.menu = menu
self.chart = chart
self.chart_description = chart_description
self.client = client
self._id_attrs = (id_,)
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['ChartInfo']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.ChartInfo`: Чарт.
"""
if not data:
return None
data = super(ChartInfo, cls).de_json(data, client)
data['chart'] = Playlist.de_json(data.get('chart'), client)
data['menu'] = ChartInfoMenu.de_json(data.get('menu'), client)
return cls(client=client, **data)

44
yandex_music/landing/chart_info_menu.py ノーマルファイル
ファイルの表示

@ -0,0 +1,44 @@
from typing import TYPE_CHECKING, List, Optional
from yandex_music import YandexMusicObject, ChartInfoMenuItem
if TYPE_CHECKING:
from yandex_music import Client
class ChartInfoMenu(YandexMusicObject):
"""Класс, представляющий меню чарта.
Attributes:
items (:obj:`list` из :obj:`yandex_music.ChartInfoMenuItem`): Список элементов меню.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
items (:obj:`list` из :obj:`yandex_music.ChartInfoMenuItem`): Список элементов меню.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
"""
def __init__(self, items: List['ChartInfoMenuItem'], client: Optional['Client'] = None):
self.items = items
self.client = client
self._id_attrs = (self.items, )
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['ChartInfoMenu']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.ChartInfoMenu`: Меню чарта.
"""
if not data:
return None
data = super(ChartInfoMenu, cls).de_json(data, client)
data['items'] = ChartInfoMenuItem.de_list(data.get('items'), client)
return cls(client=client, **data)

65
yandex_music/landing/chart_info_menu_item.py ノーマルファイル
ファイルの表示

@ -0,0 +1,65 @@
from typing import TYPE_CHECKING, Optional, List
from yandex_music import YandexMusicObject
if TYPE_CHECKING:
from yandex_music import Client
class ChartInfoMenuItem(YandexMusicObject):
"""Класс, представляющий элемент меню чарта.
Attributes:
title (:obj:`str`): Заголовок.
url (:obj:`str`): Постфикс для запроса чарта.
selected (:obj:`bool` | :obj:`None`): Текущий ли элемент.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
title (:obj:`str`): Заголовок.
url (:obj:`str`): Постфикс для запроса чарта.
selected (:obj:`bool`, optional): Текущий ли элемент.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
"""
def __init__(self, title: str, url: str, selected: Optional[bool] = None, client: Optional['Client'] = None):
self.title = title
self.url = url
self.selected = selected
self.client = client
self._id_attrs = (url, selected)
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['ChartInfoMenuItem']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.ChartInfoMenuItem`: Элемент меню.
"""
if not data:
return None
data = super(ChartInfoMenuItem, cls).de_json(data, client)
return cls(client=client, **data)
@classmethod
def de_list(cls, data: list, client: 'Client') -> List['ChartInfoMenuItem']:
"""Десериализация списка объектов.
Args:
data (:obj:`list`): Список словарей с полями и значениями десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`list` из :obj:`yandex_music.ChartInfoMenuItem`: Список элементов меню чарта.
"""
if not data:
return []
return [cls.de_json(item, client) for item in data]

61
yandex_music/playlist/tag.py ノーマルファイル
ファイルの表示

@ -0,0 +1,61 @@
from typing import TYPE_CHECKING, Optional
from yandex_music import YandexMusicObject
if TYPE_CHECKING:
from yandex_music import Client
class Tag(YandexMusicObject):
"""Класс, представляющий тег (подборку).
Attributes:
id (:obj:`str`): Уникальный идентификатор тега.
value (:obj:`str`): Значение тега (название в lower case).
name (:obj:`str`): Название тега (отображаемое).
og_description (:obj:`str`): Описание тега для OpenGraph.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
id (:obj:`str`): Уникальный идентификатор тега.
value (:obj:`str`): Значение тега (название в lower case).
name (:obj:`str`): Название тега (отображаемое).
og_description (:obj:`str`): Описание тега для OpenGraph.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
"""
def __init__(self,
id_: str,
value: str,
name: str,
og_description: str,
client: Optional['Client'] = None,
**kwargs) -> None:
super().handle_unknown_kwargs(self, **kwargs)
self.id = id_
self.value = value
self.name = name
self.og_description = og_description
self.client = client
self._id_attrs = (self.id, )
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['Tag']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.Tag`: Тег.
"""
if not data:
return None
data = super(Tag, cls).de_json(data, client)
return cls(client=client, **data)

56
yandex_music/playlist/tag_result.py ノーマルファイル
ファイルの表示

@ -0,0 +1,56 @@
from typing import TYPE_CHECKING, Optional, List
from yandex_music import YandexMusicObject
if TYPE_CHECKING:
from yandex_music import Client, PlaylistId
class TagResult(YandexMusicObject):
"""Класс, представляющий тег и его плейлисты.
Attributes:
tag (:obj:`yandex_music.Tag`): Тег.
ids (:obj:`list` из :obj:`yandex_music.PlaylistId`): Уникальные идентификаторы плейлистов тега.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
tag (:obj:`yandex_music.Tag`): Тег.
ids (:obj:`list` из :obj:`yandex_music.PlaylistId`): Уникальные идентификаторы плейлистов тега.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
"""
def __init__(self,
tag: str,
ids: List['PlaylistId'],
client: Optional['Client'] = None,
**kwargs) -> None:
super().handle_unknown_kwargs(self, **kwargs)
self.tag = tag
self.ids = ids
self.client = client
self._id_attrs = (self.tag, self.ids)
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['TagResult']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.TagResult`: Тег и его плейлисты.
"""
if not data:
return None
data = super(TagResult, cls).de_json(data, client)
from yandex_music import Tag, PlaylistId
data['tag'] = Tag.de_json(data.get('tag'), client)
data['ids'] = PlaylistId.de_list(data.get('ids'), client)
return cls(client=client, **data)