Skip to content

Commit c29d801

Browse files
authored
Add multipart support to the CreateEtchPacket mutation (anvilco#41)
* Multipart helpers * Update payload types * Update HTTP client to support multipart * Add multipart process to createEtchPacket * Add multipart example * Update multipart process to accept non-serializable things * Linting, update documentation * Update tests * Lint fixes * Less annoying example usage with envvars * Minor package updates, remove operationName * Update changelog * Bump version
1 parent e3aae80 commit c29d801

21 files changed

Lines changed: 624 additions & 312 deletions

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# 1.8.0 (2022-09-09)
2+
3+
- Added support for multipart uploads on `CreateEtchPacket` requests.
4+
- New example for multipart uploads in `examples/create_etch_upload_file_multipart.py`
5+
- Added environment variable usage in all `examples/` files for easier usage.
6+
- Updated a few minor development packages.
7+
18
# 1.7.0 (2022-09-09)
29

310
- Added support for `version_number` in PDF Fill requests.

docs/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
mkdocs==1.3.0; python_version >= "3.6"
2-
pygments==2.12.0; python_version >= "3.6"
2+
pygments==2.14.0; python_version >= "3.6"

examples/create_etch_existing_cast.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
# pylint: disable=duplicate-code
22

3+
import os
4+
35
from python_anvil.api import Anvil
46
from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket
57
from python_anvil.api_resources.payload import EtchCastRef, EtchSigner, SignerField
68

79

8-
API_KEY = 'my-api-key'
10+
API_KEY = os.environ.get("ANVIL_API_KEY")
11+
# or set your own key here
12+
# API_KEY = 'my-api-key'
913

1014

1115
def main():

examples/create_etch_markdown.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# pylint: disable=duplicate-code
22

3+
import os
4+
35
from python_anvil.api import Anvil
46
from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket
57
from python_anvil.api_resources.payload import (
@@ -11,7 +13,9 @@
1113
)
1214

1315

14-
API_KEY = 'my-api-key'
16+
API_KEY = os.environ.get("ANVIL_API_KEY")
17+
# or set your own key here
18+
# API_KEY = 'my-api-key'
1519

1620

1721
def main():

examples/create_etch_markup.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# pylint: disable=duplicate-code
22

3+
import os
4+
35
from python_anvil.api import Anvil
46
from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket
57
from python_anvil.api_resources.payload import (
@@ -10,7 +12,9 @@
1012
)
1113

1214

13-
API_KEY = 'my-api-key'
15+
API_KEY = os.environ.get("ANVIL_API_KEY")
16+
# or set your own key here
17+
# API_KEY = 'my-api-key'
1418

1519

1620
def main():

examples/create_etch_upload_file.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pylint: disable=duplicate-code
22

33
import base64
4+
import os
45

56
from python_anvil.api import Anvil
67
from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket
@@ -13,7 +14,9 @@
1314
)
1415

1516

16-
API_KEY = 'my-api-key'
17+
API_KEY = os.environ.get("ANVIL_API_KEY")
18+
# or set your own key here
19+
# API_KEY = 'my-api-key'
1720

1821

1922
def main():
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# pylint: disable=duplicate-code
2+
import os
3+
4+
from python_anvil.api import Anvil
5+
from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket
6+
from python_anvil.api_resources.payload import (
7+
DocumentUpload,
8+
EtchSigner,
9+
SignatureField,
10+
SignerField,
11+
)
12+
13+
14+
API_KEY = os.environ.get("ANVIL_API_KEY")
15+
# or set your own key here
16+
# API_KEY = 'my-api-key'
17+
18+
19+
def main():
20+
anvil = Anvil(api_key=API_KEY)
21+
22+
# Create an instance of the builder
23+
packet = CreateEtchPacket(
24+
name="Etch packet with existing template multipart",
25+
#
26+
# Optional changes to email subject and body content
27+
signature_email_subject="Please sign these forms",
28+
signature_email_body="This form requires information from your driver's "
29+
"license. Please have that available.",
30+
#
31+
# URL where Anvil will send POST requests when server events happen.
32+
# Take a look at https://www.useanvil.com/docs/api/e-signatures#webhook-notifications
33+
# for other details on how to configure webhooks on your account.
34+
# You can also use sites like webhook.site, requestbin.com or ngrok to
35+
# test webhooks.
36+
# webhook_url="https://my.webhook.example.com/etch-events/",
37+
#
38+
# Email overrides for the "reply-to" email header for signer emails.
39+
# If used, both `reply_to_email` and `reply_to_name` are required.
40+
# By default, this will point to your organization support email.
41+
# reply_to_email="[email protected]",
42+
# reply_to_name="My Name",
43+
#
44+
# Merge all PDFs into one. Use this if you have many PDF templates
45+
# and/or files, but want the final downloaded package to be only
46+
# 1 PDF file.
47+
# merge_pdfs=True,
48+
)
49+
50+
# Get your file(s) ready to sign.
51+
# For this example, the PDF hasn't been uploaded to Anvil yet.
52+
# In the `create_etch_upload_file.py` example, we are base64 encoding our
53+
# file(s) before sending. In this case, we will be providing a file's path
54+
# or file descriptor (from an `open()` call)
55+
filename = "my_local_file.pdf"
56+
file_dir = os.path.dirname(os.path.realpath(__file__))
57+
file_path = os.path.join(file_dir, filename)
58+
59+
# You can check manually if your file exists, however, the validator being
60+
# used in the `GraphqlUpload` below will also check if the file exists.
61+
#
62+
# if not os.path.exists(file_path):
63+
# raise FileNotFoundError('File does not exist. Please check `file_path` '
64+
# 'and ensure it points to an existing file.')
65+
66+
# Upload the file and define signer field locations.
67+
file1 = DocumentUpload(
68+
id="myNewFile",
69+
title="Please sign this important form",
70+
# You can send a callable that returns a file handle and the filename
71+
# you want to use in the Anvil app.
72+
# (IMPORTANT: The data must be read in as _bytes_, not text.)
73+
file=lambda: (
74+
open(file_path, "rb"), # pylint: disable=consider-using-with
75+
filename,
76+
),
77+
# or just the valid path itself
78+
# file=file_path,
79+
fields=[
80+
SignatureField(
81+
id="sign1",
82+
type="signature",
83+
page_num=0,
84+
# The position and size of the field. The coordinates provided here
85+
# (x=100, y=100) is the top-left of the rectangle.
86+
rect=dict(x=183, y=100, width=250, height=50),
87+
)
88+
],
89+
)
90+
91+
# Gather your signer data
92+
signer1 = EtchSigner(
93+
name="Jackie",
94+
95+
# Fields where the signer needs to sign.
96+
# Check your cast fields via the CLI (`anvil cast [cast_eid]`) or the
97+
# PDF Templates section on the Anvil app.
98+
# This basically says: "In the 'myNewFile' file (defined in
99+
# `file1` above), assign the signature field with cast id of
100+
# 'sign1' to this signer." You can add multiple signer fields here.
101+
fields=[
102+
SignerField(
103+
# this is the `id` in the `DocumentUpload` object above
104+
file_id="myNewFile",
105+
# This is the signing field id in the `SignatureField` above
106+
field_id="sign1",
107+
)
108+
],
109+
signer_type="embedded",
110+
#
111+
# You can also change how signatures will be collected.
112+
# "draw" will allow the signer to draw their signature
113+
# "text" will insert a text version of the signer's name into the
114+
# signature field.
115+
# signature_mode="draw",
116+
#
117+
# Whether to the signer is required to click each signature
118+
# field manually. If `False`, the PDF will be signed once the signer
119+
# accepts the PDF without making the user go through the PDF.
120+
# accept_each_field=False,
121+
#
122+
# URL of where the signer will be redirected after signing.
123+
# The URL will also have certain URL params added on, so the page
124+
# can be customized based on the signing action.
125+
# redirect_url="https://www.google.com",
126+
)
127+
128+
# Add your signer.
129+
packet.add_signer(signer1)
130+
131+
# Add files to your payload
132+
packet.add_file(file1)
133+
134+
# If needed, you can also override or add additional payload fields this way.
135+
# This is useful if the Anvil API has new features, but `python-anvil` has not
136+
# yet been updated to support it.
137+
# payload = packet.create_payload()
138+
# payload.aNewFeature = True
139+
140+
# Create your packet
141+
# If overriding/adding new fields, use the modified payload from
142+
# `packet.create_payload()`
143+
res = anvil.create_etch_packet(payload=packet, include_headers=True)
144+
print(res)
145+
146+
147+
if __name__ == '__main__':
148+
main()

examples/create_workflow_submission.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import os
12
from datetime import datetime
23

34
from python_anvil.api import Anvil
45
from python_anvil.api_resources.payload import ForgeSubmitPayload
56

67

7-
API_KEY = 'my-api-key'
8+
API_KEY = os.environ.get("ANVIL_API_KEY")
9+
# or set your own key here
10+
# API_KEY = 'my-api-key'
811

912

1013
def main():

examples/fill_pdf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import os
2+
13
from python_anvil.api import Anvil
24

35

4-
API_KEY = 'my-api-key'
6+
API_KEY = os.environ.get("ANVIL_API_KEY")
7+
# or set your own key here
8+
# API_KEY = 'my-api-key'
59

610

711
def main():

examples/generate_pdf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import os
2+
13
from python_anvil.api import Anvil
24
from python_anvil.api_resources.payload import GeneratePDFPayload
35

46

5-
API_KEY = 'my-api-key'
7+
API_KEY = os.environ.get("ANVIL_API_KEY")
8+
# or set your own key here
9+
# API_KEY = 'my-api-key'
610

711

812
def main():

0 commit comments

Comments
 (0)