Добавлен новый класс 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
このコミットが含まれているのは:
コミット
0240eb6cb9
|
@ -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.normalization
|
||||||
yandex_music.track.major
|
yandex_music.track.major
|
||||||
yandex_music.track.track
|
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_shot import TestShot
|
||||||
from .test_renewable_remainder import TestRenewableRemainder
|
from .test_renewable_remainder import TestRenewableRemainder
|
||||||
from .test_tag import TestTag
|
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, \
|
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, ChartInfoMenuItem, ChartInfoMenu, ChartInfo, Tag
|
RenewableRemainder, ChartInfoMenuItem, ChartInfoMenu, ChartInfo, Tag, MetaData
|
||||||
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,20 +17,20 @@ 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, TestChartInfoMenuItem, TestChartInfo, TestTag
|
TestRenewableRemainder, TestChartInfoMenuItem, TestChartInfo, TestTag, TestMetaData
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def artist_factory(cover, counts, ratings, link, description):
|
def artist_factory(cover, counts, ratings, link, description):
|
||||||
class ArtistFactory:
|
class ArtistFactory:
|
||||||
def get(self, popular_tracks):
|
def get(self, popular_tracks):
|
||||||
return Artist(TestArtist.id, TestArtist.reason, TestArtist.name, cover, TestArtist.various,
|
return Artist(TestArtist.id, TestArtist.error, TestArtist.reason, TestArtist.name, cover,
|
||||||
TestArtist.composer, TestArtist.genres, TestArtist.og_image, TestArtist.op_image,
|
TestArtist.various, TestArtist.composer, TestArtist.genres, TestArtist.og_image,
|
||||||
TestArtist.no_pictures_from_search, counts, TestArtist.available, ratings, [link],
|
TestArtist.op_image, TestArtist.no_pictures_from_search, counts, TestArtist.available,
|
||||||
TestArtist.tickets_available, TestArtist.likes_count, popular_tracks, TestArtist.regions,
|
ratings, [link], TestArtist.tickets_available, TestArtist.likes_count, popular_tracks,
|
||||||
TestArtist.decomposed, TestArtist.full_names, description, TestArtist.countries,
|
TestArtist.regions, TestArtist.decomposed, TestArtist.full_names, description,
|
||||||
TestArtist.en_wikipedia_link, TestArtist.db_aliases, TestArtist.aliases, TestArtist.init_date,
|
TestArtist.countries, TestArtist.en_wikipedia_link, TestArtist.db_aliases, TestArtist.aliases,
|
||||||
TestArtist.end_date)
|
TestArtist.init_date, TestArtist.end_date)
|
||||||
|
|
||||||
return ArtistFactory()
|
return ArtistFactory()
|
||||||
|
|
||||||
|
@ -46,14 +46,16 @@ def artist_without_tracks(artist_factory):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def track_factory(major, normalization):
|
def track_factory(major, normalization, user, meta_data):
|
||||||
class TrackFactory:
|
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,
|
return Track(TestTrack.id, TestTrack.title, TestTrack.available, artists, albums,
|
||||||
TestTrack.available_for_premium_users, TestTrack.lyrics_available, TestTrack.best,
|
TestTrack.available_for_premium_users, TestTrack.lyrics_available, TestTrack.best,
|
||||||
TestTrack.real_id, TestTrack.og_image, TestTrack.type, TestTrack.cover_uri, major,
|
TestTrack.real_id, TestTrack.og_image, TestTrack.type, TestTrack.cover_uri, major,
|
||||||
TestTrack.duration_ms, TestTrack.storage_dir, TestTrack.file_size, normalization,
|
TestTrack.duration_ms, TestTrack.storage_dir, TestTrack.file_size, track_without_nested_tracks,
|
||||||
TestTrack.error, TestTrack.regions, TestTrack.available_as_rbt, TestTrack.content_warning,
|
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.explicit, TestTrack.preview_duration_ms, TestTrack.available_full_without_permission,
|
||||||
TestTrack.version, TestTrack.remember_position)
|
TestTrack.version, TestTrack.remember_position)
|
||||||
|
|
||||||
|
@ -61,8 +63,8 @@ def track_factory(major, normalization):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def track(track_factory, artist, album):
|
def track(track_factory, artist, album, track_without_nested_tracks):
|
||||||
return track_factory.get([artist], [album])
|
return track_factory.get([artist], [album], track_without_nested_tracks)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
|
@ -80,6 +82,11 @@ def track_without_artists_and_albums(track_factory):
|
||||||
return track_factory.get([], [])
|
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')
|
@pytest.fixture(scope='session')
|
||||||
def album_factory(label, track_position):
|
def album_factory(label, track_position):
|
||||||
class AlbumFactory:
|
class AlbumFactory:
|
||||||
|
@ -207,7 +214,13 @@ def icon():
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def cover():
|
def cover():
|
||||||
return Cover(TestCover.type, TestCover.uri, TestCover.items_uri, TestCover.dir, TestCover.version,
|
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')
|
@pytest.fixture(scope='session')
|
||||||
|
@ -361,7 +374,8 @@ def renewable_remainder():
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def user():
|
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')
|
@pytest.fixture(scope='session')
|
||||||
|
|
|
@ -3,6 +3,7 @@ from yandex_music import Artist
|
||||||
|
|
||||||
class TestArtist:
|
class TestArtist:
|
||||||
id = 10987
|
id = 10987
|
||||||
|
error = 'not-found'
|
||||||
reason = 'not-found'
|
reason = 'not-found'
|
||||||
name = 'Elvis Presley'
|
name = 'Elvis Presley'
|
||||||
various = False
|
various = False
|
||||||
|
@ -26,6 +27,7 @@ class TestArtist:
|
||||||
|
|
||||||
def test_expected_values(self, artist, cover, counts, ratings, link, track_without_artists_and_albums, description):
|
def test_expected_values(self, artist, cover, counts, ratings, link, track_without_artists_and_albums, description):
|
||||||
assert artist.id == self.id
|
assert artist.id == self.id
|
||||||
|
assert artist.error == self.error
|
||||||
assert artist.reason == self.reason
|
assert artist.reason == self.reason
|
||||||
assert artist.name == self.name
|
assert artist.name == self.name
|
||||||
assert artist.various == self.various
|
assert artist.various == self.various
|
||||||
|
@ -66,7 +68,7 @@ class TestArtist:
|
||||||
assert artist.id == self.id
|
assert artist.id == self.id
|
||||||
|
|
||||||
def test_de_json_all(self, client, cover, counts, ratings, link, track_without_artists, description):
|
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(),
|
'various': self.various, 'composer': self.composer, 'cover': cover.to_dict(),
|
||||||
'genres': self.genres, 'op_image': self.op_image, 'og_image': self.og_image,
|
'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(),
|
'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)
|
artist = Artist.de_json(json_dict, client)
|
||||||
|
|
||||||
assert artist.id == self.id
|
assert artist.id == self.id
|
||||||
|
assert artist.error == self.error
|
||||||
assert artist.reason == self.reason
|
assert artist.reason == self.reason
|
||||||
assert artist.name == self.name
|
assert artist.name == self.name
|
||||||
assert artist.various == self.various
|
assert artist.various == self.various
|
||||||
|
|
|
@ -10,6 +10,8 @@ class TestCover:
|
||||||
custom = True
|
custom = True
|
||||||
is_custom = True
|
is_custom = True
|
||||||
prefix = None
|
prefix = None
|
||||||
|
copyright_name = 'ТАСС'
|
||||||
|
copyright_cline = 'imago stock&people'
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
def test_expected_values(self, cover):
|
def test_expected_values(self, cover):
|
||||||
|
@ -20,6 +22,8 @@ class TestCover:
|
||||||
assert cover.version == self.version
|
assert cover.version == self.version
|
||||||
assert cover.custom == self.custom
|
assert cover.custom == self.custom
|
||||||
assert cover.is_custom == self.is_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.prefix == self.prefix
|
||||||
assert cover.error == self.error
|
assert cover.error == self.error
|
||||||
|
|
||||||
|
@ -36,7 +40,8 @@ class TestCover:
|
||||||
def test_de_json_all(self, client):
|
def test_de_json_all(self, client):
|
||||||
json_dict = {'type_': self.type, 'uri': self.uri, 'items_uri': self.items_uri, 'dir_': self.dir,
|
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,
|
'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)
|
cover = Cover.de_json(json_dict, client)
|
||||||
|
|
||||||
assert cover.type == self.type
|
assert cover.type == self.type
|
||||||
|
@ -46,6 +51,8 @@ class TestCover:
|
||||||
assert cover.version == self.version
|
assert cover.version == self.version
|
||||||
assert cover.custom == self.custom
|
assert cover.custom == self.custom
|
||||||
assert cover.is_custom == self.is_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.prefix == self.prefix
|
||||||
assert cover.error == self.error
|
assert cover.error == self.error
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from yandex_music import DownloadInfo
|
||||||
@pytest.fixture(scope='class')
|
@pytest.fixture(scope='class')
|
||||||
def download_info():
|
def download_info():
|
||||||
return DownloadInfo(TestDownloadInfo.codec, TestDownloadInfo.bitrate_in_kbps, TestDownloadInfo.gain,
|
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:
|
class TestDownloadInfo:
|
||||||
|
@ -16,6 +16,7 @@ class TestDownloadInfo:
|
||||||
preview = False
|
preview = False
|
||||||
download_info_url = 'https://storage.mds.yandex.net/file-download-info/136146_d158926e.14534319.6.10994777/320' \
|
download_info_url = 'https://storage.mds.yandex.net/file-download-info/136146_d158926e.14534319.6.10994777/320' \
|
||||||
'?sign=8caf5ea72c946d4753f15298e4033b961c7acb1bb4db48eb5e6b59621e387d64&ts=5dc4a6f2 '
|
'?sign=8caf5ea72c946d4753f15298e4033b961c7acb1bb4db48eb5e6b59621e387d64&ts=5dc4a6f2 '
|
||||||
|
direct = False
|
||||||
|
|
||||||
def test_expected_values(self, download_info):
|
def test_expected_values(self, download_info):
|
||||||
assert download_info.codec == self.codec
|
assert download_info.codec == self.codec
|
||||||
|
@ -23,6 +24,7 @@ class TestDownloadInfo:
|
||||||
assert download_info.gain == self.gain
|
assert download_info.gain == self.gain
|
||||||
assert download_info.preview == self.preview
|
assert download_info.preview == self.preview
|
||||||
assert download_info.download_info_url == self.download_info_url
|
assert download_info.download_info_url == self.download_info_url
|
||||||
|
assert download_info.direct == self.direct
|
||||||
|
|
||||||
def test_de_json_none(self, client):
|
def test_de_json_none(self, client):
|
||||||
assert DownloadInfo.de_json({}, client) is None
|
assert DownloadInfo.de_json({}, client) is None
|
||||||
|
@ -32,7 +34,7 @@ class TestDownloadInfo:
|
||||||
|
|
||||||
def test_de_json_required(self, client):
|
def test_de_json_required(self, client):
|
||||||
json_dict = {'codec': self.codec, 'bitrate_in_kbps': self.bitrate_in_kbps, 'gain': self.gain,
|
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)
|
download_info = DownloadInfo.de_json(json_dict, client)
|
||||||
|
|
||||||
assert download_info.codec == self.codec
|
assert download_info.codec == self.codec
|
||||||
|
@ -40,10 +42,11 @@ class TestDownloadInfo:
|
||||||
assert download_info.gain == self.gain
|
assert download_info.gain == self.gain
|
||||||
assert download_info.preview == self.preview
|
assert download_info.preview == self.preview
|
||||||
assert download_info.download_info_url == self.download_info_url
|
assert download_info.download_info_url == self.download_info_url
|
||||||
|
assert download_info.direct == self.direct
|
||||||
|
|
||||||
def test_de_json_all(self, client):
|
def test_de_json_all(self, client):
|
||||||
json_dict = {'codec': self.codec, 'bitrate_in_kbps': self.bitrate_in_kbps, 'gain': self.gain,
|
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)
|
download_info = DownloadInfo.de_json(json_dict, client)
|
||||||
|
|
||||||
assert download_info.codec == self.codec
|
assert download_info.codec == self.codec
|
||||||
|
@ -51,11 +54,12 @@ class TestDownloadInfo:
|
||||||
assert download_info.gain == self.gain
|
assert download_info.gain == self.gain
|
||||||
assert download_info.preview == self.preview
|
assert download_info.preview == self.preview
|
||||||
assert download_info.download_info_url == self.download_info_url
|
assert download_info.download_info_url == self.download_info_url
|
||||||
|
assert download_info.direct == self.direct
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = 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)
|
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)
|
c = DownloadInfo(self.codec, self.bitrate_in_kbps, self.gain, self.preview, self.download_info_url, self.direct)
|
||||||
|
|
||||||
assert a != b
|
assert a != b
|
||||||
assert hash(a) != hash(b)
|
assert hash(a) != hash(b)
|
||||||
|
|
|
@ -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'
|
storage_dir = '51327_109b74ca.36526310.1.609676'
|
||||||
file_size = 6036792
|
file_size = 6036792
|
||||||
error = None
|
error = None
|
||||||
|
can_publish = False
|
||||||
|
state = 'playable'
|
||||||
|
desired_visibility = 'private'
|
||||||
|
filename = 'Ты не так плох.mp3'
|
||||||
regions = None
|
regions = None
|
||||||
available_as_rbt = None
|
available_as_rbt = None
|
||||||
content_warning = None
|
content_warning = None
|
||||||
|
@ -25,7 +29,8 @@ class TestTrack:
|
||||||
version = 'Radio Edit'
|
version = 'Radio Edit'
|
||||||
remember_position = False
|
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.id == self.id
|
||||||
assert track.title == self.title
|
assert track.title == self.title
|
||||||
assert track.available == self.available
|
assert track.available == self.available
|
||||||
|
@ -42,8 +47,11 @@ class TestTrack:
|
||||||
assert track.duration_ms == self.duration_ms
|
assert track.duration_ms == self.duration_ms
|
||||||
assert track.storage_dir == self.storage_dir
|
assert track.storage_dir == self.storage_dir
|
||||||
assert track.file_size == self.file_size
|
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.normalization == normalization
|
||||||
assert track.error == self.error
|
assert track.error == self.error
|
||||||
|
assert track.meta_data == meta_data
|
||||||
assert track.regions == self.regions
|
assert track.regions == self.regions
|
||||||
assert track.available_as_rbt == self.available_as_rbt
|
assert track.available_as_rbt == self.available_as_rbt
|
||||||
assert track.content_warning == self.content_warning
|
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.available_full_without_permission == self.available_full_without_permission
|
||||||
assert track.version == self.version
|
assert track.version == self.version
|
||||||
assert track.remember_position == self.remember_position
|
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):
|
def test_de_json_none(self, client):
|
||||||
assert Track.de_json({}, client) is None
|
assert Track.de_json({}, client) is None
|
||||||
|
@ -65,7 +78,8 @@ class TestTrack:
|
||||||
|
|
||||||
assert track.id == self.id
|
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,
|
json_dict = {'id_': self.id, 'title': self.title, 'available': self.available,
|
||||||
'available_for_premium_users': self.available_for_premium_users,
|
'available_for_premium_users': self.available_for_premium_users,
|
||||||
'artists': [artist.to_dict()], 'albums': [album.to_dict()],
|
'artists': [artist.to_dict()], 'albums': [album.to_dict()],
|
||||||
|
@ -77,7 +91,10 @@ class TestTrack:
|
||||||
'content_warning': self.content_warning, 'explicit': self.explicit,
|
'content_warning': self.content_warning, 'explicit': self.explicit,
|
||||||
'preview_duration_ms': self.preview_duration_ms, 'version': self.version,
|
'preview_duration_ms': self.preview_duration_ms, 'version': self.version,
|
||||||
'available_full_without_permission': self.available_full_without_permission,
|
'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)
|
track = Track.de_json(json_dict, client)
|
||||||
|
|
||||||
assert track.id == self.id
|
assert track.id == self.id
|
||||||
|
@ -96,8 +113,11 @@ class TestTrack:
|
||||||
assert track.duration_ms == self.duration_ms
|
assert track.duration_ms == self.duration_ms
|
||||||
assert track.storage_dir == self.storage_dir
|
assert track.storage_dir == self.storage_dir
|
||||||
assert track.file_size == self.file_size
|
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.normalization == normalization
|
||||||
assert track.error == self.error
|
assert track.error == self.error
|
||||||
|
assert track.meta_data == meta_data
|
||||||
assert track.regions == self.regions
|
assert track.regions == self.regions
|
||||||
assert track.available_as_rbt == self.available_as_rbt
|
assert track.available_as_rbt == self.available_as_rbt
|
||||||
assert track.content_warning == self.content_warning
|
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.available_full_without_permission == self.available_full_without_permission
|
||||||
assert track.version == self.version
|
assert track.version == self.version
|
||||||
assert track.remember_position == self.remember_position
|
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):
|
def test_equality(self):
|
||||||
a = Track(self.id)
|
a = Track(self.id)
|
||||||
|
|
|
@ -5,6 +5,8 @@ class TestUser:
|
||||||
uid = 503646255
|
uid = 503646255
|
||||||
login = 'yamusic-daily'
|
login = 'yamusic-daily'
|
||||||
name = 'yamusic-daily'
|
name = 'yamusic-daily'
|
||||||
|
display_name = 'Ilya (Marshal)'
|
||||||
|
full_name = 'Илья'
|
||||||
sex = 'unknown'
|
sex = 'unknown'
|
||||||
verified = False
|
verified = False
|
||||||
|
|
||||||
|
@ -12,6 +14,8 @@ class TestUser:
|
||||||
assert user.uid == self.uid
|
assert user.uid == self.uid
|
||||||
assert user.login == self.login
|
assert user.login == self.login
|
||||||
assert user.name == self.name
|
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.sex == self.sex
|
||||||
assert user.verified == self.verified
|
assert user.verified == self.verified
|
||||||
|
|
||||||
|
@ -19,31 +23,29 @@ class TestUser:
|
||||||
assert User.de_json({}, client) is None
|
assert User.de_json({}, client) is None
|
||||||
|
|
||||||
def test_de_json_required(self, client):
|
def test_de_json_required(self, client):
|
||||||
json_dict = {'uid': self.uid, 'login': self.login, 'name': self.name, 'sex': self.sex,
|
json_dict = {'uid': self.uid, 'login': self.login}
|
||||||
'verified': self.verified}
|
|
||||||
user = User.de_json(json_dict, client)
|
user = User.de_json(json_dict, client)
|
||||||
|
|
||||||
assert user.uid == self.uid
|
assert user.uid == self.uid
|
||||||
assert user.login == self.login
|
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):
|
def test_de_json_all(self, client):
|
||||||
json_dict = {'uid': self.uid, 'login': self.login, 'name': self.name, 'sex': self.sex,
|
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)
|
user = User.de_json(json_dict, client)
|
||||||
|
|
||||||
assert user.uid == self.uid
|
assert user.uid == self.uid
|
||||||
assert user.login == self.login
|
assert user.login == self.login
|
||||||
assert user.name == self.name
|
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.sex == self.sex
|
||||||
assert user.verified == self.verified
|
assert user.verified == self.verified
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = User(self.uid, self.login, self.name, self.sex, self.verified)
|
a = User(self.uid, self.login)
|
||||||
b = User(1, self.login, self.name, self.sex, self.verified)
|
b = User(1, self.login)
|
||||||
c = User(self.uid, self.login, '', self.sex, self.verified)
|
c = User(self.uid, self.login)
|
||||||
|
|
||||||
assert a != b
|
assert a != b
|
||||||
assert hash(a) != hash(b)
|
assert hash(a) != hash(b)
|
||||||
|
|
|
@ -47,6 +47,7 @@ from .shot.shot_event import ShotEvent
|
||||||
|
|
||||||
from .tracks_list import TracksList
|
from .tracks_list import TracksList
|
||||||
from .track.major import Major
|
from .track.major import Major
|
||||||
|
from .track.meta_data import MetaData
|
||||||
from .track.normalization import Normalization
|
from .track.normalization import Normalization
|
||||||
from .track.track import Track
|
from .track.track import Track
|
||||||
from .track.tracks_similar import SimilarTracks
|
from .track.tracks_similar import SimilarTracks
|
||||||
|
@ -127,4 +128,4 @@ __all__ = ['YandexMusicObject', 'Client', 'Account', 'PassportPhone', 'Invocatio
|
||||||
'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', 'ChartInfo', 'ChartInfoMenu',
|
'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:
|
Attributes:
|
||||||
id (:obj:`int`): Уникальный идентификатор.
|
id (:obj:`int`): Уникальный идентификатор.
|
||||||
|
error (:obj:`str`): Сообщение об ошибке с объяснением почему не вернуло исполнителя.
|
||||||
reason (:obj:`str`): Причина отсутствия исполнителя (сообщение об ошибке).
|
reason (:obj:`str`): Причина отсутствия исполнителя (сообщение об ошибке).
|
||||||
name (:obj:`str`): Название.
|
name (:obj:`str`): Название.
|
||||||
cover (:obj:`yandex_music.Cover` | :obj:`None`): Обложка.
|
cover (:obj:`yandex_music.Cover` | :obj:`None`): Обложка.
|
||||||
|
@ -41,6 +42,7 @@ class Artist(YandexMusicObject):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id_ (:obj:`int`): Уникальный идентификатор.
|
id_ (:obj:`int`): Уникальный идентификатор.
|
||||||
|
error (:obj:`str`, optional): Сообщение об ошибке с объяснением почему не вернуло исполнителя.
|
||||||
reason (:obj:`str`, optional): Причина отсутствия исполнителя (сообщение об ошибке).
|
reason (:obj:`str`, optional): Причина отсутствия исполнителя (сообщение об ошибке).
|
||||||
name (:obj:`str`, optional): Название.
|
name (:obj:`str`, optional): Название.
|
||||||
cover (:obj:`yandex_music.Cover`, optional): Обложка.
|
cover (:obj:`yandex_music.Cover`, optional): Обложка.
|
||||||
|
@ -73,6 +75,7 @@ class Artist(YandexMusicObject):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
id_: int,
|
id_: int,
|
||||||
|
error: Optional[str] = None,
|
||||||
reason: Optional[str] = None,
|
reason: Optional[str] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
cover: Optional['Cover'] = None,
|
cover: Optional['Cover'] = None,
|
||||||
|
@ -103,6 +106,7 @@ class Artist(YandexMusicObject):
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
self.id = id_
|
self.id = id_
|
||||||
|
|
||||||
|
self.error = error
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
self.name = name
|
self.name = name
|
||||||
self.cover = cover
|
self.cover = cover
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Client(YandexMusicObject):
|
||||||
uid аккаунта для отправки запроса. Так же в большинстве методов придётся передавать `uid` явно.
|
uid аккаунта для отправки запроса. Так же в большинстве методов придётся передавать `uid` явно.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
logger (:obj:`logging.Logger`): Объект логера.
|
logger (:obj:`logging.Logger`): Объект логгера.
|
||||||
token (:obj:`str`): Уникальный ключ для аутентификации.
|
token (:obj:`str`): Уникальный ключ для аутентификации.
|
||||||
base_url (:obj:`str`): Ссылка на API Yandex Music.
|
base_url (:obj:`str`): Ссылка на API Yandex Music.
|
||||||
oauth_url (:obj:`str`): Ссылка на OAuth 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,
|
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.logger = logging.getLogger(__name__)
|
||||||
self.token = token
|
self.token = token
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ class Client(YandexMusicObject):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_token(cls, token: str, *args, **kwargs) -> 'Client':
|
def from_token(cls, token: str, *args, **kwargs) -> 'Client':
|
||||||
"""Инициализция клиента по токену.
|
"""Инициализация клиента по токену.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Ничем не отличается от `Client(token)`. Так исторически сложилось.
|
Ничем не отличается от `Client(token)`. Так исторически сложилось.
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Cover(YandexMusicObject):
|
||||||
is_custom (:obj:`bool`): Является ли обложка пользовательской.
|
is_custom (:obj:`bool`): Является ли обложка пользовательской.
|
||||||
custom (:obj:`bool`): Является ли обложка пользовательской.
|
custom (:obj:`bool`): Является ли обложка пользовательской.
|
||||||
prefix (:obj:`str`): Уникальный идентификатор.
|
prefix (:obj:`str`): Уникальный идентификатор.
|
||||||
|
copyright_name (:obj:`str`): Название владельца авторским правом.
|
||||||
|
copyright_cline (:obj:`str`): Владелец прав на музыку (автор текста и т.д.), а не её записи.
|
||||||
error (:obj:`str`): Сообщение об ошибке.
|
error (:obj:`str`): Сообщение об ошибке.
|
||||||
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
||||||
|
|
||||||
|
@ -30,6 +32,8 @@ class Cover(YandexMusicObject):
|
||||||
is_custom (:obj:`bool`, optional): Является ли обложка пользовательской.
|
is_custom (:obj:`bool`, optional): Является ли обложка пользовательской.
|
||||||
custom (:obj:`bool`, optional): Является ли обложка пользовательской.
|
custom (:obj:`bool`, optional): Является ли обложка пользовательской.
|
||||||
prefix (:obj:`str`, optional): Уникальный идентификатор.
|
prefix (:obj:`str`, optional): Уникальный идентификатор.
|
||||||
|
copyright_name (:obj:`str`, optional): Название владельца авторским правом.
|
||||||
|
copyright_cline (:obj:`str`, optional): Владелец прав на музыку (автор текста и т.д.), а не её записи.
|
||||||
error (:obj:`str`, optional): Сообщение об ошибке.
|
error (:obj:`str`, optional): Сообщение об ошибке.
|
||||||
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
||||||
**kwargs: Произвольные ключевые аргументы полученные от API.
|
**kwargs: Произвольные ключевые аргументы полученные от API.
|
||||||
|
@ -43,6 +47,8 @@ class Cover(YandexMusicObject):
|
||||||
version: Optional[str] = None,
|
version: Optional[str] = None,
|
||||||
custom: Optional[bool] = None,
|
custom: Optional[bool] = None,
|
||||||
is_custom: Optional[bool] = None,
|
is_custom: Optional[bool] = None,
|
||||||
|
copyright_name: Optional[str] = None,
|
||||||
|
copyright_cline: Optional[str] = None,
|
||||||
prefix: Optional[str] = None,
|
prefix: Optional[str] = None,
|
||||||
error: Optional[str] = None,
|
error: Optional[str] = None,
|
||||||
client: Optional['Client'] = None,
|
client: Optional['Client'] = None,
|
||||||
|
@ -55,6 +61,8 @@ class Cover(YandexMusicObject):
|
||||||
self.version = version
|
self.version = version
|
||||||
self.custom = custom
|
self.custom = custom
|
||||||
self.is_custom = is_custom
|
self.is_custom = is_custom
|
||||||
|
self.copyright_name = copyright_name
|
||||||
|
self.copyright_cline = copyright_cline
|
||||||
self.error = error
|
self.error = error
|
||||||
|
|
||||||
self.client = client
|
self.client = client
|
||||||
|
|
|
@ -19,6 +19,7 @@ class DownloadInfo(YandexMusicObject):
|
||||||
gain (:obj:`bool`): Усиление TODO.
|
gain (:obj:`bool`): Усиление TODO.
|
||||||
preview (:obj:`bool`): Предварительный просмотр TODO.
|
preview (:obj:`bool`): Предварительный просмотр TODO.
|
||||||
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
|
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
|
||||||
|
direct (:obj:`bool`): Прямая ли ссылка.
|
||||||
direct_link (:obj:`str`): Прямая ссылка на загрузку. Доступна после получения ссылки.
|
direct_link (:obj:`str`): Прямая ссылка на загрузку. Доступна после получения ссылки.
|
||||||
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ class DownloadInfo(YandexMusicObject):
|
||||||
gain (:obj:`bool`): Усиление TODO.
|
gain (:obj:`bool`): Усиление TODO.
|
||||||
preview (:obj:`bool`): Предварительный просмотр TODO.
|
preview (:obj:`bool`): Предварительный просмотр TODO.
|
||||||
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
|
download_info_url (:obj:`str`): Ссылка на XML документ содержащий данные для загрузки трека.
|
||||||
|
direct (:obj:`bool`): Прямая ли ссылка.
|
||||||
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
||||||
**kwargs: Произвольные ключевые аргументы полученные от API.
|
**kwargs: Произвольные ключевые аргументы полученные от API.
|
||||||
"""
|
"""
|
||||||
|
@ -38,6 +40,7 @@ class DownloadInfo(YandexMusicObject):
|
||||||
gain: bool,
|
gain: bool,
|
||||||
preview: bool,
|
preview: bool,
|
||||||
download_info_url: str,
|
download_info_url: str,
|
||||||
|
direct: bool,
|
||||||
client: Optional['Client'] = None,
|
client: Optional['Client'] = None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self.codec = codec
|
self.codec = codec
|
||||||
|
@ -45,6 +48,7 @@ class DownloadInfo(YandexMusicObject):
|
||||||
self.gain = gain
|
self.gain = gain
|
||||||
self.preview = preview
|
self.preview = preview
|
||||||
self.download_info_url = download_info_url
|
self.download_info_url = download_info_url
|
||||||
|
self.direct = direct
|
||||||
|
|
||||||
self.direct_link = None
|
self.direct_link = None
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,19 @@ if TYPE_CHECKING:
|
||||||
class User(YandexMusicObject):
|
class User(YandexMusicObject):
|
||||||
"""Класс, представляющий пользователя.
|
"""Класс, представляющий пользователя.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Когда данный класс используется в `MadeFor` и `Playlist, то доступны все поля кроме `display_name` и
|
||||||
|
`full_name`.
|
||||||
|
|
||||||
|
При наличии экземпляра класса в `user_info` у `Track` (у самозагруженных треков) доступны только `uid`,
|
||||||
|
'`login`, 'display_name` и `full_name`.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
uid (:obj:`int`): Идентификатор пользователя.
|
uid (:obj:`int`): Идентификатор пользователя.
|
||||||
login (:obj:`str`): Логин пользователя.
|
login (:obj:`str`): Логин пользователя.
|
||||||
name (:obj:`str`): Имя пользователя.
|
name (:obj:`str`): Имя пользователя.
|
||||||
|
display_name (:obj:`str`, optional): Отображаемое пользователя.
|
||||||
|
full_name (:obj:`str`, optional): Полное имя пользователя.
|
||||||
sex (:obj:`str`): Пол пользователя.
|
sex (:obj:`str`): Пол пользователя.
|
||||||
verified (:obj:`bool`): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
|
verified (:obj:`bool`): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
|
||||||
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`): Клиент Yandex Music.
|
||||||
|
@ -20,9 +29,11 @@ class User(YandexMusicObject):
|
||||||
Args:
|
Args:
|
||||||
uid (:obj:`int`): Идентификатор пользователя.
|
uid (:obj:`int`): Идентификатор пользователя.
|
||||||
login (:obj:`str`): Логин пользователя.
|
login (:obj:`str`): Логин пользователя.
|
||||||
name (:obj:`str`): Имя пользователя.
|
name (:obj:`str`, optional): Имя пользователя.
|
||||||
sex (:obj:`str`): Пол пользователя.
|
display_name (:obj:`str`, optional): Отображаемое пользователя.
|
||||||
verified (:obj:`bool`): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
|
full_name (:obj:`str`, optional): Полное имя пользователя.
|
||||||
|
sex (:obj:`str`, optional): Пол пользователя.
|
||||||
|
verified (:obj:`bool`, optional): Участвует ли пользователь в генерации плейлистов дня и т.д., и т.п.
|
||||||
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music.
|
||||||
**kwargs: Произвольные ключевые аргументы полученные от API.
|
**kwargs: Произвольные ключевые аргументы полученные от API.
|
||||||
"""
|
"""
|
||||||
|
@ -30,14 +41,19 @@ class User(YandexMusicObject):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
uid: int,
|
uid: int,
|
||||||
login: str,
|
login: str,
|
||||||
name: str,
|
name: Optional[str] = None,
|
||||||
sex: str,
|
display_name: Optional[str] = None,
|
||||||
verified: bool,
|
full_name: Optional[str] = None,
|
||||||
|
sex: Optional[str] = None,
|
||||||
|
verified: Optional[bool] = None,
|
||||||
client: Optional['Client'] = None,
|
client: Optional['Client'] = None,
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
self.uid = uid
|
self.uid = uid
|
||||||
self.login = login
|
self.login = login
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.display_name = display_name
|
||||||
|
self.full_name = full_name
|
||||||
self.sex = sex
|
self.sex = sex
|
||||||
self.verified = verified
|
self.verified = verified
|
||||||
|
|
||||||
|
|
|
@ -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
|
from yandex_music.exceptions import InvalidBitrate
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
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):
|
class Track(YandexMusicObject):
|
||||||
|
@ -15,6 +15,9 @@ class Track(YandexMusicObject):
|
||||||
|
|
||||||
Известные значения поля `type`: `music`.
|
Известные значения поля `type`: `music`.
|
||||||
|
|
||||||
|
Поля `can_publish`, `state`, `desired_visibility`, `filename`, `user_info` доступны только у треков что были
|
||||||
|
загружены пользователем.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
id (:obj:`int` | :obj:`str`): Уникальный идентификатор.
|
id (:obj:`int` | :obj:`str`): Уникальный идентификатор.
|
||||||
title (:obj:`str`): Название.
|
title (:obj:`str`): Название.
|
||||||
|
@ -32,8 +35,16 @@ class Track(YandexMusicObject):
|
||||||
duration_ms (:obj:`int`): Длительность трека в миллисекундах.
|
duration_ms (:obj:`int`): Длительность трека в миллисекундах.
|
||||||
storage_dir (:obj:`str`): В какой папке на сервере хранится файл TODO.
|
storage_dir (:obj:`str`): В какой папке на сервере хранится файл TODO.
|
||||||
file_size (:obj:`int`): Размер файла. 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`): Значения для нормализации трека.
|
normalization (:obj:`list` из :obj:`yandex_music.Normalization`): Значения для нормализации трека.
|
||||||
error (:obj:`str`): Сообщение об ошибке.
|
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.
|
regions (:obj:`list` из :obj:`str`): Регион TODO.
|
||||||
available_as_rbt (:obj:`bool`): TODO.
|
available_as_rbt (:obj:`bool`): TODO.
|
||||||
content_warning (:obj:`str`): Тип откровенного контента.
|
content_warning (:obj:`str`): Тип откровенного контента.
|
||||||
|
@ -62,8 +73,16 @@ class Track(YandexMusicObject):
|
||||||
duration_ms (:obj:`int`, optional): Длительность трека в миллисекундах.
|
duration_ms (:obj:`int`, optional): Длительность трека в миллисекундах.
|
||||||
storage_dir (:obj:`str`, optional): В какой папке на сервере хранится файл TODO.
|
storage_dir (:obj:`str`, optional): В какой папке на сервере хранится файл TODO.
|
||||||
file_size (:obj:`int`, 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): Значения для нормализации трека.
|
normalization (:obj:`list` из :obj:`yandex_music.Normalization`, optional): Значения для нормализации трека.
|
||||||
error (:obj:`str`, 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.
|
regions (:obj:`list` из :obj:`str`, optional): Регион TODO.
|
||||||
available_as_rbt (:obj:`bool`, optional): TODO.
|
available_as_rbt (:obj:`bool`, optional): TODO.
|
||||||
content_warning (:obj:`str`, optional): Тип откровенного контента.
|
content_warning (:obj:`str`, optional): Тип откровенного контента.
|
||||||
|
@ -93,8 +112,16 @@ class Track(YandexMusicObject):
|
||||||
duration_ms: Optional[int] = None,
|
duration_ms: Optional[int] = None,
|
||||||
storage_dir: Optional[str] = None,
|
storage_dir: Optional[str] = None,
|
||||||
file_size: Optional[int] = None,
|
file_size: Optional[int] = None,
|
||||||
|
substituted: Optional['Track'] = None,
|
||||||
|
matched_track: Optional['Track'] = None,
|
||||||
normalization: Optional['Normalization'] = None,
|
normalization: Optional['Normalization'] = None,
|
||||||
error: Optional[str] = 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,
|
regions: Optional[List[str]] = None,
|
||||||
available_as_rbt: Optional[bool] = None,
|
available_as_rbt: Optional[bool] = None,
|
||||||
content_warning: Optional[str] = None,
|
content_warning: Optional[str] = None,
|
||||||
|
@ -122,8 +149,16 @@ class Track(YandexMusicObject):
|
||||||
self.duration_ms = duration_ms
|
self.duration_ms = duration_ms
|
||||||
self.storage_dir = storage_dir
|
self.storage_dir = storage_dir
|
||||||
self.file_size = file_size
|
self.file_size = file_size
|
||||||
|
self.substituted = substituted
|
||||||
|
self.matched_track = matched_track
|
||||||
self.normalization = normalization
|
self.normalization = normalization
|
||||||
self.error = error
|
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.regions = regions
|
||||||
self.available_as_rbt = available_as_rbt
|
self.available_as_rbt = available_as_rbt
|
||||||
self.content_warning = content_warning
|
self.content_warning = content_warning
|
||||||
|
@ -238,11 +273,15 @@ class Track(YandexMusicObject):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
data = super(Track, cls).de_json(data, client)
|
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['albums'] = Album.de_list(data.get('albums'), client)
|
||||||
data['artists'] = Artist.de_list(data.get('artists'), client)
|
data['artists'] = Artist.de_list(data.get('artists'), client)
|
||||||
data['normalization'] = Normalization.de_json(data.get('normalization'), client)
|
data['normalization'] = Normalization.de_json(data.get('normalization'), client)
|
||||||
data['major'] = Major.de_json(data.get('major'), 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)
|
return cls(client=client, **data)
|
||||||
|
|
||||||
|
@ -260,11 +299,7 @@ class Track(YandexMusicObject):
|
||||||
if not data:
|
if not data:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
tracks = list()
|
return [cls.de_json(track, client) for track in data]
|
||||||
for track in data:
|
|
||||||
tracks.append(cls.de_json(track, client))
|
|
||||||
|
|
||||||
return tracks
|
|
||||||
|
|
||||||
# camelCase псевдонимы
|
# camelCase псевдонимы
|
||||||
|
|
||||||
|
|
読み込み中…
新しいイシューから参照