From f68b7e59b8d6e1c4be119948d4051027321ebd68 Mon Sep 17 00:00:00 2001 From: maxime Date: Thu, 23 Jun 2022 07:21:49 +0200 Subject: [PATCH] handle HALFAPI_DOMAIN_MODULE environment variable --- halfapi/conf.py | 5 +++++ halfapi/half_domain.py | 38 +++++++++++++++++++++------------ halfapi/halfapi.py | 48 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/halfapi/conf.py b/halfapi/conf.py index 95f234b..8dac7d4 100644 --- a/halfapi/conf.py +++ b/halfapi/conf.py @@ -98,12 +98,17 @@ PROJECT_NAME = CONFIG.get('project_name', if environ.get('HALFAPI_DOMAIN_NAME'): DOMAIN_NAME = environ.get('HALFAPI_DOMAIN_NAME') CONFIG['domain'] = {} + CONFIG['domain'][DOMAIN_NAME] = { 'enabled': True, 'name': DOMAIN_NAME, 'prefix': False } + if environ.get('HALFAPI_DOMAIN_MODULE'): + dom_module = environ.get('HALFAPI_DOMAIN_MODULE') + CONFIG['domain'][DOMAIN_NAME]['module'] = dom_module + if len(CONFIG.get('domain', {}).keys()) == 0: logger.info('No domains') diff --git a/halfapi/half_domain.py b/halfapi/half_domain.py index 22b01df..30b69f3 100644 --- a/halfapi/half_domain.py +++ b/halfapi/half_domain.py @@ -27,7 +27,7 @@ from .lib.domain_middleware import DomainMiddleware from .logging import logger class HalfDomain(Starlette): - def __init__(self, domain, router=None, acl=None, app=None): + def __init__(self, domain, module=None, router=None, acl=None, app=None): """ Parameters: domain (str): Module name (should be importable) @@ -37,7 +37,7 @@ class HalfDomain(Starlette): """ self.app = app - self.m_domain = importlib.import_module(domain) + self.m_domain = importlib.import_module(domain) if module is None else module self.name = getattr(self.m_domain, '__name__', domain) self.id = getattr(self.m_domain, '__id__') self.version = getattr(self.m_domain, '__version__', '0.0.0') @@ -47,13 +47,17 @@ class HalfDomain(Starlette): self.deps = getattr(self.m_domain, '__deps__', tuple()) if not router: - self.router = getattr('__router__', domain, '.routers') + self.router = getattr(domain, '__router__', '.routers') else: self.router = router - self.m_router = importlib.import_module(self.router, domain) + self.m_router = None + try: + self.m_router = importlib.import_module(self.router, self.m_domain.__package__) + except AttributeError: + raise Exception('no router module') - self.m_acl = HalfDomain.m_acl(domain, acl) + self.m_acl = HalfDomain.m_acl(self.m_domain, acl) self.config = { **app.config } @@ -86,31 +90,37 @@ class HalfDomain(Starlette): ) @staticmethod - def m_acl(domain, acl=None): - """ Returns the imported acl module for the domain + def m_acl(module, acl=None): + """ Returns the imported acl module for the domain module """ if (not acl): - acl = getattr('__acl__', domain, '.acl') + acl = getattr(module, '__acl__', '.acl') - return importlib.import_module(acl, domain) + return importlib.import_module(acl, module.__package__) @staticmethod - def acls(domain, acl=None): + def acls(domain, module=None, acl=None): """ Returns the ACLS constant for the given domain """ - m_acl = HalfDomain.m_acl(domain, acl) + if not module: + module = importlib.import_module(domain) + + m_acl = HalfDomain.m_acl(module, acl) try: return getattr(m_acl, 'ACLS') except AttributeError: raise Exception(f'Missing acl.ACLS constant in {domain} module') @staticmethod - def acls_route(domain, acl=None): + def acls_route(domain, module=None, acl=None): d_res = {} - m_acl = HalfDomain.m_acl(domain, acl) + if module is None: + module = importlib.import_module(domain) - for acl_name, doc, order in HalfDomain.acls(domain, acl): + m_acl = HalfDomain.m_acl(module, acl) + + for acl_name, doc, order in HalfDomain.acls(domain, acl=acl): fct = getattr(m_acl, acl_name) d_res[acl_name] = { 'callable': fct, diff --git a/halfapi/halfapi.py b/halfapi/halfapi.py index 31e3e8c..149e5af 100644 --- a/halfapi/halfapi.py +++ b/halfapi/halfapi.py @@ -122,7 +122,12 @@ class HalfAPI(Starlette): domain_key = domain.get('name', key) - self.add_domain(domain_key, domain.get('router'), domain.get('acl'), path) + self.add_domain( + domain_key, + domain.get('module'), + domain.get('router'), + domain.get('acl'), + path) schemas.append(self.__domains[domain_key].schema()) @@ -209,7 +214,10 @@ class HalfAPI(Starlette): def acls_route(self): res = { - domain: HalfDomain.acls_route(domain, domain_conf.get('acl')) + domain: HalfDomain.acls_route( + domain, + module=domain_conf.get('module'), + acl=domain_conf.get('acl')) for domain, domain_conf in self.config.get('domain', {}).items() if isinstance(domain_conf, dict) and domain_conf.get('enabled', False) } @@ -237,16 +245,38 @@ class HalfAPI(Starlette): def domains(self): return self.__domains - def add_domain(self, name, router=None, acl=None, path='/', config=None): + def add_domain(self, name, module=None, router=None, acl=None, path='/', config=None): + + # logger.debug('HalfApi.add_domain %s %s %s %s %s', + # name, + # module, + # router, + # acl, + # path, + # config) + if config: self.config['domain'][name] = config - self.__domains[name] = HalfDomain( - name, - router, - acl, - self - ) + if not module: + module = name + + try: + self.__domains[name] = HalfDomain( + name, + module=importlib.import_module(module), + router=router, + acl=acl, + app=self + ) + + except ImportError as exc: + print( + 'Cannot instantiate HalfDomain {} with module {}'.format( + name, + module + )) + raise exc self.mount(path, self.__domains[name])