[lib.schemas] router schema update
This commit is contained in:
parent
238bd99bd3
commit
1ccfa0d10e
@ -99,3 +99,10 @@ def args_check(fct):
|
||||
return await fct(req, *args, **kwargs)
|
||||
|
||||
return caller
|
||||
|
||||
# ACLS list for doc and priorities
|
||||
# Write your own constant in your domain or import this one
|
||||
ACLS = (
|
||||
('private', public.__doc__, 0),
|
||||
('public', public.__doc__, 999)
|
||||
)
|
||||
|
@ -1,17 +1,28 @@
|
||||
import re
|
||||
from schema import Schema, Optional
|
||||
from schema import Schema, Optional, Or
|
||||
from .. import __version__
|
||||
|
||||
VERBS = ('GET', 'POST', 'PUT', 'PATCH', 'DELETE')
|
||||
|
||||
ITERABLE_STR = Or([ str ], { str }, ( str ))
|
||||
|
||||
ACLS_SCHEMA = Schema([{
|
||||
'acl': str,
|
||||
Optional('args'): {
|
||||
Optional('required'): [ str ],
|
||||
Optional('optional'): [ str ]
|
||||
Optional('required'): ITERABLE_STR,
|
||||
Optional('optional'): ITERABLE_STR
|
||||
},
|
||||
Optional('out'): [ str ]
|
||||
Optional('out'): ITERABLE_STR
|
||||
}])
|
||||
ROUTER_ACLS_SCHEMA = Schema([{
|
||||
'acl': lambda n: callable(n),
|
||||
Optional('args'): {
|
||||
Optional('required'): ITERABLE_STR,
|
||||
Optional('optional'): ITERABLE_STR
|
||||
},
|
||||
Optional('out'): ITERABLE_STR
|
||||
}])
|
||||
|
||||
|
||||
is_callable_dotted_notation = lambda x: re.match(
|
||||
r'^(([a-zA-Z_])+\.?)*:[a-zA-Z_]+$', 'ab_c.TEST:get')
|
||||
@ -48,3 +59,11 @@ API_SCHEMA = Schema({
|
||||
'domain': DOMAIN_SCHEMA,
|
||||
'paths': ROUTE_SCHEMA
|
||||
})
|
||||
|
||||
ROUTER_SCHEMA = Schema({
|
||||
Or('', str): {
|
||||
# Optional('GET'): [],#ACLS_SCHEMA,
|
||||
Optional(Or(*VERBS)): ROUTER_ACLS_SCHEMA,
|
||||
Optional('SUBROUTES'): [Optional(str)]
|
||||
}
|
||||
})
|
||||
|
@ -1,44 +1,71 @@
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from types import ModuleType
|
||||
from typing import Dict
|
||||
from pprint import pprint
|
||||
|
||||
from halfapi.lib.constants import VERBS
|
||||
from schema import SchemaError
|
||||
from .constants import VERBS, ROUTER_SCHEMA
|
||||
from ..logging import logger
|
||||
|
||||
def read_router(m_router: ModuleType) -> Dict:
|
||||
"""
|
||||
Reads a module and returns a router dict
|
||||
|
||||
If the module has a "ROUTES" constant, it just returns this constant,
|
||||
Else, if the module has an "ACLS" constant, it builds the accurate dict
|
||||
|
||||
TODO: May be another thing, may be not a part of halfAPI
|
||||
|
||||
"""
|
||||
m_path = None
|
||||
|
||||
if not hasattr(m_router, 'ROUTES'):
|
||||
routes = {'':{}}
|
||||
acls = getattr(m_router, 'ACLS') if hasattr(m_router, 'ACLS') else None
|
||||
try:
|
||||
if not hasattr(m_router, 'ROUTES'):
|
||||
routes = {'':{}}
|
||||
acls = getattr(m_router, 'ACLS') if hasattr(m_router, 'ACLS') else None
|
||||
|
||||
if acls is not None:
|
||||
for verb in VERBS:
|
||||
if not hasattr(m_router, verb.lower()):
|
||||
continue
|
||||
if acls is not None:
|
||||
for verb in VERBS:
|
||||
if not hasattr(m_router, verb.lower()):
|
||||
# verb in function names are lowercase
|
||||
continue
|
||||
|
||||
""" There is a "verb" route in the router
|
||||
""" There is a "verb" route in the router
|
||||
"""
|
||||
|
||||
if verb.upper() not in acls:
|
||||
continue
|
||||
|
||||
routes[''][verb.upper()] = []
|
||||
routes[''][verb.upper()] = acls[verb.upper()].copy()
|
||||
|
||||
routes['']['SUBROUTES'] = []
|
||||
if hasattr(m_router, '__path__'):
|
||||
""" Module is a package
|
||||
"""
|
||||
m_path = getattr(m_router, '__path__')
|
||||
if isinstance(m_path, list) and len(m_path) == 1:
|
||||
routes['']['SUBROUTES'] = [
|
||||
elt.name
|
||||
for elt in os.scandir(m_path[0])
|
||||
if elt.is_dir()
|
||||
]
|
||||
else:
|
||||
routes = getattr(m_router, 'ROUTES')
|
||||
|
||||
if verb.upper() not in acls:
|
||||
continue
|
||||
try:
|
||||
ROUTER_SCHEMA.validate(routes)
|
||||
except SchemaError as exc:
|
||||
logger.error(routes)
|
||||
raise exc
|
||||
|
||||
routes[''][verb.upper()] = []
|
||||
routes[''][verb.upper()] = acls[verb.upper()].copy()
|
||||
|
||||
routes['']['SUBROUTES'] = []
|
||||
if hasattr(m_router, '__path__'):
|
||||
""" Module is a package
|
||||
"""
|
||||
m_path = getattr(m_router, '__path__')
|
||||
if isinstance(m_path, list) and len(m_path) == 1:
|
||||
routes['']['SUBROUTES'] = [
|
||||
elt.name
|
||||
for elt in os.scandir(m_path[0])
|
||||
if elt.is_dir()
|
||||
]
|
||||
else:
|
||||
routes = getattr(m_router, 'ROUTES')
|
||||
|
||||
return routes
|
||||
return routes
|
||||
except ImportError as exc:
|
||||
# TODO: Proper exception handling
|
||||
raise exc
|
||||
except FileNotFoundError as exc:
|
||||
# TODO: Proper exception handling
|
||||
logger.error(m_path)
|
||||
raise exc
|
||||
|
@ -48,8 +48,6 @@ def JSONRoute(data: Any) -> Coroutine:
|
||||
return wrapped
|
||||
|
||||
|
||||
|
||||
|
||||
def gen_domain_routes(m_domain: ModuleType):
|
||||
"""
|
||||
Yields the Route objects for a domain
|
||||
|
@ -16,7 +16,7 @@ ROUTES = {
|
||||
'acl': acl.public,
|
||||
'args': {
|
||||
'required': {'foo', 'bar'},
|
||||
'optional': {}
|
||||
'optional': set()
|
||||
}
|
||||
}]
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user