|
21 | 21 | from astroquery import log |
22 | 22 | from astroquery.utils import commons, async_to_sync |
23 | 23 | from astroquery.utils.class_or_instance import class_or_instance |
| 24 | +from astropy.utils.console import ProgressBarOrSpinner |
24 | 25 | from astroquery.exceptions import InvalidQueryError, MaxResultsWarning, InputWarning, NoResultsWarning |
25 | 26 |
|
26 | 27 | from astroquery.mast import utils |
@@ -106,7 +107,13 @@ def _parse_result(self, response, *, verbose=False): # Used by the async_to_syn |
106 | 107 | MaxResultsWarning) |
107 | 108 | elif self.service == self._list_products: |
108 | 109 | # Results from post_list_products endpoint need to be handled differently |
109 | | - results = Table(response.json()['products']) |
| 110 | + if isinstance(response, list): # multiple async responses from batching |
| 111 | + combined_products = [] |
| 112 | + for resp in response: |
| 113 | + combined_products.extend(resp.json().get('products', [])) |
| 114 | + return Table(combined_products) |
| 115 | + |
| 116 | + results = Table(response.json()['products']) # single async response |
110 | 117 |
|
111 | 118 | return results |
112 | 119 |
|
@@ -370,13 +377,38 @@ def get_product_list_async(self, datasets): |
370 | 377 | 'list of strings, Astropy Row, Astropy Column, or Astropy Table.') |
371 | 378 |
|
372 | 379 | # Filter out empty strings from IDs |
373 | | - datasets = [item.strip() for item in datasets if item.strip() != '' and item is not None] |
374 | | - if not len(datasets): |
| 380 | + datasets = [item.strip() for item in datasets if item and item.strip()] |
| 381 | + if not datasets: |
375 | 382 | raise InvalidQueryError("Dataset list is empty, no associated products.") |
376 | 383 |
|
377 | | - # Send async service request |
378 | | - params = {'dataset_ids': datasets} |
379 | | - return self._service_api_connection.missions_request_async(self.service, params) |
| 384 | + # Filter out duplicates |
| 385 | + datasets = list(set(datasets)) |
| 386 | + |
| 387 | + # Batch API calls if number of datasets exceeds maximum |
| 388 | + max_batch = 1000 |
| 389 | + num_datasets = len(datasets) |
| 390 | + if num_datasets > max_batch: |
| 391 | + # Split datasets into chunks |
| 392 | + dataset_chunks = list(utils.split_list_into_chunks(datasets, max_batch)) |
| 393 | + |
| 394 | + results = [] # list to store responses from each batch |
| 395 | + with ProgressBarOrSpinner(num_datasets, f'Fetching products for {num_datasets} unique datasets ' |
| 396 | + f'in {len(dataset_chunks)} batches ...') as pb: |
| 397 | + datasets_fetched = 0 |
| 398 | + pb.update(0) |
| 399 | + for chunk in dataset_chunks: |
| 400 | + # Send request for each chunk and add response to list |
| 401 | + params = {'dataset_ids': chunk} |
| 402 | + results.append(self._service_api_connection.missions_request_async(self.service, params)) |
| 403 | + |
| 404 | + # Update progress bar with the number of datasets that have had products fetched |
| 405 | + datasets_fetched += len(chunk) |
| 406 | + pb.update(datasets_fetched) |
| 407 | + return results |
| 408 | + else: |
| 409 | + # Single batch request |
| 410 | + params = {'dataset_ids': datasets} |
| 411 | + return self._service_api_connection.missions_request_async(self.service, params) |
380 | 412 |
|
381 | 413 | def get_unique_product_list(self, datasets): |
382 | 414 | """ |
|
0 commit comments