Добавлен новый класс MetaData.

Добавлено поле error классу Artist.
Класс User расширен для поддержки поля user_info из Track (поля full_name, display_name).
Добавлены новые поля классу Track: substituted, matched_track, can_publish, state, desired_visibility, filename, user_info, meta_data.
Новые поля класса Cover: copyright_name, copyright_cline.
Добавлено поле direct классу DownloadInfo.
Предупреждения о новых полях включены по умолчанию.
Документация и тесты к новым поля. #339
このコミットが含まれているのは:
Il`ya Semyonov 2020-06-06 17:06:23 +03:00
コミット 0240eb6cb9
18個のファイルの変更285行の追加54行の削除

ファイルの表示

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

ファイルの表示

@ -6,3 +6,4 @@
yandex_music.track.normalization
yandex_music.track.major
yandex_music.track.track
yandex_music.track.meta_data

ファイルの表示

@ -78,3 +78,4 @@ from .test_shot_data import TestShotData
from .test_shot import TestShot
from .test_renewable_remainder import TestRenewableRemainder
from .test_tag import TestTag
from .test_meta_data import TestMetaData

ファイルの表示

@ -7,7 +7,7 @@ from yandex_music import Counts, TrackId, CaseForms, Ratings, Icon, Album, Lyric
PersonalPlaylistsData, RotorSettings, TrackShortOld, PlayContextsData, Status, Settings, StationResult, Enum, \
TrackWithAds, VideoSupplement, ArtistEvent, ChartItem, Event, AlbumEvent, Day, PlayContext, Plus, Title, Label, \
GeneratedPlaylist, Video, Vinyl, SearchResult, BlockEntity, Block, PlaylistAbsence, ShotType, ShotData, Shot, \
RenewableRemainder, ChartInfoMenuItem, ChartInfoMenu, ChartInfo, Tag
RenewableRemainder, ChartInfoMenuItem, ChartInfoMenu, ChartInfo, Tag, MetaData
from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, TestAlbum, TestLyrics, \
TestTrack, TestInvocationInfo, TestPlaylist, TestAutoRenewable, TestStation, TestNormalization, TestMajor, \
TestTrackPosition, TestBest, TestChart, TestPermissions, TestPlus, TestProduct, TestCover, TestPlayCounter, \
@ -17,20 +17,20 @@ from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, Tes
TestTrackShortOld, TestPager, TestStatus, TestSettings, TestStationResult, TestLabel, TestTrackWithAds, \
TestVideoSupplement, TestEvent, TestDay, TestPlayContext, TestGeneratedPlaylist, TestVideo, TestVinyl, \
TestSearchResult, TestBlockEntity, TestBlock, TestPlaylistAbsence, TestShot, TestShotData, TestShotType, \
TestRenewableRemainder, TestChartInfoMenuItem, TestChartInfo, TestTag
TestRenewableRemainder, TestChartInfoMenuItem, TestChartInfo, TestTag, TestMetaData
@pytest.fixture(scope='session')
def artist_factory(cover, counts, ratings, link, description):
class ArtistFactory:
def get(self, popular_tracks):
return Artist(TestArtist.id, TestArtist.reason, TestArtist.name, cover, TestArtist.various,
TestArtist.composer, TestArtist.genres, TestArtist.og_image, TestArtist.op_image,
TestArtist.no_pictures_from_search, counts, TestArtist.available, ratings, [link],
TestArtist.tickets_available, TestArtist.likes_count, popular_tracks, TestArtist.regions,
TestArtist.decomposed, TestArtist.full_names, description, TestArtist.countries,
TestArtist.en_wikipedia_link, TestArtist.db_aliases, TestArtist.aliases, TestArtist.init_date,
TestArtist.end_date)
return Artist(TestArtist.id, TestArtist.error, TestArtist.reason, TestArtist.name, cover,
TestArtist.various, TestArtist.composer, TestArtist.genres, TestArtist.og_image,
TestArtist.op_image, TestArtist.no_pictures_from_search, counts, TestArtist.available,
ratings, [link], TestArtist.tickets_available, TestArtist.likes_count, popular_tracks,
TestArtist.regions, TestArtist.decomposed, TestArtist.full_names, description,
TestArtist.countries, TestArtist.en_wikipedia_link, TestArtist.db_aliases, TestArtist.aliases,
TestArtist.init_date, TestArtist.end_date)
return ArtistFactory()
@ -46,14 +46,16 @@ def artist_without_tracks(artist_factory):
@pytest.fixture(scope='session')
def track_factory(major, normalization):
def track_factory(major, normalization, user, meta_data):
class TrackFactory:
def get(self, artists, albums):
def get(self, artists, albums, track_without_nested_tracks=None):
return Track(TestTrack.id, TestTrack.title, TestTrack.available, artists, albums,
TestTrack.available_for_premium_users, TestTrack.lyrics_available, TestTrack.best,
TestTrack.real_id, TestTrack.og_image, TestTrack.type, TestTrack.cover_uri, major,
TestTrack.duration_ms, TestTrack.storage_dir, TestTrack.file_size, normalization,
TestTrack.error, TestTrack.regions, TestTrack.available_as_rbt, TestTrack.content_warning,
TestTrack.duration_ms, TestTrack.storage_dir, TestTrack.file_size, track_without_nested_tracks,
track_without_nested_tracks, normalization, TestTrack.error, TestTrack.can_publish,
TestTrack.state, TestTrack.desired_visibility, TestTrack.filename, user, meta_data,
TestTrack.regions, TestTrack.available_as_rbt, TestTrack.content_warning,
TestTrack.explicit, TestTrack.preview_duration_ms, TestTrack.available_full_without_permission,
TestTrack.version, TestTrack.remember_position)
@ -61,8 +63,8 @@ def track_factory(major, normalization):
@pytest.fixture(scope='session')
def track(track_factory, artist, album):
return track_factory.get([artist], [album])
def track(track_factory, artist, album, track_without_nested_tracks):
return track_factory.get([artist], [album], track_without_nested_tracks)
@pytest.fixture(scope='session')
@ -80,6 +82,11 @@ def track_without_artists_and_albums(track_factory):
return track_factory.get([], [])
@pytest.fixture(scope='session')
def track_without_nested_tracks(artist, album, track_factory):
return track_factory.get([artist], [album])
@pytest.fixture(scope='session')
def album_factory(label, track_position):
class AlbumFactory:
@ -207,7 +214,13 @@ def icon():
@pytest.fixture(scope='session')
def cover():
return Cover(TestCover.type, TestCover.uri, TestCover.items_uri, TestCover.dir, TestCover.version,
TestCover.custom, TestCover.is_custom, TestCover.prefix, TestCover.error)
TestCover.custom, TestCover.is_custom, TestCover.copyright_name, TestCover.copyright_cline,
TestCover.prefix, TestCover.error)
@pytest.fixture(scope='session')
def meta_data():
return MetaData(TestMetaData.album, TestMetaData.volume, TestMetaData.year)
@pytest.fixture(scope='session')
@ -361,7 +374,8 @@ def renewable_remainder():
@pytest.fixture(scope='session')
def user():
return User(TestUser.uid, TestUser.login, TestUser.name, TestUser.sex, TestUser.verified)
return User(TestUser.uid, TestUser.login, TestUser.name, TestUser.display_name,
TestUser.full_name, TestUser.sex, TestUser.verified)
@pytest.fixture(scope='session')

ファイルの表示

@ -3,6 +3,7 @@ from yandex_music import Artist
class TestArtist:
id = 10987
error = 'not-found'
reason = 'not-found'
name = 'Elvis Presley'
various = False
@ -26,6 +27,7 @@ class TestArtist:
def test_expected_values(self, artist, cover, counts, ratings, link, track_without_artists_and_albums, description):
assert artist.id == self.id
assert artist.error == self.error
assert artist.reason == self.reason
assert artist.name == self.name
assert artist.various == self.various
@ -66,7 +68,7 @@ class TestArtist:
assert artist.id == self.id
def test_de_json_all(self, client, cover, counts, ratings, link, track_without_artists, description):
json_dict = {'id_': self.id, 'reason': self.reason, 'name': self.name,
json_dict = {'id_': self.id, 'reason': self.reason, 'error': self.error, 'name': self.name,
'various': self.various, 'composer': self.composer, 'cover': cover.to_dict(),
'genres': self.genres, 'op_image': self.op_image, 'og_image': self.og_image,
'no_pictures_from_search': self.no_pictures_from_search, 'counts': counts.to_dict(),
@ -80,6 +82,7 @@ class TestArtist:
artist = Artist.de_json(json_dict, client)
assert artist.id == self.id
assert artist.error == self.error
assert artist.reason == self.reason
assert artist.name == self.name
assert artist.various == self.various

ファイルの表示

@ -10,6 +10,8 @@ class TestCover:
custom = True
is_custom = True
prefix = None
copyright_name = 'ТАСС'
copyright_cline = 'imago stock&people'
error = None
def test_expected_values(self, cover):
@ -20,6 +22,8 @@ class TestCover:
assert cover.version == self.version
assert cover.custom == self.custom
assert cover.is_custom == self.is_custom
assert cover.copyright_name == self.copyright_name
assert cover.copyright_cline == self.copyright_cline
assert cover.prefix == self.prefix
assert cover.error == self.error
@ -36,7 +40,8 @@ class TestCover:
def test_de_json_all(self, client):
json_dict = {'type_': self.type, 'uri': self.uri, 'items_uri': self.items_uri, 'dir_': self.dir,
'version': self.version, 'custom': self.custom, 'is_custom': self.is_custom, 'prefix': self.prefix,
'error': self.error}
'error': self.error, 'copyright_name': self.copyright_name,
'copyright_cline': self.copyright_cline}
cover = Cover.de_json(json_dict, client)
assert cover.type == self.type
@ -46,6 +51,8 @@ class TestCover:
assert cover.version == self.version
assert cover.custom == self.custom
assert cover.is_custom == self.is_custom
assert cover.copyright_name == self.copyright_name
assert cover.copyright_cline == self.copyright_cline
assert cover.prefix == self.prefix
assert cover.error == self.error

ファイルの表示

@ -6,7 +6,7 @@ from yandex_music import DownloadInfo
@pytest.fixture(scope='class')
def download_info():
return DownloadInfo(TestDownloadInfo.codec, TestDownloadInfo.bitrate_in_kbps, TestDownloadInfo.gain,
TestDownloadInfo.preview, TestDownloadInfo.download_info_url)
TestDownloadInfo.preview, TestDownloadInfo.download_info_url, TestDownloadInfo.direct)
class TestDownloadInfo:
@ -16,6 +16,7 @@ class TestDownloadInfo:
preview = False
download_info_url = 'https://storage.mds.yandex.net/file-download-info/136146_d158926e.14534319.6.10994777/320' \
'?sign=8caf5ea72c946d4753f15298e4033b961c7acb1bb4db48eb5e6b59621e387d64&ts=5dc4a6f2 '
direct = False
def test_expected_values(self, download_info):
assert download_info.codec == self.codec
@ -23,6 +24,7 @@ class TestDownloadInfo:
assert download_info.gain == self.gain
assert download_info.preview == self.preview
assert download_info.download_info_url == self.download_info_url
assert download_info.direct == self.direct
def test_de_json_none(self, client):
assert DownloadInfo.de_json({}, client) is None
@ -32,7 +34,7 @@ class TestDownloadInfo:
def test_de_json_required(self, client):
json_dict = {'codec': self.codec, 'bitrate_in_kbps': self.bitrate_in_kbps, 'gain': self.gain,
'preview': self.preview, 'download_info_url': self.download_info_url}
'preview': self.preview, 'download_info_url': self.download_info_url, 'direct': self.direct}
download_info = DownloadInfo.de_json(json_dict, client)
assert download_info.codec == self.codec
@ -40,10 +42,11 @@ class TestDownloadInfo:
assert download_info.gain == self.gain
assert download_info.preview == self.preview
assert download_info.download_info_url == self.download_info_url
assert download_info.direct == self.direct
def test_de_json_all(self, client):
json_dict = {'codec': self.codec, 'bitrate_in_kbps': self.bitrate_in_kbps, 'gain': self.gain,
'preview': self.preview, 'download_info_url': self.download_info_url}
'preview': self.preview, 'download_info_url': self.download_info_url, 'direct': self.direct}
download_info = DownloadInfo.de_json(json_dict, client)
assert download_info.codec == self.codec
@ -51,11 +54,12 @@ class TestDownloadInfo:
assert download_info.gain == self.gain
assert download_info.preview == self.preview
assert download_info.download_info_url == self.download_info_url
assert download_info.direct == self.direct
def test_equality(self):
a = DownloadInfo(self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url)
b = DownloadInfo(self.codec, 128, self.gain, True, self.download_info_url)
c = DownloadInfo(self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url)
a = DownloadInfo(self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url, self.direct)
b = DownloadInfo(self.codec, 128, self.gain, True, self.download_info_url, True)
c = DownloadInfo(self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url, self.direct)
assert a != b
assert hash(a) != hash(b)

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

@ -0,0 +1,42 @@
from yandex_music import MetaData
class TestMetaData:
album = 'VK Virus Bot'
volume = 1
year = 2018
def test_expected_values(self, meta_data):
assert meta_data.album == self.album
assert meta_data.volume == self.volume
assert meta_data.year == self.year
def test_de_json_none(self, client):
assert MetaData.de_json({}, client) is None
def test_de_json_required(self, client):
json_dict = {'album': self.album, 'volume': self.volume, 'year': self.year}
meta_data = MetaData.de_json(json_dict, client)
assert meta_data.album == self.album
assert meta_data.volume == self.volume
assert meta_data.year == self.year
def test_de_json_all(self, client):
json_dict = {'album': self.album, 'volume': self.volume, 'year': self.year}
meta_data = MetaData.de_json(json_dict, client)
assert meta_data.album == self.album
assert meta_data.volume == self.volume
assert meta_data.year == self.year
def test_equality(self):
a = MetaData(self.album, self.volume, self.year)
b = MetaData(self.album, 0, 2016)
c = MetaData(self.album, self.volume, self.year)
assert a != b
assert hash(a) != hash(b)
assert a is not b
assert a == c

ファイルの表示

@ -16,6 +16,10 @@ class TestTrack:
storage_dir = '51327_109b74ca.36526310.1.609676'
file_size = 6036792
error = None
can_publish = False
state = 'playable'
desired_visibility = 'private'
filename = 'Ты не так плох.mp3'
regions = None
available_as_rbt = None
content_warning = None
@ -25,7 +29,8 @@ class TestTrack:
version = 'Radio Edit'
remember_position = False
def test_expected_values(self, track, artist, album, major, normalization):
def test_expected_values(self, track, artist, album, major, normalization,
track_without_nested_tracks, user, meta_data):
assert track.id == self.id
assert track.title == self.title
assert track.available == self.available
@ -42,8 +47,11 @@ class TestTrack:
assert track.duration_ms == self.duration_ms
assert track.storage_dir == self.storage_dir
assert track.file_size == self.file_size
assert track.substituted == track_without_nested_tracks
assert track.matched_track == track_without_nested_tracks
assert track.normalization == normalization
assert track.error == self.error
assert track.meta_data == meta_data
assert track.regions == self.regions
assert track.available_as_rbt == self.available_as_rbt
assert track.content_warning == self.content_warning
@ -52,6 +60,11 @@ class TestTrack:
assert track.available_full_without_permission == self.available_full_without_permission
assert track.version == self.version
assert track.remember_position == self.remember_position
assert track.can_publish == self.can_publish
assert track.state == self.state
assert track.desired_visibility == self.desired_visibility
assert track.filename == self.filename
assert track.user_info == user
def test_de_json_none(self, client):
assert Track.de_json({}, client) is None
@ -65,7 +78,8 @@ class TestTrack:
assert track.id == self.id
def test_de_json_all(self, client, artist, album, major, normalization):
def test_de_json_all(self, client, artist, album, major, normalization,
track_without_nested_tracks, user, meta_data):
json_dict = {'id_': self.id, 'title': self.title, 'available': self.available,
'available_for_premium_users': self.available_for_premium_users,
'artists': [artist.to_dict()], 'albums': [album.to_dict()],
@ -77,7 +91,10 @@ class TestTrack:
'content_warning': self.content_warning, 'explicit': self.explicit,
'preview_duration_ms': self.preview_duration_ms, 'version': self.version,
'available_full_without_permission': self.available_full_without_permission,
'remember_position': self.remember_position}
'remember_position': self.remember_position, 'substituted': track_without_nested_tracks.to_dict(),
'matched_track': track_without_nested_tracks.to_dict(), 'can_publish': self.can_publish,
'state': self.state, 'desired_visibility': self.desired_visibility, 'filename': self.filename,
'user_info': user.to_dict(), 'meta_data': meta_data.to_dict()}
track = Track.de_json(json_dict, client)
assert track.id == self.id
@ -96,8 +113,11 @@ class TestTrack:
assert track.duration_ms == self.duration_ms
assert track.storage_dir == self.storage_dir
assert track.file_size == self.file_size
assert track.substituted == track_without_nested_tracks
assert track.matched_track == track_without_nested_tracks
assert track.normalization == normalization
assert track.error == self.error
assert track.meta_data == meta_data
assert track.regions == self.regions
assert track.available_as_rbt == self.available_as_rbt
assert track.content_warning == self.content_warning
@ -106,6 +126,11 @@ class TestTrack:
assert track.available_full_without_permission == self.available_full_without_permission
assert track.version == self.version
assert track.remember_position == self.remember_position
assert track.can_publish == self.can_publish
assert track.state == self.state
assert track.desired_visibility == self.desired_visibility
assert track.filename == self.filename
assert track.user_info == user
def test_equality(self):
a = Track(self.id)

ファイルの表示

@ -5,6 +5,8 @@ class TestUser:
uid = 503646255
login = 'yamusic-daily'
name = 'yamusic-daily'
display_name = 'Ilya (Marshal)'
full_name = 'Илья'
sex = 'unknown'
verified = False
@ -12,6 +14,8 @@ class TestUser:
assert user.uid == self.uid
assert user.login == self.login
assert user.name == self.name
assert user.display_name == self.display_name
assert user.full_name == self.full_name
assert user.sex == self.sex
assert user.verified == self.verified
@ -19,31 +23,29 @@ class TestUser:
assert User.de_json({}, client) is None
def test_de_json_required(self, client):
json_dict = {'uid': self.uid, 'login': self.login, 'name': self.name, 'sex': self.sex,
'verified': self.verified}
json_dict = {'uid': self.uid, 'login': self.login}
user = User.de_json(json_dict, client)
assert user.uid == self.uid
assert user.login == self.login
assert user.name == self.name
assert user.sex == self.sex
assert user.verified == self.verified
def test_de_json_all(self, client):
json_dict = {'uid': self.uid, 'login': self.login, 'name': self.name, 'sex': self.sex,
'verified': self.verified}
'verified': self.verified, 'display_name': self.display_name, 'full_name': self.full_name}
user = User.de_json(json_dict, client)
assert user.uid == self.uid
assert user.login == self.login
assert user.name == self.name
assert user.display_name == self.display_name
assert user.full_name == self.full_name
assert user.sex == self.sex
assert user.verified == self.verified
def test_equality(self):
a = User(self.uid, self.login, self.name, self.sex, self.verified)
b = User(1, self.login, self.name, self.sex, self.verified)
c = User(self.uid, self.login, '', self.sex, self.verified)
a = User(self.uid, self.login)
b = User(1, self.login)
c = User(self.uid, self.login)
assert a != b
assert hash(a) != hash(b)

ファイルの表示

@ -47,6 +47,7 @@ from .shot.shot_event import ShotEvent
from .tracks_list import TracksList
from .track.major import Major
from .track.meta_data import MetaData
from .track.normalization import Normalization
from .track.track import Track
from .track.tracks_similar import SimilarTracks
@ -127,4 +128,4 @@ __all__ = ['YandexMusicObject', 'Client', 'Account', 'PassportPhone', 'Invocatio
'Sequence', 'StationTracksResult', 'BriefInfo', 'Description', 'PlaylistId', 'Vinyl', 'Supplement', 'Lyrics',
'VideoSupplement', 'ArtistTracks', 'Pager', 'ArtistAlbums', 'PlaylistAbsence', 'Shot', 'ShotEvent',
'ShotType', 'ShotData', 'SimilarTracks', 'UserSettings', 'RenewableRemainder', 'ChartInfo', 'ChartInfoMenu',
'ChartInfoMenuItem', 'Tag', 'TagResult', 'PlaylistRecommendations', 'LandingList']
'ChartInfoMenuItem', 'Tag', 'TagResult', 'PlaylistRecommendations', 'LandingList', 'MetaData']

ファイルの表示

@ -11,6 +11,7 @@ class Artist(YandexMusicObject):
Attributes:
id (:obj:`int`): Уникальный идентификатор.
error (:obj:`str`): Сообщение об ошибке с объяснением почему не вернуло исполнителя.
reason (:obj:`str`): Причина отсутствия исполнителя (сообщение об ошибке).
name (:obj:`str`): Название.
cover (:obj:`yandex_music.Cover` | :obj:`None`): Обложка.
@ -41,6 +42,7 @@ class Artist(YandexMusicObject):
Args:
id_ (:obj:`int`): Уникальный идентификатор.
error (:obj:`str`, optional): Сообщение об ошибке с объяснением почему не вернуло исполнителя.
reason (:obj:`str`, optional): Причина отсутствия исполнителя (сообщение об ошибке).
name (:obj:`str`, optional): Название.
cover (:obj:`yandex_music.Cover`, optional): Обложка.
@ -73,6 +75,7 @@ class Artist(YandexMusicObject):
def __init__(self,
id_: int,
error: Optional[str] = None,
reason: Optional[str] = None,
name: Optional[str] = None,
cover: Optional['Cover'] = None,
@ -103,6 +106,7 @@ class Artist(YandexMusicObject):
**kwargs) -> None:
self.id = id_
self.error = error
self.reason = reason
self.name = name
self.cover = cover

ファイルの表示

@ -49,7 +49,7 @@ class Client(YandexMusicObject):
uid аккаунта для отправки запроса. Так же в большинстве методов придётся передавать `uid` явно.
Attributes:
logger (:obj:`logging.Logger`): Объект логера.
logger (:obj:`logging.Logger`): Объект логгера.
token (:obj:`str`): Уникальный ключ для аутентификации.
base_url (:obj:`str`): Ссылка на API Yandex Music.
oauth_url (:obj:`str`): Ссылка на OAuth Yandex Music.
@ -67,7 +67,7 @@ class Client(YandexMusicObject):
"""
def __init__(self, token: str = None, fetch_account_status: bool = True, base_url: str = None,
oauth_url: str = None, request: Request = None, report_new_fields=False) -> None:
oauth_url: str = None, request: Request = None, report_new_fields=True) -> None:
self.logger = logging.getLogger(__name__)
self.token = token
@ -133,7 +133,7 @@ class Client(YandexMusicObject):
@classmethod
def from_token(cls, token: str, *args, **kwargs) -> 'Client':
"""Инициализция клиента по токену.
"""Инициализация клиента по токену.
Note:
Ничем не отличается от `Client(token)`. Так исторически сложилось.

ファイルの表示

@ -18,6 +18,8 @@ class Cover(YandexMusicObject):
is_custom (:obj:`bool`): Является ли обложка пользовательской.
custom (:obj:`bool`): Является ли обложка пользовательской.
prefix (:obj:`str`): Уникальный идентификатор.
copyright_name (:obj:`str`): Название владельца авторским правом.
copyright_cline (:obj:`str`): Владелец прав на музыку (автор текста и т.д.), а не её записи.
error (:obj:`str`): Сообщение об ошибке.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
@ -30,6 +32,8 @@ class Cover(YandexMusicObject):
is_custom (:obj:`bool`, optional): Является ли обложка пользовательской.
custom (:obj:`bool`, optional): Является ли обложка пользовательской.
prefix (:obj:`str`, optional): Уникальный идентификатор.
copyright_name (:obj:`str`, optional): Название владельца авторским правом.
copyright_cline (:obj:`str`, optional): Владелец прав на музыку (автор текста и т.д.), а не её записи.
error (:obj:`str`, optional): Сообщение об ошибке.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
@ -43,6 +47,8 @@ class Cover(YandexMusicObject):
version: Optional[str] = None,
custom: Optional[bool] = None,
is_custom: Optional[bool] = None,
copyright_name: Optional[str] = None,
copyright_cline: Optional[str] = None,
prefix: Optional[str] = None,
error: Optional[str] = None,
client: Optional['Client'] = None,
@ -55,6 +61,8 @@ class Cover(YandexMusicObject):
self.version = version
self.custom = custom
self.is_custom = is_custom
self.copyright_name = copyright_name
self.copyright_cline = copyright_cline
self.error = error
self.client = client

ファイルの表示

@ -19,6 +19,7 @@ class DownloadInfo(YandexMusicObject):
gain (:obj:`bool`): Усиление TODO.
preview (:obj:`bool`): Предварительный просмотр TODO.
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
direct (:obj:`bool`): Прямая ли ссылка.
direct_link (:obj:`str`): Прямая ссылка на загрузку. Доступна после получения ссылки.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
@ -28,6 +29,7 @@ class DownloadInfo(YandexMusicObject):
gain (:obj:`bool`): Усиление TODO.
preview (:obj:`bool`): Предварительный просмотр TODO.
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
direct (:obj:`bool`): Прямая ли ссылка.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
"""
@ -38,6 +40,7 @@ class DownloadInfo(YandexMusicObject):
gain: bool,
preview: bool,
download_info_url: str,
direct: bool,
client: Optional['Client'] = None,
**kwargs):
self.codec = codec
@ -45,6 +48,7 @@ class DownloadInfo(YandexMusicObject):
self.gain = gain
self.preview = preview
self.download_info_url = download_info_url
self.direct = direct
self.direct_link = None

ファイルの表示

@ -9,10 +9,19 @@ if TYPE_CHECKING:
class User(YandexMusicObject):
"""Класс, представляющий пользователя.
Note:
Когда данный класс используется в `MadeFor` и `Playlist, то доступны все поля кроме `display_name` и
`full_name`.
При наличии экземпляра класса в `user_info` у `Track` (у самозагруженных треков) доступны только `uid`,
'`login`, 'display_name` и `full_name`.
Attributes:
uid (:obj:`int`): Идентификатор пользователя.
login (:obj:`str`): Логин пользователя.
name (:obj:`str`): Имя пользователя.
display_name (:obj:`str`, optional): Отображаемое пользователя.
full_name (:obj:`str`, optional): Полное имя пользователя.
sex (:obj:`str`): Пол пользователя.
verified (:obj:`bool`): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
@ -20,9 +29,11 @@ class User(YandexMusicObject):
Args:
uid (:obj:`int`): Идентификатор пользователя.
login (:obj:`str`): Логин пользователя.
name (:obj:`str`): Имя пользователя.
sex (:obj:`str`): Пол пользователя.
verified (:obj:`bool`): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
name (:obj:`str`, optional): Имя пользователя.
display_name (:obj:`str`, optional): Отображаемое пользователя.
full_name (:obj:`str`, optional): Полное имя пользователя.
sex (:obj:`str`, optional): Пол пользователя.
verified (:obj:`bool`, optional): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
"""
@ -30,14 +41,19 @@ class User(YandexMusicObject):
def __init__(self,
uid: int,
login: str,
name: str,
sex: str,
verified: bool,
name: Optional[str] = None,
display_name: Optional[str] = None,
full_name: Optional[str] = None,
sex: Optional[str] = None,
verified: Optional[bool] = None,
client: Optional['Client'] = None,
**kwargs) -> None:
self.uid = uid
self.login = login
self.name = name
self.display_name = display_name
self.full_name = full_name
self.sex = sex
self.verified = verified

57
yandex_music/track/meta_data.py ノーマルファイル
ファイルの表示

@ -0,0 +1,57 @@
from typing import TYPE_CHECKING, Optional
from yandex_music import YandexMusicObject
if TYPE_CHECKING:
from yandex_music import Client
class MetaData(YandexMusicObject):
"""Класс, представляющий метаданные трека.
Attributes:
album (:obj:`str`): Название альбома.
volume (:obj:`int`): Диск (раздел).
year (:obj:`int`): Год выхода.
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
Args:
album (:obj:`str`): Название альбома.
volume (:obj:`int`): Диск (раздел).
year (:obj:`int`): Год выхода.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
**kwargs: Произвольные ключевые аргументы полученные от API.
"""
def __init__(self,
album: str,
volume: int,
year: int,
client: Optional['Client'] = None,
**kwargs) -> None:
self.album = album
self.volume = volume
self.year = year
self.client = client
self._id_attrs = (self.album, self.volume, self.year)
super().handle_unknown_kwargs(self, **kwargs)
@classmethod
def de_json(cls, data: dict, client: 'Client') -> Optional['MetaData']:
"""Десериализация объекта.
Args:
data (:obj:`dict`): Поля и значения десериализуемого объекта.
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
Returns:
:obj:`yandex_music.MetaData`: Метаданные трека
"""
if not data:
return None
data = super(MetaData, cls).de_json(data, client)
return cls(client=client, **data)

ファイルの表示

@ -4,7 +4,7 @@ from yandex_music import YandexMusicObject
from yandex_music.exceptions import InvalidBitrate
if TYPE_CHECKING:
from yandex_music import Client, Normalization, Major, Album, Artist, Supplement, DownloadInfo
from yandex_music import Client, Normalization, Major, Album, Artist, Supplement, DownloadInfo, User, MetaData
class Track(YandexMusicObject):
@ -15,6 +15,9 @@ class Track(YandexMusicObject):
Известные значения поля `type`: `music`.
Поля `can_publish`, `state`, `desired_visibility`, `filename`, `user_info` доступны только у треков что были
загружены пользователем.
Attributes:
id (:obj:`int` | :obj:`str`): Уникальный идентификатор.
title (:obj:`str`): Название.
@ -32,8 +35,16 @@ class Track(YandexMusicObject):
duration_ms (:obj:`int`): Длительность трека в миллисекундах.
storage_dir (:obj:`str`): В какой папке на сервере хранится файл TODO.
file_size (:obj:`int`): Размер файла. TODO добавить единицу измерения.
substituted (:obj:`yandex_music.Track`): Замещённый трек.
matched_track (:obj:`yandex_music.Track`): Соответствующий трек TODO.
normalization (:obj:`list` из :obj:`yandex_music.Normalization`): Значения для нормализации трека.
error (:obj:`str`): Сообщение об ошибке.
can_publish (:obj:`bool`): Может ли быть опубликован.
state (:obj:`str`): Состояние, например, playable.
desired_visibility (:obj:`str`): Видимость трека.
filename (:obj:`str`): Название файла.
user_info (:obj:`yandex_music.User`): Информация о пользователе, который загрузил трек.
meta_data (:obj:`yandex_music.MetaData`): Информация о метаданных трека.
regions (:obj:`list` из :obj:`str`): Регион TODO.
available_as_rbt (:obj:`bool`): TODO.
content_warning (:obj:`str`): Тип откровенного контента.
@ -62,8 +73,16 @@ class Track(YandexMusicObject):
duration_ms (:obj:`int`, optional): Длительность трека в миллисекундах.
storage_dir (:obj:`str`, optional): В какой папке на сервере хранится файл TODO.
file_size (:obj:`int`, optional): Размер файла. TODO добавить единицу измерения.
substituted (:obj:`yandex_music.Track`, optional): Замещённый трек.
matched_track (:obj:`yandex_music.Track`, optional): Соответствующий трек TODO.
normalization (:obj:`list` из :obj:`yandex_music.Normalization`, optional): Значения для нормализации трека.
error (:obj:`str`, optional): Сообщение об ошибке.
can_publish (:obj:`bool`, optional): Может ли быть опубликован.
state (:obj:`str`, optional): Состояние, например, playable.
desired_visibility (:obj:`str`, optional): Видимость трека.
filename (:obj:`str`, optional): Название файла.
user_info (:obj:`yandex_music.User`, optional): Информация о пользователе, который загрузил трек.
meta_data (:obj:`yandex_music.MetaData`, optional): Информация о метаданных трека.
regions (:obj:`list` из :obj:`str`, optional): Регион TODO.
available_as_rbt (:obj:`bool`, optional): TODO.
content_warning (:obj:`str`, optional): Тип откровенного контента.
@ -93,8 +112,16 @@ class Track(YandexMusicObject):
duration_ms: Optional[int] = None,
storage_dir: Optional[str] = None,
file_size: Optional[int] = None,
substituted: Optional['Track'] = None,
matched_track: Optional['Track'] = None,
normalization: Optional['Normalization'] = None,
error: Optional[str] = None,
can_publish: Optional[bool] = None,
state: Optional[str] = None,
desired_visibility: Optional[str] = None,
filename: Optional[str] = None,
user_info: Optional['User'] = None,
meta_data: Optional['MetaData'] = None,
regions: Optional[List[str]] = None,
available_as_rbt: Optional[bool] = None,
content_warning: Optional[str] = None,
@ -122,8 +149,16 @@ class Track(YandexMusicObject):
self.duration_ms = duration_ms
self.storage_dir = storage_dir
self.file_size = file_size
self.substituted = substituted
self.matched_track = matched_track
self.normalization = normalization
self.error = error
self.can_publish = can_publish
self.state = state
self.desired_visibility = desired_visibility
self.filename = filename
self.user_info = user_info
self.meta_data = meta_data
self.regions = regions
self.available_as_rbt = available_as_rbt
self.content_warning = content_warning
@ -238,11 +273,15 @@ class Track(YandexMusicObject):
return None
data = super(Track, cls).de_json(data, client)
from yandex_music import Normalization, Major, Album, Artist
from yandex_music import Normalization, Major, Album, Artist, User, MetaData
data['albums'] = Album.de_list(data.get('albums'), client)
data['artists'] = Artist.de_list(data.get('artists'), client)
data['normalization'] = Normalization.de_json(data.get('normalization'), client)
data['major'] = Major.de_json(data.get('major'), client)
data['substituted'] = Track.de_json(data.get('substituted'), client)
data['matched_track'] = Track.de_json(data.get('matched_track'), client)
data['user_info'] = User.de_json(data.get('user_info'), client)
data['meta_data'] = MetaData.de_json(data.get('meta_data'), client)
return cls(client=client, **data)
@ -260,11 +299,7 @@ class Track(YandexMusicObject):
if not data:
return []
tracks = list()
for track in data:
tracks.append(cls.de_json(track, client))
return tracks
return [cls.de_json(track, client) for track in data]
# camelCase псевдонимы