Skip to content

Commit 5073f8c

Browse files
committed
Added initial version of generator code
1 parent dab756f commit 5073f8c

File tree

6 files changed

+553
-1
lines changed

6 files changed

+553
-1
lines changed

generator/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class ActionNotFoundError(Exception):
2+
pass
3+
4+
class PropertyNotFoundError(Exception):
5+
pass
6+
7+
class MissingKeyError(Exception):
8+
pass

generator/generate.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import sys
2+
import os
3+
import yaml
4+
import argparse
5+
6+
from jinja2 import Environment, FileSystemLoader
7+
8+
from utils import get_additional_parameters
9+
from exceptions import MissingKeyError
10+
11+
def render_prop_mixin(env: Environment,
12+
name: str,
13+
properties: list,
14+
base_name: str,
15+
template_name: str="mixins.py",
16+
path_prefix: str="../webexteamssdk/models/mixins/"
17+
) -> str:
18+
""" Renders a simple property mixin for the SDK based on the
19+
information provided in the descriptor file.
20+
21+
Args:
22+
env(Environment): The jinja environment to render under. Defines
23+
the templates that will be used.
24+
name(str): The name of our endpoint. Will be turned into the class
25+
name as {name}SimplePropertyMixin.
26+
properties(list): List of property extracted from the list.properties
27+
key in the descriptor file.
28+
base_name(str): Base name of the descriptor file. Used to generate
29+
the filenames.
30+
template_name(str): Name of the template to use. Default: mixins.py
31+
path_prefix(str): Path to the mixins folder.
32+
Default: ../webexteamssdk/models/mixins/
33+
34+
Returns:
35+
str: Path to the generated
36+
"""
37+
38+
# Render template based on loaded properties
39+
tmpl = env.get_template(template_name)
40+
out = tmpl.render(name=name, properties=properties)
41+
42+
target_path = os.path.join(path_prefix, f"{base_name}.py")
43+
44+
with open(target_path, "w") as fh:
45+
fh.writelines(out)
46+
47+
return target_path
48+
49+
def render_api_class(env: Environment,
50+
descr: dict,
51+
base_name: str,
52+
template_name: str = "api.py",
53+
path_prefix: str = "../webexteamssdk/api/"
54+
) -> str:
55+
""" Renders an API class based on the properties described in
56+
the descr file.
57+
58+
Args:
59+
env(Environment): The jinja environment to render under. Defines
60+
the templates that will be used.
61+
descr(dict): Descriptor parsed from the yaml file defining the
62+
properties of the endpoint and target api model.
63+
base_name(str): Base name of the descriptor file. Used to generate
64+
the filenames.
65+
template_name(str): Name of the template to use. Default: api.py
66+
path_prefix(str): Path to the target api folder that the output will
67+
we placed in. Default: ../webexteamssdk/api/
68+
69+
Returns:
70+
str: The path to the generated api class
71+
"""
72+
create_parameters = get_additional_parameters(descr, 'create')
73+
update_parameters = get_additional_parameters(descr, 'update')
74+
75+
additional_code = descr.get("additional_code", None)
76+
77+
# Render template
78+
tpl = env.get_template(template_name)
79+
out = tpl.render(name=descr['name'],
80+
endpoint=descr['endpoint'],
81+
object_type=descr['object_type'],
82+
query_parameters=descr['query_parameters'],
83+
create_parameters=create_parameters,
84+
update_parameters=update_parameters,
85+
methods=descr['methods'],
86+
additional_code=additional_code),
87+
88+
target_path = os.path.join(path_prefix, f"{base_name}.py")
89+
90+
with open(target_path, "w") as fh:
91+
fh.writelines(out)
92+
93+
return target_path
94+
95+
def main():
96+
# Setup arg parser
97+
parser = argparse.ArgumentParser(description='Generate new endpoints for the SDK')
98+
parser.add_argument('-d',
99+
'--descriptor',
100+
help="Path to the descriptor .yaml file",
101+
type=str,
102+
required=True)
103+
parser.add_argument('-t',
104+
'--template_dir',
105+
help="Path to the templates directory",
106+
type=str,
107+
default="templates",
108+
required=False)
109+
args = parser.parse_args()
110+
111+
# Setup jinja environment and load information from description file
112+
env = Environment(loader=FileSystemLoader(args.template_dir))
113+
114+
descr_file = args.descriptor
115+
base_name = os.path.splitext(os.path.basename(descr_file))[0]
116+
117+
descr = yaml.safe_load(open(descr_file))
118+
119+
# Check that all required keys are present
120+
required_keys = [
121+
'name',
122+
'list.properties',
123+
'endpoint',
124+
'object_type',
125+
'query_parameters',
126+
'methods'
127+
]
128+
129+
for key in required_keys:
130+
# Check all keys - subkeys (i.e. d['list']['properties']
131+
# can be passed in dot notation, so list.properties)
132+
keys = key.split(".")
133+
134+
d = descr
135+
for sub_key in keys:
136+
if sub_key not in d.keys():
137+
raise MissingKeyError(f"Missing required key '{key}'")
138+
else:
139+
d = d.get(sub_key)
140+
141+
mixin_path = render_prop_mixin(env=env,
142+
name=descr['name'],
143+
properties=descr['list']['properties'],
144+
base_name=base_name
145+
)
146+
print(f"Rendered mixin for {descr['name']} to {mixin_path}")
147+
148+
api_path = render_api_class(env=env,
149+
descr=descr,
150+
base_name=base_name)
151+
print(f"Rendered api class for {descr['name']} to {api_path}")
152+
153+
154+
if __name__ == "__main__":
155+
main()
156+
# print("Manually add: ")
157+
# print("In webexteamssdk/models/immutable.py")
158+
# print(f"from .mixins.{ base_name } import { descr['name'] }BasicPropertiesMixin")
159+
160+
# cls_model_def = f"""
161+
# class { descr['name'] }(ImmutableData, { descr['name'] }BasicPropertiesMixin):
162+
# \"\"\"Webex { descr['name'] } data model\"\"\"
163+
# """
164+
# print(cls_model_def)
165+
166+
# print(f"{descr['object_type']}={ descr['name'] }")
167+
168+
# print()
169+
# print()
170+
# print("In webexteamssdk/api/__init__.py")
171+
# print(f"from {base_name} import {descr['name']}API")
172+
# print(f"self.{descr['object_type']}s = {descr['name']}(self._session, object_factory)")

generator/models/meeting_invitees.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ update:
5454
list:
5555
properties:
5656
- name: id
57-
description: Unique id for meeting invitee
57+
description: Unique id for the meeting invitee
5858
type: basestring
5959
- name: email
6060
description: Email address for the meeting invitee

0 commit comments

Comments
 (0)