@@ -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,15 @@ 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 ()
116146 if self .api .rate_limit and (wait_for is None or self .product == "account-information" ):
117147 data = self ._make_request ()
118- if data .status_code == 503 : # pragma: no cover
148+ status_code = data .status_code if self .product not in FEEDS_PRODUCTS_LIST else 200
149+ if status_code == 503 : # pragma: no cover
119150 sleeptime = 60
120151 log .info (
121152 "503 encountered for [%s] - sleeping [%s] seconds before retrying request." ,
@@ -135,12 +166,15 @@ def _get_results(self):
135166 def data (self ):
136167 if self ._data is None :
137168 results = self ._get_results ()
138- self .setStatus (results .status_code , results )
169+ status_code = results .status_code if self .product not in FEEDS_PRODUCTS_LIST else 200
170+ self .setStatus (status_code , results )
139171 if (
140172 self .kwargs .get ("format" , "json" ) == "json"
141173 and self .product not in FEEDS_PRODUCTS_LIST # Special handling of feeds products' data to preserve the result in jsonline format
142174 ):
143175 self ._data = results .json ()
176+ elif self .product in FEEDS_PRODUCTS_LIST :
177+ self ._data = results # Uses generator to handle large data results from feeds endpoint
144178 else :
145179 self ._data = results .text
146180 limit_exceeded , message = self .check_limit_exceeded ()
@@ -155,6 +189,10 @@ def data(self):
155189 return self ._data
156190
157191 def check_limit_exceeded (self ):
192+ if self .product in FEEDS_PRODUCTS_LIST :
193+ # bypass here as this is handled in generator already
194+ return False , ""
195+
158196 if self .kwargs .get ("format" , "json" ) == "json" and self .product not in FEEDS_PRODUCTS_LIST :
159197 if "response" in self ._data and "limit_exceeded" in self ._data ["response" ] and self ._data ["response" ]["limit_exceeded" ] is True :
160198 return True , self ._data ["response" ]["message" ]
@@ -172,7 +210,7 @@ def status(self):
172210
173211 def setStatus (self , code , response = None ):
174212 self ._status = code
175- if code == 200 :
213+ if code == 200 or ( self . product in FEEDS_PRODUCTS_LIST and code == 206 ) :
176214 return
177215
178216 reason = None
@@ -211,7 +249,7 @@ def response(self):
211249 return self ._response
212250
213251 def items (self ):
214- return self .response ().items ()
252+ return self .response ().items () if isinstance ( self . response (), dict ) else self . response ()
215253
216254 def emails (self ):
217255 """Find and returns all emails mentioned in the response"""
0 commit comments