Skip to content

Commit 1990a40

Browse files
authored
Merge pull request #1 from JStarL/main
First Draft of aws_json_1_1 with few changes to shared_functions.py
2 parents 740d1da + 865a57e commit 1990a40

File tree

5 files changed

+207
-13
lines changed

5 files changed

+207
-13
lines changed

model_inventory.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def extract_services(input_dir: Path):
77
service_entries = []
88
for model_file in input_dir.glob("*.json"):
99
try:
10-
with open(model_file, "r") as f:
10+
with open(model_file, "r", encoding="utf-8") as f:
1111
model_data = json.load(f)
1212

1313
shapes = model_data.get("shapes", model_data)
@@ -25,6 +25,18 @@ def extract_services(input_dir: Path):
2525
"servicename": shape_name,
2626
"protocol": protocol
2727
})
28+
except json.JSONDecodeError as e:
29+
service_entries.append({
30+
"filename": model_file.name,
31+
"servicename": "ERROR",
32+
"protocol": f"JSON decode error: {e}"
33+
})
34+
except UnicodeDecodeError as e:
35+
service_entries.append({
36+
"filename": model_file.name,
37+
"servicename": "ERROR",
38+
"protocol": f"Encoding error: {e}"
39+
})
2840
except Exception as e:
2941
service_entries.append({
3042
"filename": model_file.name,

process_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
def extract_services(input_dir: Path):
1717
for model_file in input_dir.glob("*.json"):
1818
try:
19-
with open(model_file, "r") as f:
19+
with open(model_file, "r", encoding="utf-8") as f:
2020
model_data = json.load(f)
2121

2222
shapes = model_data.get("shapes", model_data)

processors/aws_json_1_1.py

Lines changed: 176 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,178 @@
1+
# processors/rest_json1.py
2+
3+
import json, yaml
4+
from pathlib import Path
5+
import sys
6+
from processors.shared_functions import (
7+
LiteralStr,
8+
literal_str_representer,
9+
html_to_md,
10+
init_openapi_spec,
11+
add_info,
12+
add_servers,
13+
add_component_schema_string,
14+
add_component_schema_boolean,
15+
add_component_schema_integer,
16+
add_component_schema_timestamp,
17+
add_component_schema_double,
18+
add_component_schema_float,
19+
add_component_schema_long,
20+
add_component_schema_blob,
21+
add_component_schema_enum,
22+
add_component_schema_map,
23+
add_component_schema_document,
24+
add_component_schema_list,
25+
add_component_schema_union,
26+
add_component_schema_structure,
27+
add_operation,
28+
)
29+
30+
yaml.add_representer(LiteralStr, literal_str_representer)
31+
132
def process(model_entry):
33+
34+
services_to_skip = []
35+
file_name = model_entry['filename']
36+
if file_name in services_to_skip:
37+
print(f"skipping {file_name}")
38+
return
39+
40+
protocol = model_entry['protocol']
241
service_name = model_entry['servicename'].split('#')[0].split('com.amazonaws.')[1]
3-
print(f"processing {service_name} with protocol {model_entry['protocol']}")
42+
print(f"processing {service_name} with protocol {protocol}")
43+
44+
model_path = Path(model_entry['filepath'])
45+
46+
with open(model_path, "r", encoding="utf-8") as f:
47+
model_data = json.load(f)
48+
49+
# Basic OpenAPI structure
50+
openapi_spec = init_openapi_spec(service_name, file_name, protocol)
51+
52+
shapes = model_data.get("shapes", model_data)
53+
54+
shapes_dict = {
55+
"service": [],
56+
"operation": []
57+
}
58+
59+
for shape_name, shape in shapes.items():
60+
if shape.get("type") == "service":
61+
add_info(openapi_spec, shape)
62+
add_servers(openapi_spec, file_name, shape)
63+
shape["my_name"] = shape_name
64+
shapes_dict["service"].append(shape)
65+
elif shape.get("type") == "string":
66+
add_component_schema_string(openapi_spec, shape_name, shape)
67+
elif shape.get("type") == "boolean":
68+
add_component_schema_boolean(openapi_spec, shape_name, shape)
69+
elif shape.get("type") == "integer":
70+
add_component_schema_integer(openapi_spec, shape_name, shape)
71+
elif shape.get("type") == "timestamp":
72+
add_component_schema_timestamp(openapi_spec, shape_name, shape)
73+
elif shape.get("type") == "double":
74+
add_component_schema_double(openapi_spec, shape_name, shape)
75+
elif shape.get("type") == "float":
76+
add_component_schema_float(openapi_spec, shape_name, shape)
77+
elif shape.get("type") == "long":
78+
add_component_schema_long(openapi_spec, shape_name, shape)
79+
elif shape.get("type") == "blob":
80+
add_component_schema_blob(openapi_spec, shape_name, shape)
81+
elif shape.get("type") == "enum":
82+
add_component_schema_enum(openapi_spec, shape_name, shape)
83+
elif shape.get("type") == "map":
84+
add_component_schema_map(openapi_spec, shape_name, shape)
85+
elif shape.get("type") == "document":
86+
add_component_schema_document(openapi_spec, shape_name, shape)
87+
elif shape.get("type") == "list":
88+
add_component_schema_list(openapi_spec, shape_name, shape)
89+
elif shape.get("type") == "union":
90+
add_component_schema_union(openapi_spec, shape_name, shape)
91+
elif shape.get("type") == "structure":
92+
add_component_schema_structure(openapi_spec, shape_name, shape)
93+
elif shape.get("type") == "operation":
94+
add_operation(openapi_spec, shape_name, shape, shapes)
95+
shape["my_name"] = shape_name
96+
shapes_dict["operation"].append(shape)
97+
98+
# process the service to get the paths
99+
service_name2 = model_entry['servicename'].split('#')[1]
100+
101+
# Sort the operations, we will need them to be in alphabetic order for creating paths
102+
shapes_dict["operation"].sort(key=lambda x: x["my_name"])
103+
104+
# Setup the "paths" attribute
105+
openapi_spec["paths"] = {}
106+
107+
# create the path
108+
for operation in shapes_dict["operation"]:
109+
key_string = "/#X-Amz-Target=" + service_name2 + "." + operation["my_name"].split('#')[1]
110+
openapi_spec["paths"][key_string] = create_path(operation, service_name2)
111+
112+
# Write output YAML
113+
outdir = Path("testdir")
114+
outdir.mkdir(exist_ok=True)
115+
outfile = outdir / f"{service_name}.yaml"
116+
with open(outfile, "w", encoding="utf-8") as f:
117+
yaml.dump(openapi_spec, f, sort_keys=False, allow_unicode=True)
118+
119+
def create_path(operation, service_name2):
120+
result = {}
121+
result["post"] = {}
122+
result_post = result["post"]
123+
124+
result_post["operationId"] = operation["my_name"].split('#')[1]
125+
result_post["description"] = LiteralStr(html_to_md(operation["traits"].get("smithy.api#documentation", "")))
126+
127+
result_post["requestBody"] = {}
128+
result_request_body = result_post["requestBody"]
129+
result_request_body["required"] = True
130+
result_request_body["content"] = {}
131+
result_request_body["content"]["application/json"] = {}
132+
result_request_body["content"]["application/json"]["schema"] = {}
133+
result_request_body["content"]["application/json"]["schema"]["$ref"] = "#/components/schemas/" + operation["input"]["target"].split("#")[1]
134+
135+
result_post["parameters"] = {}
136+
result_parameters_inside = result_post["parameters"]
137+
result_parameters_inside["name"] = "X-Amz-Target"
138+
result_parameters_inside["in"] = "header"
139+
result_parameters_inside["required"] = True
140+
result_parameters_inside["schema"] = {}
141+
result_parameters_inside["schema"]["type"] = "string"
142+
result_parameters_inside["schema"]["enum"] = [service_name2 + "." + operation["my_name"].split('#')[1]]
143+
144+
# Static Information
145+
result["parameters"] = []
146+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Content-Sha256'})
147+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Date'})
148+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Algorithm'})
149+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Credential'})
150+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Security-Token'})
151+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-Signature'})
152+
result["parameters"].append({ '$ref': '#/components/parameters/X-Amz-SignedHeaders'})
153+
154+
result_post["responses"] = {}
155+
result_responses = result_post["responses"]
156+
# 200 response
157+
result_responses["200"] = {}
158+
result_responses["200"]["description"] = "Success"
159+
result_responses["200"]["content"] = {}
160+
result_responses["200"]["content"]["application/json"] = {}
161+
result_responses["200"]["content"]["application/json"]["schema"] = {"$ref": ('#/components/schemas/' + operation["output"]["target"].split('#')[1])}
162+
163+
error_code = 480
164+
165+
if operation.get("errors", False) is not False:
166+
for error in operation["errors"]:
167+
error_string = str(error_code)
168+
error_name = error["target"].split('#')[1]
169+
170+
result_responses[error_string] = {}
171+
result_responses[error_string]["description"] = error_name
172+
result_responses[error_string]["content"] = {}
173+
result_responses[error_string]["content"]["application/json"] = {}
174+
result_responses[error_string]["content"]["application/json"]["schema"] = {"$ref": ('#/components/schemas/' + error_name)}
175+
176+
error_code += 1
177+
178+
return result

processors/rest_json1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def process(model_entry):
4141

4242
model_path = Path(model_entry['filepath'])
4343

44-
with open(model_path, "r") as f:
44+
with open(model_path, "r", encoding="utf-8") as f:
4545
model_data = json.load(f)
4646

4747
# Basic OpenAPI structure

processors/shared_functions.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def init_openapi_spec(service_name, file_name, protocol):
3939
}
4040

4141
def add_info(openapi_spec, service_shape):
42-
openapi_spec["info"]["version"] = service_shape["version"]
42+
if "version" in service_shape:
43+
openapi_spec["info"]["version"] = service_shape["version"]
4344
openapi_spec["info"]["title"] = service_shape["traits"]["smithy.api#title"]
4445
openapi_spec["info"]["description"] = LiteralStr(html_to_md(service_shape["traits"]["smithy.api#documentation"]))
4546

@@ -328,7 +329,7 @@ def add_component_schema_map(openapi_spec, shape_name, shape):
328329

329330
# Get value type
330331
value_target = shape.get("value", {}).get("target", "smithy.api#String")
331-
value_type = value_target.split("#")[-1]
332+
value_type = value_target.split("#")[-1].lower()
332333

333334
# Handle scalar types
334335
scalar_map = {
@@ -507,18 +508,24 @@ def add_operation(openapi_spec, shape_name, shape, shapes):
507508
print(f"adding operation {operation_id}")
508509

509510
# process traits
510-
path = shape["traits"]["smithy.api#http"]["uri"]
511-
verb = shape["traits"]["smithy.api#http"]["method"].lower()
512-
if "code" in shape["traits"]["smithy.api#http"]:
513-
success_code = shape["traits"]["smithy.api#http"]["code"]
514-
else:
515-
success_code = 200
511+
traits = shape.get("traits", {})
512+
http = traits.get("smithy.api#http", {})
513+
path = http.get("uri", None)
514+
verb = http.get("method", None)
515+
if verb:
516+
verb = verb.lower()
517+
518+
if path is None or verb is None:
519+
return
520+
521+
success_code = http.get("code", 200)
522+
516523
if path not in openapi_spec["paths"]:
517524
openapi_spec["paths"][path] = {}
518525
if verb not in openapi_spec["paths"][path]:
519526
openapi_spec["paths"][path][verb] = {}
520527
openapi_spec["paths"][path][verb]["operationId"] = operation_id
521-
if "smithy.api#documentation" in shape["traits"]:
528+
if "smithy.api#documentation" in traits:
522529
description = LiteralStr(html_to_md(shape["traits"]["smithy.api#documentation"]))
523530
openapi_spec["paths"][path][verb]["description"] = description
524531

0 commit comments

Comments
 (0)