diff --git a/tests/__init__.py b/tests/__init__.py index e44a428..b4d1cf8 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -73,3 +73,4 @@ from .test_vinyl import TestVinyl from .test_shot_type import TestShotType from .test_shot_data import TestShotData from .test_shot import TestShot +from .test_renewable_remainder import TestRenewableRemainder diff --git a/tests/conftest.py b/tests/conftest.py index 7c1b923..fb2db5c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,8 @@ from yandex_music import Counts, TrackId, CaseForms, Ratings, Icon, Album, Lyric Account, Client, TrackShort, Value, DiscreteScale, PlaylistId, MixLink, Link, PassportPhone, User, Promotion, \ 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 + GeneratedPlaylist, Video, Vinyl, SearchResult, BlockEntity, Block, PlaylistAbsence, ShotType, ShotData, Shot, \ + RenewableRemainder from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, TestAlbum, TestLyrics, \ TestTrack, TestInvocationInfo, TestPlaylist, TestAutoRenewable, TestStation, TestNormalization, TestMajor, \ TestTrackPosition, TestBest, TestChart, TestPermissions, TestPlus, TestProduct, TestCover, TestPlayCounter, \ @@ -15,15 +16,16 @@ from . import TestCounts, TestTrackId, TestCaseForms, TestRatings, TestIcon, Tes TestUser, TestPassportPhone, TestPromotion, TestTitle, TestPersonalPlaylistsData, TestRotorSettings, \ TestTrackShortOld, TestPager, TestStatus, TestSettings, TestStationResult, TestLabel, TestTrackWithAds, \ TestVideoSupplement, TestEvent, TestDay, TestPlayContext, TestGeneratedPlaylist, TestVideo, TestVinyl, \ - TestSearchResult, TestBlockEntity, TestBlock, TestPlaylistAbsence, TestShot, TestShotData, TestShotType + TestSearchResult, TestBlockEntity, TestBlock, TestPlaylistAbsence, TestShot, TestShotData, TestShotType, \ + TestRenewableRemainder @pytest.fixture(scope='session') def artist_factory(cover, counts, ratings, link, description): class ArtistFactory: def get(self, popular_tracks): - return Artist(TestArtist.id, TestArtist.error, TestArtist.name, cover, TestArtist.various, - TestArtist.composer, TestArtist.genres, TestArtist.op_image, + 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, @@ -48,12 +50,12 @@ def track_factory(major, normalization): class TrackFactory: def get(self, artists, albums): return Track(TestTrack.id, TestTrack.title, TestTrack.available, artists, albums, - TestTrack.available_for_premium_users, TestTrack.lyrics_available, 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.explicit, - TestTrack.preview_duration_ms, TestTrack.available_full_without_permission, TestTrack.version, - TestTrack.remember_position) + 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.explicit, TestTrack.preview_duration_ms, TestTrack.available_full_without_permission, + TestTrack.version, TestTrack.remember_position) return TrackFactory() @@ -85,10 +87,10 @@ def album_factory(label, track_position): return Album(TestAlbum.id, TestAlbum.error, TestAlbum.title, TestAlbum.track_count, artists, [label], TestAlbum.available, TestAlbum.available_for_premium_users, TestAlbum.version, TestAlbum.cover_uri, TestAlbum.content_warning, TestAlbum.original_release_year, - TestAlbum.genre, TestAlbum.og_image, TestAlbum.buy, TestAlbum.recent, TestAlbum.very_important, - TestAlbum.available_for_mobile, TestAlbum.available_partially, TestAlbum.bests, - TestAlbum.prerolls, volumes, TestAlbum.year, TestAlbum.release_date, TestAlbum.type, - track_position, TestAlbum.regions) + TestAlbum.genre, TestAlbum.meta_type, TestAlbum.og_image, TestAlbum.buy, TestAlbum.recent, + TestAlbum.very_important, TestAlbum.available_for_mobile, TestAlbum.available_partially, + TestAlbum.bests, TestAlbum.prerolls, volumes, TestAlbum.year, TestAlbum.release_date, + TestAlbum.type, track_position, TestAlbum.regions) return AlbumFactory() @@ -164,7 +166,8 @@ def video(): @pytest.fixture(scope='session') def vinyl(): - return Vinyl(TestVinyl.url, TestVinyl.title, TestVinyl.year, TestVinyl.price, TestVinyl.media, TestVinyl.picture) + return Vinyl(TestVinyl.url, TestVinyl.title, TestVinyl.year, TestVinyl.price, TestVinyl.media, TestVinyl.offer_id, + TestVinyl.artist_ids, TestVinyl.picture) @pytest.fixture(scope='session') @@ -190,8 +193,8 @@ def icon(): @pytest.fixture(scope='session') def cover(): - return Cover(TestCover.type, TestCover.uri, TestCover.items_uri, TestCover.dir, - TestCover.version, TestCover.custom, TestCover.prefix, TestCover.error) + return Cover(TestCover.type, TestCover.uri, TestCover.items_uri, TestCover.dir, TestCover.version, + TestCover.custom, TestCover.is_custom, TestCover.prefix, TestCover.error) @pytest.fixture(scope='session') @@ -338,6 +341,11 @@ def passport_phone(): return PassportPhone(TestPassportPhone.phone) +@pytest.fixture(scope='session') +def renewable_remainder(): + return RenewableRemainder(TestRenewableRemainder.days) + + @pytest.fixture(scope='session') def user(): return User(TestUser.uid, TestUser.login, TestUser.name, TestUser.sex, TestUser.verified) @@ -362,9 +370,9 @@ def price(): @pytest.fixture(scope='session') -def subscription(auto_renewable): - return Subscription([auto_renewable], TestSubscription.can_start_trial, TestSubscription.mcdonalds, - TestSubscription.end) +def subscription(renewable_remainder, auto_renewable): + return Subscription(renewable_remainder, [auto_renewable], TestSubscription.can_start_trial, + TestSubscription.mcdonalds, TestSubscription.end) @pytest.fixture(scope='session') @@ -376,8 +384,8 @@ def rotor_settings(): @pytest.fixture(scope='session') def product(price): return Product(TestProduct.product_id, TestProduct.type, TestProduct.common_period_duration, TestProduct.duration, - TestProduct.trial_duration, price, TestProduct.feature, TestProduct.debug, TestProduct.features, - TestProduct.description, TestProduct.available, TestProduct.trial_available, + TestProduct.trial_duration, price, TestProduct.feature, TestProduct.debug, TestProduct.plus, + TestProduct.features, TestProduct.description, TestProduct.available, TestProduct.trial_available, TestProduct.vendor_trial_available, TestProduct.button_text, TestProduct.button_additional_text, TestProduct.payment_method_types) @@ -399,9 +407,9 @@ def track_position(): @pytest.fixture(scope='session') def status(account, permissions, subscription, plus): - return Status(account, permissions, subscription, TestStatus.cache_limit, TestStatus.subeditor, - TestStatus.subeditor_level, plus, TestStatus.default_email, TestStatus.skips_per_hour, - TestStatus.station_exists, TestStatus.premium_region) + return Status(account, permissions, TestStatus.advertisement, subscription, TestStatus.cache_limit, + TestStatus.subeditor, TestStatus.subeditor_level, plus, TestStatus.default_email, + TestStatus.skips_per_hour, TestStatus.station_exists, TestStatus.premium_region) @pytest.fixture(scope='session') diff --git a/tests/test_album.py b/tests/test_album.py index b1b1bd9..1337b7e 100644 --- a/tests/test_album.py +++ b/tests/test_album.py @@ -13,6 +13,7 @@ class TestAlbum: content_warning = None original_release_year = None genre = 'alternative' + meta_type = 'music' og_image = 'avatars.yandex.net/get-music-content/95061/89c14a7d.a.5239478-1/%%' buy = [] recent = False @@ -40,6 +41,7 @@ class TestAlbum: assert album.content_warning == self.content_warning assert album.original_release_year == self.original_release_year assert album.genre == self.genre + assert album.meta_type == self.meta_type assert album.og_image == self.og_image assert album.buy == self.buy assert album.recent == self.recent @@ -76,7 +78,8 @@ class TestAlbum: 'og_image': self.og_image, 'recent': self.recent, 'very_important': self.very_important, 'available_for_mobile': self.available_for_mobile, 'available_partially': self.available_partially, 'bests': self.bests, 'prerolls': self.prerolls, 'volumes': [[track.to_dict()]], 'year': self.year, - 'release_date': self.release_date, 'type_': self.type, 'track_position': track_position.to_dict()} + 'release_date': self.release_date, 'type_': self.type, 'track_position': track_position.to_dict(), + 'meta_type': self.meta_type} album = Album.de_json(json_dict, client) assert album.id == self.id @@ -92,6 +95,7 @@ class TestAlbum: assert album.content_warning == self.content_warning assert album.original_release_year == self.original_release_year assert album.genre == self.genre + assert album.meta_type == self.meta_type assert album.og_image == self.og_image assert album.buy == self.buy assert album.recent == self.recent diff --git a/tests/test_artist.py b/tests/test_artist.py index 82381e0..9733fc9 100644 --- a/tests/test_artist.py +++ b/tests/test_artist.py @@ -3,11 +3,12 @@ from yandex_music import Artist class TestArtist: id = 10987 - error = 'not-found' + reason = 'not-found' name = 'Elvis Presley' various = False composer = None genres = None + og_image = '' op_image = None no_pictures_from_search = None available = None @@ -25,12 +26,13 @@ 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 assert artist.composer == self.composer assert artist.cover == cover assert artist.genres == self.genres + assert artist.og_image == self.og_image assert artist.op_image == self.op_image assert artist.no_pictures_from_search == self.no_pictures_from_search assert artist.counts == counts @@ -64,10 +66,11 @@ 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, 'error': self.error, 'name': self.name, 'various': self.various, - 'composer': self.composer, 'cover': cover.to_dict(), 'genres': self.genres, - 'op_image': self.op_image, 'no_pictures_from_search': self.no_pictures_from_search, - 'counts': counts.to_dict(), 'available': self.available, 'ratings': ratings.to_dict(), + json_dict = {'id_': self.id, 'reason': self.reason, '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(), + 'available': self.available, 'ratings': ratings.to_dict(), 'links': [link.to_dict()], 'tickets_available': self.tickets_available, 'likes_count': self.likes_count, 'popular_tracks': [track_without_artists.to_dict()], 'regions': self.regions, 'decomposed': self.decomposed, 'full_names': self.full_names, @@ -77,12 +80,13 @@ 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 assert artist.composer == self.composer assert artist.cover == cover assert artist.genres == self.genres + assert artist.og_image == self.og_image assert artist.op_image == self.op_image assert artist.no_pictures_from_search == self.no_pictures_from_search assert artist.counts == counts diff --git a/tests/test_brief_info.py b/tests/test_brief_info.py index eb60816..ce30329 100644 --- a/tests/test_brief_info.py +++ b/tests/test_brief_info.py @@ -4,8 +4,8 @@ from yandex_music import BriefInfo @pytest.fixture(scope='class') -def brief_info(artist, track, album, cover, playlist_id, video, chart, vinyl): - return BriefInfo(artist, [album], [album], TestBriefInfo.last_release_ids, [track], [artist], [cover], +def brief_info(artist, track, album, playlist, cover, playlist_id, video, chart, vinyl): + return BriefInfo(artist, [album], [playlist], [album], TestBriefInfo.last_release_ids, [track], [artist], [cover], TestBriefInfo.concerts, [video], [vinyl], TestBriefInfo.has_promotions, [playlist_id], [chart]) @@ -14,9 +14,10 @@ class TestBriefInfo: concerts = None has_promotions = False - def test_expected_values(self, brief_info, artist, track, album, cover, playlist_id, video, chart, vinyl): + def test_expected_values(self, brief_info, artist, track, album, playlist, cover, playlist_id, video, chart, vinyl): assert brief_info.artist == artist assert brief_info.albums == [album] + assert brief_info.playlists == [playlist] assert brief_info.also_albums == [album] assert brief_info.last_release_ids == self.last_release_ids assert brief_info.popular_tracks == [track] @@ -32,16 +33,17 @@ class TestBriefInfo: def test_de_json_none(self, client): assert BriefInfo.de_json({}, client) is None - def test_de_json_required(self, client, artist, track, album, cover, playlist_id, video, vinyl): + def test_de_json_required(self, client, artist, track, album, playlist, cover, playlist_id, video, vinyl): json_dict = {'artist': artist.to_dict(), 'albums': [album.to_dict()], 'also_albums': [album.to_dict()], 'last_release_ids': self.last_release_ids, 'popular_tracks': [track.to_dict()], 'similar_artists': [artist.to_dict()], 'all_covers': [cover.to_dict()], 'concerts': self.concerts, 'videos': [video.to_dict()], 'vinyls': [vinyl.to_dict()], 'has_promotions': self.has_promotions, - 'playlist_ids': [playlist_id.to_dict()]} + 'playlist_ids': [playlist_id.to_dict()], 'playlists': [playlist.to_dict()]} brief_info = BriefInfo.de_json(json_dict, client) assert brief_info.artist == artist assert brief_info.albums == [album] + assert brief_info.playlists == [playlist] assert brief_info.also_albums == [album] assert brief_info.last_release_ids == self.last_release_ids assert brief_info.popular_tracks == [track] @@ -53,16 +55,18 @@ class TestBriefInfo: assert brief_info.has_promotions == self.has_promotions assert brief_info.playlist_ids == [playlist_id] - def test_de_json_all(self, client, artist, track, album, cover, playlist_id, video, chart, vinyl): + def test_de_json_all(self, client, artist, track, album, playlist, cover, playlist_id, video, chart, vinyl): json_dict = {'artist': artist.to_dict(), 'albums': [album.to_dict()], 'also_albums': [album.to_dict()], 'last_release_ids': self.last_release_ids, 'popular_tracks': [track.to_dict()], 'similar_artists': [artist.to_dict()], 'all_covers': [cover.to_dict()], 'concerts': self.concerts, 'videos': [video.to_dict()], 'vinyls': [vinyl.to_dict()], 'has_promotions': self.has_promotions, - 'playlist_ids': [playlist_id.to_dict()], 'tracks_in_chart': [chart.to_dict()]} + 'playlist_ids': [playlist_id.to_dict()], 'tracks_in_chart': [chart.to_dict()], + 'playlists': [playlist.to_dict()]} brief_info = BriefInfo.de_json(json_dict, client) assert brief_info.artist == artist assert brief_info.albums == [album] + assert brief_info.playlists == [playlist] assert brief_info.also_albums == [album] assert brief_info.last_release_ids == self.last_release_ids assert brief_info.popular_tracks == [track] @@ -75,15 +79,15 @@ class TestBriefInfo: assert brief_info.playlist_ids == [playlist_id] assert brief_info.tracks_in_chart == [chart] - def test_equality(self, artist, track, album, cover, playlist_id, video, vinyl): - a = BriefInfo(artist, [album], [album], self.last_release_ids, [track], [artist], [cover], self.concerts, - [video], [vinyl], self.has_promotions, [playlist_id]) - b = BriefInfo(artist, [album], [album], self.last_release_ids, [], [artist], [cover], self.concerts, + def test_equality(self, artist, track, album, playlist, cover, playlist_id, video, vinyl): + a = BriefInfo(artist, [album], [playlist], [album], self.last_release_ids, [track], [artist], [cover], + self.concerts, [video], [vinyl], self.has_promotions, [playlist_id]) + b = BriefInfo(artist, [album], [], [album], self.last_release_ids, [], [artist], [cover], self.concerts, [video], [vinyl], True, [playlist_id]) - c = BriefInfo(artist, [album], [album], [1, 2, 3], [track], [artist], [], self.concerts, - [video], [vinyl], self.has_promotions, [playlist_id]) - d = BriefInfo(artist, [album], [album], self.last_release_ids, [track], [artist], [cover], self.concerts, + c = BriefInfo(artist, [album], [playlist], [album], [1, 2, 3], [track], [artist], [], self.concerts, [video], [vinyl], self.has_promotions, [playlist_id]) + d = BriefInfo(artist, [album], [playlist], [album], self.last_release_ids, [track], [artist], [cover], + self.concerts, [video], [vinyl], self.has_promotions, [playlist_id]) assert a != b != c assert hash(a) != hash(b) != hash(c) diff --git a/tests/test_cover.py b/tests/test_cover.py index 10201fc..d80e308 100644 --- a/tests/test_cover.py +++ b/tests/test_cover.py @@ -8,6 +8,7 @@ class TestCover: dir = '/get-music-user-playlist/34120/pvg900XixWaHcr/' version = '1572609906461' custom = True + is_custom = True prefix = None error = None @@ -18,6 +19,7 @@ class TestCover: assert cover.dir == self.dir assert cover.version == self.version assert cover.custom == self.custom + assert cover.is_custom == self.is_custom assert cover.prefix == self.prefix assert cover.error == self.error @@ -33,7 +35,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, 'prefix': self.prefix, 'error': self.error} + 'version': self.version, 'custom': self.custom, 'is_custom': self.is_custom, 'prefix': self.prefix, + 'error': self.error} cover = Cover.de_json(json_dict, client) assert cover.type == self.type @@ -42,6 +45,7 @@ class TestCover: assert cover.dir == self.dir assert cover.version == self.version assert cover.custom == self.custom + assert cover.is_custom == self.is_custom assert cover.prefix == self.prefix assert cover.error == self.error diff --git a/tests/test_product.py b/tests/test_product.py index 54b5200..584db52 100644 --- a/tests/test_product.py +++ b/tests/test_product.py @@ -10,6 +10,7 @@ class TestProduct: trial_duration = 0 feature = 'basic-music' debug = False + plus = False features = ['basic-music'] available = None trial_available = None @@ -27,6 +28,7 @@ class TestProduct: assert product.price == price assert product.feature == self.feature assert product.debug == self.debug + assert product.plus == self.plus assert product.features == self.features assert product.description == self.description assert product.available == self.available @@ -46,7 +48,7 @@ class TestProduct: json_dict = {'product_id': self.product_id, 'type_': self.type, 'common_period_duration': self.common_period_duration, 'duration': self.duration, 'trial_duration': self.trial_duration, 'price': price.to_dict(), 'feature': self.feature, - 'debug': self.debug} + 'debug': self.debug, 'plus': self.plus} product = Product.de_json(json_dict, client) assert product.product_id == self.product_id @@ -57,12 +59,13 @@ class TestProduct: assert product.price == price assert product.feature == self.feature assert product.debug == self.debug + assert product.plus == self.plus def test_de_json_all(self, client, price): json_dict = {'product_id': self.product_id, 'type_': self.type, 'common_period_duration': self.common_period_duration, 'duration': self.duration, 'trial_duration': self.trial_duration, 'price': price.to_dict(), 'feature': self.feature, - 'debug': self.debug, 'features': self.features, 'description': self.description, + 'debug': self.debug, 'plus': self.plus, 'features': self.features, 'description': self.description, 'available': self.available, 'trial_available': self.trial_available, 'vendor_trial_available': self.vendor_trial_available, 'button_text': self.button_text, 'button_additional_text': self.button_additional_text, @@ -77,6 +80,7 @@ class TestProduct: assert product.price == price assert product.feature == self.feature assert product.debug == self.debug + assert product.plus == self.plus assert product.features == self.features assert product.description == self.description assert product.available == self.available @@ -88,11 +92,11 @@ class TestProduct: def test_equality(self, price): a = Product(self.product_id, self.type, self.common_period_duration, self.duration, self.trial_duration, price, - self.feature, self.debug) + self.feature, self.debug, self.plus) b = Product('', self.type, self.common_period_duration, self.duration, self.trial_duration, price, - self.feature, self.debug) + self.feature, self.debug, self.plus) c = Product(self.product_id, self.type, self.common_period_duration, self.duration, self.trial_duration, price, - self.feature, self.debug) + self.feature, self.debug, self.plus) assert a != b assert hash(a) != hash(b) diff --git a/tests/test_renewable_remainder.py b/tests/test_renewable_remainder.py new file mode 100644 index 0000000..85a994f --- /dev/null +++ b/tests/test_renewable_remainder.py @@ -0,0 +1,34 @@ +from yandex_music import RenewableRemainder + + +class TestRenewableRemainder: + days = 0 + + def test_expected_values(self, renewable_remainder): + assert renewable_remainder.days == self.days + + def test_de_json_none(self, client): + assert RenewableRemainder.de_json({}, client) is None + + def test_de_json_required(self, client): + json_dict = {'days': self.days} + renewable_remainder = RenewableRemainder.de_json(json_dict, client) + + assert renewable_remainder.days == self.days + + def test_de_json_all(self, client): + json_dict = {'days': self.days} + renewable_remainder = RenewableRemainder.de_json(json_dict, client) + + assert renewable_remainder.days == self.days + + def test_equality(self): + a = RenewableRemainder(self.days) + b = RenewableRemainder(10) + c = RenewableRemainder(self.days) + + assert a != b + assert hash(a) != hash(b) + assert a is not b + + assert a == c diff --git a/tests/test_status.py b/tests/test_status.py index f19c306..ea43c80 100644 --- a/tests/test_status.py +++ b/tests/test_status.py @@ -2,6 +2,7 @@ from yandex_music import Status class TestStatus: + advertisement = 'Оформите постоянную подписку – первый месяц бесплатно!' cache_limit = 99 subeditor = False subeditor_level = 0 @@ -14,6 +15,7 @@ class TestStatus: assert status.account == account assert status.permissions == permissions assert status.subscription == subscription + assert status.advertisement == self.advertisement assert status.cache_limit == self.cache_limit assert status.subeditor == self.subeditor assert status.subeditor_level == self.subeditor_level @@ -27,23 +29,27 @@ class TestStatus: assert Status.de_json({}, client) is None def test_de_json_required(self, client, account, permissions): - json_dict = {'account': account.to_dict(), 'permissions': permissions.to_dict()} + json_dict = {'account': account.to_dict(), 'permissions': permissions.to_dict(), + 'advertisement': self.advertisement} status = Status.de_json(json_dict, client) assert status.account == account assert status.permissions == permissions + assert status.advertisement == self.advertisement def test_de_json_all(self, client, account, permissions, subscription, plus): json_dict = {'account': account.to_dict(), 'permissions': permissions.to_dict(), 'subscription': subscription.to_dict(), 'cache_limit': self.cache_limit, 'subeditor': self.subeditor, 'subeditor_level': self.subeditor_level, 'plus': plus.to_dict(), 'default_email': self.default_email, 'skips_per_hour': self.skips_per_hour, - 'station_exists': self.station_exists, 'premium_region': self.premium_region} + 'station_exists': self.station_exists, 'premium_region': self.premium_region, + 'advertisement': self.advertisement} status = Status.de_json(json_dict, client) assert status.account == account assert status.permissions == permissions assert status.subscription == subscription + assert status.advertisement == self.advertisement assert status.cache_limit == self.cache_limit assert status.subeditor == self.subeditor assert status.subeditor_level == self.subeditor_level @@ -54,9 +60,9 @@ class TestStatus: assert status.premium_region == self.premium_region def test_equality(self, account, permissions, subscription): - a = Status(account, permissions) - b = Status(None, permissions, subscription, self.cache_limit) - c = Status(account, permissions) + a = Status(account, permissions, self.advertisement) + b = Status(None, permissions, '') + c = Status(account, permissions, self.advertisement) assert a != b assert hash(a) != hash(b) diff --git a/tests/test_subscription.py b/tests/test_subscription.py index 4cbacb7..f284b44 100644 --- a/tests/test_subscription.py +++ b/tests/test_subscription.py @@ -6,7 +6,8 @@ class TestSubscription: mcdonalds = False end = None - def test_expected_values(self, subscription, auto_renewable): + def test_expected_values(self, subscription, renewable_remainder, auto_renewable): + assert subscription.non_auto_renewable_remainder == renewable_remainder assert subscription.auto_renewable == [auto_renewable] assert subscription.can_start_trial == self.can_start_trial assert subscription.mcdonalds == self.mcdonalds @@ -15,23 +16,29 @@ class TestSubscription: def test_de_json_none(self, client): assert Subscription.de_json({}, client) is None - def test_de_json_required(self, client): - json_dict = {} + def test_de_json_required(self, client, renewable_remainder, auto_renewable): + json_dict = {'non_auto_renewable_remainder': renewable_remainder.to_dict(), + 'auto_renewable': [auto_renewable.to_dict()]} subscription = Subscription.de_json(json_dict, client) - def test_de_json_all(self, client, auto_renewable): + assert subscription.non_auto_renewable_remainder == renewable_remainder + assert subscription.auto_renewable == [auto_renewable] + + def test_de_json_all(self, client, renewable_remainder, auto_renewable): json_dict = {'auto_renewable': [auto_renewable.to_dict()], 'can_start_trial': self.can_start_trial, - 'mcdonalds': self.mcdonalds, 'end': self.end} + 'mcdonalds': self.mcdonalds, 'end': self.end, 'non_auto_renewable_remainder': + renewable_remainder.to_dict()} subscription = Subscription.de_json(json_dict, client) + assert subscription.non_auto_renewable_remainder == renewable_remainder assert subscription.auto_renewable == [auto_renewable] assert subscription.can_start_trial == self.can_start_trial assert subscription.mcdonalds == self.mcdonalds assert subscription.end == self.end - def test_equality(self, auto_renewable): - a = Subscription([auto_renewable]) - b = Subscription(None) + def test_equality(self, renewable_remainder, auto_renewable): + a = Subscription(renewable_remainder, [auto_renewable]) + b = Subscription(renewable_remainder, []) assert a != b != auto_renewable assert hash(a) != hash(b) != hash(auto_renewable) diff --git a/tests/test_track.py b/tests/test_track.py index c407371..19e5f45 100644 --- a/tests/test_track.py +++ b/tests/test_track.py @@ -7,6 +7,7 @@ class TestTrack: available = True available_for_premium_users = True lyrics_available = False + best = False real_id = '10994777' og_image = 'avatars.yandex.net/get-music-content/28589/daef4251.a.1193829-1/%%' type = 'music' @@ -32,6 +33,7 @@ class TestTrack: assert track.artists == [artist] assert track.albums == [album] assert track.lyrics_available == self.lyrics_available + assert track.best == self.best assert track.real_id == self.real_id assert track.og_image == self.og_image assert track.type == self.type @@ -58,21 +60,16 @@ class TestTrack: assert Track.de_list({}, client) == [] def test_de_json_required(self, client, artist, album): - json_dict = {'id_': self.id, 'title': self.title, 'available': self.available, - 'artists': [artist.to_dict()], 'albums': [album.to_dict()]} + json_dict = {'id_': self.id} track = Track.de_json(json_dict, client) assert track.id == self.id - assert track.title == self.title - assert track.available == self.available - assert track.artists == [artist] - assert track.albums == [album] def test_de_json_all(self, client, artist, album, major, normalization): 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()], - 'lyrics_available': self.lyrics_available, 'real_id': self.real_id, + 'lyrics_available': self.lyrics_available, 'best': self.best, 'real_id': self.real_id, 'og_image': self.og_image, 'type_': self.type, 'cover_uri': self.cover_uri, 'major': major.to_dict(), 'duration_ms': self.duration_ms, 'storage_dir': self.storage_dir, 'file_size': self.file_size, 'normalization': normalization.to_dict(), 'error': self.error, @@ -90,6 +87,7 @@ class TestTrack: assert track.artists == [artist] assert track.albums == [album] assert track.lyrics_available == self.lyrics_available + assert track.best == self.best assert track.real_id == self.real_id assert track.og_image == self.og_image assert track.type == self.type @@ -109,10 +107,10 @@ class TestTrack: assert track.version == self.version assert track.remember_position == self.remember_position - def test_equality(self, artist, album): - a = Track(self.id, self.title, self.available, [artist], [album]) - b = Track(self.id, '', self.available, [artist], []) - c = Track(self.id, self.title, self.available, [artist], [album]) + def test_equality(self): + a = Track(self.id) + b = Track(10) + c = Track(self.id) assert a != b assert hash(a) != hash(b) diff --git a/tests/test_vinyl.py b/tests/test_vinyl.py index f523c99..1be4a30 100644 --- a/tests/test_vinyl.py +++ b/tests/test_vinyl.py @@ -8,6 +8,8 @@ class TestVinyl: year = 2005 media = '2 Грампластинка (LP)' price = 4483 + offer_id = 28640019 + artist_ids = [4, 24326, 618511, 2643503] def test_expected_values(self, vinyl): assert vinyl.url == self.url @@ -16,6 +18,8 @@ class TestVinyl: assert vinyl.year == self.year assert vinyl.price == self.price assert vinyl.media == self.media + assert vinyl.offer_id == self.offer_id + assert vinyl.artist_ids == self.artist_ids def test_de_json_none(self, client): assert Vinyl.de_json({}, client) is None @@ -24,7 +28,8 @@ class TestVinyl: assert Vinyl.de_list({}, client) == [] def test_de_json_required(self, client): - json_dict = {'url': self.url, 'title': self.title, 'year': self.year, 'price': self.price, 'media': self.media} + json_dict = {'url': self.url, 'title': self.title, 'year': self.year, 'price': self.price, 'media': self.media, + 'offer_id': self.offer_id, 'artist_ids': self.artist_ids} vinyl = Vinyl.de_json(json_dict, client) assert vinyl.url == self.url @@ -32,10 +37,12 @@ class TestVinyl: assert vinyl.year == self.year assert vinyl.price == self.price assert vinyl.media == self.media + assert vinyl.offer_id == self.offer_id + assert vinyl.artist_ids == self.artist_ids def test_de_json_all(self, client): json_dict = {'url': self.url, 'picture': self.picture, 'title': self.title, 'year': self.year, - 'price': self.price, 'media': self.media} + 'price': self.price, 'media': self.media, 'offer_id': self.offer_id, 'artist_ids': self.artist_ids} vinyl = Vinyl.de_json(json_dict, client) assert vinyl.url == self.url @@ -44,11 +51,13 @@ class TestVinyl: assert vinyl.year == self.year assert vinyl.price == self.price assert vinyl.media == self.media + assert vinyl.offer_id == self.offer_id + assert vinyl.artist_ids == self.artist_ids def test_equality(self): - a = Vinyl(self.url, self.title, 2020, 200, self.media, self.picture) - b = Vinyl(self.url, self.title, self.year, self.price, self.media, self.picture) - c = Vinyl(self.url, self.title, self.year, self.price, self.media, self.picture) + a = Vinyl(self.url, self.title, 2020, 200, self.media, self.offer_id, [10]) + b = Vinyl(self.url, self.title, self.year, self.price, self.media, self.offer_id, self.artist_ids) + c = Vinyl(self.url, self.title, self.year, self.price, self.media, self.offer_id, self.artist_ids) assert a != b assert hash(a) != hash(b) diff --git a/yandex_music/__init__.py b/yandex_music/__init__.py index 404859e..1416049 100644 --- a/yandex_music/__init__.py +++ b/yandex_music/__init__.py @@ -12,6 +12,7 @@ from .account.subscription import Subscription from .account.price import Price from .account.product import Product from .account.auto_renewable import AutoRenewable +from .account.renewable_remainder import RenewableRemainder from .account.passport_phone import PassportPhone from .account.permissions import Permissions @@ -118,4 +119,4 @@ __all__ = ['YandexMusicObject', 'Client', 'Account', 'PassportPhone', 'Invocatio 'Dashboard', 'RotorSettings', 'AdParams', 'Restrictions', 'Value', 'Enum', 'DiscreteScale', 'StationResult', 'Sequence', 'StationTracksResult', 'BriefInfo', 'Description', 'PlaylistId', 'Vinyl', 'Supplement', 'Lyrics', 'VideoSupplement', 'ArtistTracks', 'Pager', 'ArtistAlbums', 'PlaylistAbsence', 'Shot', 'ShotEvent', - 'ShotType', 'ShotData', 'SimilarTracks', 'UserSettings'] + 'ShotType', 'ShotData', 'SimilarTracks', 'UserSettings', 'RenewableRemainder'] diff --git a/yandex_music/account/product.py b/yandex_music/account/product.py index ceea49d..678c2c5 100644 --- a/yandex_music/account/product.py +++ b/yandex_music/account/product.py @@ -18,6 +18,7 @@ class Product(YandexMusicObject): price (:obj:`yandex_music.Price`): Цена. feature (:obj:`str`): Предоставляемая возможность. debug (:obj:`bool`): Отладочный продукт. + plus (:obj:`bool`): Даёт ли подписку "Плюс". features (:obj:`list` из :obj:`str`): Список предоставляемых возможностей. description (:obj:`str`): Описание. available (:obj:`bool`): Доступна ли покупка. @@ -37,6 +38,7 @@ class Product(YandexMusicObject): price (:obj:`yandex_music.Price`): Цена. feature (:obj:`str`): Предоставляемая возможность. debug (:obj:`bool`): Отладочный продукт. + plus (:obj:`bool`): Даёт ли подписку "Плюс". features (:obj:`list` из :obj:`str`, optional): Список предоставляемых возможностей. description (:obj:`str`, optional): Описание. available (:obj:`bool`, optional): Доступна ли покупка. @@ -58,6 +60,7 @@ class Product(YandexMusicObject): price: Optional['Price'], feature: str, debug: bool, + plus: bool, features: List[str] = None, description: Optional[str] = None, available: Optional[bool] = None, @@ -78,6 +81,7 @@ class Product(YandexMusicObject): self.price = price self.feature = feature self.debug = debug + self.plus = plus self.features = features self.description = description diff --git a/yandex_music/account/renewable_remainder.py b/yandex_music/account/renewable_remainder.py new file mode 100644 index 0000000..3442524 --- /dev/null +++ b/yandex_music/account/renewable_remainder.py @@ -0,0 +1,49 @@ +from typing import TYPE_CHECKING, Optional + +from yandex_music import YandexMusicObject + +if TYPE_CHECKING: + from yandex_music import Client + + +class RenewableRemainder(YandexMusicObject): + """Класс, представляющий напоминания о продлении подписки. + + Attributes: + days (:obj:`int`): Количество дней (до окончания подписки, по всей видимости). + client (:obj:`yandex_music.Client`): Клиент Yandex Music. + + Args: + days (:obj:`int`): Количество дней (до окончания подписки, по всей видимости). + client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music. + **kwargs: Произвольные ключевые аргументы полученные от API. + """ + + def __init__(self, + days: int, + client: Optional['Client'] = None, + **kwargs) -> None: + super().handle_unknown_kwargs(self, **kwargs) + + self.days = days + + self.client = client + self._id_attrs = (self.days,) + + @classmethod + def de_json(cls, data: dict, client: 'Client') -> Optional['RenewableRemainder']: + """Десериализация объекта. + + Args: + data (:obj:`dict`): Поля и значения десериализуемого объекта. + client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music. + + Returns: + :obj:`yandex_music.PassportPhone`: Напоминание о продлении подписки. + """ + if not data: + return None + + data = super(RenewableRemainder, cls).de_json(data, client) + + return cls(client=client, **data) diff --git a/yandex_music/account/status.py b/yandex_music/account/status.py index 387fb6f..e5b5732 100644 --- a/yandex_music/account/status.py +++ b/yandex_music/account/status.py @@ -12,6 +12,7 @@ class Status(YandexMusicObject): Attributes: account (:obj:`yandex_music.Account`): Основная информация об аккаунте. permissions (:obj:`yandex_music.Permissions`): Информация о правах пользователя. + advertisement (:obj:`str`): Рекламное объявление. subscription (:obj:`yandex_music.Subscription`): Информация о подписках. cache_limit (:obj:`int`): Максимальное количество загруженных треков. subeditor (:obj:`bool`): Наличие статуса модератора проверки корректности информации. @@ -26,7 +27,8 @@ class Status(YandexMusicObject): Args: account (:obj:`yandex_music.Account`): Основная информация об аккаунте permissions (:obj:`yandex_music.Permissions`): Информация о правах пользователя. - subscription (:obj:`yandex_music.Subscription`): Информация о подписках. + advertisement (:obj:`str`): Рекламное объявление. + subscription (:obj:`yandex_music.Subscription`, optional): Информация о подписках. cache_limit (:obj:`int`, optional): Максимальное количество загруженных треков. subeditor (:obj:`bool`, optional): Наличие статуса модератора проверки корректности информации. subeditor_level (:obj:`int`, optional): Уровень статуса модератора. @@ -42,6 +44,7 @@ class Status(YandexMusicObject): def __init__(self, account: Optional['Account'], permissions: Optional['Permissions'], + advertisement: str, subscription: Optional['Subscription'] = None, cache_limit: Optional[int] = None, subeditor: Optional[bool] = None, @@ -57,6 +60,7 @@ class Status(YandexMusicObject): self.account = account self.permissions = permissions + self.advertisement = advertisement self.subscription = subscription self.cache_limit = cache_limit @@ -69,7 +73,7 @@ class Status(YandexMusicObject): self.premium_region = premium_region self.client = client - self._id_attrs = (self.account, self.permissions) + self._id_attrs = (self.account, self.permissions, self.advertisement) @classmethod def de_json(cls, data: dict, client: 'Client') -> Optional['Status']: diff --git a/yandex_music/account/subscription.py b/yandex_music/account/subscription.py index 031a8f0..d6bc9e3 100644 --- a/yandex_music/account/subscription.py +++ b/yandex_music/account/subscription.py @@ -3,13 +3,14 @@ from typing import TYPE_CHECKING, Optional, List from yandex_music import YandexMusicObject if TYPE_CHECKING: - from yandex_music import Client, AutoRenewable + from yandex_music import Client, AutoRenewable, RenewableRemainder class Subscription(YandexMusicObject): """Класс, представляющий информацию о подписках пользователя. Attributes: + non_auto_renewable_remainder (:obj:yandex_music.RenewableRemainder`): Напоминание о продлении. auto_renewable (:obj:`list` из :obj:`yandex_music.AutoRenewable`): Автопродление. can_start_trial (:obj:`bool`): Есть ли возможность начать пробный период. mcdonalds (:obj:`bool`): mcdonalds TODO. @@ -17,6 +18,7 @@ class Subscription(YandexMusicObject): client (:obj:`yandex_music.Client`): Клиент Yandex Music. Args: + non_auto_renewable_remainder (:obj:yandex_music.RenewableRemainder`): Напоминание о продлении. auto_renewable (:obj:`list` из :obj:`yandex_music.AutoRenewable`, optional): Автопродление. can_start_trial (:obj:`bool`, optional): Есть ли возможность начать пробный период. mcdonalds (:obj:`bool`, optional): mcdonalds TODO. @@ -26,7 +28,8 @@ class Subscription(YandexMusicObject): """ def __init__(self, - auto_renewable: List['AutoRenewable'] = None, + non_auto_renewable_remainder: 'RenewableRemainder', + auto_renewable: List['AutoRenewable'], can_start_trial: Optional[bool] = None, mcdonalds: Optional[bool] = None, end: Optional[str] = None, @@ -34,13 +37,14 @@ class Subscription(YandexMusicObject): **kwargs) -> None: super().handle_unknown_kwargs(self, **kwargs) + self.non_auto_renewable_remainder = non_auto_renewable_remainder self.auto_renewable = auto_renewable self.can_start_trial = can_start_trial self.mcdonalds = mcdonalds self.end = end self.client = client - self._id_attrs = (self.auto_renewable,) + self._id_attrs = (self.non_auto_renewable_remainder, self.auto_renewable) @classmethod def de_json(cls, data: dict, client: 'Client') -> Optional['Subscription']: @@ -57,7 +61,9 @@ class Subscription(YandexMusicObject): return None data = super(Subscription, cls).de_json(data, client) - from yandex_music import AutoRenewable + from yandex_music import AutoRenewable, RenewableRemainder data['auto_renewable'] = AutoRenewable.de_list(data.get('auto_renewable'), client) + data['non_auto_renewable_remainder'] = RenewableRemainder.de_json( + data.get('non_auto_renewable_remainder'), client) return cls(client=client, **data) diff --git a/yandex_music/album/album.py b/yandex_music/album/album.py index 7596b31..9809b58 100644 --- a/yandex_music/album/album.py +++ b/yandex_music/album/album.py @@ -16,6 +16,8 @@ class Album(YandexMusicObject): Известные ошибки: `not-found` - альбом с таким ID не существует. + Известные значения поля `meta_type`: `music`. + Attributes: id (:obj:`int`): Идентификатор альбома. error (:obj:`str`): Ошибка получения альбома. @@ -56,6 +58,7 @@ class Album(YandexMusicObject): cover_uri (:obj:`str`, optional): Ссылка на обложку. content_warning (:obj:`str`, optional): Предупреждение о содержимом альбома. genre (:obj:`str`, optional): Жанр музыки. + meta_type (:obj:`str`, optional): Мета тип TODO. og_image (:obj:`str`, optional): Ссылка на превью Open Graph. recent (:obj:`bool`, optional): Является ли альбом новым. very_important (:obj:`bool`, optional): Популярен ли альбом у слушателей. @@ -86,6 +89,7 @@ class Album(YandexMusicObject): content_warning: Optional[str] = None, original_release_year=None, genre: Optional[str] = None, + meta_type: Optional[str] = None, og_image: Optional[str] = None, buy: Optional[list] = None, recent: Optional[bool] = None, @@ -116,6 +120,7 @@ class Album(YandexMusicObject): self.version = version self.cover_uri = cover_uri self.genre = genre + self.meta_type = meta_type self.year = year self.release_date = release_date self.bests = bests diff --git a/yandex_music/artist/artist.py b/yandex_music/artist/artist.py index 810f827..35e22b1 100644 --- a/yandex_music/artist/artist.py +++ b/yandex_music/artist/artist.py @@ -11,12 +11,13 @@ class Artist(YandexMusicObject): Attributes: id (:obj:`int`): Уникальный идентификатор. - error (:obj:`str`): Сообщение об ошибке. + reason (:obj:`str`): Причина отсутствия исполнителя (сообщение об ошибке). name (:obj:`str`): Название. cover (:obj:`yandex_music.Cover` | :obj:`None`): Обложка. various (:obj:`bool`): TODO. composer (:obj:`bool`): TODO. genres (:obj:`list` из :obj:`str`): Жанры. + og_image (:obj:`str`, optional): Ссылка на изображение для Open Graph. op_image (:obj:`str`): Ссылка на изображение обложки. Используется когда не указано поле cover. no_pictures_from_search: TODO. counts (:obj:`yandex_music.Counts` | :obj:`None`): Счётчики. @@ -40,12 +41,13 @@ 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): Обложка. various (:obj:`bool`, optional): TODO. composer (:obj:`bool`, optional): TODO. genres (:obj:`list` из :obj:`str`, optional): Жанры. + og_image (:obj:`str`, optional): Ссылка на изображение для Open Graph. op_image (:obj:`str`, optional): Ссылка на изображение обложки. Используется когда не указано поле cover. no_pictures_from_search: TODO. counts (:obj:`yandex_music.Counts`, optional): Счётчики. @@ -71,12 +73,13 @@ class Artist(YandexMusicObject): def __init__(self, id_: int, - error: Optional[str] = None, + reason: Optional[str] = None, name: Optional[str] = None, cover: Optional['Cover'] = None, various: Optional[bool] = None, composer: Optional[bool] = None, genres: Optional[List[str]] = None, + og_image: Optional[str] = None, op_image: Optional[str] = None, no_pictures_from_search=None, counts: Optional['Counts'] = None, @@ -102,12 +105,13 @@ class Artist(YandexMusicObject): self.id = id_ - self.error = error + self.reason = reason self.name = name self.cover = cover self.various = various self.composer = composer self.genres = genres + self.og_image = og_image self.op_image = op_image self.no_pictures_from_search = no_pictures_from_search self.counts = counts @@ -133,10 +137,20 @@ class Artist(YandexMusicObject): self.client = client self._id_attrs = (self.id, self.name, self.cover) + def download_og_image(self, filename: str, size: str = '200x200') -> None: + """Загрузка изображения для Open Graph. + + Args: + filename (:obj:`str`): Путь для сохранения файла с названием и расширением. + size (:obj:`str`, optional): Размер обложки. + """ + self.client.request.download(f'https://{self.og_image.replace("%%", size)}', filename) + def download_op_image(self, filename: str, size: str = '200x200') -> None: """Загрузка обложки. - Используйте это только когда нет self.cover! + Notes: + Используйте это только когда нет self.cover! Args: filename (:obj:`str`): Путь для сохранения файла с названием и расширением. @@ -220,6 +234,8 @@ class Artist(YandexMusicObject): # camelCase псевдонимы + #: Псевдоним для :attr:`download_og_image` + downloadOgImage = download_og_image #: Псевдоним для :attr:`download_op_image` downloadOpImage = download_op_image #: Псевдоним для :attr:`get_tracks` diff --git a/yandex_music/artist/brief_info.py b/yandex_music/artist/brief_info.py index da9b90b..22f7082 100644 --- a/yandex_music/artist/brief_info.py +++ b/yandex_music/artist/brief_info.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Optional, List from yandex_music import YandexMusicObject if TYPE_CHECKING: - from yandex_music import Client, Artist, Track, Album, Cover, PlaylistId, Video, Chart, Vinyl + from yandex_music import Client, Artist, Track, Album, Cover, PlaylistId, Video, Chart, Vinyl, Playlist class BriefInfo(YandexMusicObject): @@ -12,6 +12,7 @@ class BriefInfo(YandexMusicObject): Attributes: artist (:obj:`yandex_music.Artist` | :obj:`None`): Артист. albums (:obj:`list` из :obj:`yandex_music.Album`): Альбомы. + playlists (:obj:`list` из :obj:`yandex_music.Playlist`): Плейлисты. also_albums (:obj:`list` из :obj:`yandex_music.Album`): Сборники. last_release_ids (:obj:`list` из :obj:`int`): Уникальные идентификаторы последних выпущенных треков. popular_tracks (:obj:`list` из :obj:`yandex_music.Track`): Популярные треки. @@ -28,6 +29,7 @@ class BriefInfo(YandexMusicObject): Args: artist (:obj:`yandex_music.Artist` | :obj:`None`): Артист. albums (:obj:`list` из :obj:`yandex_music.Album`): Альбомы. + playlists (:obj:`list` из :obj:`yandex_music.Playlist`): Плейлисты. also_albums (:obj:`list` из :obj:`yandex_music.Album`): Сборники. last_release_ids (:obj:`list` из :obj:`int`): Уникальные идентификаторы последних выпущенных треков. popular_tracks (:obj:`list` из :obj:`yandex_music.Track`): Популярные треки. @@ -46,6 +48,7 @@ class BriefInfo(YandexMusicObject): def __init__(self, artist: Optional['Artist'], albums: List['Album'], + playlists: List['Playlist'], also_albums: List['Album'], last_release_ids: List[int], popular_tracks: List['Track'], @@ -63,6 +66,7 @@ class BriefInfo(YandexMusicObject): self.artist = artist self.albums = albums + self.playlists = playlists self.also_albums = also_albums self.last_release_ids = last_release_ids self.popular_tracks = popular_tracks @@ -77,9 +81,9 @@ class BriefInfo(YandexMusicObject): self.tracks_in_chart = tracks_in_chart self.client = client - self._id_attrs = (self.artist, self.albums, self.also_albums, self.last_release_ids, self.popular_tracks, - self.similar_artists, self.all_covers, self.concerts, self.videos, self.vinyls, - self.has_promotions, self.playlist_ids) + self._id_attrs = (self.artist, self.albums, self.playlists, self.also_albums, self.last_release_ids, + self.popular_tracks, self.similar_artists, self.all_covers, self.concerts, self.videos, + self.vinyls, self.has_promotions, self.playlist_ids) @classmethod def de_json(cls, data: dict, client: 'Client') -> Optional['BriefInfo']: @@ -96,7 +100,8 @@ class BriefInfo(YandexMusicObject): return None data = super(BriefInfo, cls).de_json(data, client) - from yandex_music import Artist, Track, Album, Cover, PlaylistId, Video, Chart, Vinyl + from yandex_music import Artist, Track, Album, Cover, PlaylistId, Video, Chart, Vinyl, Playlist + data['playlists'] = Playlist.de_list(data.get('playlists'), client) data['artist'] = Artist.de_json(data.get('artist'), client) data['similar_artists'] = Artist.de_list(data.get('similar_artists'), client) data['popular_tracks'] = Track.de_list(data.get('popular_tracks'), client) diff --git a/yandex_music/artist/vinyl.py b/yandex_music/artist/vinyl.py index a29b19f..84ab9f5 100644 --- a/yandex_music/artist/vinyl.py +++ b/yandex_music/artist/vinyl.py @@ -15,6 +15,8 @@ class Vinyl(YandexMusicObject): year (:obj:`int`): Год выпуска. price (:obj:`int`): Цена. media (:obj:`str`): Средство распространения. + offer_id (:obj:`int`): Уникальный идентификатор предложения. + artist_ids (:obj:`list` из :obj:`int`): Перечень уникальный идентификаторов исполнителей. picture (:obj:`str`): Ссылка на обложку. client (:obj:`yandex_music.Client`): Клиент Yandex Music. @@ -24,6 +26,8 @@ class Vinyl(YandexMusicObject): year (:obj:`int`): Год выпуска. price (:obj:`int`): Цена. media (:obj:`str`): Средство распространения. + offer_id (:obj:`int`): Уникальный идентификатор предложения. + artist_ids (:obj:`list` из :obj:`int`): Перечень уникальный идентификаторов исполнителей. picture (:obj:`str`, optional): Ссылка на обложку. client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music. **kwargs: Произвольные ключевые аргументы полученные от API. @@ -35,6 +39,8 @@ class Vinyl(YandexMusicObject): year: int, price: int, media: str, + offer_id: int, + artist_ids: List[int], picture: Optional[str] = None, client: Optional['Client'] = None, **kwargs) -> None: @@ -46,9 +52,12 @@ class Vinyl(YandexMusicObject): self.year = year self.price = price self.media = media + self.offer_id = offer_id + self.artist_ids = artist_ids self.client = client - self._id_attrs = (self.title, self.price, self.year, self.url, self.price, self.media) + self._id_attrs = (self.title, self.price, self.year, self.url, self.price, + self.media, self.offer_id, self.artist_ids) @classmethod def de_json(cls, data: dict, client: 'Client') -> Optional['Vinyl']: diff --git a/yandex_music/cover.py b/yandex_music/cover.py index 71b607f..ac5f63c 100644 --- a/yandex_music/cover.py +++ b/yandex_music/cover.py @@ -15,6 +15,7 @@ class Cover(YandexMusicObject): items_uri (:obj:`str`): Список ссылок на изображения. dir (:obj:`str`): Директория хранения изображения на сервере. version (:obj:`str`): Версия. + is_custom (:obj:`bool`): Является ли обложка пользовательской. custom (:obj:`bool`): Является ли обложка пользовательской. prefix (:obj:`str`): Уникальный идентификатор. error (:obj:`str`): Сообщение об ошибке. @@ -26,6 +27,7 @@ class Cover(YandexMusicObject): items_uri (:obj:`str`, optional): Список ссылок на изображения. dir_ (:obj:`str`, optional): Директория хранения изображения на сервере. version (:obj:`str`, optional): Версия. + is_custom (:obj:`bool`, optional): Является ли обложка пользовательской. custom (:obj:`bool`, optional): Является ли обложка пользовательской. prefix (:obj:`str`, optional): Уникальный идентификатор. error (:obj:`str`, optional): Сообщение об ошибке. @@ -40,6 +42,7 @@ class Cover(YandexMusicObject): dir_: Optional[str] = None, version: Optional[str] = None, custom: Optional[bool] = None, + is_custom: Optional[bool] = None, prefix: Optional[str] = None, error: Optional[str] = None, client: Optional['Client'] = None, @@ -53,6 +56,7 @@ class Cover(YandexMusicObject): self.dir = dir_ self.version = version self.custom = custom + self.is_custom = is_custom self.error = error self.client = client diff --git a/yandex_music/track/track.py b/yandex_music/track/track.py index ae24b60..c0a0e84 100644 --- a/yandex_music/track/track.py +++ b/yandex_music/track/track.py @@ -23,6 +23,7 @@ class Track(YandexMusicObject): albums (:obj:`list` из :obj:`yandex_music.Album`): Альбомы. available_for_premium_users (:obj:`bool`): Доступен ли для пользователей с подпиской. lyrics_available (:obj:`bool`): Доступен ли текст песни. + best (:obj:`bool`): Лучшей ли трек TODO. real_id (:obj:`int` | :obj:`str`): TODO. og_image (:obj:`str`): Ссылка на превью Open Graph. type (:obj:`str`): Тип. @@ -52,6 +53,7 @@ class Track(YandexMusicObject): albums (:obj:`list` из :obj:`yandex_music.Album`, optional): Альбомы. available_for_premium_users (:obj:`bool`, optional): Доступен ли для пользователей с подпиской. lyrics_available (:obj:`bool`, optional): Доступен ли текст песни. + best (:obj:`bool`, optional): Лучшей ли трек TODO. real_id (:obj:`int` | :obj:`str`, optional): TODO. og_image (:obj:`str`, optional): Ссылка на превью Open Graph. type_ (:obj:`str`, optional): Тип. @@ -82,6 +84,7 @@ class Track(YandexMusicObject): albums: List['Album'] = None, available_for_premium_users: Optional[bool] = None, lyrics_available: Optional[bool] = None, + best: Optional[bool] = None, real_id: Optional[Union[str, int]] = None, og_image: Optional[str] = None, type_: Optional[str] = None, @@ -105,13 +108,14 @@ class Track(YandexMusicObject): super().handle_unknown_kwargs(self, **kwargs) self.id = id_ + self.title = title self.available = available self.artists = artists self.albums = albums - self.available_for_premium_users = available_for_premium_users self.lyrics_available = lyrics_available + self.best = best self.real_id = real_id self.og_image = og_image self.type = type_ @@ -134,7 +138,7 @@ class Track(YandexMusicObject): self.download_info = None self.client = client - self._id_attrs = (self.id, self.title, self.available, self.artists, self.albums) + self._id_attrs = (self.id,) def get_download_info(self, get_direct_links=False) -> List['DownloadInfo']: """Сокращение для::