Skip to content

Commit 2a1a4e8

Browse files
authored
♻️ rework and harmonize client naming conventions (#339)
1 parent 7eea2fc commit 2a1a4e8

File tree

11 files changed

+197
-149
lines changed

11 files changed

+197
-149
lines changed

README.md

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -195,32 +195,6 @@ result = mindee_client.parse(
195195
)
196196
```
197197

198-
## Further Reading
199-
Complete details on the working of the library are available in the following guides:
200-
201-
* [Getting started](https://developers.mindee.com/docs/python-getting-started)
202-
* [Python Command Line Interface (CLI)](https://developers.mindee.com/docs/python-cli)
203-
* [Python Generated](https://developers.mindee.com/docs/generated-api-python)
204-
* [Python Custom APIs (Deprecated - API Builder)](https://developers.mindee.com/docs/python-api-builder)
205-
* [Python Invoice OCR](https://developers.mindee.com/docs/python-invoice-ocr)
206-
* [Python International Id OCR](https://developers.mindee.com/docs/python-international-id-ocr)
207-
* [Python Resume OCR](https://developers.mindee.com/docs/python-resume-ocr)
208-
* [Python Receipt OCR](https://developers.mindee.com/docs/python-receipt-ocr)
209-
* [Python Financial Document OCR](https://developers.mindee.com/docs/python-financial-document-ocr)
210-
* [Python Passport OCR](https://developers.mindee.com/docs/python-passport-ocr)
211-
* [Python Proof of Address OCR](https://developers.mindee.com/docs/python-proof-of-address-ocr)
212-
* [Python US Driver License OCR](https://developers.mindee.com/docs/python-eu-driver-license-ocr)
213-
* [Python FR Bank Account Detail OCR](https://developers.mindee.com/docs/python-fr-bank-account-details-ocr)
214-
* [Python FR Carte Grise OCR](https://developers.mindee.com/docs/python-fr-carte-grise-ocr)
215-
* [Python FR Health Card OCR](https://developers.mindee.com/docs/python-fr-health-card-ocr)
216-
* [Python FR ID Card OCR](https://developers.mindee.com/docs/python-fr-carte-nationale-didentite-ocr)
217-
* [Python US Bank Check OCR](https://developers.mindee.com/docs/python-us-bank-check-ocr)
218-
* [Python US W9 OCR](https://developers.mindee.com/docs/python-us-w9-ocr)
219-
* [Python Barcode Reader API](https://developers.mindee.com/docs/python-barcode-reader-ocr)
220-
* [Python Cropper API](https://developers.mindee.com/docs/python-cropper-ocr)
221-
* [Python Invoice Splitter API](https://developers.mindee.com/docs/python-invoice-splitter-api)
222-
* [Python Multi Receipts Detector API](https://developers.mindee.com/docs/python-multi-receipts-detector-ocr)
223-
224198
You can view the source code on [GitHub](https://github.com/mindee/mindee-api-python).
225199

226200
You can also take a look at the

docs/extras/code_samples/default_v2.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ params = InferenceParameters(
1919
input_source = mindee_client.source_from_path(input_path)
2020

2121
# Upload the file
22-
response = mindee_client.enqueue_and_parse(
22+
response = mindee_client.enqueue_and_get_inference(
2323
input_source, params
2424
)
2525

docs/extras/guide/getting_started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ custom_endpoint = mindee_client.create_endpoint(
219219
"my-account-name",
220220
# "my-version" # optional
221221
)
222-
result = mindee_client.enqueue_and_parse(product.GeneratedV1, input_doc, endpoint=custom_endpoint)
222+
result = mindee_client.enqueue_and_get_inference(product.GeneratedV1, input_doc, endpoint=custom_endpoint)
223223
```
224224

225225
This is because the `GeneratedV1` class is enough to handle the return processing, but the actual endpoint needs to be specified.

mindee/client_v2.py

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from time import sleep
2-
from typing import Optional, Union
2+
from typing import Optional
33

44
from mindee.client_mixin import ClientMixin
55
from mindee.error.mindee_error import MindeeError
@@ -14,6 +14,7 @@
1414
is_valid_get_response,
1515
is_valid_post_response,
1616
)
17+
from mindee.parsing.v2.common_response import CommonStatus
1718
from mindee.parsing.v2.inference_response import InferenceResponse
1819
from mindee.parsing.v2.job_response import JobResponse
1920

@@ -37,7 +38,7 @@ def __init__(self, api_key: Optional[str] = None) -> None:
3738
self.api_key = api_key
3839
self.mindee_api = MindeeApiV2(api_key)
3940

40-
def enqueue(
41+
def enqueue_inference(
4142
self, input_source: LocalInputSource, params: InferenceParameters
4243
) -> JobResponse:
4344
"""
@@ -49,39 +50,52 @@ def enqueue(
4950
:param params: Parameters to set when sending a file.
5051
:return: A valid inference response.
5152
"""
52-
logger.debug("Enqueuing document to '%s'", params.model_id)
53+
logger.debug("Enqueuing inference using model: %s", params.model_id)
5354

54-
response = self.mindee_api.predict_async_req_post(
55-
input_source=input_source, options=params
55+
response = self.mindee_api.req_post_inference_enqueue(
56+
input_source=input_source, params=params
5657
)
5758
dict_response = response.json()
5859

5960
if not is_valid_post_response(response):
6061
handle_error_v2(dict_response)
61-
6262
return JobResponse(dict_response)
6363

64-
def parse_queued(
65-
self,
66-
queue_id: str,
67-
) -> Union[InferenceResponse, JobResponse]:
64+
def get_job(self, job_id: str) -> JobResponse:
6865
"""
69-
Parses a queued document.
66+
Get the status of an inference that was previously enqueued.
67+
68+
Can be used for polling.
7069
71-
:param queue_id: queue_id received from the API.
70+
:param job_id: UUID of the job to retrieve.
71+
:return: A job response.
7272
"""
73-
logger.debug("Fetching from queue '%s'.", queue_id)
73+
logger.debug("Fetching job: %s", job_id)
7474

75-
response = self.mindee_api.get_inference_from_queue(queue_id)
75+
response = self.mindee_api.req_get_job(job_id)
7676
if not is_valid_get_response(response):
7777
handle_error_v2(response.json())
78+
dict_response = response.json()
79+
return JobResponse(dict_response)
80+
81+
def get_inference(self, inference_id: str) -> InferenceResponse:
82+
"""
83+
Get the result of an inference that was previously enqueued.
84+
85+
The inference will only be available after it has finished processing.
7886
87+
:param inference_id: UUID of the inference to retrieve.
88+
:return: An inference response.
89+
"""
90+
logger.debug("Fetching inference: %s", inference_id)
91+
92+
response = self.mindee_api.req_get_inference(inference_id)
93+
if not is_valid_get_response(response):
94+
handle_error_v2(response.json())
7995
dict_response = response.json()
80-
if "job" in dict_response:
81-
return JobResponse(dict_response)
8296
return InferenceResponse(dict_response)
8397

84-
def enqueue_and_parse(
98+
def enqueue_and_get_inference(
8599
self, input_source: LocalInputSource, params: InferenceParameters
86100
) -> InferenceResponse:
87101
"""
@@ -101,40 +115,28 @@ def enqueue_and_parse(
101115
params.polling_options.delay_sec,
102116
params.polling_options.max_retries,
103117
)
104-
queue_result = self.enqueue(input_source, params)
118+
enqueue_response = self.enqueue_inference(input_source, params)
105119
logger.debug(
106-
"Successfully enqueued document with job id: %s", queue_result.job.id
120+
"Successfully enqueued inference with job id: %s", enqueue_response.job.id
107121
)
108122
sleep(params.polling_options.initial_delay_sec)
109-
retry_counter = 1
110-
poll_results = self.parse_queued(
111-
queue_result.job.id,
112-
)
113-
while retry_counter < params.polling_options.max_retries:
114-
if not isinstance(poll_results, JobResponse):
115-
break
116-
if poll_results.job.status == "Failed":
117-
if poll_results.job.error:
118-
detail = poll_results.job.error.detail
123+
try_counter = 0
124+
while try_counter < params.polling_options.max_retries:
125+
job_response = self.get_job(enqueue_response.job.id)
126+
if job_response.job.status == CommonStatus.FAILED.value:
127+
if job_response.job.error:
128+
detail = job_response.job.error.detail
119129
else:
120130
detail = "No error detail available."
121131
raise MindeeError(
122-
f"Parsing failed for job {poll_results.job.id}: {detail}"
132+
f"Parsing failed for job {job_response.job.id}: {detail}"
123133
)
124-
logger.debug(
125-
"Polling server for parsing result with job id: %s",
126-
queue_result.job.id,
127-
)
128-
retry_counter += 1
134+
if job_response.job.status == CommonStatus.PROCESSED.value:
135+
return self.get_inference(job_response.job.id)
136+
try_counter += 1
129137
sleep(params.polling_options.delay_sec)
130-
poll_results = self.parse_queued(queue_result.job.id)
131-
132-
if not isinstance(poll_results, InferenceResponse):
133-
raise MindeeError(
134-
f"Couldn't retrieve document after {retry_counter} tries."
135-
)
136138

137-
return poll_results
139+
raise MindeeError(f"Couldn't retrieve document after {try_counter + 1} tries.")
138140

139141
@staticmethod
140142
def load_inference(local_response: LocalResponse) -> InferenceResponse:

mindee/input/inference_parameters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class InferenceParameters:
1313
rag: bool = False
1414
"""If set to `True`, will enable Retrieval-Augmented Generation."""
1515
alias: Optional[str] = None
16-
"""Optional alias for the file."""
16+
"""Use an alias to link the file to your own DB. If empty, no alias will be used."""
1717
webhook_ids: Optional[List[str]] = None
1818
"""IDs of webhooks to propagate the API response to."""
1919
polling_options: Optional[PollingOptions] = None

mindee/mindee_http/mindee_api_v2.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,45 +67,58 @@ def set_from_env(self) -> None:
6767
func(env_val)
6868
logger.debug("Value was set from env: %s", name)
6969

70-
def predict_async_req_post(
71-
self, input_source: LocalInputSource, options: InferenceParameters
70+
def req_post_inference_enqueue(
71+
self, input_source: LocalInputSource, params: InferenceParameters
7272
) -> requests.Response:
7373
"""
7474
Make an asynchronous request to POST a document for prediction on the V2 API.
7575
7676
:param input_source: Input object.
77-
:param options: Options for the enqueueing of the document.
77+
:param params: Options for the enqueueing of the document.
7878
:return: requests response.
7979
"""
80-
data = {"model_id": options.model_id}
80+
data = {"model_id": params.model_id}
8181
url = f"{self.url_root}/inferences/enqueue"
8282

83-
if options.rag:
83+
if params.rag:
8484
data["rag"] = "true"
85-
if options.webhook_ids and len(options.webhook_ids) > 0:
86-
data["webhook_ids"] = ",".join(options.webhook_ids)
87-
if options.alias and len(options.alias):
88-
data["alias"] = options.alias
85+
if params.webhook_ids and len(params.webhook_ids) > 0:
86+
data["webhook_ids"] = ",".join(params.webhook_ids)
87+
if params.alias and len(params.alias):
88+
data["alias"] = params.alias
8989

90-
files = {"file": input_source.read_contents(options.close_file)}
90+
files = {"file": input_source.read_contents(params.close_file)}
9191
response = requests.post(
9292
url=url,
9393
files=files,
9494
headers=self.base_headers,
9595
data=data,
9696
timeout=self.request_timeout,
9797
)
98-
9998
return response
10099

101-
def get_inference_from_queue(self, queue_id: str) -> requests.Response:
100+
def req_get_job(self, job_id: str) -> requests.Response:
101+
"""
102+
Sends a request matching a given queue_id. Returns either a Job or a Document.
103+
104+
:param job_id: Job ID, returned by the enqueue request.
105+
"""
106+
return requests.get(
107+
f"{self.url_root}/jobs/{job_id}",
108+
headers=self.base_headers,
109+
timeout=self.request_timeout,
110+
allow_redirects=False,
111+
)
112+
113+
def req_get_inference(self, inference_id: str) -> requests.Response:
102114
"""
103115
Sends a request matching a given queue_id. Returns either a Job or a Document.
104116
105-
:param queue_id: queue_id received from the API
117+
:param inference_id: Inference ID, returned by the job request.
106118
"""
107119
return requests.get(
108-
f"{self.url_root}/jobs/{queue_id}",
120+
f"{self.url_root}/inferences/{inference_id}",
109121
headers=self.base_headers,
110122
timeout=self.request_timeout,
123+
allow_redirects=False,
111124
)

mindee/parsing/v2/common_response.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import json
2+
from enum import Enum
23

34
from mindee.logger import logger
45
from mindee.parsing.common.string_dict import StringDict
56

67

8+
class CommonStatus(str, Enum):
9+
"""Response status."""
10+
11+
PROCESSING = "Processing"
12+
FAILED = "Failed"
13+
PROCESSED = "Processed"
14+
15+
716
class CommonResponse:
817
"""Base class for V1 & V2 responses."""
918

0 commit comments

Comments
 (0)