-
Notifications
You must be signed in to change notification settings - Fork 5
/
add_code_samples_to_oas.py
160 lines (151 loc) · 8.07 KB
/
add_code_samples_to_oas.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import os
import re
import ruamel.yaml
ASANA_OAS_DIR = './defs/asana_oas.yaml'
LANGUAGES = ['java', 'node', 'python', 'php', 'ruby']
# ReadMe code configurations
readme_code_config = {
'java': {
# TODO: Dynamically pull the latest java-asana package version number
# NOTE: this FoldedScalarString method adds this line as a YAML block scalar style so in the future when ReadMe supports '\n' in their install we can go back and add it in here
# Context: more info on YAML Multiline: https://yaml-multiline.info/
'install': ruamel.yaml.scalarstring.FoldedScalarString('<dependency><groupId>com.asana</groupId><artifactId>asana</artifactId><version>1.0.0</version></dependency>'),
},
'node': {
'install': 'npm install asana',
},
'node-sdk-v1': {
'install': 'npm install [email protected]',
},
'python': {
'install': 'pip install asana',
},
'python-sdk-v3': {
'install': 'pip install asana==3.2.2',
},
'php': {
'install': 'composer require asana/asana',
},
'ruby': {
'install': 'gem install asana',
}
}
# Let ruamel.yaml know that we don't want to use aliases/anchors in the output YAML file
ruamel.yaml.representer.RoundTripRepresenter.ignore_aliases = lambda x, y: True
yaml = ruamel.yaml.YAML()
# Configure ruamel.yaml to preserve OpenAPI Spec file formatting
yaml.preserve_quotes = True
yaml.indent(sequence=4, offset=2)
# Helper function to convert snakecase to camel case
def camel_case(s):
# Split underscore using split
temp = s.split('_')
# Joining result
return temp[0] + ''.join(word.title() for word in temp[1:])
# Gather sample code
print('Gathering sample code')
code_samples = {}
for language in LANGUAGES:
if language in ["node", "python"]:
# Add sample code for new Node library
version = 'v3' if language == "node" else "v5"
sample_name = f"{language}-sdk-{version}"
for dirpath,_,filenames in os.walk(f'./build/{language}/docs'):
for filename in filenames:
if re.search("^.*Api.yaml$", filename):
with open(f'{dirpath}/{filename}') as fp:
data = yaml.load(fp)
for resource, operations in data.items():
# Swagger Codegen Generator adds "Api" suffix to end of resource names we need
# to remove it so we can find a matching resource in our OpenAPI Spec
resource_name = resource.replace("Api", '').lower()
# Set resource key in code_samples dict
code_samples.setdefault(resource_name, {})
# Loop through each operation
for operation, code_sample in operations.items():
# Convert operation name from snake case to camel case
# NOTE: the python generator snake cases all opertionIDs we need to
# change this to camel case so we can find a matching resource in our OpenAPI Spec
operation_name_camel_case = camel_case(operation)
# Set operation name
code_samples[resource_name].setdefault(operation_name_camel_case, [])
# Add sample code
code_samples[resource_name][operation_name_camel_case].append(
{
"language": language,
"install": readme_code_config[language]['install'],
"code": code_sample,
"name": sample_name
}
)
# Add sample for Node v1 library
version = 'v1' if language == "node" else "v3"
sample_name = f"{language}-sdk-{version}"
for dirpath,_,filenames in os.walk(f'./build/{sample_name}/samples'):
for filename in filenames:
with open(f'{dirpath}/{filename}') as fp:
data = yaml.load(fp)
for resource, operations in data.items():
# Set resource key in code_samples dict
resource_name = resource
code_samples.setdefault(resource_name, {})
# Loop through each operation
for operation, code_sample in operations.items():
# Convert operation name from snake case to camel case
operation_name_camel_case = camel_case(operation)
# Set operation name
code_samples[resource_name].setdefault(operation_name_camel_case, [])
# Add sample code
code_samples[resource_name][operation_name_camel_case].append(
{
"language": language,
"install": readme_code_config[sample_name]['install'],
"code": code_sample,
"name": sample_name
}
)
else:
# Add sample code for current client libraries
for dirpath,_,filenames in os.walk(f'./build/{language}/samples'):
for filename in filenames:
with open(f'{dirpath}/{filename}') as fp:
data = yaml.load(fp)
for resource, operations in data.items():
# Set resource key in code_samples dict
# NOTE: java resource name has a "base" suffix. We'll need to remove this so we
# can group the sample code together with the other languages
resource_name = resource.replace("base", '') if language == 'java' else resource
code_samples.setdefault(resource_name, {})
# Loop through each operation
for operation, code_sample in operations.items():
# Convert operation name from snake case to camel case
operation_name_camel_case = camel_case(operation)
# Set operation name
code_samples[resource_name].setdefault(operation_name_camel_case, [])
# Add sample code
code_samples[resource_name][operation_name_camel_case].append(
{
"language": language,
"install": readme_code_config[language]['install'],
"code": code_sample
}
)
# TODO: Find a more efficient way to inject the sample code
# Load OAS file
with open(ASANA_OAS_DIR) as fp:
data = yaml.load(fp)
# Add code samples to each enpoint in the OAS
for resource, operations in code_samples.items():
print(f'Adding code samples to {resource}')
for operation in operations:
for endpoint, endpoint_data in data['paths'].items():
for method, method_data in endpoint_data.items():
if method in ['delete', 'get', 'post', 'put']:
if method_data['operationId'] == operation:
modified_data = data['paths'][endpoint][method]
modified_data.setdefault('x-readme', {})
modified_data['x-readme'].setdefault('code-samples', [])
modified_data['x-readme']['code-samples'] = code_samples[resource][operation]
# Update OpenAPI Spec file with injected code samples
with open(ASANA_OAS_DIR, 'w') as fp:
yaml.dump(data, fp)