halfapi/halfapi/lib/domain.py

115 lines
2.8 KiB
Python

#!/usr/bin/env python3
import importlib
from types import ModuleType
from typing import Generator, Dict, List
VERBS = ('GET', 'POST', 'PUT', 'PATCH', 'DELETE')
def get_fct_name(http_verb: str, path: str) -> str:
"""
Returns the predictable name of the function for a route
Parameters:
- http_verb (str): The Route's HTTP method (GET, POST, ...)
- path (str): The functions path
Returns:
str: The *unique* function name for a route and it's verb
Examples:
>>> get_fct_name('get', '')
'get'
>>> get_fct_name('GET', '')
'get'
>>> get_fct_name('POST', 'foo')
'post_foo'
>>> get_fct_name('POST', 'bar')
'post_bar'
>>> get_fct_name('DEL', 'foo/{boo}')
'del_foo_BOO'
>>> get_fct_name('DEL', '{boo:zoo}/far')
'del_BOO_far'
"""
if path and path[0] == '/':
path = path[1:]
fct_name = [http_verb.lower()]
for elt in path.split('/'):
if elt and elt[0] == '{':
fct_name.append(elt[1:-1].split(':')[0].upper())
elif elt:
fct_name.append(elt)
return '_'.join(fct_name)
def gen_routes(route_params: Dict, path: List, m_router: ModuleType) -> Generator:
d_res = {'fqtn': route_params.get('FQTN')}
for verb in VERBS:
params = route_params.get(verb)
if params is None:
continue
if len(params) == 0:
print(f'No ACL for route [{verb}] "/".join(path)')
try:
fct_name = get_fct_name(verb, path[-1])
fct = getattr(m_router, fct_name)
except AttributeError:
print(f'{fct_name} is not defined in {m_router.__name__}')
continue
d_res[verb] = {'fct': fct, 'params': params}
yield f"/{'/'.join([ elt for elt in path if elt ])}", d_res
def gen_router_routes(m_router, path=None):
"""
{
'/truc/toto': {
}
}
"""
if not hasattr(m_router, 'ROUTES'):
print(f'Missing *ROUTES* constant in *{m_router.__name__}*')
if path is None:
path = []
routes = m_router.ROUTES
for subpath, route_params in routes.items():
path.append(subpath)
for r_path, d_route in gen_routes(route_params, path, m_router):
yield r_path, d_route
subroutes = route_params.get('SUBROUTES', [])
for subroute in subroutes:
path.append(subroute)
submod = importlib.import_module(f'.{subroute}', m_router.__name__)
for r_path, d_route in gen_router_routes(submod, path):
yield r_path, d_route
path.pop()
path.pop()
def gen_domain_routes(domain):
m_router = importlib.import_module('.routers', domain)
return gen_router_routes(m_router, [domain])