Skip to content

Commit fd25b03

Browse files
authored
Merge pull request #1 from sQu4rks/meeting_endpoint_family
Meeting endpoint family
2 parents 0c83e76 + 3112445 commit fd25b03

14 files changed

+1702
-3
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)")
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: MeetingInvitee
2+
endpoint: meetingInvitees
3+
object_type: meetingInvitee
4+
methods:
5+
- list
6+
- get
7+
- create
8+
- delete
9+
- update
10+
query_parameters:
11+
- name: meetingId
12+
description: Unique id of the meeting for which invitees are requested.
13+
optional: False
14+
type: basestring
15+
- name: max
16+
description: Limit the number of meeting invitees
17+
optional: True
18+
type: int
19+
- name: hostEmail
20+
description: Email address for the meeting host (requires admin scope)
21+
optional: True
22+
type: basestring
23+
- name: panelist
24+
description: Filter invitees or attendees based on their panelist status
25+
optional: True
26+
type: bool
27+
create:
28+
required:
29+
- meetingId
30+
- email
31+
optional:
32+
- displayName
33+
- coHost
34+
- name: hostEmail
35+
description: Email address for the meeting host (requires admin scope)
36+
type: basestring
37+
- name: sendEmail
38+
description: If true, send an e-mail to the invitee
39+
type: bool
40+
- panelist
41+
update:
42+
required:
43+
- email
44+
optional:
45+
- displayName
46+
- coHost
47+
- name: hostEmail
48+
description: Email address for the meeting host (requires admin scope)
49+
type: basestring
50+
- name: sendEmail
51+
description: If true, send an e-mail to the invitee
52+
type: bool
53+
- panelist
54+
list:
55+
properties:
56+
- name: id
57+
description: Unique id for the meeting invitee
58+
type: basestring
59+
- name: email
60+
description: Email address for the meeting invitee
61+
type: basestring
62+
- name: displayName
63+
description: Display name of the meeting invitee
64+
type: basestring
65+
- name: coHost
66+
description: CoHost status of the invitee
67+
type: bool
68+
- name: meetingId
69+
description: Unique id for the meeting that the invitee is part of
70+
type: basestring
71+
- name: panelist
72+
description: Flag to indicate if the invitee is panelist or not
73+
type: bool
74+
additional_code: >
75+
def bulk(self, meetingId, hostEmail=None, items=None, **request_parameters):
76+
""" Bulk insert meeting invitees
77+
78+
Args:
79+
meetingId(basestring): Id of the meeting the invitees should be added to.
80+
hostEmail(basestring): Email of the meeting host.
81+
items(list): List of invitees. Each invitee is a dict with email as the
82+
required key and displayName, coHost, sendEmail and panelist as optional
83+
properties.
84+
**request_parameters: Additional request parameters (provides
85+
support for parameters that may be added in the future).
86+
87+
Returns:
88+
GeneratorContainer: A GeneratorContainer which, when iterated,
89+
yields the meetingInvitees returned by the Webex query.
90+
91+
Raises:
92+
TypeError: If the parameter types are incorrect.
93+
ApiError: If the Webex Teams cloud returns an error.
94+
"""
95+
check_type(meetingId, basestring)
96+
check_type(hostEmail, basestring, optional=True)
97+
check_type(items, list, optional=True)
98+
99+
post_data = dict_from_items_with_values(
100+
request_parameters,
101+
meetingId=meetingId,
102+
items=items,
103+
hostEmail=hostEmail,
104+
)
105+
106+
# API request
107+
json_data = self._session.put(API_ENDPOINT + '/bulkInsert',
108+
json=post_data)
109+
110+
# Return an object created from the response JSON data
111+
for itm in json_data['items']:
112+
yield self._object_factory(OBJECT_TYPE, itm)
113+
114+
115+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: MeetingTemplate
2+
endpoint: meetings/templates
3+
object_type: meetingTemplate
4+
methods:
5+
- list
6+
- get
7+
query_parameters:
8+
- name: templateType
9+
description: Meeting template types (meeting, webinar)
10+
optional: True
11+
type: basestring
12+
- name: locale
13+
description: Locale for the meeting template (i.e. en_US)
14+
optional: True
15+
type: basestring
16+
- name: isDefault
17+
description: Flag to indicate if default or non-default meeting templates are returned
18+
optional: True
19+
type: bool
20+
- name: isStandard
21+
description: Flag to indicate if standard or non-standard meeting templates are returned
22+
optional: True
23+
type: bool
24+
- name: hostEmail
25+
description: Email address of a meeting host (Requires admin-level scope)
26+
optional: True
27+
type: bool
28+
- name: siteUrl
29+
description: URL of the Webex site from which we are listing.
30+
optional: True
31+
type: bool
32+
list:
33+
properties:
34+
- name: id
35+
description: Unique id for meeting template
36+
type: basestring
37+
- name: name
38+
description: Name of the meeting template
39+
type: basestring
40+
- name: locale
41+
description: Locale for the meeting template
42+
type: basestring
43+
- name: siteUrl
44+
description: Site URL for the meeting template
45+
type: basestring
46+
- name: templateType
47+
description: Type of the meeting template (meeting, webinar)
48+
type: basestring
49+
- name: isDefault
50+
description: Whether or not the meeting template is a default template
51+
type: bool
52+
- name: isStandard
53+
description: Whether or not the meeting template is a standard template
54+
type: bool
55+
- name: meeting
56+
description: Meeting object which is used to create a meeting by the meeting template. Please note that the meeting object should be used to create a meeting immediately.
57+
type: dict

0 commit comments

Comments
 (0)