Skip to content

Commit 27bcb06

Browse files
fix memory safety issues, simplify all http calls, allow non-client creation
1 parent 3857258 commit 27bcb06

68 files changed

Lines changed: 326 additions & 250 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

mindee/error/mindee_http_error.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from mindee.error.mindee_error import MindeeError
2-
from mindee.parsing.common import StringDict
2+
from mindee.parsing.common.string_dict import StringDict
33

44

55
class MindeeHTTPError(RuntimeError):

mindee/input/url_input_source.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from mindee.error.mindee_error import MindeeSourceError
1111
from mindee.input.bytes_input import BytesInput
1212
from mindee.logger import logger
13+
from mindee.parsing.common.string_dict import StringDict
1314

1415

1516
class URLInputSource:
@@ -192,10 +193,16 @@ def __make_request(
192193
:return: The content of the response.
193194
:raises MindeeSourceError: If max redirects are exceeded or the request fails.
194195
"""
195-
http_client = http_client or httpx.Client()
196-
result = http_client.get(
197-
url, headers=headers, timeout=120, auth=auth, follow_redirects=True
198-
)
196+
get_kwargs: StringDict = {
197+
"headers": headers,
198+
"timeout": 120,
199+
"auth": auth,
200+
"follow_redirects": True,
201+
}
202+
if http_client is None:
203+
result = httpx.get(url, **get_kwargs)
204+
else:
205+
result = http_client.get(url, **get_kwargs)
199206
if 299 < result.status_code < 400:
200207
if redirects == max_redirects:
201208
raise MindeeSourceError(
@@ -204,13 +211,18 @@ def __make_request(
204211
f"aborting operation."
205212
)
206213
return URLInputSource.__make_request(
207-
result.headers["Location"], auth, headers, redirects + 1, max_redirects
214+
result.headers["Location"],
215+
auth,
216+
headers,
217+
redirects + 1,
218+
max_redirects,
219+
http_client,
208220
)
209221

210222
if result.status_code >= 400 or result.status_code < 200:
211223
raise MindeeSourceError(
212224
f"Couldn't retrieve file from server, error code {result.status_code}."
213225
)
214-
215-
http_client.close()
226+
if http_client is not None and not http_client.is_closed:
227+
http_client.close()
216228
return result.content

mindee/mindee_http/response_validation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import httpx
44

5-
from mindee.parsing.common import StringDict
5+
from mindee.parsing.common.string_dict import StringDict
66

77

88
def is_valid_sync_response(response: httpx.Response) -> bool:

mindee/v1/client.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class Client(ClientMixin):
6262

6363
api_key: str
6464
"""API key for all endpoints."""
65-
http_client: httpx.Client
65+
http_client: httpx.Client | None
6666
"""HTTP client for making requests."""
6767

6868
def __init__(
@@ -75,7 +75,7 @@ def __init__(
7575
:param http_client: HTTP client for making requests.
7676
"""
7777
self.api_key = api_key
78-
self.http_client = http_client or httpx.Client()
78+
self.http_client = http_client
7979

8080
def parse(
8181
self,
@@ -597,3 +597,20 @@ def create_endpoint(
597597
)
598598
version = "1"
599599
return self._build_endpoint(endpoint_name, account_name, version)
600+
601+
def close(self):
602+
"""Close the HTTP client."""
603+
if self.http_client and not self.http_client.is_closed:
604+
self.http_client.close()
605+
606+
def __enter__(self):
607+
return self
608+
609+
def __exit__(self, exc_type, exc_val, exc_tb):
610+
self.close()
611+
612+
def __del__(self):
613+
"""Ensure the HTTP client is closed when the object is garbage collected."""
614+
if self.http_client and self.http_client and not self.http_client.is_closed:
615+
logger.info("Force-closing unclosed Mindee Client (V1) %s.", str(self))
616+
self.close()

mindee/v1/mindee_http/base_endpoint.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ class BaseEndpoint:
77
"""Base endpoint class for the Mindee API."""
88

99
settings: BaseSettings
10-
http_client: httpx.Client
10+
"""Settings relating to all endpoints."""
11+
http_client: httpx.Client | None
12+
"""HTTP client for making requests."""
1113

1214
def __init__(
1315
self, settings: BaseSettings, http_client: httpx.Client | None = None
@@ -19,14 +21,4 @@ def __init__(
1921
:param http_client: HTTP client for making requests.
2022
"""
2123
self.settings = settings
22-
self.http_client = http_client or httpx.Client()
23-
24-
def close(self) -> None:
25-
"""Closes the underlying HTTP client."""
26-
self.http_client.close()
27-
28-
def __enter__(self):
29-
return self
30-
31-
def __exit__(self, exc_type, exc_val, exc_tb):
32-
self.close()
24+
self.http_client = http_client

0 commit comments

Comments
 (0)