diff --git a/docs/source/yandex_music.artist.rst b/docs/source/yandex_music.artist.rst index fab914a2..7261d5f6 100644 --- a/docs/source/yandex_music.artist.rst +++ b/docs/source/yandex_music.artist.rst @@ -20,4 +20,5 @@ Submodules yandex_music.artist.description yandex_music.artist.link yandex_music.artist.ratings + yandex_music.artist.stats yandex_music.artist.vinyl diff --git a/docs/source/yandex_music.artist.stats.rst b/docs/source/yandex_music.artist.stats.rst new file mode 100644 index 00000000..22531601 --- /dev/null +++ b/docs/source/yandex_music.artist.stats.rst @@ -0,0 +1,7 @@ +yandex\_music.artist.stats +========================== + +.. automodule:: yandex_music.artist.stats + :members: + :undoc-members: + :show-inheritance: diff --git a/tests/__init__.py b/tests/__init__.py index d9e087d7..00d77eae 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -78,6 +78,7 @@ from .test_station import TestStation from .test_station_data import TestStationData from .test_station_result import TestStationResult +from .test_stats import TestStats from .test_status import TestStatus from .test_subscription import TestSubscription from .test_suggestions import TestSuggestions diff --git a/tests/conftest.py b/tests/conftest.py index 028667f6..dd4ccb2f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -81,6 +81,7 @@ Station, StationData, StationResult, + Stats, Status, Subscription, Tag, @@ -173,6 +174,7 @@ TestStation, TestStationData, TestStationResult, + TestStats, TestStatus, TestSubscription, TestTag, @@ -1326,3 +1328,8 @@ def r_128(): @pytest.fixture(scope='session') def lyrics_info(): return LyricsInfo(TestLyricsInfo.has_available_sync_lyrics, TestLyricsInfo.has_available_text_lyrics) + + +@pytest.fixture(scope='session') +def stats(): + return Stats(TestStats.last_month_listeners, TestStats.last_month_listeners_delta) diff --git a/tests/test_brief_info.py b/tests/test_brief_info.py index d266b021..4aabe35f 100644 --- a/tests/test_brief_info.py +++ b/tests/test_brief_info.py @@ -4,7 +4,7 @@ @pytest.fixture(scope='class') -def brief_info(artist, track, album, playlist, cover, playlist_id, video, chart, vinyl): +def brief_info(artist, track, album, playlist, cover, playlist_id, video, chart, vinyl, stats): return BriefInfo( artist, [album], @@ -20,6 +20,7 @@ def brief_info(artist, track, album, playlist, cover, playlist_id, video, chart, [vinyl], TestBriefInfo.has_promotions, [playlist_id], + stats, [chart], ) @@ -29,7 +30,9 @@ class TestBriefInfo: concerts = None has_promotions = False - def test_expected_values(self, brief_info, artist, track, album, playlist, cover, playlist_id, video, chart, vinyl): + def test_expected_values( + self, brief_info, artist, track, album, playlist, cover, playlist_id, video, chart, vinyl, stats + ): assert brief_info.artist == artist assert brief_info.albums == [album] assert brief_info.playlists == [playlist] @@ -44,6 +47,7 @@ def test_expected_values(self, brief_info, artist, track, album, playlist, cover assert brief_info.vinyls == [vinyl] assert brief_info.has_promotions == self.has_promotions assert brief_info.playlist_ids == [playlist_id] + assert brief_info.stats == stats assert brief_info.tracks_in_chart == [chart] def test_de_json_none(self, client): @@ -83,7 +87,7 @@ def test_de_json_required(self, client, artist, track, album, playlist, cover, p 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, playlist, cover, playlist_id, video, chart, vinyl): + def test_de_json_all(self, client, artist, track, album, playlist, cover, playlist_id, video, chart, vinyl, stats): json_dict = { 'artist': artist.to_dict(), 'albums': [album.to_dict()], @@ -100,6 +104,7 @@ def test_de_json_all(self, client, artist, track, album, playlist, cover, playli 'playlist_ids': [playlist_id.to_dict()], 'tracks_in_chart': [chart.to_dict()], 'playlists': [playlist.to_dict()], + 'stats': stats.to_dict(), } brief_info = BriefInfo.de_json(json_dict, client) @@ -117,9 +122,10 @@ def test_de_json_all(self, client, artist, track, album, playlist, cover, playli assert brief_info.vinyls == [vinyl] assert brief_info.has_promotions == self.has_promotions assert brief_info.playlist_ids == [playlist_id] + assert brief_info.stats == stats assert brief_info.tracks_in_chart == [chart] - def test_equality(self, artist, track, album, playlist, cover, playlist_id, video, vinyl): + def test_equality(self, artist, track, album, playlist, cover, playlist_id, video, vinyl, stats): a = BriefInfo( artist, [album], @@ -135,6 +141,7 @@ def test_equality(self, artist, track, album, playlist, cover, playlist_id, vide [vinyl], self.has_promotions, [playlist_id], + stats, ) b = BriefInfo( artist, @@ -151,6 +158,7 @@ def test_equality(self, artist, track, album, playlist, cover, playlist_id, vide [vinyl], True, [playlist_id], + stats, ) c = BriefInfo( artist, @@ -167,6 +175,7 @@ def test_equality(self, artist, track, album, playlist, cover, playlist_id, vide [vinyl], self.has_promotions, [playlist_id], + stats, ) d = BriefInfo( artist, @@ -183,6 +192,7 @@ def test_equality(self, artist, track, album, playlist, cover, playlist_id, vide [vinyl], self.has_promotions, [playlist_id], + stats, ) assert a != b != c diff --git a/tests/test_stats.py b/tests/test_stats.py new file mode 100644 index 00000000..8f0462b7 --- /dev/null +++ b/tests/test_stats.py @@ -0,0 +1,44 @@ +from yandex_music import Stats + + +class TestStats: + last_month_listeners = 15111 + last_month_listeners_delta = 5111 + + def test_expected_values(self, stats): + assert stats.last_month_listeners == stats.last_month_listeners + assert stats.last_month_listeners_delta == stats.last_month_listeners_delta + + def test_de_json_none(self, client): + assert Stats.de_json({}, client) is None + + def test_de_json_required(self, client): + json_dict = { + 'last_month_listeners': self.last_month_listeners, + 'last_month_listeners_delta': self.last_month_listeners_delta, + } + stats = Stats.de_json(json_dict, client) + + assert stats.last_month_listeners == self.last_month_listeners + assert stats.last_month_listeners_delta == self.last_month_listeners_delta + + def test_de_json_all(self, client): + json_dict = { + 'last_month_listeners': self.last_month_listeners, + 'last_month_listeners_delta': self.last_month_listeners_delta, + } + stats = Stats.de_json(json_dict, client) + + assert stats.last_month_listeners == self.last_month_listeners + assert stats.last_month_listeners_delta == self.last_month_listeners_delta + + def test_equality(self): + a = Stats(self.last_month_listeners, self.last_month_listeners_delta) + b = Stats(51234, self.last_month_listeners_delta) + c = Stats(self.last_month_listeners, self.last_month_listeners_delta) + + assert a != b + assert hash(a) != hash(b) + assert a is not b + + assert a == c diff --git a/yandex_music/__init__.py b/yandex_music/__init__.py index e8bb5a59..16ff9b2e 100644 --- a/yandex_music/__init__.py +++ b/yandex_music/__init__.py @@ -38,6 +38,7 @@ from .artist.description import Description from .artist.link import Link from .artist.ratings import Ratings +from .artist.stats import Stats from .artist.vinyl import Vinyl from .playlist.case_forms import CaseForms @@ -169,6 +170,7 @@ 'Experiments', 'Cover', 'Ratings', + 'Stats', 'Counts', 'Link', 'Artist', diff --git a/yandex_music/artist/brief_info.py b/yandex_music/artist/brief_info.py index 8c7379ce..a77eb3fe 100644 --- a/yandex_music/artist/brief_info.py +++ b/yandex_music/artist/brief_info.py @@ -14,6 +14,7 @@ JSONType, Playlist, PlaylistId, + Stats, Track, Video, Vinyl, @@ -39,6 +40,7 @@ class BriefInfo(YandexMusicModel): vinyls (:obj:`list` из :obj:`yandex_music.Vinyl`): Пластинки. has_promotions (:obj:`bool`): Рекламируется ли TODO. playlist_ids (:obj:`list` из :obj:`yandex_music.PlaylistId`): Уникальные идентификаторы плейлистов. + stats (:obj:`yandex_music.Stats`, optional): Статистика прослушиваний за месяц. tracks_in_chart (:obj:`list` из :obj:`yandex_music.Chart`, optional): Треки в чарте. client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music. """ @@ -57,6 +59,7 @@ class BriefInfo(YandexMusicModel): vinyls: List['Vinyl'] has_promotions: bool playlist_ids: List['PlaylistId'] + stats: Optional['Stats'] = None tracks_in_chart: List['Chart'] = field(default_factory=list) client: Optional['ClientType'] = None @@ -92,7 +95,7 @@ def de_json(cls, data: 'JSONType', client: 'ClientType') -> Optional['BriefInfo' return None cls_data = cls.cleanup_data(data, client) - from yandex_music import Album, Artist, Chart, Cover, Playlist, PlaylistId, Track, Video, Vinyl + from yandex_music import Album, Artist, Chart, Cover, Playlist, PlaylistId, Stats, Track, Video, Vinyl cls_data['playlists'] = Playlist.de_list(data.get('playlists'), client) cls_data['artist'] = Artist.de_json(data.get('artist'), client) @@ -106,5 +109,6 @@ def de_json(cls, data: 'JSONType', client: 'ClientType') -> Optional['BriefInfo' cls_data['videos'] = Video.de_list(data.get('videos'), client) cls_data['tracks_in_chart'] = Chart.de_list(data.get('tracks_in_chart'), client) cls_data['vinyls'] = Vinyl.de_list(data.get('vinyls'), client) + cls_data['stats'] = Stats.de_json(data.get('stats'), client) return cls(client=client, **cls_data) # type: ignore diff --git a/yandex_music/artist/stats.py b/yandex_music/artist/stats.py new file mode 100644 index 00000000..788fe442 --- /dev/null +++ b/yandex_music/artist/stats.py @@ -0,0 +1,25 @@ +from typing import TYPE_CHECKING, Optional + +from yandex_music import YandexMusicModel +from yandex_music.utils import model + +if TYPE_CHECKING: + from yandex_music import ClientType + + +@model +class Stats(YandexMusicModel): + """Класс, представляющий статистику слушателей артиста. + + Attributes: + last_month_listeners (:obj:`int`): Количество слушателей за последний месяц. + last_month_listeners_delta (:obj:`int`): Изменение количества слушателей за последний месяц. + client (:obj:`yandex_music.Client`, optional): Клиент Yandex Music. + """ + + last_month_listeners: int + last_month_listeners_delta: int + client: Optional['ClientType'] = None + + def __post_init__(self) -> None: + self._id_attrs = (self.last_month_listeners, self.last_month_listeners_delta)