-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate_endpoints.py
147 lines (130 loc) · 4.18 KB
/
generate_endpoints.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
import inspect
import functools
import cep
from munch import munchify
def get_func_args(func):
"""
retrieve function args and attributs
:param
func: string func signature
func_name: string func name
namespace: flask namespace corresponding to the code project or library
:return: Dict of method args
"""
func_args = {}
# use inspect method to retrieve all args:
func_args["all_args"] = [
k for k in inspect.signature(func).parameters if k != "self"
]
func_args['path_args'] = [
arg
for arg in func_args["all_args"]
if (arg in func.api_path)
]
func_args['free_args'] = [
arg
for arg in func_args["all_args"]
if (arg not in func.api_path)
]
print(f'func {func.__name__} args = {func_args}')
return func_args
def get_class_name(func, namespace):
"""
create flask class from function endpoint
create a common flask class for all methods (get, put...) of an endpoint
Args:
str unformated_endpoint: the original endpoint defined in as '/...{}'
str namespace
Returns:
str class_name: the common flask class for all methods
"""
class_name = (
func.api_path
.strip("/")
.replace("{", "")
.replace("}", "")
.replace("/", "_")
.replace("-", "")
.capitalize()
)
if class_name == "":
class_name = (namespace + "_").capitalize()
print(f'class_name: {class_name}')
return class_name
def get_endpoint(func, func_args):
"""
generate flask endpoint from decorator endpoint in list_func_args[1]
Args:
str api_path: the original endpoint defined in as '/...{}'
list all_args: the function parameters
Returns:
formated endpoint for flask as '/...<int:>'
"""
endpoint_args = {}
for arg in func_args["path_args"]:
if ("Id" in arg) or ("id" in arg):
endpoint_args[arg] = f"<int:{arg}>"
else:
endpoint_args[arg] = f"<string:{arg}>"
return func.api_path.format(**endpoint_args)
def record_endpoints(namespace):
"""
generate a dict of all functions in a given namespace/class
the searched namespace has to be a class in the module cep.py
args:
str namespace
returns:
dict endpoints
endpoints = {
endpoint_name: {
'class': class_name,
'methods': [{
'rest_method': func.rest_method,
'func_name': func.__name__,
'func_args': {'path_args': _, 'free_args': _}
}]
}
}
"""
endpoints = {}
cls = getattr(cep, namespace)
for func_name in dir(cls):
func = getattr(cls, func_name) # func object
if callable(func) and "__" not in func_name :
func_args = get_func_args(func)
class_name = get_class_name(func, namespace)
endpoint_name = get_endpoint(func, func_args)
method = {
'rest_method': func.rest_method,
'func_name': func.__name__,
'func_args': func_args,
}
if endpoint_name not in endpoints:
endpoints[endpoint_name] = {
'class_name': class_name,
'methods': [method]
}
else:
endpoints[endpoint_name]['methods'].append(method)
print(f'endpoints: {endpoints}')
return endpoints
def record_namespace():
exclude_list = ["__", "add_args", "add_path"]
namespaces = {
namespace: getattr(cep, namespace).__doc__
#namespace: getattr(cep, namespace).__doc__
for namespace in dir(cep)
if not any(x in namespace for x in exclude_list)
}
print(f'flask namespace: client: {namespaces}')
return namespaces
def render_data_generator():
"""
render a namespace template
generate all the flask endpoints for a namespace
"""
namespaces = record_namespace()
for namespace, client in namespaces.items():
endpoints = record_endpoints(namespace)
data_to_render = munchify({"endpoints": endpoints, "namespace": namespace, "client": client})
yield data_to_render