@@ -77,7 +77,53 @@ def _wait_time(self):
7777
7878 return wait_for
7979
80+ def _get_feeds_results_generator (self , parameters , headers ):
81+ with Client (verify = self .api .verify_ssl , proxy = self .api .proxy_url , timeout = None ) as session :
82+ status_code = None
83+ while status_code != 200 :
84+ resp_data = session .get (url = self .url , params = parameters , headers = headers , ** self .api .extra_request_params )
85+ status_code = resp_data .status_code
86+ self .setStatus (status_code , resp_data )
87+
88+ # Check limit exceeded here
89+ if "response" in resp_data .text and "limit_exceeded" in resp_data .text :
90+ self ._limit_exceeded = True
91+ self ._limit_exceeded_message = "limit exceeded"
92+
93+ yield resp_data
94+
95+ if self ._limit_exceeded :
96+ raise ServiceException (503 , "Limit Exceeded{}" .format (self ._limit_exceeded_message ))
97+
98+ if not self .kwargs .get ("sessionID" ):
99+ # we'll only do iterative request for queries that has sessionID.
100+ # Otherwise, we will have an infinite request if sessionID was not provided but the required data asked is more than the maximum (1 hour of data)
101+ break
102+
103+ def _get_session_params (self ):
104+ parameters = deepcopy (self .kwargs )
105+ parameters .pop ("output_format" , None )
106+ parameters .pop (
107+ "format" , None
108+ ) # For some unknownn reasons, even if "format" is not included in the cli params for feeds endpoint, it is being populated thus we need to remove it. Happens only if using CLI.
109+ headers = {}
110+ if self .kwargs .get ("output_format" , OutputFormat .JSONL .value ) == OutputFormat .CSV .value :
111+ parameters ["headers" ] = int (bool (self .kwargs .get ("headers" , False )))
112+ headers ["accept" ] = HEADER_ACCEPT_KEY_CSV_FORMAT
113+
114+ header_api_key = parameters .pop ("X-Api-Key" , None )
115+ if header_api_key :
116+ headers ["X-Api-Key" ] = header_api_key
117+
118+ return {"parameters" : parameters , "headers" : headers }
119+
80120 def _make_request (self ):
121+ if self .product in FEEDS_PRODUCTS_LIST :
122+ session_params = self ._get_session_params ()
123+ parameters = session_params .get ("parameters" )
124+ headers = session_params .get ("headers" )
125+
126+ return self ._get_feeds_results_generator (parameters = parameters , headers = headers )
81127
82128 with Client (verify = self .api .verify_ssl , proxy = self .api .proxy_url , timeout = None ) as session :
83129 if self .product in [
@@ -92,30 +138,16 @@ def _make_request(self):
92138 patch_data = self .kwargs .copy ()
93139 patch_data .update (self .api .extra_request_params )
94140 return session .patch (url = self .url , json = patch_data )
95- elif self .product in FEEDS_PRODUCTS_LIST :
96- parameters = deepcopy (self .kwargs )
97- parameters .pop ("output_format" , None )
98- parameters .pop (
99- "format" , None
100- ) # For some unknownn reasons, even if "format" is not included in the cli params for feeds endpoint, it is being populated thus we need to remove it. Happens only if using CLI.
101- headers = {}
102- if self .kwargs .get ("output_format" , OutputFormat .JSONL .value ) == OutputFormat .CSV .value :
103- parameters ["headers" ] = int (bool (self .kwargs .get ("headers" , False )))
104- headers ["accept" ] = HEADER_ACCEPT_KEY_CSV_FORMAT
105-
106- header_api_key = parameters .pop ("X-Api-Key" , None )
107- if header_api_key :
108- headers ["X-Api-Key" ] = header_api_key
109-
110- return session .get (url = self .url , params = parameters , headers = headers , ** self .api .extra_request_params )
111141 else :
112142 return session .get (url = self .url , params = self .kwargs , ** self .api .extra_request_params )
113143
114144 def _get_results (self ):
115145 wait_for = self ._wait_time ()
146+ print (f"JD: waitfor: { wait_for } " )
116147 if self .api .rate_limit and (wait_for is None or self .product == "account-information" ):
117148 data = self ._make_request ()
118- if data .status_code == 503 : # pragma: no cover
149+ status_code = data .status_code if self .product not in FEEDS_PRODUCTS_LIST else 200
150+ if status_code == 503 : # pragma: no cover
119151 sleeptime = 60
120152 log .info (
121153 "503 encountered for [%s] - sleeping [%s] seconds before retrying request." ,
@@ -129,18 +161,22 @@ def _get_results(self):
129161
130162 if wait_for > 0 :
131163 log .info ("Sleeping for [%s] prior to requesting [%s]." , wait_for , self .product )
164+ print ("Sleeping for [%s] prior to requesting [%s]." , wait_for , self .product )
132165 time .sleep (wait_for )
133166 return self ._make_request ()
134167
135168 def data (self ):
136169 if self ._data is None :
137170 results = self ._get_results ()
138- self .setStatus (results .status_code , results )
171+ status_code = results .status_code if self .product not in FEEDS_PRODUCTS_LIST else 200
172+ self .setStatus (status_code , results )
139173 if (
140174 self .kwargs .get ("format" , "json" ) == "json"
141175 and self .product not in FEEDS_PRODUCTS_LIST # Special handling of feeds products' data to preserve the result in jsonline format
142176 ):
143177 self ._data = results .json ()
178+ elif self .product in FEEDS_PRODUCTS_LIST :
179+ self ._data = results # Uses generator to handle large data results from feeds endpoint
144180 else :
145181 self ._data = results .text
146182 limit_exceeded , message = self .check_limit_exceeded ()
@@ -155,6 +191,10 @@ def data(self):
155191 return self ._data
156192
157193 def check_limit_exceeded (self ):
194+ if self .product in FEEDS_PRODUCTS_LIST :
195+ # bypass here as this is handled in generator already
196+ return False , ""
197+
158198 if self .kwargs .get ("format" , "json" ) == "json" and self .product not in FEEDS_PRODUCTS_LIST :
159199 if "response" in self ._data and "limit_exceeded" in self ._data ["response" ] and self ._data ["response" ]["limit_exceeded" ] is True :
160200 return True , self ._data ["response" ]["message" ]
@@ -172,7 +212,7 @@ def status(self):
172212
173213 def setStatus (self , code , response = None ):
174214 self ._status = code
175- if code == 200 :
215+ if code == 200 or code == 206 :
176216 return
177217
178218 reason = None
@@ -211,7 +251,7 @@ def response(self):
211251 return self ._response
212252
213253 def items (self ):
214- return self .response ().items ()
254+ return self .response ().items () if isinstance ( self . response (), dict ) else self . response ()
215255
216256 def emails (self ):
217257 """Find and returns all emails mentioned in the response"""
0 commit comments