Skip to content

Commit f4bf2d5

Browse files
ianardeeMindee
andauthored
✨ add support for us mail v3 (#294)
Co-authored-by: Mindee <opensource@mindee.com>
1 parent 30d2b9e commit f4bf2d5

17 files changed

+478
-19
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from mindee import Client, product, AsyncPredictResponse
2+
3+
# Init a new client
4+
mindee_client = Client(api_key="my-api-key")
5+
6+
# Load a file from disk
7+
input_doc = mindee_client.source_from_path("/path/to/the/file.ext")
8+
9+
# Load a file from disk and enqueue it.
10+
result: AsyncPredictResponse = mindee_client.enqueue_and_parse(
11+
product.us.UsMailV3,
12+
input_doc,
13+
)
14+
15+
# Print a brief summary of the parsed data
16+
print(result.document)

docs/extras/guide/us_mail_v2.md renamed to docs/extras/guide/us_mail_v3.md

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ input_doc = mindee_client.source_from_path("/path/to/the/file.ext")
2121

2222
# Load a file from disk and enqueue it.
2323
result: AsyncPredictResponse = mindee_client.enqueue_and_parse(
24-
product.us.UsMailV2,
24+
product.us.UsMailV3,
2525
input_doc,
2626
)
2727

@@ -32,7 +32,20 @@ print(result.document)
3232

3333
**Output (RST):**
3434
```rst
35-
:Sender Name: zed
35+
########
36+
Document
37+
########
38+
:Mindee ID: f9c36f59-977d-4ddc-9f2d-31c294c456ac
39+
:Filename: default_sample.jpg
40+
41+
Inference
42+
#########
43+
:Product: mindee/us_mail v3.0
44+
:Rotation applied: Yes
45+
46+
Prediction
47+
==========
48+
:Sender Name: company zed
3649
:Sender Address:
3750
:City: Dallas
3851
:Complete Address: 54321 Elm Street, Dallas, Texas 54321
@@ -41,11 +54,12 @@ print(result.document)
4154
:Street: 54321 Elm Street
4255
:Recipient Names: Jane Doe
4356
:Recipient Addresses:
44-
+-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+
45-
| City | Complete Address | Is Address Change | Postal Code | Private Mailbox Number | State | Street |
46-
+=================+=====================================+===================+=============+========================+=======+===========================+
47-
| Detroit | 1234 Market Street PMB 4321, Det... | | 12345 | 4321 | MI | 1234 Market Street |
48-
+-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+
57+
+-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+-----------------+
58+
| City | Complete Address | Is Address Change | Postal Code | Private Mailbox Number | State | Street | Unit |
59+
+=================+=====================================+===================+=============+========================+=======+===========================+=================+
60+
| Detroit | 1234 Market Street PMB 4321, Det... | False | 12345 | 4321 | MI | 1234 Market Street | |
61+
+-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+-----------------+
62+
:Return to Sender: False
4963
```
5064

5165
# Field Types
@@ -77,7 +91,7 @@ Fields which are specific to this product; they are not used in any other produc
7791
### Recipient Addresses Field
7892
The addresses of the recipients.
7993

80-
A `UsMailV2RecipientAddress` implements the following attributes:
94+
A `UsMailV3RecipientAddress` implements the following attributes:
8195

8296
* **city** (`str`): The city of the recipient's address.
8397
* **complete** (`str`): The complete address of the recipient.
@@ -86,12 +100,13 @@ A `UsMailV2RecipientAddress` implements the following attributes:
86100
* **private_mailbox_number** (`str`): The private mailbox number of the recipient's address.
87101
* **state** (`str`): Second part of the ISO 3166-2 code, consisting of two letters indicating the US State.
88102
* **street** (`str`): The street of the recipient's address.
103+
* **unit** (`str`): The unit number of the recipient's address.
89104
Fields which are specific to this product; they are not used in any other product.
90105

91106
### Sender Address Field
92107
The address of the sender.
93108

94-
A `UsMailV2SenderAddress` implements the following attributes:
109+
A `UsMailV3SenderAddress` implements the following attributes:
95110

96111
* **city** (`str`): The city of the sender's address.
97112
* **complete** (`str`): The complete address of the sender.
@@ -100,10 +115,17 @@ A `UsMailV2SenderAddress` implements the following attributes:
100115
* **street** (`str`): The street of the sender's address.
101116

102117
# Attributes
103-
The following fields are extracted for US Mail V2:
118+
The following fields are extracted for US Mail V3:
119+
120+
## Return to Sender
121+
**is_return_to_sender** ([BooleanField](#booleanfield)): Whether the mailing is marked as return to sender.
122+
123+
```py
124+
print(result.document.inference.prediction.is_return_to_sender.value)
125+
```
104126

105127
## Recipient Addresses
106-
**recipient_addresses** (List[[UsMailV2RecipientAddress](#recipient-addresses-field)]): The addresses of the recipients.
128+
**recipient_addresses** (List[[UsMailV3RecipientAddress](#recipient-addresses-field)]): The addresses of the recipients.
107129

108130
```py
109131
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
119141
```
120142

121143
## Sender Address
122-
**sender_address** ([UsMailV2SenderAddress](#sender-address-field)): The address of the sender.
144+
**sender_address** ([UsMailV3SenderAddress](#sender-address-field)): The address of the sender.
123145

124146
```py
125147
print(result.document.inference.prediction.sender_address.value)

docs/product/bill_of_lading_v1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Bill of Lading V1
33

44
**Sample Code:**
55

6-
.. literalinclude:: /extras/code_samples/bill_of_lading_v1.txt
6+
.. literalinclude:: /extras/code_samples/bill_of_lading_v1_async.txt
77
:language: Python
88

99
.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1.BillOfLadingV1

docs/product/ind/indian_passport_v1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Passport - India V1
33

44
**Sample Code:**
55

6-
.. literalinclude:: /extras/code_samples/ind_passport_v1.txt
6+
.. literalinclude:: /extras/code_samples/ind_passport_v1_async.txt
77
:language: Python
88

99
.. autoclass:: mindee.product.ind.indian_passport.indian_passport_v1.IndianPassportV1

docs/product/international_id_v2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ International ID V2
33

44
**Sample Code:**
55

6-
.. literalinclude:: /extras/code_samples/international_id_v2.txt
6+
.. literalinclude:: /extras/code_samples/international_id_v2_async.txt
77
:language: Python
88

99
.. autoclass:: mindee.product.international_id.international_id_v2.InternationalIdV2

docs/product/nutrition_facts_label_v1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Nutrition Facts Label V1
33

44
**Sample Code:**
55

6-
.. literalinclude:: /extras/code_samples/nutrition_facts_v1.txt
6+
.. literalinclude:: /extras/code_samples/nutrition_facts_v1_async.txt
77
:language: Python
88

99
.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1.NutritionFactsLabelV1

docs/product/us/us_mail_v2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ US Mail V2
33

44
**Sample Code:**
55

6-
.. literalinclude:: /extras/code_samples/us_mail_v2.txt
6+
.. literalinclude:: /extras/code_samples/us_mail_v2_async.txt
77
:language: Python
88

99
.. autoclass:: mindee.product.us.us_mail.us_mail_v2.UsMailV2

docs/product/us/us_mail_v3.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
US Mail V3
2+
----------
3+
4+
**Sample Code:**
5+
6+
.. literalinclude:: /extras/code_samples/us_mail_v3_async.txt
7+
:language: Python
8+
9+
.. autoclass:: mindee.product.us.us_mail.us_mail_v3.UsMailV3
10+
:members:
11+
:inherited-members:
12+
13+
.. autoclass:: mindee.product.us.us_mail.us_mail_v3_document.UsMailV3Document
14+
:members:
15+
:inherited-members:
16+
17+
.. autoclass:: mindee.product.us.us_mail.us_mail_v3_sender_address.UsMailV3SenderAddress
18+
:members:
19+
:inherited-members:
20+
21+
.. autoclass:: mindee.product.us.us_mail.us_mail_v3_recipient_address.UsMailV3RecipientAddress
22+
:members:
23+
:inherited-members:

mindee/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class CommandConfig(Generic[TypeInference]):
167167
),
168168
"us-mail": CommandConfig(
169169
help="US Mail",
170-
doc_class=product.us.UsMailV2,
170+
doc_class=product.us.UsMailV3,
171171
is_sync=False,
172172
is_async=True,
173173
),

mindee/product/us/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
UsMailV2RecipientAddress,
2020
)
2121
from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress
22+
from mindee.product.us.us_mail.us_mail_v3 import UsMailV3
23+
from mindee.product.us.us_mail.us_mail_v3_document import UsMailV3Document
24+
from mindee.product.us.us_mail.us_mail_v3_recipient_address import (
25+
UsMailV3RecipientAddress,
26+
)
27+
from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress
2228
from mindee.product.us.w9.w9_v1 import W9V1
2329
from mindee.product.us.w9.w9_v1_document import W9V1Document
2430
from mindee.product.us.w9.w9_v1_page import W9V1Page

mindee/product/us/us_mail/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44
UsMailV2RecipientAddress,
55
)
66
from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress
7+
from mindee.product.us.us_mail.us_mail_v3 import UsMailV3
8+
from mindee.product.us.us_mail.us_mail_v3_document import UsMailV3Document
9+
from mindee.product.us.us_mail.us_mail_v3_recipient_address import (
10+
UsMailV3RecipientAddress,
11+
)
12+
from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import List
2+
3+
from mindee.parsing.common.inference import Inference
4+
from mindee.parsing.common.page import Page
5+
from mindee.parsing.common.string_dict import StringDict
6+
from mindee.product.us.us_mail.us_mail_v3_document import (
7+
UsMailV3Document,
8+
)
9+
10+
11+
class UsMailV3(Inference):
12+
"""US Mail API version 3 inference prediction."""
13+
14+
prediction: UsMailV3Document
15+
"""Document-level prediction."""
16+
pages: List[Page[UsMailV3Document]]
17+
"""Page-level prediction(s)."""
18+
endpoint_name = "us_mail"
19+
"""Name of the endpoint."""
20+
endpoint_version = "3"
21+
"""Version of the endpoint."""
22+
23+
def __init__(self, raw_prediction: StringDict):
24+
"""
25+
US Mail v3 inference.
26+
27+
:param raw_prediction: Raw prediction from the HTTP response.
28+
"""
29+
super().__init__(raw_prediction)
30+
31+
self.prediction = UsMailV3Document(raw_prediction["prediction"])
32+
self.pages = []
33+
for page in raw_prediction["pages"]:
34+
try:
35+
page_prediction = page["prediction"]
36+
except KeyError:
37+
continue
38+
if page_prediction:
39+
self.pages.append(Page(UsMailV3Document, page))
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from typing import List, Optional
2+
3+
from mindee.parsing.common.prediction import Prediction
4+
from mindee.parsing.common.string_dict import StringDict
5+
from mindee.parsing.common.summary_helper import clean_out_string
6+
from mindee.parsing.standard.boolean import BooleanField
7+
from mindee.parsing.standard.text import StringField
8+
from mindee.product.us.us_mail.us_mail_v3_recipient_address import (
9+
UsMailV3RecipientAddress,
10+
)
11+
from mindee.product.us.us_mail.us_mail_v3_sender_address import UsMailV3SenderAddress
12+
13+
14+
class UsMailV3Document(Prediction):
15+
"""US Mail API version 3.0 document data."""
16+
17+
is_return_to_sender: BooleanField
18+
"""Whether the mailing is marked as return to sender."""
19+
recipient_addresses: List[UsMailV3RecipientAddress]
20+
"""The addresses of the recipients."""
21+
recipient_names: List[StringField]
22+
"""The names of the recipients."""
23+
sender_address: UsMailV3SenderAddress
24+
"""The address of the sender."""
25+
sender_name: StringField
26+
"""The name of the sender."""
27+
28+
def __init__(
29+
self,
30+
raw_prediction: StringDict,
31+
page_id: Optional[int] = None,
32+
):
33+
"""
34+
US Mail document.
35+
36+
:param raw_prediction: Raw prediction from HTTP response
37+
:param page_id: Page number for multi pages pdf input
38+
"""
39+
super().__init__(raw_prediction, page_id)
40+
self.is_return_to_sender = BooleanField(
41+
raw_prediction["is_return_to_sender"],
42+
page_id=page_id,
43+
)
44+
self.recipient_addresses = [
45+
UsMailV3RecipientAddress(prediction, page_id=page_id)
46+
for prediction in raw_prediction["recipient_addresses"]
47+
]
48+
self.recipient_names = [
49+
StringField(prediction, page_id=page_id)
50+
for prediction in raw_prediction["recipient_names"]
51+
]
52+
self.sender_address = UsMailV3SenderAddress(
53+
raw_prediction["sender_address"],
54+
page_id=page_id,
55+
)
56+
self.sender_name = StringField(
57+
raw_prediction["sender_name"],
58+
page_id=page_id,
59+
)
60+
61+
@staticmethod
62+
def _recipient_addresses_separator(char: str) -> str:
63+
out_str = " "
64+
out_str += f"+{char * 17}"
65+
out_str += f"+{char * 37}"
66+
out_str += f"+{char * 19}"
67+
out_str += f"+{char * 13}"
68+
out_str += f"+{char * 24}"
69+
out_str += f"+{char * 7}"
70+
out_str += f"+{char * 27}"
71+
out_str += f"+{char * 17}"
72+
return out_str + "+"
73+
74+
def _recipient_addresses_to_str(self) -> str:
75+
if not self.recipient_addresses:
76+
return ""
77+
78+
lines = f"\n{self._recipient_addresses_separator('-')}\n ".join(
79+
[item.to_table_line() for item in self.recipient_addresses]
80+
)
81+
out_str = ""
82+
out_str += f"\n{self._recipient_addresses_separator('-')}\n "
83+
out_str += " | City "
84+
out_str += " | Complete Address "
85+
out_str += " | Is Address Change"
86+
out_str += " | Postal Code"
87+
out_str += " | Private Mailbox Number"
88+
out_str += " | State"
89+
out_str += " | Street "
90+
out_str += " | Unit "
91+
out_str += f" |\n{self._recipient_addresses_separator('=')}"
92+
out_str += f"\n {lines}"
93+
out_str += f"\n{self._recipient_addresses_separator('-')}"
94+
return out_str
95+
96+
def __str__(self) -> str:
97+
recipient_names = f"\n { ' ' * 17 }".join(
98+
[str(item) for item in self.recipient_names],
99+
)
100+
out_str: str = f":Sender Name: {self.sender_name}\n"
101+
out_str += f":Sender Address:\n{self.sender_address.to_field_list()}\n"
102+
out_str += f":Recipient Names: {recipient_names}\n"
103+
out_str += f":Recipient Addresses: {self._recipient_addresses_to_str()}\n"
104+
out_str += f":Return to Sender: {self.is_return_to_sender}\n"
105+
return clean_out_string(out_str)

0 commit comments

Comments
 (0)