Skip to content

Commit c02c48f

Browse files
committed
Add devdock template lifecycle example
1 parent fcb4535 commit c02c48f

1 file changed

Lines changed: 193 additions & 0 deletions

File tree

  • examples/api2-devdock-template-lifecycle
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
"""Run the API2 contract Template lifecycle scenario against a devdock API2 server.
2+
3+
This example is intentionally checked into the SDK repository: it should read
4+
the API facts from API2's injected scenario JSON and exercise public SDK
5+
methods as normal user code would.
6+
"""
7+
8+
import json
9+
import os
10+
import time
11+
from pathlib import Path
12+
13+
from transloadit.client import Transloadit
14+
15+
16+
def required_env(name):
17+
value = os.environ.get(name)
18+
if not value:
19+
raise RuntimeError(f"{name} must be set")
20+
return value
21+
22+
23+
def fail(message):
24+
raise RuntimeError(message)
25+
26+
27+
def load_scenario():
28+
configured_path = os.environ.get("API2_SDK_EXAMPLE_SCENARIO")
29+
scenario_path = (
30+
Path(configured_path) if configured_path else Path(__file__).with_name("api2-scenario.json")
31+
)
32+
with scenario_path.open(encoding="utf-8") as scenario_file:
33+
return json.load(scenario_file)
34+
35+
36+
def response_data(response, operation):
37+
data = response.data
38+
if not isinstance(data, dict):
39+
fail(f"{operation} returned non-JSON data: {data!r}")
40+
if data.get("error"):
41+
fail(f"{operation} returned {data.get('error')}: {data.get('message')}")
42+
return data
43+
44+
45+
def require_template_id(data, operation):
46+
template_id = data.get("id") or data.get("template_id")
47+
if not template_id:
48+
fail(f"{operation} returned no template id: {data!r}")
49+
return template_id
50+
51+
52+
def template_content(content):
53+
if not isinstance(content, dict):
54+
fail(f"template content must be an object: {content!r}")
55+
56+
return dict(content)
57+
58+
59+
def template_payload(name, config):
60+
require_signature_auth = 1 if config["requireSignatureAuth"] else 0
61+
return {
62+
"name": name,
63+
"require_signature_auth": require_signature_auth,
64+
"template": template_content(config["content"]),
65+
}
66+
67+
68+
def response_flag(data, *names):
69+
for name in names:
70+
if name in data:
71+
value = data[name]
72+
if isinstance(value, bool):
73+
return value
74+
if isinstance(value, int):
75+
return value != 0
76+
if isinstance(value, str):
77+
return value.lower() in ("1", "true", "yes")
78+
return False
79+
80+
81+
def template_result(data):
82+
content = data.get("content") or data.get("template") or {}
83+
if not isinstance(content, dict):
84+
fail(f"template response content must be an object: {content!r}")
85+
86+
return {
87+
"content": content,
88+
"id": data.get("id") or data.get("template_id"),
89+
"name": data.get("name") or data.get("template_name"),
90+
"requireSignatureAuth": response_flag(
91+
data,
92+
"require_signature_auth",
93+
"requireSignatureAuth",
94+
),
95+
}
96+
97+
98+
def list_count(data):
99+
count = data.get("count")
100+
if isinstance(count, int):
101+
return count
102+
103+
items = data.get("items")
104+
if isinstance(items, list):
105+
return len(items)
106+
107+
fail(f"template list response did not contain a count or items list: {data!r}")
108+
109+
110+
def deleted_get_result(response):
111+
data = response.data
112+
if not isinstance(data, dict):
113+
return False, ""
114+
115+
error_code = data.get("error")
116+
if isinstance(error_code, str) and error_code:
117+
return False, error_code
118+
119+
return response.status_code is not None and response.status_code < 400, ""
120+
121+
122+
def write_result(result):
123+
result_path = os.environ.get("API2_SDK_EXAMPLE_RESULT")
124+
if not result_path:
125+
return
126+
127+
with Path(result_path).open("w", encoding="utf-8") as result_file:
128+
json.dump(result, result_file, indent=2)
129+
result_file.write("\n")
130+
131+
132+
def main():
133+
scenario = load_scenario()
134+
endpoint = required_env("TRANSLOADIT_ENDPOINT")
135+
client = Transloadit(
136+
auth_key=required_env("TRANSLOADIT_KEY"),
137+
auth_secret=required_env("TRANSLOADIT_SECRET"),
138+
service=endpoint,
139+
)
140+
141+
template_name = f"{scenario['template']['namePrefix']}-{time.time_ns()}"
142+
template_id = None
143+
delete_template = True
144+
145+
try:
146+
created = response_data(
147+
client.create_template(template_payload(template_name, scenario["template"])),
148+
"createTemplate",
149+
)
150+
template_id = require_template_id(created, "createTemplate")
151+
152+
fetched = response_data(client.get_template(template_id), "getTemplate")
153+
listed = response_data(
154+
client.list_templates({"pagesize": scenario["list"]["pageSize"]}),
155+
"listTemplates",
156+
)
157+
158+
updated_template_name = f"{template_name}{scenario['update']['nameSuffix']}"
159+
response_data(
160+
client.update_template(
161+
template_id,
162+
template_payload(updated_template_name, scenario["update"]),
163+
),
164+
"updateTemplate",
165+
)
166+
updated = response_data(client.get_template(template_id), "getTemplate updated")
167+
168+
response_data(client.delete_template(template_id), "deleteTemplate")
169+
delete_template = False
170+
171+
deleted_get_succeeded, deleted_error_code = deleted_get_result(client.get_template(template_id))
172+
173+
write_result(
174+
{
175+
"deletedErrorCode": deleted_error_code,
176+
"deletedGetSucceeded": deleted_get_succeeded,
177+
"fetched": template_result(fetched),
178+
"listCount": list_count(listed),
179+
"templateId": template_id,
180+
"templateName": template_name,
181+
"updated": template_result(updated),
182+
"updatedTemplateName": updated_template_name,
183+
}
184+
)
185+
finally:
186+
if template_id and delete_template:
187+
client.delete_template(template_id)
188+
189+
print(f"Python Transloadit SDK devdock scenario {scenario['scenarioId']} passed for {endpoint}")
190+
191+
192+
if __name__ == "__main__":
193+
main()

0 commit comments

Comments
 (0)