ymdantic 0.2.1__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. ymdantic-0.2.2/.github/workflows/tests.yml +104 -0
  2. {ymdantic-0.2.1 → ymdantic-0.2.2}/.pre-commit-config.yaml +5 -0
  3. {ymdantic-0.2.1 → ymdantic-0.2.2}/PKG-INFO +1 -1
  4. {ymdantic-0.2.1 → ymdantic-0.2.2}/pyproject.toml +1 -1
  5. {ymdantic-0.2.1 → ymdantic-0.2.2}/uv.lock +1 -1
  6. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/client/session/aiohttp_client.py +62 -3
  7. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/client/yandex_music.py +12 -6
  8. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/search/base.py +16 -1
  9. ymdantic-0.2.1/.github/workflows/tests.yml +0 -40
  10. {ymdantic-0.2.1 → ymdantic-0.2.2}/.editorconfig +0 -0
  11. {ymdantic-0.2.1 → ymdantic-0.2.2}/.github/workflows/pypi-release.yml +0 -0
  12. {ymdantic-0.2.1 → ymdantic-0.2.2}/.gitignore +0 -0
  13. {ymdantic-0.2.1 → ymdantic-0.2.2}/LICENSE +0 -0
  14. {ymdantic-0.2.1 → ymdantic-0.2.2}/README.md +0 -0
  15. {ymdantic-0.2.1 → ymdantic-0.2.2}/examples/chart.py +0 -0
  16. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/__init__.py +0 -0
  17. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/account/__init__.py +0 -0
  18. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/account/test_settings.py +0 -0
  19. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/conftest.py +0 -0
  20. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/search/__init__.py +0 -0
  21. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/search/test_search_instant_mixed.py +0 -0
  22. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/tracks/__init__.py +0 -0
  23. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/tracks/test_get_track.py +0 -0
  24. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/tracks/test_get_track_download_info.py +0 -0
  25. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/tracks/test_get_track_file_info.py +0 -0
  26. {ymdantic-0.2.1 → ymdantic-0.2.2}/tests/tracks/test_get_tracks.py +0 -0
  27. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/__init__.py +0 -0
  28. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/adapters/__init__.py +0 -0
  29. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/adapters/pydantic_factory.py +0 -0
  30. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/adapters/to_camel.py +0 -0
  31. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/adapters/to_query_params.py +0 -0
  32. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/client/__init__.py +0 -0
  33. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/client/session/__init__.py +0 -0
  34. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/client/session/aiohttp_method.py +0 -0
  35. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/__init__.py +0 -0
  36. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/editorial_artists.py +0 -0
  37. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/editorial_compilation.py +0 -0
  38. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/editorial_new_releases.py +0 -0
  39. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/editorial_promotion.py +0 -0
  40. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/language.py +0 -0
  41. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/open_playlist.py +0 -0
  42. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/enums/special.py +0 -0
  43. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/exceptions/__init__.py +0 -0
  44. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/exceptions/custom_exceptions.py +0 -0
  45. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/mixins.py +0 -0
  46. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/__init__.py +0 -0
  47. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/account/__init__.py +0 -0
  48. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/account/settings.py +0 -0
  49. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/action_button.py +0 -0
  50. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/agent.py +0 -0
  51. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/albums/__init__.py +0 -0
  52. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/albums/album.py +0 -0
  53. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/albums/label.py +0 -0
  54. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/__init__.py +0 -0
  55. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/artist.py +0 -0
  56. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/artist_data.py +0 -0
  57. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/artist_track_chart_position.py +0 -0
  58. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/band_link_scanner_link.py +0 -0
  59. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/concert.py +0 -0
  60. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/counts.py +0 -0
  61. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/description.py +0 -0
  62. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/extra_action.py +0 -0
  63. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/ratings.py +0 -0
  64. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/social_link.py +0 -0
  65. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/artists/video.py +0 -0
  66. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/base.py +0 -0
  67. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/chart_position.py +0 -0
  68. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/clips/__init__.py +0 -0
  69. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/clips/clip.py +0 -0
  70. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/concerts/__init__.py +0 -0
  71. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/concerts/city_case_forms.py +0 -0
  72. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/concerts/concert.py +0 -0
  73. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/content_restrictions.py +0 -0
  74. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/cover.py +0 -0
  75. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/custom_wave.py +0 -0
  76. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/derived_colors.py +0 -0
  77. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/error.py +0 -0
  78. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/__init__.py +0 -0
  79. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/album.py +0 -0
  80. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/artist.py +0 -0
  81. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/chart.py +0 -0
  82. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/chart_block.py +0 -0
  83. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/cover.py +0 -0
  84. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/editorial/__init__.py +0 -0
  85. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/editorial/new_releases.py +0 -0
  86. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/editorial/response.py +0 -0
  87. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/in_style.py +0 -0
  88. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/liked_playlist.py +0 -0
  89. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/open_playlist.py +0 -0
  90. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/personal_playlist.py +0 -0
  91. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/playlist.py +0 -0
  92. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/promotion.py +0 -0
  93. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/__init__.py +0 -0
  94. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/skeleton_response.py +0 -0
  95. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/tab_block.py +0 -0
  96. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/tab_data.py +0 -0
  97. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/tab_source.py +0 -0
  98. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/tabs_block.py +0 -0
  99. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/skeleton/tabs_source.py +0 -0
  100. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/special.py +0 -0
  101. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/view_all_action.py +0 -0
  102. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing/waves.py +0 -0
  103. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing3/__init__.py +0 -0
  104. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing3/block.py +0 -0
  105. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing3/chart.py +0 -0
  106. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/landing3/menu.py +0 -0
  107. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/pager.py +0 -0
  108. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/__init__.py +0 -0
  109. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/cover.py +0 -0
  110. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/owner.py +0 -0
  111. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/playlist.py +0 -0
  112. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/tag.py +0 -0
  113. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/playlists/track.py +0 -0
  114. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/response.py +0 -0
  115. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/s3.py +0 -0
  116. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/search/__init__.py +0 -0
  117. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/search/results.py +0 -0
  118. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/theme.py +0 -0
  119. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/__init__.py +0 -0
  120. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/album.py +0 -0
  121. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/download_info.py +0 -0
  122. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/fade.py +0 -0
  123. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/file_info.py +0 -0
  124. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/lyrics_info.py +0 -0
  125. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/major.py +0 -0
  126. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/podcast.py +0 -0
  127. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/position.py +0 -0
  128. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/r128.py +0 -0
  129. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/tracks/track.py +0 -0
  130. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/models/trailer.py +0 -0
  131. {ymdantic-0.2.1 → ymdantic-0.2.2}/ymdantic/py.typed +0 -0
@@ -0,0 +1,104 @@
1
+ name: Testing YMdantic
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ pull_request_target:
7
+ types: [opened, synchronize, reopened]
8
+
9
+ jobs:
10
+ lint:
11
+ if: github.event_name != 'pull_request_target'
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.12", "3.13", "3.14"]
17
+ check:
18
+ - name: Ruff format
19
+ cmd: ruff format --diff
20
+ - name: Ruff check
21
+ cmd: ruff check ymdantic tests
22
+ - name: Mypy
23
+ cmd: mypy ymdantic tests
24
+
25
+ name: "${{ matrix.check.name }} (py${{ matrix.python-version }})"
26
+
27
+ steps:
28
+ - uses: actions/checkout@v6
29
+
30
+ - name: Install uv
31
+ uses: astral-sh/setup-uv@v7
32
+ with:
33
+ version: "0.9.17"
34
+ python-version: ${{ matrix.python-version }}
35
+ enable-cache: true
36
+
37
+ - name: Install deps
38
+ run: uv sync --locked --all-groups
39
+
40
+ - name: Run check
41
+ run: uv run ${{ matrix.check.cmd }}
42
+
43
+ test_push:
44
+ if: github.event_name == 'push'
45
+ runs-on: ubuntu-latest
46
+ strategy:
47
+ fail-fast: false
48
+ matrix:
49
+ python-version: ["3.12", "3.13", "3.14"]
50
+
51
+ name: "Pytest push (py${{ matrix.python-version }})"
52
+
53
+ steps:
54
+ - uses: actions/checkout@v6
55
+
56
+ - name: Install uv
57
+ uses: astral-sh/setup-uv@v7
58
+ with:
59
+ version: "0.9.17"
60
+ python-version: ${{ matrix.python-version }}
61
+ enable-cache: true
62
+
63
+ - name: Install deps
64
+ run: uv sync --locked --all-groups
65
+
66
+ - name: Run Pytest
67
+ env:
68
+ YM_TOKEN: ${{ secrets.YM_TOKEN }}
69
+ run: uv run pytest -vv tests
70
+
71
+ test_pr_approved:
72
+ if: github.event_name == 'pull_request_target'
73
+ runs-on: ubuntu-latest
74
+ environment: pull_requests
75
+ strategy:
76
+ fail-fast: false
77
+ matrix:
78
+ python-version: ["3.12", "3.13", "3.14"]
79
+
80
+ name: "Pytest PR approved (py${{ matrix.python-version }})"
81
+
82
+ permissions:
83
+ contents: read
84
+ pull-requests: read
85
+
86
+ steps:
87
+ - uses: actions/checkout@v6
88
+ with:
89
+ ref: ${{ github.event.pull_request.head.sha }}
90
+
91
+ - name: Install uv
92
+ uses: astral-sh/setup-uv@v7
93
+ with:
94
+ version: "0.9.17"
95
+ python-version: ${{ matrix.python-version }}
96
+ enable-cache: true
97
+
98
+ - name: Install deps
99
+ run: uv sync --locked --all-groups
100
+
101
+ - name: Run Pytest
102
+ env:
103
+ YM_TOKEN: ${{ secrets.YM_TOKEN }}
104
+ run: uv run pytest -vv tests
@@ -1,4 +1,9 @@
1
1
  repos:
2
+ - repo: https://github.com/astral-sh/uv-pre-commit
3
+ rev: 0.9.7
4
+ hooks:
5
+ - id: uv-lock
6
+
2
7
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
8
  rev: v6.0.0
4
9
  hooks:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ymdantic
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Фреймворк предоставляющий доступ к API Яндекс Музыки (с Pydantic валидацией)
5
5
  Author-email: KatantDev <vlad26@mail.ru>
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ymdantic"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  description = "Фреймворк предоставляющий доступ к API Яндекс Музыки (с Pydantic валидацией)"
5
5
  authors = [{ name = "KatantDev", email = "vlad26@mail.ru" }]
6
6
  requires-python = ">=3.12,<3.15"
@@ -1122,7 +1122,7 @@ wheels = [
1122
1122
 
1123
1123
  [[package]]
1124
1124
  name = "ymdantic"
1125
- version = "0.2.1"
1125
+ version = "0.2.2"
1126
1126
  source = { editable = "." }
1127
1127
  dependencies = [
1128
1128
  { name = "aiohttp" },
@@ -3,7 +3,7 @@ import urllib.parse
3
3
  from types import TracebackType
4
4
  from typing import Any, Optional, Self
5
5
 
6
- from aiohttp import ClientError, ClientSession, ClientTimeout, FormData
6
+ from aiohttp import ClientError, ClientSession, ClientTimeout, FormData, TCPConnector
7
7
  from dataclass_rest.base_client import BaseClient
8
8
  from dataclass_rest.exceptions import ClientLibraryError
9
9
  from dataclass_rest.http_request import HttpRequest
@@ -22,14 +22,73 @@ class AiohttpClient(BaseClient):
22
22
  session: Optional[ClientSession] = None,
23
23
  headers: Optional[dict[str, Any]] = None,
24
24
  timeout: Optional[ClientTimeout] = None,
25
+ proxy: Optional[str] = None,
25
26
  ) -> None:
26
27
  super().__init__()
27
28
  self.base_url = base_url
28
29
  self.headers = headers or {}
30
+ self.proxy = proxy
31
+ self.timeout = timeout
29
32
 
30
- self._session = session or ClientSession(
33
+ self._session = session or self._create_session(headers=headers)
34
+
35
+ def _create_session(self, headers: dict[str, Any] | None) -> ClientSession:
36
+ """
37
+ Создает ClientSession с учетом прокси.
38
+
39
+ Поддерживает HTTP, HTTPS и SOCKS прокси (4, 4a, 5).
40
+
41
+ :param headers:
42
+ :return: aiohttp ClientSession.
43
+ """
44
+ if self.proxy is None:
45
+ return ClientSession(
46
+ headers=headers,
47
+ timeout=self.timeout or ClientTimeout(total=0),
48
+ )
49
+
50
+ try:
51
+ from aiohttp_socks import ProxyConnector # noqa: PLC0415
52
+ except ImportError as e:
53
+ raise ImportError(
54
+ "Warning: aiohttp_socks not installed. "
55
+ "SOCKS proxies will not work. "
56
+ "Install with: pip install aiohttp_socks",
57
+ ) from e
58
+
59
+ # Определяем тип прокси по схеме
60
+ proxy_lower = self.proxy.lower()
61
+
62
+ # SOCKS прокси (поддерживаются socks4, socks4a, socks5, socks5h)
63
+ if any(
64
+ scheme in proxy_lower
65
+ for scheme in ["socks4", "socks5", "socks5h", "socks4a"]
66
+ ):
67
+ # Используем ProxyConnector для SOCKS
68
+ connector = ProxyConnector.from_url(self.proxy)
69
+ return ClientSession(
70
+ connector=connector,
71
+ headers=headers,
72
+ timeout=self.timeout or ClientTimeout(total=0),
73
+ )
74
+
75
+ # HTTP/HTTPS прокси
76
+ if proxy_lower.startswith(("http://", "https://")):
77
+ connector = TCPConnector()
78
+ return ClientSession(
79
+ connector=connector,
80
+ proxy=self.proxy,
81
+ headers=headers,
82
+ timeout=self.timeout or ClientTimeout(total=0),
83
+ )
84
+
85
+ # Если схема не распознана, предполагаем HTTP
86
+ connector = TCPConnector()
87
+ return ClientSession(
88
+ connector=connector,
89
+ proxy=f"http://{self.proxy}",
31
90
  headers=headers,
32
- timeout=timeout or ClientTimeout(total=0),
91
+ timeout=self.timeout or ClientTimeout(total=0),
33
92
  )
34
93
 
35
94
  async def close(self) -> None:
@@ -51,6 +51,7 @@ from ymdantic.models import (
51
51
  )
52
52
  from ymdantic.models.account import AccountSettings, SetAccountSettingsParams
53
53
  from ymdantic.models.landing.artist import LandingArtistItemData
54
+ from ymdantic.models.search.base import SearchParamsDict
54
55
 
55
56
 
56
57
  class YMClient(AiohttpClient):
@@ -61,15 +62,20 @@ class YMClient(AiohttpClient):
61
62
  token: str,
62
63
  user_id: int | None = None,
63
64
  base_url: str = "https://api.music.yandex.net/",
65
+ proxy: str | None = None, # Формат: scheme://login:password@ip:port
64
66
  ) -> None:
65
67
  self.user_id = user_id
68
+
69
+ headers = {
70
+ "Accept": "application/json",
71
+ "Authorization": f"OAuth {token}",
72
+ "X-Yandex-Music-Client": "YandexMusicAndroid/24023621",
73
+ }
74
+
66
75
  super().__init__(
67
76
  base_url=base_url,
68
- headers={
69
- "Accept": "application/json",
70
- "Authorization": f"OAuth {token}",
71
- "X-Yandex-Music-Client": "YandexMusicAndroid/24023621",
72
- },
77
+ headers=headers,
78
+ proxy=proxy,
73
79
  )
74
80
 
75
81
  def _init_request_body_factory(self) -> FactoryProtocol:
@@ -441,7 +447,7 @@ class YMClient(AiohttpClient):
441
447
 
442
448
  async def search_instant_mixed(
443
449
  self,
444
- **params: Unpack[SearchParams], # type: ignore[misc]
450
+ **params: Unpack[SearchParamsDict],
445
451
  ) -> SearchInstantMixedResponse:
446
452
  response = await self.search_instant_mixed_request(
447
453
  params=SearchParams(**params),
@@ -1,4 +1,4 @@
1
- from typing import Annotated, Literal
1
+ from typing import Annotated, Literal, NotRequired, TypedDict
2
2
 
3
3
  from pydantic import Field
4
4
 
@@ -24,6 +24,21 @@ class SearchParams(YMPostBaseModel):
24
24
  nocorrect: bool = False
25
25
 
26
26
 
27
+ class SearchParamsDict(TypedDict, total=False):
28
+ """Fields for search function."""
29
+
30
+ text: str
31
+ with_likes_count: NotRequired[bool]
32
+ page: NotRequired[int]
33
+ page_size: NotRequired[int]
34
+ with_best_results: NotRequired[bool]
35
+ type: NotRequired[Literal["all"]]
36
+ filter: NotRequired[
37
+ Literal["track", "artist", "album", "playlist", "podcast", "book", "clip"]
38
+ ]
39
+ nocorrect: NotRequired[bool]
40
+
41
+
27
42
  class SearchFilter(YMBaseModel):
28
43
  """Фильтры для поиска."""
29
44
 
@@ -1,40 +0,0 @@
1
- name: Testing YMdantic
2
-
3
- on: push
4
-
5
- jobs:
6
- lint:
7
- runs-on: ubuntu-latest
8
- strategy:
9
- fail-fast: false
10
- matrix:
11
- python-version: ["3.12", "3.13", "3.14"]
12
- check:
13
- - name: Ruff format
14
- cmd: ruff format --diff
15
- - name: Ruff check
16
- cmd: ruff check ymdantic tests
17
- - name: Mypy
18
- cmd: mypy ymdantic tests
19
- - name: Pytest
20
- cmd: pytest -vv tests
21
-
22
- name: "${{ matrix.check.name }} (py${{ matrix.python-version }})"
23
-
24
- steps:
25
- - uses: actions/checkout@v6
26
-
27
- - name: Install uv
28
- uses: astral-sh/setup-uv@v7
29
- with:
30
- version: "0.9.17"
31
- python-version: ${{ matrix.python-version }}
32
- enable-cache: true
33
-
34
- - name: Install deps
35
- run: uv sync --locked --all-groups
36
-
37
- - name: Run check
38
- env:
39
- YM_TOKEN: ${{ secrets.YM_TOKEN }}
40
- run: uv run ${{ matrix.check.cmd }}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes