Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/_test-integrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
WORKFLOW_ID: ${{ secrets.WORKFLOW_ID_SE_TESTS }}
MINDEE_V2_API_KEY: ${{ secrets.MINDEE_V2_SE_TESTS_API_KEY }}
MINDEE_V2_FINDOC_MODEL_ID: ${{ secrets.MINDEE_V2_SE_TESTS_FINDOC_MODEL_ID }}
MINDEE_V2_SE_TESTS_BLANK_PDF_URL: ${{ secrets.MINDEE_V2_SE_TESTS_BLANK_PDF_URL }}
run: |
pytest -m integration

Expand Down
13 changes: 0 additions & 13 deletions mindee/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,16 +562,3 @@ def create_endpoint(
)
version = "1"
return self._build_endpoint(endpoint_name, account_name, version)

@staticmethod
def source_from_url(
url: str,
) -> UrlInputSource:
"""
Load a document from a URL.

:param url: Raw byte input
"""
return UrlInputSource(
url,
)
15 changes: 14 additions & 1 deletion mindee/client_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import BinaryIO, Union

from mindee.error import MindeeClientError
from mindee.input import Base64Input, BytesInput, FileInput, PathInput
from mindee.input import Base64Input, BytesInput, FileInput, PathInput, UrlInputSource


class ClientMixin:
Expand Down Expand Up @@ -89,3 +89,16 @@ def _validate_async_params(
)
if max_retries < min_retries:
raise MindeeClientError(f"Cannot set retries to less than {min_retries}.")

@staticmethod
def source_from_url(
url: str,
) -> UrlInputSource:
"""
Load a document from a URL.

:param url: Raw byte input
"""
return UrlInputSource(
url,
)
19 changes: 11 additions & 8 deletions mindee/client_v2.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from time import sleep
from typing import Optional
from typing import Optional, Union

from mindee.client_mixin import ClientMixin
from mindee.error.mindee_error import MindeeError
from mindee.error.mindee_http_error_v2 import handle_error_v2
from mindee.input import UrlInputSource
from mindee.input.inference_parameters import InferenceParameters
from mindee.input.polling_options import PollingOptions
from mindee.input.sources.local_input_source import LocalInputSource
Expand All @@ -13,7 +14,7 @@
is_valid_get_response,
is_valid_post_response,
)
from mindee.parsing.v2.common_response import CommonStatus
from mindee.parsing.v2.field.common_response import CommonStatus
from mindee.parsing.v2.inference_response import InferenceResponse
from mindee.parsing.v2.job_response import JobResponse

Expand All @@ -38,13 +39,14 @@ def __init__(self, api_key: Optional[str] = None) -> None:
self.mindee_api = MindeeApiV2(api_key)

def enqueue_inference(
self, input_source: LocalInputSource, params: InferenceParameters
self,
input_source: Union[LocalInputSource, UrlInputSource],
params: InferenceParameters,
) -> JobResponse:
"""
Enqueues a document to a given model.

:param input_source: The document/source file to use.
Has to be created beforehand.
:param input_source: The document/source file to use. Can be local or remote.

:param params: Parameters to set when sending a file.
:return: A valid inference response.
Expand Down Expand Up @@ -95,13 +97,14 @@ def get_inference(self, inference_id: str) -> InferenceResponse:
return InferenceResponse(dict_response)

def enqueue_and_get_inference(
self, input_source: LocalInputSource, params: InferenceParameters
self,
input_source: Union[LocalInputSource, UrlInputSource],
params: InferenceParameters,
) -> InferenceResponse:
"""
Enqueues to an asynchronous endpoint and automatically polls for a response.

:param input_source: The document/source file to use.
Has to be created beforehand.
:param input_source: The document/source file to use. Can be local or remote.

:param params: Parameters to set when sending a file.

Expand Down
2 changes: 1 addition & 1 deletion mindee/input/local_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import Any, BinaryIO, Dict, Type, TypeVar, Union

from mindee.error.mindee_error import MindeeError
from mindee.parsing.v2.common_response import CommonResponse
from mindee.parsing.v2.field.common_response import CommonResponse


class LocalResponse:
Expand Down
35 changes: 24 additions & 11 deletions mindee/mindee_http/mindee_api_v2.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
from typing import Dict, Optional
from typing import Dict, Optional, Union

import requests

from mindee.error.mindee_error import MindeeApiV2Error
from mindee.input import LocalInputSource
from mindee.input import LocalInputSource, UrlInputSource
from mindee.input.inference_parameters import InferenceParameters
from mindee.logger import logger
from mindee.mindee_http.base_settings import USER_AGENT
Expand Down Expand Up @@ -68,7 +68,9 @@ def set_from_env(self) -> None:
logger.debug("Value was set from env: %s", name)

def req_post_inference_enqueue(
self, input_source: LocalInputSource, params: InferenceParameters
self,
input_source: Union[LocalInputSource, UrlInputSource],
params: InferenceParameters,
) -> requests.Response:
"""
Make an asynchronous request to POST a document for prediction on the V2 API.
Expand All @@ -87,14 +89,25 @@ def req_post_inference_enqueue(
if params.alias and len(params.alias):
data["alias"] = params.alias

files = {"file": input_source.read_contents(params.close_file)}
response = requests.post(
url=url,
files=files,
headers=self.base_headers,
data=data,
timeout=self.request_timeout,
)
if isinstance(input_source, LocalInputSource):
files = {"file": input_source.read_contents(params.close_file)}
response = requests.post(
url=url,
files=files,
headers=self.base_headers,
data=data,
timeout=self.request_timeout,
)
elif isinstance(input_source, UrlInputSource):
data["url"] = input_source.url
response = requests.post(
url=url,
headers=self.base_headers,
data=data,
timeout=self.request_timeout,
)
else:
raise MindeeApiV2Error("Invalid input source.")
return response

def req_get_job(self, job_id: str) -> requests.Response:
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Optional

from mindee.parsing.v2.dynamic_field import DynamicField
from mindee.parsing.v2.field.dynamic_field import DynamicField


class BaseField(DynamicField):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ def get_field_type(raw_response: StringDict, indent_level: int = 0) -> DynamicFi
"""Get appropriate field types."""
if isinstance(raw_response, dict):
if "value" in raw_response:
field_file = import_module("mindee.parsing.v2.simple_field")
field_file = import_module("mindee.parsing.v2.field.simple_field")
field_class = getattr(field_file, FieldType.SIMPLE.value)
elif "items" in raw_response:
field_file = import_module("mindee.parsing.v2.list_field")
field_file = import_module("mindee.parsing.v2.field.list_field")
field_class = getattr(field_file, FieldType.LIST.value)
elif "fields" in raw_response:
field_file = import_module("mindee.parsing.v2.object_field")
field_file = import_module("mindee.parsing.v2.field.object_field")
field_class = getattr(field_file, FieldType.OBJECT.value)
else:
raise MindeeApiV2Error(f"Unrecognized field format in {raw_response}.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from typing import Dict

from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.dynamic_field import DynamicField, FieldType, get_field_type
from mindee.parsing.v2.field.dynamic_field import (
DynamicField,
FieldType,
get_field_type,
)


class InferenceResultFields(Dict[str, DynamicField]):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from typing import List

from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.dynamic_field import DynamicField, FieldType, get_field_type
from mindee.parsing.v2.field.dynamic_field import (
DynamicField,
FieldType,
get_field_type,
)


class ListField(DynamicField):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.base_field import BaseField
from mindee.parsing.v2.dynamic_field import FieldType
from mindee.parsing.v2.inference_result_fields import InferenceResultFields
from mindee.parsing.v2.field.base_field import BaseField
from mindee.parsing.v2.field.dynamic_field import FieldType
from mindee.parsing.v2.field.inference_result_fields import InferenceResultFields


class ObjectField(BaseField):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Union

from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.base_field import BaseField
from mindee.parsing.v2.dynamic_field import FieldType
from mindee.parsing.v2.field.base_field import BaseField
from mindee.parsing.v2.field.dynamic_field import FieldType


class SimpleField(BaseField):
Expand All @@ -12,7 +12,13 @@ class SimpleField(BaseField):

def __init__(self, raw_response: StringDict, indent_level: int = 0):
super().__init__(FieldType.SIMPLE, indent_level)
self.value = raw_response["value"] = raw_response.get("value", None)
value = raw_response.get("value", None)
if isinstance(value, int) and not isinstance(raw_response.get("value"), bool):
self.value = float(value)
else:
self.value = value

def __str__(self) -> str:
if isinstance(self.value, bool):
return "True" if self.value else "False"
return str(self.value if self.value is not None else "")
2 changes: 1 addition & 1 deletion mindee/parsing/v2/inference_response.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.common_response import CommonResponse
from mindee.parsing.v2.field.common_response import CommonResponse
from mindee.parsing.v2.inference import Inference


Expand Down
2 changes: 1 addition & 1 deletion mindee/parsing/v2/inference_result.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Optional

from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.inference_result_fields import InferenceResultFields
from mindee.parsing.v2.field.inference_result_fields import InferenceResultFields
from mindee.parsing.v2.inference_result_options import InferenceResultOptions


Expand Down
2 changes: 1 addition & 1 deletion mindee/parsing/v2/job_response.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from mindee.parsing.common.string_dict import StringDict
from mindee.parsing.v2.common_response import CommonResponse
from mindee.parsing.v2.field.common_response import CommonResponse
from mindee.parsing.v2.job import Job


Expand Down
2 changes: 1 addition & 1 deletion tests/data
20 changes: 20 additions & 0 deletions tests/test_client_v2_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,23 @@ def test_invalid_uuid_must_throw_error_422(v2_client: ClientV2) -> None:

exc: MindeeHTTPErrorV2 = exc_info.value
assert exc.status == 422


@pytest.mark.integration
@pytest.mark.v2
def test_url_input_source_must_not_raise_errors(
v2_client: ClientV2,
findoc_model_id: str,
) -> None:
"""
Load a blank PDF from an HTTPS URL and make sure the inference call completes without raising any errors.
"""
url = os.getenv("MINDEE_V2_SE_TESTS_BLANK_PDF_URL")

input_doc = v2_client.source_from_url(url)
options = InferenceParameters(findoc_model_id)
response: InferenceResponse = v2_client.enqueue_and_get_inference(
input_doc, options
)
assert response is not None
assert response.inference is not None
6 changes: 3 additions & 3 deletions tests/v2/test_inference_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

import pytest

from mindee.parsing.v2.field.list_field import ListField
from mindee.parsing.v2.field.object_field import ObjectField
from mindee.parsing.v2.field.simple_field import SimpleField
from mindee.parsing.v2.inference import Inference
from mindee.parsing.v2.inference_file import InferenceFile
from mindee.parsing.v2.inference_model import InferenceModel
from mindee.parsing.v2.inference_response import InferenceResponse
from mindee.parsing.v2.list_field import ListField
from mindee.parsing.v2.object_field import ObjectField
from mindee.parsing.v2.simple_field import SimpleField
from tests.test_inputs import V2_DATA_DIR


Expand Down