1
1
import asyncio
2
2
from typing import Any , Optional
3
3
4
- import aiohttp
5
4
from aiohttp import ClientSession , ClientTimeout , TCPConnector
6
5
from aiohttp .client_exceptions import ClientError
7
6
from pydantic import BaseModel
@@ -27,15 +26,15 @@ class AsyncClient:
27
26
def from_env (
28
27
cls ,
29
28
verify_ssl : bool = True ,
30
- timeout : float = 120 ,
29
+ timeout : Optional [ float ] = None ,
31
30
max_retries : int = 3 ,
32
31
retry_delay : float = 1.0 ,
33
32
):
34
33
"""Initialize AsyncClient using API key from environment variable.
35
34
36
35
Args:
37
36
verify_ssl: Whether to verify SSL certificates
38
- timeout: Request timeout in seconds
37
+ timeout: Request timeout in seconds. None means no timeout (infinite)
39
38
max_retries: Maximum number of retry attempts
40
39
retry_delay: Delay between retries in seconds
41
40
"""
@@ -56,7 +55,7 @@ def __init__(
56
55
self ,
57
56
api_key : str = None ,
58
57
verify_ssl : bool = True ,
59
- timeout : float = 120 ,
58
+ timeout : Optional [ float ] = None ,
60
59
max_retries : int = 3 ,
61
60
retry_delay : float = 1.0 ,
62
61
):
@@ -65,7 +64,7 @@ def __init__(
65
64
Args:
66
65
api_key: API key for authentication. If None, will try to load from environment
67
66
verify_ssl: Whether to verify SSL certificates
68
- timeout: Request timeout in seconds
67
+ timeout: Request timeout in seconds. None means no timeout (infinite)
69
68
max_retries: Maximum number of retry attempts
70
69
retry_delay: Delay between retries in seconds
71
70
"""
@@ -91,7 +90,7 @@ def __init__(
91
90
self .retry_delay = retry_delay
92
91
93
92
ssl = None if verify_ssl else False
94
- self .timeout = ClientTimeout (total = timeout )
93
+ self .timeout = ClientTimeout (total = timeout ) if timeout is not None else None
95
94
96
95
self .session = ClientSession (
97
96
headers = self .headers , connector = TCPConnector (ssl = ssl ), timeout = self .timeout
@@ -137,6 +136,33 @@ async def _make_request(self, method: str, url: str, **kwargs) -> Any:
137
136
logger .info (f"⏳ Waiting { retry_delay } s before retry { attempt + 2 } " )
138
137
await asyncio .sleep (retry_delay )
139
138
139
+ async def markdownify (self , website_url : str ):
140
+ """Send a markdownify request"""
141
+ logger .info (f"🔍 Starting markdownify request for { website_url } " )
142
+
143
+ request = MarkdownifyRequest (website_url = website_url )
144
+ logger .debug ("✅ Request validation passed" )
145
+
146
+ result = await self ._make_request (
147
+ "POST" , f"{ API_BASE_URL } /markdownify" , json = request .model_dump ()
148
+ )
149
+ logger .info ("✨ Markdownify request completed successfully" )
150
+ return result
151
+
152
+ async def get_markdownify (self , request_id : str ):
153
+ """Get the result of a previous markdownify request"""
154
+ logger .info (f"🔍 Fetching markdownify result for request { request_id } " )
155
+
156
+ # Validate input using Pydantic model
157
+ GetMarkdownifyRequest (request_id = request_id )
158
+ logger .debug ("✅ Request ID validation passed" )
159
+
160
+ result = await self ._make_request (
161
+ "GET" , f"{ API_BASE_URL } /markdownify/{ request_id } "
162
+ )
163
+ logger .info (f"✨ Successfully retrieved result for request { request_id } " )
164
+ return result
165
+
140
166
async def smartscraper (
141
167
self ,
142
168
website_url : str ,
@@ -154,17 +180,11 @@ async def smartscraper(
154
180
)
155
181
logger .debug ("✅ Request validation passed" )
156
182
157
- try :
158
- async with self .session .post (
159
- f"{ API_BASE_URL } /smartscraper" , json = request .model_dump ()
160
- ) as response :
161
- response .raise_for_status ()
162
- result = await handle_async_response (response )
163
- logger .info ("✨ Smartscraper request completed successfully" )
164
- return result
165
- except aiohttp .ClientError as e :
166
- logger .error (f"❌ Smartscraper request failed: { str (e )} " )
167
- raise ConnectionError (f"Failed to connect to API: { str (e )} " )
183
+ result = await self ._make_request (
184
+ "POST" , f"{ API_BASE_URL } /smartscraper" , json = request .model_dump ()
185
+ )
186
+ logger .info ("✨ Smartscraper request completed successfully" )
187
+ return result
168
188
169
189
async def get_smartscraper (self , request_id : str ):
170
190
"""Get the result of a previous smartscraper request"""
@@ -174,80 +194,8 @@ async def get_smartscraper(self, request_id: str):
174
194
GetSmartScraperRequest (request_id = request_id )
175
195
logger .debug ("✅ Request ID validation passed" )
176
196
177
- async with self .session .get (
178
- f"{ API_BASE_URL } /smartscraper/{ request_id } "
179
- ) as response :
180
- result = await handle_async_response (response )
181
- logger .info (f"✨ Successfully retrieved result for request { request_id } " )
182
- return result
183
-
184
- async def get_credits (self ):
185
- """Get credits information"""
186
- logger .info ("💳 Fetching credits information" )
187
-
188
- async with self .session .get (
189
- f"{ API_BASE_URL } /credits" ,
190
- ) as response :
191
- result = await handle_async_response (response )
192
- logger .info (
193
- f"✨ Credits info retrieved: { result .get ('remaining_credits' )} credits remaining"
194
- )
195
- return result
196
-
197
- async def submit_feedback (
198
- self , request_id : str , rating : int , feedback_text : Optional [str ] = None
199
- ):
200
- """Submit feedback for a request"""
201
- logger .info (f"📝 Submitting feedback for request { request_id } " )
202
- logger .debug (f"⭐ Rating: { rating } , Feedback: { feedback_text } " )
203
-
204
- feedback = FeedbackRequest (
205
- request_id = request_id , rating = rating , feedback_text = feedback_text
206
- )
207
- logger .debug ("✅ Feedback validation passed" )
208
-
209
- async with self .session .post (
210
- f"{ API_BASE_URL } /feedback" , json = feedback .model_dump ()
211
- ) as response :
212
- result = await handle_async_response (response )
213
- logger .info ("✨ Feedback submitted successfully" )
214
- return result
215
-
216
- async def close (self ):
217
- """Close the session to free up resources"""
218
- logger .info ("🔒 Closing AsyncClient session" )
219
- await self .session .close ()
220
- logger .debug ("✅ Session closed successfully" )
221
-
222
- async def __aenter__ (self ):
223
- return self
224
-
225
- async def __aexit__ (self , exc_type , exc_val , exc_tb ):
226
- await self .close ()
227
-
228
- async def markdownify (self , website_url : str ):
229
- """Send a markdownify request"""
230
- logger .info (f"🔍 Starting markdownify request for { website_url } " )
231
-
232
- request = MarkdownifyRequest (website_url = website_url )
233
- logger .debug ("✅ Request validation passed" )
234
-
235
- result = await self ._make_request (
236
- "POST" , f"{ API_BASE_URL } /markdownify" , json = request .model_dump ()
237
- )
238
- logger .info ("✨ Markdownify request completed successfully" )
239
- return result
240
-
241
- async def get_markdownify (self , request_id : str ):
242
- """Get the result of a previous markdownify request"""
243
- logger .info (f"🔍 Fetching markdownify result for request { request_id } " )
244
-
245
- # Validate input using Pydantic model
246
- GetMarkdownifyRequest (request_id = request_id )
247
- logger .debug ("✅ Request ID validation passed" )
248
-
249
197
result = await self ._make_request (
250
- "GET" , f"{ API_BASE_URL } /markdownify /{ request_id } "
198
+ "GET" , f"{ API_BASE_URL } /smartscraper /{ request_id } "
251
199
)
252
200
logger .info (f"✨ Successfully retrieved result for request { request_id } " )
253
201
return result
@@ -288,3 +236,46 @@ async def get_localscraper(self, request_id: str):
288
236
)
289
237
logger .info (f"✨ Successfully retrieved result for request { request_id } " )
290
238
return result
239
+
240
+ async def submit_feedback (
241
+ self , request_id : str , rating : int , feedback_text : Optional [str ] = None
242
+ ):
243
+ """Submit feedback for a request"""
244
+ logger .info (f"📝 Submitting feedback for request { request_id } " )
245
+ logger .debug (f"⭐ Rating: { rating } , Feedback: { feedback_text } " )
246
+
247
+ feedback = FeedbackRequest (
248
+ request_id = request_id , rating = rating , feedback_text = feedback_text
249
+ )
250
+ logger .debug ("✅ Feedback validation passed" )
251
+
252
+ result = await self ._make_request (
253
+ "POST" , f"{ API_BASE_URL } /feedback" , json = feedback .model_dump ()
254
+ )
255
+ logger .info ("✨ Feedback submitted successfully" )
256
+ return result
257
+
258
+ async def get_credits (self ):
259
+ """Get credits information"""
260
+ logger .info ("💳 Fetching credits information" )
261
+
262
+ result = await self ._make_request (
263
+ "GET" ,
264
+ f"{ API_BASE_URL } /credits" ,
265
+ )
266
+ logger .info (
267
+ f"✨ Credits info retrieved: { result .get ('remaining_credits' )} credits remaining"
268
+ )
269
+ return result
270
+
271
+ async def close (self ):
272
+ """Close the session to free up resources"""
273
+ logger .info ("🔒 Closing AsyncClient session" )
274
+ await self .session .close ()
275
+ logger .debug ("✅ Session closed successfully" )
276
+
277
+ async def __aenter__ (self ):
278
+ return self
279
+
280
+ async def __aexit__ (self , exc_type , exc_val , exc_tb ):
281
+ await self .close ()
0 commit comments