Skip to content

Commit dc95cd9

Browse files
authored
Support a user-configurable connection timeout (#11)
1 parent 4d172bb commit dc95cd9

1 file changed

Lines changed: 46 additions & 6 deletions

File tree

instaparser/client.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,26 @@ class InstaparserClient:
108108

109109
BASE_URL = "https://instaparser.com"
110110

111-
def __init__(self, api_key: str, base_url: str | None = None):
111+
def __init__(
112+
self,
113+
api_key: str,
114+
base_url: str | None = None,
115+
timeout: float | None = 60,
116+
):
112117
"""
113118
Initialize the Instaparser client.
114119
115120
Args:
116121
api_key: Your Instaparser API key
117122
base_url: Optional base URL for the API (defaults to production)
123+
timeout: Default timeout in seconds for blocking operations
118124
"""
119125
self.api_key = api_key
120126
self.base_url = base_url or self.BASE_URL
121127
self.headers = {
122128
"Authorization": f"Bearer {api_key}",
123129
}
130+
self.timeout = timeout
124131

125132
def __repr__(self) -> str:
126133
return f"<InstaparserClient base_url={self.base_url!r}>"
@@ -134,6 +141,7 @@ def _request(
134141
params: dict | None = None,
135142
multipart_fields: dict[str, str] | None = None,
136143
multipart_files: dict[str, BinaryIO | bytes] | None = None,
144+
timeout: float | None = None,
137145
) -> HTTPResponse:
138146
"""
139147
Make an HTTP request using urllib.
@@ -145,6 +153,7 @@ def _request(
145153
params: Query parameters
146154
multipart_fields: Form fields for multipart upload
147155
multipart_files: Files for multipart upload
156+
timeout: Timeout in seconds for blocking operations
148157
149158
Returns:
150159
HTTPResponse on success
@@ -166,8 +175,11 @@ def _request(
166175
data = json.dumps(json_data).encode("utf-8")
167176
headers["Content-Type"] = "application/json"
168177

178+
if timeout is None:
179+
timeout = self.timeout
180+
169181
req = Request(url, data=data, headers=headers, method=method)
170-
response: HTTPResponse = urlopen(req)
182+
response: HTTPResponse = urlopen(req, timeout=timeout)
171183
return response
172184

173185
def _read_json(self, response: HTTPResponse) -> dict[str, Any]:
@@ -186,7 +198,14 @@ def _read_json(self, response: HTTPResponse) -> dict[str, Any]:
186198
pass
187199
return {"raw": body}
188200

189-
def article(self, url: str, content: str | None = None, output: str = "html", use_cache: bool = True) -> Article:
201+
def article(
202+
self,
203+
url: str,
204+
content: str | None = None,
205+
output: str = "html",
206+
use_cache: bool = True,
207+
timeout: float | None = None,
208+
) -> Article:
190209
"""
191210
Parse an article from a URL or HTML content.
192211
@@ -195,6 +214,7 @@ def article(self, url: str, content: str | None = None, output: str = "html", us
195214
content: Optional raw HTML content to parse instead of fetching from URL
196215
output: Output format - 'html' (default), 'text', or 'markdown'
197216
use_cache: Whether to use cache (default: True)
217+
timeout: Timeout in seconds (default: use default client timeout)
198218
199219
Returns:
200220
Article object with parsed content
@@ -217,7 +237,12 @@ def article(self, url: str, content: str | None = None, output: str = "html", us
217237
payload["content"] = content
218238

219239
try:
220-
response = self._request("POST", "/api/1/article", json_data=payload)
240+
response = self._request(
241+
"POST",
242+
"/api/1/article",
243+
json_data=payload,
244+
timeout=timeout,
245+
)
221246
except HTTPError as e:
222247
_map_http_error(e)
223248

@@ -245,6 +270,7 @@ def summary(
245270
content: str | None = None,
246271
use_cache: bool = True,
247272
stream_callback: Callable[[str], None] | None = None,
273+
timeout: float | None = None,
248274
) -> Summary:
249275
"""
250276
Generate a summary of an article.
@@ -255,6 +281,7 @@ def summary(
255281
use_cache: Whether to use cache (default: True)
256282
stream_callback: Optional callback function called for each line of streaming response.
257283
If provided, enables streaming mode. The callback receives each line as a string.
284+
timeout: Timeout in seconds (default: use default client timeout)
258285
259286
Returns:
260287
Summary object with key_sentences and overview attributes
@@ -279,7 +306,12 @@ def summary(
279306
payload["content"] = content
280307

281308
try:
282-
response = self._request("POST", "/api/1/summary", json_data=payload)
309+
response = self._request(
310+
"POST",
311+
"/api/1/summary",
312+
json_data=payload,
313+
timeout=timeout,
314+
)
283315
except HTTPError as e:
284316
_map_http_error(e)
285317

@@ -312,6 +344,7 @@ def pdf(
312344
file: BinaryIO | bytes | None = None,
313345
output: str = "html",
314346
use_cache: bool = True,
347+
timeout: float | None = None,
315348
) -> PDF:
316349
"""
317350
Parse a PDF from a URL or file.
@@ -321,6 +354,7 @@ def pdf(
321354
file: PDF file to upload (required for POST request, can be file-like object or bytes)
322355
output: Output format - 'html' (default), 'text', or 'markdown'
323356
use_cache: Whether to use cache (default: True)
357+
timeout: Timeout in seconds (default: use default client timeout)
324358
325359
Returns:
326360
PDF object with parsed PDF content (inherits from Article)
@@ -349,6 +383,7 @@ def pdf(
349383
"/api/1/pdf",
350384
multipart_fields=fields,
351385
multipart_files={"file": file},
386+
timeout=timeout,
352387
)
353388
except HTTPError as e:
354389
_map_http_error(e)
@@ -361,7 +396,12 @@ def pdf(
361396
params["use_cache"] = "false"
362397

363398
try:
364-
response = self._request("GET", "/api/1/pdf", params=params)
399+
response = self._request(
400+
"GET",
401+
"/api/1/pdf",
402+
params=params,
403+
timeout=timeout,
404+
)
365405
except HTTPError as e:
366406
_map_http_error(e)
367407
else:

0 commit comments

Comments
 (0)