|
1 | 1 | import asyncio |
2 | 2 | import aiohttp |
3 | 3 | import logging |
4 | | -from typing import List, Optional, Union, TypeVar, Type, Dict, Any, Generic |
| 4 | +from typing import List, Optional, Union, TypeVar, Type, Dict, Any, Generic, AsyncGenerator |
5 | 5 |
|
6 | 6 | from .methods.fetch import _fetch_api |
7 | 7 | from .apitypes.common import ( |
@@ -114,14 +114,92 @@ async def query( |
114 | 114 | query_options.fields = "id" |
115 | 115 | return await self._post_query(query_options) |
116 | 116 |
|
117 | | - async def validate_filters(self, filters: Union[List, str, None]) -> Dict[str, Any]: |
118 | | - """Validates filters against the schema for this specific endpoint.""" |
119 | | - return await self._client.validate_filters(self._endpoint_path, filters) |
120 | | - |
121 | | - async def get_available_fields(self) -> List[str]: |
122 | | - """Gets all available filterable fields for this endpoint.""" |
123 | | - return await self._client.get_available_fields(self._endpoint_path) |
124 | | - |
| 117 | + async def query_all_pages( |
| 118 | + self, query_options: QueryRequest = QueryRequest(), max_pages: Optional[int] = None |
| 119 | + ) -> List[T_QueryItem]: |
| 120 | + """ |
| 121 | + Fetch all results across multiple pages automatically. |
| 122 | + |
| 123 | + Args: |
| 124 | + query_options: The query to execute |
| 125 | + max_pages: Maximum number of pages to fetch (None for unlimited) |
| 126 | + |
| 127 | + Returns: |
| 128 | + List of all results from all pages |
| 129 | + """ |
| 130 | + if not query_options.fields: |
| 131 | + query_options.fields = "id" |
| 132 | + |
| 133 | + all_results = [] |
| 134 | + page_number = 1 |
| 135 | + |
| 136 | + while True: |
| 137 | + # Create a copy of the query options with the current page number |
| 138 | + current_query = QueryRequest( |
| 139 | + filters=query_options.filters, |
| 140 | + fields=query_options.fields, |
| 141 | + sort=query_options.sort, |
| 142 | + reverse=query_options.reverse, |
| 143 | + results=query_options.results, |
| 144 | + page=page_number, |
| 145 | + user=query_options.user, |
| 146 | + count=query_options.count, |
| 147 | + compact_filters=query_options.compact_filters, |
| 148 | + normalized_filters=query_options.normalized_filters, |
| 149 | + ) |
| 150 | + |
| 151 | + response = await self._post_query(current_query) |
| 152 | + all_results.extend(response.results) |
| 153 | + |
| 154 | + if not response.more: |
| 155 | + break |
| 156 | + |
| 157 | + if max_pages and page_number >= max_pages: |
| 158 | + break |
| 159 | + |
| 160 | + page_number += 1 |
| 161 | + |
| 162 | + return all_results |
| 163 | + |
| 164 | + async def query_paginated( |
| 165 | + self, query_options: QueryRequest = QueryRequest() |
| 166 | + ) -> AsyncGenerator[QueryResponse[T_QueryItem], None]: |
| 167 | + """ |
| 168 | + Generator that yields query responses page by page. |
| 169 | + |
| 170 | + Args: |
| 171 | + query_options: The query to execute |
| 172 | + |
| 173 | + Yields: |
| 174 | + QueryResponse objects for each page |
| 175 | + """ |
| 176 | + if not query_options.fields: |
| 177 | + query_options.fields = "id" |
| 178 | + |
| 179 | + page_number = 1 |
| 180 | + |
| 181 | + while True: |
| 182 | + # Create a copy of the query options with the current page number |
| 183 | + current_query = QueryRequest( |
| 184 | + filters=query_options.filters, |
| 185 | + fields=query_options.fields, |
| 186 | + sort=query_options.sort, |
| 187 | + reverse=query_options.reverse, |
| 188 | + results=query_options.results, |
| 189 | + page=page_number, |
| 190 | + user=query_options.user, |
| 191 | + count=query_options.count, |
| 192 | + compact_filters=query_options.compact_filters, |
| 193 | + normalized_filters=query_options.normalized_filters, |
| 194 | + ) |
| 195 | + |
| 196 | + response = await self._post_query(current_query) |
| 197 | + yield response |
| 198 | + |
| 199 | + if not response.more: |
| 200 | + break |
| 201 | + |
| 202 | + page_number += 1 |
125 | 203 |
|
126 | 204 | class _VNClient(_BaseEntityClient[VN, VN]): |
127 | 205 | def __init__(self, client: "VNDB"): |
@@ -229,6 +307,88 @@ async def delete_entry(self, vn_id: VNDBID) -> None: |
229 | 307 | session = self._client._get_session() |
230 | 308 | await _fetch_api(session=session, method="DELETE", url=url, token=self._client.api_token) |
231 | 309 |
|
| 310 | + async def query_all_pages( |
| 311 | + self, user_id: VNDBID, query_options: QueryRequest = QueryRequest(), max_pages: Optional[int] = None |
| 312 | + ) -> List[UlistItem]: |
| 313 | + """ |
| 314 | + Fetch all ulist results across multiple pages automatically. |
| 315 | + |
| 316 | + Args: |
| 317 | + user_id: The user ID to query |
| 318 | + query_options: The query to execute |
| 319 | + max_pages: Maximum number of pages to fetch (None for unlimited) |
| 320 | + |
| 321 | + Returns: |
| 322 | + List of all results from all pages |
| 323 | + """ |
| 324 | + all_results = [] |
| 325 | + page_number = 1 |
| 326 | + |
| 327 | + while True: |
| 328 | + # Create a copy of the query options with the current page number |
| 329 | + current_query = QueryRequest( |
| 330 | + filters=query_options.filters, |
| 331 | + fields=query_options.fields, |
| 332 | + sort=query_options.sort, |
| 333 | + reverse=query_options.reverse, |
| 334 | + results=query_options.results, |
| 335 | + page=page_number, |
| 336 | + user=query_options.user, |
| 337 | + count=query_options.count, |
| 338 | + compact_filters=query_options.compact_filters, |
| 339 | + normalized_filters=query_options.normalized_filters, |
| 340 | + ) |
| 341 | + |
| 342 | + response = await self.query(user_id, current_query) |
| 343 | + all_results.extend(response.results) |
| 344 | + |
| 345 | + if not response.more: |
| 346 | + break |
| 347 | + |
| 348 | + if max_pages and page_number >= max_pages: |
| 349 | + break |
| 350 | + |
| 351 | + page_number += 1 |
| 352 | + |
| 353 | + return all_results |
| 354 | + |
| 355 | + async def query_paginated( |
| 356 | + self, user_id: VNDBID, query_options: QueryRequest = QueryRequest() |
| 357 | + ) -> AsyncGenerator[QueryResponse[UlistItem], None]: |
| 358 | + """ |
| 359 | + Generator that yields ulist query responses page by page. |
| 360 | + |
| 361 | + Args: |
| 362 | + user_id: The user ID to query |
| 363 | + query_options: The query to execute |
| 364 | + |
| 365 | + Yields: |
| 366 | + QueryResponse objects for each page |
| 367 | + """ |
| 368 | + page_number = 1 |
| 369 | + |
| 370 | + while True: |
| 371 | + # Create a copy of the query options with the current page number |
| 372 | + current_query = QueryRequest( |
| 373 | + filters=query_options.filters, |
| 374 | + fields=query_options.fields, |
| 375 | + sort=query_options.sort, |
| 376 | + reverse=query_options.reverse, |
| 377 | + results=query_options.results, |
| 378 | + page=page_number, |
| 379 | + user=query_options.user, |
| 380 | + count=query_options.count, |
| 381 | + compact_filters=query_options.compact_filters, |
| 382 | + normalized_filters=query_options.normalized_filters, |
| 383 | + ) |
| 384 | + |
| 385 | + response = await self.query(user_id, current_query) |
| 386 | + yield response |
| 387 | + |
| 388 | + if not response.more: |
| 389 | + break |
| 390 | + |
| 391 | + page_number += 1 |
232 | 392 |
|
233 | 393 | class _RlistClient: |
234 | 394 | def __init__(self, client: "VNDB"): |
|
0 commit comments