@@ -659,7 +659,7 @@ def _query_resource(
659659 use_document_model: if None, will defer to the self.use_document_model attribute
660660 num_chunks: Maximum number of chunks of data to yield. None will yield all possible.
661661 chunk_size: Number of data entries per chunk.
662- timeout : Time in seconds to wait until a request timeout error is thrown
662+ timeout (float or None) : Time in seconds to wait until a request timeout error is thrown
663663
664664 Returns:
665665 A Resource, a dict with two keys, "data" containing a list of documents, and
@@ -805,27 +805,32 @@ def _query_resource(
805805 except RequestException as ex :
806806 raise MPRestError (str (ex ))
807807
808- def _submit_requests ( # noqa
808+ def _submit_requests (
809809 self ,
810- url ,
811- criteria ,
812- use_document_model ,
813- chunk_size ,
814- num_chunks = None ,
815- timeout = None ,
810+ url : str ,
811+ criteria : dict [str , Any ],
812+ use_document_model : bool ,
813+ chunk_size : int | None ,
814+ num_chunks : int | None = None ,
815+ timeout : int | None = None ,
816+ max_batch_size : int = 100 ,
817+ norecur : bool = False ,
816818 ) -> dict :
817819 """Handle submitting requests sequentially with pagination.
818820
819821 If criteria contains comma-separated parameters (except those that are naturally comma-separated),
820822 split them into multiple sequential requests and combine results.
821823
822824 Arguments:
823- criteria: dictionary of criteria to filter down
824- url: url used to make request
825- use_document_model: if None, will defer to the self.use_document_model attribute
826- num_chunks: Maximum number of chunks of data to yield. None will yield all possible.
827- chunk_size: Number of data entries per chunk.
828- timeout: Time in seconds to wait until a request timeout error is thrown
825+ url (str): url used to make request
826+ criteria (dict of str): dictionary of criteria to filter down
827+ use_document_model (bool): whether to use the document model
828+ num_chunks (int or None): Maximum number of chunks of data to yield. None will yield all possible.
829+ chunk_size (int or None): Number of data entries per chunk.
830+ timeout (int or None): Time in seconds to wait until a request timeout error is thrown
831+ max_batch_size (int) : Maximum size of a batch when retrieving batches in parallel
832+ norecur (bool) : Whether to forbid recursive splitting of a query field
833+ when a direct query fails
829834
830835 Returns:
831836 Dictionary containing data and metadata
@@ -884,14 +889,6 @@ def _submit_requests( # noqa
884889 timeout = timeout ,
885890 )
886891
887- # Check if we got 0 results - some parameters are silently ignored by the API
888- # when passed as comma-separated values, so we need to split them anyway
889- if total_num_docs == 0 and len (split_values ) > 1 :
890- # Treat this the same as a 422 error - split into batches
891- raise MPRestError (
892- "Got 0 results for comma-separated parameter, will try splitting"
893- )
894-
895892 # If successful, continue with normal pagination
896893 data_chunks = [data ["data" ]]
897894 total_data : dict [str , Any ] = {"data" : []}
@@ -903,18 +900,26 @@ def _submit_requests( # noqa
903900 # Continue with pagination if needed (handled below)
904901
905902 except MPRestError as e :
906- # If we get 422 or 414 error, or 0 results for comma-separated params, split into batches
907- if any (trace in str (e ) for trace in ("422" , "414" , "Got 0 results" )):
903+ # If we get 422 or 414 error, split into batches
904+ if not norecur and any (
905+ trace in str (e )
906+ for trace in (
907+ "422" ,
908+ "414" ,
909+ )
910+ ):
908911 total_data = {"data" : []}
909912 total_num_docs = 0
910913 data_chunks = []
911914
912915 # Batch the split values to reduce number of requests
913916 # Use batches of up to 100 values to balance URL length and request count
914- batch_size = min (100 , max (1 , len (split_values ) // 10 ))
917+ num_batches = min (
918+ max_batch_size , max (1 , len (split_values ) // max_batch_size )
919+ )
920+ batch_size = min (len (split_values ), max_batch_size )
915921
916922 # Setup progress bar for split parameter requests
917- num_batches = ceil (len (split_values ) / batch_size )
918923 pbar_message = f"Retrieving { len (split_values )} { split_param } values in { num_batches } batches"
919924 pbar = (
920925 tqdm (
@@ -938,6 +943,7 @@ def _submit_requests( # noqa
938943 chunk_size = chunk_size ,
939944 num_chunks = num_chunks ,
940945 timeout = timeout ,
946+ norecur = len (batch ) <= max_batch_size ,
941947 )
942948
943949 data_chunks .append (result ["data" ])
@@ -983,6 +989,12 @@ def _submit_requests( # noqa
983989 if "meta" in data :
984990 total_data ["meta" ] = data ["meta" ]
985991
992+ # otherwise, paginate sequentially
993+ if chunk_size is None or chunk_size < 1 :
994+ raise ValueError (
995+ "A positive chunk size must be provided to enable pagination"
996+ )
997+
986998 # Get max number of response pages
987999 max_pages = (
9881000 num_chunks if num_chunks is not None else ceil (total_num_docs / chunk_size )
@@ -1002,7 +1014,7 @@ def _submit_requests( # noqa
10021014 desc = pbar_message ,
10031015 total = num_docs_needed ,
10041016 )
1005- if not self .mute_progress_bars
1017+ if not self .mute_progress_bars and total_num_docs > 0
10061018 else None
10071019 )
10081020
@@ -1022,10 +1034,6 @@ def _submit_requests( # noqa
10221034 pbar .close ()
10231035 return new_total_data
10241036
1025- # otherwise, paginate sequentially
1026- if chunk_size is None :
1027- raise ValueError ("A chunk size must be provided to enable pagination" )
1028-
10291037 # Warning to select specific fields only for many results
10301038 if criteria .get ("_all_fields" , False ) and (total_num_docs / chunk_size > 10 ):
10311039 warnings .warn (
0 commit comments