From 2bd25b86eaa1c44c685d87993d4dc8bf7de56ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ianar=C3=A9=20s=C3=A9vi?= Date: Wed, 26 Nov 2025 15:13:15 +0100 Subject: [PATCH 1/3] update test lib --- tests/data | 2 +- tests/v2/input/test_local_response.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/data b/tests/data index 7d843db0..932b387e 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit 7d843db01df952740d0f2d39f62fc3efb86f92bb +Subproject commit 932b387e48d909202d7b69ccf9230531dee3f036 diff --git a/tests/v2/input/test_local_response.py b/tests/v2/input/test_local_response.py index 449e35df..82654579 100644 --- a/tests/v2/input/test_local_response.py +++ b/tests/v2/input/test_local_response.py @@ -14,7 +14,7 @@ def file_path() -> Path: def _assert_local_response(local_response): fake_hmac_signing = "ogNjY44MhvKPGTtVsI8zG82JqWQa68woYQH" - signature = "a1bc9012fa63539d602f163d8980604a0cf2b2ae88e56009cfa1db33382736cf" + signature = "b9c2dfc67c2ba457603dd9880d45f089ae79b95bf6389b4a4387ef255c924fe7" assert local_response._file is not None assert not local_response.is_valid_hmac_signature( From c9d5b345d9d398e9cf2dd47962fc85b6b71172fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ianar=C3=A9=20s=C3=A9vi?= Date: Wed, 26 Nov 2025 15:15:22 +0100 Subject: [PATCH 2/3] :coffin: remove unused feedback calls from CLI --- mindee/cli.py | 2 +- mindee/commands/cli_parser.py | 100 +++------------------------------- tests/v1/test_cli.py | 44 ++++++--------- 3 files changed, 24 insertions(+), 122 deletions(-) diff --git a/mindee/cli.py b/mindee/cli.py index 9edad465..86fa8221 100644 --- a/mindee/cli.py +++ b/mindee/cli.py @@ -4,4 +4,4 @@ def main() -> None: """Run the Command Line Interface.""" parser = MindeeParser() - parser.call_endpoint() + parser.call_parse() diff --git a/mindee/commands/cli_parser.py b/mindee/commands/cli_parser.py index 0323e6c1..0c7f9859 100644 --- a/mindee/commands/cli_parser.py +++ b/mindee/commands/cli_parser.py @@ -9,10 +9,8 @@ from mindee.input.sources import LocalInputSource, UrlInputSource from mindee.parsing.common.async_predict_response import AsyncPredictResponse from mindee.parsing.common.document import Document, serialize_for_json -from mindee.parsing.common.feedback_response import FeedbackResponse from mindee.parsing.common.inference import Inference from mindee.parsing.common.predict_response import PredictResponse -from mindee.parsing.common.string_dict import StringDict class MindeeArgumentParser(ArgumentParser): @@ -75,19 +73,6 @@ def add_sending_options(self) -> None: ) self.add_argument(dest="path", help="Full path to the file") - def add_feedback_options(self) -> None: - """Adds the option to give feedback manually.""" - self.add_argument( - dest="document_id", - help="Mindee UUID of the document.", - type=str, - ) - self.add_argument( - dest="feedback", - type=json.loads, - help='Feedback JSON string to send, ex \'{"key": "value"}\'.', - ) - def add_custom_options(self) -> None: """Adds options to custom-type documents.""" self.add_argument( @@ -128,8 +113,6 @@ class MindeeParser: """Document to be parsed.""" product_class: Type[Inference] """Product to parse.""" - feedback: Optional[StringDict] - """Dict representation of a feedback.""" def __init__( self, @@ -147,38 +130,11 @@ def __init__( else: api_key = self.parsed_args.api_key if "api_key" in self.parsed_args else "" self.client = Client(api_key=api_key) - self._set_input() + self.input_doc = self._get_input_doc() self.document_info = ( document_info if document_info else PRODUCTS[self.parsed_args.product_name] ) - def call_endpoint(self) -> None: - """Calls the proper type of endpoint according to given command.""" - if self.parsed_args.parse_type == "parse": - self.call_parse() - else: - self.call_feedback() - - def call_feedback(self) -> None: - """Sends feedback to an API.""" - custom_endpoint: Optional[Endpoint] = None - if self.parsed_args.product_name in ("custom", "generated"): - custom_endpoint = self.client.create_endpoint( - self.parsed_args.endpoint_name, - self.parsed_args.account_name, - self.parsed_args.api_version, - ) - if self.feedback is None: - raise MindeeClientError("Invalid feedback provided.") - - response: FeedbackResponse = self.client.send_feedback( - self.document_info.doc_class, - self.parsed_args.document_id, - {"feedback": self.feedback}, - custom_endpoint, - ) - print(json.dumps(response.feedback, indent=2)) - def call_parse(self) -> None: """Calls an endpoint with the appropriate method, and displays the results.""" response: Union[PredictResponse, AsyncPredictResponse] @@ -277,19 +233,13 @@ def _set_args(self) -> Namespace: for name, info in PRODUCTS.items(): parse_subparser = parse_product_subparsers.add_parser(name, help=info.help) - call_parser = parse_subparser.add_subparsers( - dest="parse_type", required=True - ) - parse_subp = call_parser.add_parser("parse") - feedback_subp = call_parser.add_parser("feedback") - - parse_subp.add_main_options() - parse_subp.add_sending_options() - parse_subp.add_display_options() + parse_subparser.add_main_options() + parse_subparser.add_sending_options() + parse_subparser.add_display_options() if name in ("custom", "generated"): - parse_subp.add_custom_options() + parse_subparser.add_custom_options() else: - parse_subp.add_argument( + parse_subparser.add_argument( "-t", "--full-text", dest="include_words", @@ -298,7 +248,7 @@ def _set_args(self) -> Namespace: ) if info.is_async and info.is_sync: - parse_subp.add_argument( + parse_subparser.add_argument( "-A", "--asynchronous", dest="async_parse", @@ -308,9 +258,6 @@ def _set_args(self) -> Namespace: default=False, ) - feedback_subp.add_main_options() - feedback_subp.add_feedback_options() - parsed_args = self.parser.parse_args() return parsed_args @@ -332,36 +279,3 @@ def _get_input_doc(self) -> Union[LocalInputSource, UrlInputSource]: elif self.parsed_args.input_type == "url": return self.client.source_from_url(self.parsed_args.path) return self.client.source_from_path(self.parsed_args.path) - - def _get_feedback_doc(self) -> StringDict: - """Loads a feedback.""" - json_doc: StringDict = {} - if self.parsed_args.input_type == "file": - with open(self.parsed_args.path, "rb", buffering=30) as f_f: - json_doc = json.loads(f_f.read()) - elif self.parsed_args.input_type == "base64": - with open(self.parsed_args.path, "rt", encoding="ascii") as f_b64: - json_doc = json.loads(f_b64.read()) - elif self.parsed_args.input_type == "bytes": - with open(self.parsed_args.path, "rb") as f_b: - json_doc = json.loads(f_b.read()) - else: - if ( - not self.parsed_args.feedback - or "feedback" not in self.parsed_args.feedback - ): - raise MindeeClientError("Invalid feedback.") - if not json_doc or "feedback" not in json_doc: - raise MindeeClientError("Invalid feedback.") - return json_doc - - def _set_input(self) -> None: - """Loads an input document, or a feedback document.""" - self.feedback = None - if self.parsed_args.parse_type == "feedback": - if not self.parsed_args.feedback: - self.feedback = self._get_feedback_doc() - else: - self.feedback = self.parsed_args.feedback - else: - self.input_doc = self._get_input_doc() diff --git a/tests/v1/test_cli.py b/tests/v1/test_cli.py index d7ea0379..0d0d947d 100644 --- a/tests/v1/test_cli.py +++ b/tests/v1/test_cli.py @@ -4,7 +4,7 @@ import pytest from mindee.commands.cli_parser import MindeeParser -from mindee.error.mindee_http_error import MindeeHTTPClientError, MindeeHTTPError +from mindee.error.mindee_http_error import MindeeHTTPError from tests.utils import FILE_TYPES_DIR, V1_PRODUCT_DATA_DIR, clear_envvars @@ -124,19 +124,19 @@ def ots_doc_feedback(monkeypatch): def test_cli_custom_doc(custom_doc): with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=custom_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_generated_doc_sync(generated_doc_sync): with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=generated_doc_sync) - parser.call_endpoint() + parser.call_parse() def test_cli_generated_doc_async(generated_doc_async): with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=generated_doc_async) - parser.call_endpoint() + parser.call_parse() def test_cli_invoice(ots_doc): @@ -144,11 +144,11 @@ def test_cli_invoice(ots_doc): ots_doc.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() ots_doc.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_receipt(ots_doc): @@ -156,11 +156,11 @@ def test_cli_receipt(ots_doc): ots_doc.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() ots_doc.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_financial_doc(ots_doc): @@ -168,11 +168,11 @@ def test_cli_financial_doc(ots_doc): ots_doc.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() ots_doc.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_passport(ots_doc): @@ -180,11 +180,11 @@ def test_cli_passport(ots_doc): ots_doc.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() ots_doc.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_us_bank_check(ots_doc): @@ -192,11 +192,11 @@ def test_cli_us_bank_check(ots_doc): ots_doc.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() ots_doc.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc) - parser.call_endpoint() + parser.call_parse() def test_cli_invoice_splitter_enqueue(ots_doc_enqueue_and_parse): @@ -204,20 +204,8 @@ def test_cli_invoice_splitter_enqueue(ots_doc_enqueue_and_parse): ots_doc_enqueue_and_parse.api_key = "" with pytest.raises(RuntimeError): parser = MindeeParser(parsed_args=ots_doc_enqueue_and_parse) - parser.call_endpoint() + parser.call_parse() ots_doc_enqueue_and_parse.api_key = "dummy" with pytest.raises(MindeeHTTPError): parser = MindeeParser(parsed_args=ots_doc_enqueue_and_parse) - parser.call_endpoint() - - -def test_cli_feedback(ots_doc_feedback): - ots_doc_feedback.document_id = "dummy-document-id" - ots_doc_feedback.api_key = "" - with pytest.raises(RuntimeError): - parser = MindeeParser(parsed_args=ots_doc_feedback) - parser.call_endpoint() - ots_doc_feedback.api_key = "dummy" - with pytest.raises(MindeeHTTPClientError): - parser = MindeeParser(parsed_args=ots_doc_feedback) - parser.call_endpoint() + parser.call_parse() From d604ab4d402018987d19592581a1a2a4d02a45ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ianar=C3=A9=20s=C3=A9vi?= Date: Wed, 26 Nov 2025 16:57:31 +0100 Subject: [PATCH 3/3] :bug: fix env var for v2 API key --- mindee/mindee_http/mindee_api_v2.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/mindee/mindee_http/mindee_api_v2.py b/mindee/mindee_http/mindee_api_v2.py index 8a7260fd..a8e380c8 100644 --- a/mindee/mindee_http/mindee_api_v2.py +++ b/mindee/mindee_http/mindee_api_v2.py @@ -32,8 +32,15 @@ def __init__( self, api_key: Optional[str], ): - self.api_key = api_key - if not self.api_key or len(self.api_key) == 0: + self.api_key = ( + api_key + if api_key + else os.environ.get(API_KEY_V2_ENV_NAME, API_KEY_V2_DEFAULT) + ) + self.request_timeout = TIMEOUT_DEFAULT + self.set_base_url(BASE_URL_DEFAULT) + self.set_from_env() + if not self.api_key: raise MindeeApiV2Error( ( f"Missing API key," @@ -42,9 +49,6 @@ def __init__( f"'{API_KEY_V2_ENV_NAME}' environment variable." ) ) - self.request_timeout = TIMEOUT_DEFAULT - self.set_base_url(BASE_URL_DEFAULT) - self.set_from_env() self.url_root = f"{self.base_url.rstrip('/')}" @property