diff --git a/docs/extras/code_samples/us_mail_v3_async.txt b/docs/extras/code_samples/us_mail_v3_async.txt new file mode 100644 index 00000000..38f5ed7f --- /dev/null +++ b/docs/extras/code_samples/us_mail_v3_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.us.UsMailV3, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/guide/us_mail_v2.md b/docs/extras/guide/us_mail_v3.md similarity index 80% rename from docs/extras/guide/us_mail_v2.md rename to docs/extras/guide/us_mail_v3.md index 03954424..241611fa 100644 --- a/docs/extras/guide/us_mail_v2.md +++ b/docs/extras/guide/us_mail_v3.md @@ -21,7 +21,7 @@ input_doc = mindee_client.source_from_path("/path/to/the/file.ext") # Load a file from disk and enqueue it. result: AsyncPredictResponse = mindee_client.enqueue_and_parse( - product.us.UsMailV2, + product.us.UsMailV3, input_doc, ) @@ -32,7 +32,20 @@ print(result.document) **Output (RST):** ```rst -:Sender Name: zed +######## +Document +######## +:Mindee ID: f9c36f59-977d-4ddc-9f2d-31c294c456ac +:Filename: default_sample.jpg + +Inference +######### +:Product: mindee/us_mail v3.0 +:Rotation applied: Yes + +Prediction +========== +:Sender Name: company zed :Sender Address: :City: Dallas :Complete Address: 54321 Elm Street, Dallas, Texas 54321 @@ -41,11 +54,12 @@ print(result.document) :Street: 54321 Elm Street :Recipient Names: Jane Doe :Recipient Addresses: - +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+ - | City | Complete Address | Is Address Change | Postal Code | Private Mailbox Number | State | Street | - +=================+=====================================+===================+=============+========================+=======+===========================+ - | Detroit | 1234 Market Street PMB 4321, Det... | | 12345 | 4321 | MI | 1234 Market Street | - +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+ + +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+-----------------+ + | City | Complete Address | Is Address Change | Postal Code | Private Mailbox Number | State | Street | Unit | + +=================+=====================================+===================+=============+========================+=======+===========================+=================+ + | Detroit | 1234 Market Street PMB 4321, Det... | False | 12345 | 4321 | MI | 1234 Market Street | | + +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+-----------------+ +:Return to Sender: False ``` # Field Types @@ -77,7 +91,7 @@ Fields which are specific to this product; they are not used in any other produc ### Recipient Addresses Field The addresses of the recipients. -A `UsMailV2RecipientAddress` implements the following attributes: +A `UsMailV3RecipientAddress` implements the following attributes: * **city** (`str`): The city of the recipient's address. * **complete** (`str`): The complete address of the recipient. @@ -86,12 +100,13 @@ A `UsMailV2RecipientAddress` implements the following attributes: * **private_mailbox_number** (`str`): The private mailbox number of the recipient's address. * **state** (`str`): Second part of the ISO 3166-2 code, consisting of two letters indicating the US State. * **street** (`str`): The street of the recipient's address. +* **unit** (`str`): The unit number of the recipient's address. Fields which are specific to this product; they are not used in any other product. ### Sender Address Field The address of the sender. -A `UsMailV2SenderAddress` implements the following attributes: +A `UsMailV3SenderAddress` implements the following attributes: * **city** (`str`): The city of the sender's address. * **complete** (`str`): The complete address of the sender. @@ -100,10 +115,17 @@ A `UsMailV2SenderAddress` implements the following attributes: * **street** (`str`): The street of the sender's address. # Attributes -The following fields are extracted for US Mail V2: +The following fields are extracted for US Mail V3: + +## Return to Sender +**is_return_to_sender** ([BooleanField](#booleanfield)): Whether the mailing is marked as return to sender. + +```py +print(result.document.inference.prediction.is_return_to_sender.value) +``` ## Recipient Addresses -**recipient_addresses** (List[[UsMailV2RecipientAddress](#recipient-addresses-field)]): The addresses of the recipients. +**recipient_addresses** (List[[UsMailV3RecipientAddress](#recipient-addresses-field)]): The addresses of the recipients. ```py for recipient_addresses_elem in result.document.inference.prediction.recipient_addresses: @@ -119,7 +141,7 @@ for recipient_names_elem in result.document.inference.prediction.recipient_names ``` ## Sender Address -**sender_address** ([UsMailV2SenderAddress](#sender-address-field)): The address of the sender. +**sender_address** ([UsMailV3SenderAddress](#sender-address-field)): The address of the sender. ```py print(result.document.inference.prediction.sender_address.value) diff --git a/docs/product/bill_of_lading_v1.rst b/docs/product/bill_of_lading_v1.rst index 92bd22bb..52cd1dfa 100644 --- a/docs/product/bill_of_lading_v1.rst +++ b/docs/product/bill_of_lading_v1.rst @@ -3,7 +3,7 @@ Bill of Lading V1 **Sample Code:** -.. literalinclude:: /extras/code_samples/bill_of_lading_v1.txt +.. literalinclude:: /extras/code_samples/bill_of_lading_v1_async.txt :language: Python .. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1.BillOfLadingV1 diff --git a/docs/product/ind/indian_passport_v1.rst b/docs/product/ind/indian_passport_v1.rst index d6aa690d..1bd99232 100644 --- a/docs/product/ind/indian_passport_v1.rst +++ b/docs/product/ind/indian_passport_v1.rst @@ -3,7 +3,7 @@ Passport - India V1 **Sample Code:** -.. literalinclude:: /extras/code_samples/ind_passport_v1.txt +.. literalinclude:: /extras/code_samples/ind_passport_v1_async.txt :language: Python .. autoclass:: mindee.product.ind.indian_passport.indian_passport_v1.IndianPassportV1 diff --git a/docs/product/international_id_v2.rst b/docs/product/international_id_v2.rst index 40e2ba93..04a0206c 100644 --- a/docs/product/international_id_v2.rst +++ b/docs/product/international_id_v2.rst @@ -3,7 +3,7 @@ International ID V2 **Sample Code:** -.. literalinclude:: /extras/code_samples/international_id_v2.txt +.. literalinclude:: /extras/code_samples/international_id_v2_async.txt :language: Python .. autoclass:: mindee.product.international_id.international_id_v2.InternationalIdV2 diff --git a/docs/product/nutrition_facts_label_v1.rst b/docs/product/nutrition_facts_label_v1.rst index 997b5048..00ec5fec 100644 --- a/docs/product/nutrition_facts_label_v1.rst +++ b/docs/product/nutrition_facts_label_v1.rst @@ -3,7 +3,7 @@ Nutrition Facts Label V1 **Sample Code:** -.. literalinclude:: /extras/code_samples/nutrition_facts_v1.txt +.. literalinclude:: /extras/code_samples/nutrition_facts_v1_async.txt :language: Python .. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1.NutritionFactsLabelV1 diff --git a/docs/product/us/us_mail_v2.rst b/docs/product/us/us_mail_v2.rst index 0812ccf4..f2335753 100644 --- a/docs/product/us/us_mail_v2.rst +++ b/docs/product/us/us_mail_v2.rst @@ -3,7 +3,7 @@ US Mail V2 **Sample Code:** -.. literalinclude:: /extras/code_samples/us_mail_v2.txt +.. literalinclude:: /extras/code_samples/us_mail_v2_async.txt :language: Python .. autoclass:: mindee.product.us.us_mail.us_mail_v2.UsMailV2 diff --git a/docs/product/us/us_mail_v3.rst b/docs/product/us/us_mail_v3.rst new file mode 100644 index 00000000..a689a7fd --- /dev/null +++ b/docs/product/us/us_mail_v3.rst @@ -0,0 +1,23 @@ +US Mail V3 +---------- + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/us_mail_v3_async.txt + :language: Python + +.. autoclass:: mindee.product.us.us_mail.us_mail_v3.UsMailV3 + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v3_document.UsMailV3Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v3_sender_address.UsMailV3SenderAddress + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v3_recipient_address.UsMailV3RecipientAddress + :members: + :inherited-members: diff --git a/mindee/cli.py b/mindee/cli.py index 7bfccee1..157b0ee6 100644 --- a/mindee/cli.py +++ b/mindee/cli.py @@ -167,7 +167,7 @@ class CommandConfig(Generic[TypeInference]): ), "us-mail": CommandConfig( help="US Mail", - doc_class=product.us.UsMailV2, + doc_class=product.us.UsMailV3, is_sync=False, is_async=True, ), diff --git a/mindee/product/us/__init__.py b/mindee/product/us/__init__.py index 8a9012a2..14d32f0f 100644 --- a/mindee/product/us/__init__.py +++ b/mindee/product/us/__init__.py @@ -19,6 +19,12 @@ UsMailV2RecipientAddress, ) from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress +from mindee.product.us.us_mail.us_mail_v3 import UsMailV3 +from mindee.product.us.us_mail.us_mail_v3_document import UsMailV3Document +from mindee.product.us.us_mail.us_mail_v3_recipient_address import ( + UsMailV3RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress from mindee.product.us.w9.w9_v1 import W9V1 from mindee.product.us.w9.w9_v1_document import W9V1Document from mindee.product.us.w9.w9_v1_page import W9V1Page diff --git a/mindee/product/us/us_mail/__init__.py b/mindee/product/us/us_mail/__init__.py index 3e78f043..bcb5367a 100644 --- a/mindee/product/us/us_mail/__init__.py +++ b/mindee/product/us/us_mail/__init__.py @@ -4,3 +4,9 @@ UsMailV2RecipientAddress, ) from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress +from mindee.product.us.us_mail.us_mail_v3 import UsMailV3 +from mindee.product.us.us_mail.us_mail_v3_document import UsMailV3Document +from mindee.product.us.us_mail.us_mail_v3_recipient_address import ( + UsMailV3RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress diff --git a/mindee/product/us/us_mail/us_mail_v3.py b/mindee/product/us/us_mail/us_mail_v3.py new file mode 100644 index 00000000..ed6e7473 --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v3.py @@ -0,0 +1,39 @@ +from typing import List + +from mindee.parsing.common.inference import Inference +from mindee.parsing.common.page import Page +from mindee.parsing.common.string_dict import StringDict +from mindee.product.us.us_mail.us_mail_v3_document import ( + UsMailV3Document, +) + + +class UsMailV3(Inference): + """US Mail API version 3 inference prediction.""" + + prediction: UsMailV3Document + """Document-level prediction.""" + pages: List[Page[UsMailV3Document]] + """Page-level prediction(s).""" + endpoint_name = "us_mail" + """Name of the endpoint.""" + endpoint_version = "3" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + US Mail v3 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = UsMailV3Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(UsMailV3Document, page)) diff --git a/mindee/product/us/us_mail/us_mail_v3_document.py b/mindee/product/us/us_mail/us_mail_v3_document.py new file mode 100644 index 00000000..ed0928d7 --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v3_document.py @@ -0,0 +1,105 @@ +from typing import List, Optional + +from mindee.parsing.common.prediction import Prediction +from mindee.parsing.common.string_dict import StringDict +from mindee.parsing.common.summary_helper import clean_out_string +from mindee.parsing.standard.boolean import BooleanField +from mindee.parsing.standard.text import StringField +from mindee.product.us.us_mail.us_mail_v3_recipient_address import ( + UsMailV3RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress + + +class UsMailV3Document(Prediction): + """US Mail API version 3.0 document data.""" + + is_return_to_sender: BooleanField + """Whether the mailing is marked as return to sender.""" + recipient_addresses: List[UsMailV3RecipientAddress] + """The addresses of the recipients.""" + recipient_names: List[StringField] + """The names of the recipients.""" + sender_address: UsMailV3SenderAddress + """The address of the sender.""" + sender_name: StringField + """The name of the sender.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + US Mail document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.is_return_to_sender = BooleanField( + raw_prediction["is_return_to_sender"], + page_id=page_id, + ) + self.recipient_addresses = [ + UsMailV3RecipientAddress(prediction, page_id=page_id) + for prediction in raw_prediction["recipient_addresses"] + ] + self.recipient_names = [ + StringField(prediction, page_id=page_id) + for prediction in raw_prediction["recipient_names"] + ] + self.sender_address = UsMailV3SenderAddress( + raw_prediction["sender_address"], + page_id=page_id, + ) + self.sender_name = StringField( + raw_prediction["sender_name"], + page_id=page_id, + ) + + @staticmethod + def _recipient_addresses_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 17}" + out_str += f"+{char * 37}" + out_str += f"+{char * 19}" + out_str += f"+{char * 13}" + out_str += f"+{char * 24}" + out_str += f"+{char * 7}" + out_str += f"+{char * 27}" + out_str += f"+{char * 17}" + return out_str + "+" + + def _recipient_addresses_to_str(self) -> str: + if not self.recipient_addresses: + return "" + + lines = f"\n{self._recipient_addresses_separator('-')}\n ".join( + [item.to_table_line() for item in self.recipient_addresses] + ) + out_str = "" + out_str += f"\n{self._recipient_addresses_separator('-')}\n " + out_str += " | City " + out_str += " | Complete Address " + out_str += " | Is Address Change" + out_str += " | Postal Code" + out_str += " | Private Mailbox Number" + out_str += " | State" + out_str += " | Street " + out_str += " | Unit " + out_str += f" |\n{self._recipient_addresses_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._recipient_addresses_separator('-')}" + return out_str + + def __str__(self) -> str: + recipient_names = f"\n { ' ' * 17 }".join( + [str(item) for item in self.recipient_names], + ) + out_str: str = f":Sender Name: {self.sender_name}\n" + out_str += f":Sender Address:\n{self.sender_address.to_field_list()}\n" + out_str += f":Recipient Names: {recipient_names}\n" + out_str += f":Recipient Addresses: {self._recipient_addresses_to_str()}\n" + out_str += f":Return to Sender: {self.is_return_to_sender}\n" + return clean_out_string(out_str) diff --git a/mindee/product/us/us_mail/us_mail_v3_recipient_address.py b/mindee/product/us/us_mail/us_mail_v3_recipient_address.py new file mode 100644 index 00000000..91ce313c --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v3_recipient_address.py @@ -0,0 +1,114 @@ +from typing import Dict, Optional + +from mindee.parsing.common.string_dict import StringDict +from mindee.parsing.common.summary_helper import clean_out_string, format_for_display +from mindee.parsing.standard.base import ( + FieldConfidenceMixin, + FieldPositionMixin, + bool_to_string, + to_opt_bool, +) + + +class UsMailV3RecipientAddress(FieldPositionMixin, FieldConfidenceMixin): + """The addresses of the recipients.""" + + city: Optional[str] + """The city of the recipient's address.""" + complete: Optional[str] + """The complete address of the recipient.""" + is_address_change: Optional[bool] + """Indicates if the recipient's address is a change of address.""" + postal_code: Optional[str] + """The postal code of the recipient's address.""" + private_mailbox_number: Optional[str] + """The private mailbox number of the recipient's address.""" + state: Optional[str] + """Second part of the ISO 3166-2 code, consisting of two letters indicating the US State.""" + street: Optional[str] + """The street of the recipient's address.""" + unit: Optional[str] + """The unit number of the recipient's address.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.city = raw_prediction["city"] + self.complete = raw_prediction["complete"] + self.is_address_change = to_opt_bool(raw_prediction, "is_address_change") + self.postal_code = raw_prediction["postal_code"] + self.private_mailbox_number = raw_prediction["private_mailbox_number"] + self.state = raw_prediction["state"] + self.street = raw_prediction["street"] + self.unit = raw_prediction["unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city) + out_dict["complete"] = format_for_display(self.complete) + out_dict["is_address_change"] = bool_to_string(self.is_address_change) + out_dict["postal_code"] = format_for_display(self.postal_code) + out_dict["private_mailbox_number"] = format_for_display( + self.private_mailbox_number + ) + out_dict["state"] = format_for_display(self.state) + out_dict["street"] = format_for_display(self.street) + out_dict["unit"] = format_for_display(self.unit) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city, 15) + out_dict["complete"] = format_for_display(self.complete, 35) + out_dict["is_address_change"] = bool_to_string(self.is_address_change) + out_dict["postal_code"] = format_for_display(self.postal_code, None) + out_dict["private_mailbox_number"] = format_for_display( + self.private_mailbox_number, None + ) + out_dict["state"] = format_for_display(self.state, None) + out_dict["street"] = format_for_display(self.street, 25) + out_dict["unit"] = format_for_display(self.unit, 15) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['city']:<15} | " + out_str += f"{printable['complete']:<35} | " + out_str += f"{printable['is_address_change']:<17} | " + out_str += f"{printable['postal_code']:<11} | " + out_str += f"{printable['private_mailbox_number']:<22} | " + out_str += f"{printable['state']:<5} | " + out_str += f"{printable['street']:<25} | " + out_str += f"{printable['unit']:<15} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"City: {printable['city']}, \n" + out_str += f"Complete Address: {printable['complete']}, \n" + out_str += f"Is Address Change: {printable['is_address_change']}, \n" + out_str += f"Postal Code: {printable['postal_code']}, \n" + out_str += f"Private Mailbox Number: {printable['private_mailbox_number']}, \n" + out_str += f"State: {printable['state']}, \n" + out_str += f"Street: {printable['street']}, \n" + out_str += f"Unit: {printable['unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/us/us_mail/us_mail_v3_sender_address.py b/mindee/product/us/us_mail/us_mail_v3_sender_address.py new file mode 100644 index 00000000..232d79fd --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v3_sender_address.py @@ -0,0 +1,74 @@ +from typing import Dict, Optional + +from mindee.parsing.common.string_dict import StringDict +from mindee.parsing.common.summary_helper import clean_out_string, format_for_display +from mindee.parsing.standard.base import FieldConfidenceMixin, FieldPositionMixin + + +class UsMailV3SenderAddress(FieldPositionMixin, FieldConfidenceMixin): + """The address of the sender.""" + + city: Optional[str] + """The city of the sender's address.""" + complete: Optional[str] + """The complete address of the sender.""" + postal_code: Optional[str] + """The postal code of the sender's address.""" + state: Optional[str] + """Second part of the ISO 3166-2 code, consisting of two letters indicating the US State.""" + street: Optional[str] + """The street of the sender's address.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.city = raw_prediction["city"] + self.complete = raw_prediction["complete"] + self.postal_code = raw_prediction["postal_code"] + self.state = raw_prediction["state"] + self.street = raw_prediction["street"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city) + out_dict["complete"] = format_for_display(self.complete) + out_dict["postal_code"] = format_for_display(self.postal_code) + out_dict["state"] = format_for_display(self.state) + out_dict["street"] = format_for_display(self.street) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :City: {printable['city']}\n" + out_str += f" :Complete Address: {printable['complete']}\n" + out_str += f" :Postal Code: {printable['postal_code']}\n" + out_str += f" :State: {printable['state']}\n" + out_str += f" :Street: {printable['street']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"City: {printable['city']}, \n" + out_str += f"Complete Address: {printable['complete']}, \n" + out_str += f"Postal Code: {printable['postal_code']}, \n" + out_str += f"State: {printable['state']}, \n" + out_str += f"Street: {printable['street']}, \n" + return clean_out_string(out_str) diff --git a/tests/data b/tests/data index a5fd00da..86f3c9de 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit a5fd00da05d7928549c24b150c5ad1ce4ae608b0 +Subproject commit 86f3c9de490a0f29e56cacee0cd63dbebfa86dc8 diff --git a/tests/product/us/us_mail/test_us_mail_v3.py b/tests/product/us/us_mail/test_us_mail_v3.py new file mode 100644 index 00000000..aefa85ff --- /dev/null +++ b/tests/product/us/us_mail/test_us_mail_v3.py @@ -0,0 +1,54 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product.us.us_mail.us_mail_v3 import UsMailV3 +from mindee.product.us.us_mail.us_mail_v3_document import ( + UsMailV3Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "us_mail" / "response_v3" + +UsMailV3DocumentType = Document[ + UsMailV3Document, + Page[UsMailV3Document], +] + + +@pytest.fixture +def complete_doc() -> UsMailV3DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(UsMailV3, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> UsMailV3DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(UsMailV3, json_data["document"]) + + +def test_complete_doc(complete_doc: UsMailV3DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: UsMailV3DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.sender_name.value is None + assert prediction.sender_address.city is None + assert prediction.sender_address.complete is None + assert prediction.sender_address.postal_code is None + assert prediction.sender_address.state is None + assert prediction.sender_address.street is None + assert len(prediction.recipient_names) == 0 + assert len(prediction.recipient_addresses) == 0 + assert prediction.is_return_to_sender.value is None