From a9b074fa9a09af3709450afb343735f6d5ad4789 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Sun, 23 Oct 2022 11:27:39 -0500 Subject: [PATCH] support for plugins,needs a bit more work --- cms/__init__.py | 56 +++++++++++++++++++++++++++++++++++++++----- index.py | 42 ++++++++++++++++++++++++++++----- static/js/menu.js | 4 ++-- templates/index.html | 2 +- 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/cms/__init__.py b/cms/__init__.py index e1df8c6..8c5a781 100644 --- a/cms/__init__.py +++ b/cms/__init__.py @@ -4,19 +4,23 @@ import pandas as pd import transport import copy from jinja2 import Environment, BaseLoader +import importlib +import importlib.util class components : + @staticmethod def folders (_path): _content = os.listdir(_path) - return [_name for _name in _content if os.path.isdir(os.sep.join([_path,_name]))] - + return [_name for _name in _content if os.path.isdir(os.sep.join([_path,_name])) if not _name.startswith('_')] + @staticmethod def content (_folder) : if os.path.exists(_folder) : # return [{'text':_name.split('.')[0].replace('_', ' ').replace('-',' ').strip(),'uri': os.sep.join([_folder,_name])} for _name in os.listdir(_folder) if not _name.startswith('_') and os.path.isfile( os.sep.join([_folder,_name]))] return [{'text':_name.split('.')[0].replace('_', ' ').replace('-',' ').strip(),'uri': os.sep.join([_folder,_name])} for _name in os.listdir(_folder) if not _name.startswith('_') and os.path.isfile( os.sep.join([_folder,_name]))] else: return [] + @staticmethod def menu(_path,_config): """ This function will read menu and sub-menu items from disk structure, @@ -45,6 +49,7 @@ class components : _submenu[_index] = _item _index += 1 return _object + @staticmethod def html(uri,id,_args={}) : """ This function reads a given uri and returns the appropriate html document, and applies environment context @@ -58,6 +63,7 @@ class components : appContext = Environment(loader=BaseLoader()).from_string(_html) return appContext.render(**_args) # return _html + @staticmethod def data (_args): """ :store data-store parameters (data-transport, github.com/lnyemba/data-transport) @@ -68,11 +74,49 @@ class components : _queries= copy.deepcopy(_store['query']) _data = reader.read(**_query) return _data + @staticmethod def csv(uri) : return pd.read(uri).to_html() - def apply(**_args): + @staticmethod + def load_plugin(**_args): """ - :uri uri of the mapping function - :args arguments of the function + This function will load external module form a given location and return a pointer to a function in a given module + :path absolute path of the file (considered plugin) to be loaded + :name name of the function to be applied """ - + _path = _args['path'] #os.sep.join([_args['root'],'plugin']) + if os.path.isdir(_path): + files = os.listdir(_path) + if files : + files = [name for name in files if name.endswith('.py')] + if files: + _path = os.sep.join([_path,files[0]]) + else: + return None + else: + return None + #-- We have a file ... + _name = _args['name'] + spec = importlib.util.spec_from_file_location(_name, _path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + return getattr(module,_name) if hasattr(module,_name) else None + @staticmethod + def plugins(_config) : + PATH= os.sep.join([_config['layout']['root'],'_plugins']) + _map = {} + if not os.path.exists(PATH) : + return _map + _conf = _config['plugins'] + + for _key in _conf : + _path = os.sep.join([PATH,_key+".py"]) + + for _name in _conf[_key] : + _pointer = components.load_plugin(path=_path,name=_name) + if _pointer : + _uri = "/".join(["api",_key,_name]) + _map[_uri] = _pointer + return _map + \ No newline at end of file diff --git a/index.py b/index.py index 07da5f8..2d34c18 100644 --- a/index.py +++ b/index.py @@ -39,10 +39,12 @@ def _index (): _args['index'] = e.render(**_args) _index_page = "index.html" except Exception as e: + print () + print (e) _index_page = "404.html" _args['uri'] = request.base_url pass - print (_config ); + return render_template(_index_page,**_args) @_app.route('/id/') @@ -60,8 +62,8 @@ def _dialog (): _id = request.headers['dom'] _html = cms.components.html(_uri,_id) e = Environment(loader=BaseLoader()).from_string(_html) - _data = cms.components.data(_config) - _args = {'system':_config['system'],'data':_data} + # _data = cms.components.data(_config) + _args = {'system':_config['system']} _html = ''.join(["
",str( e.render(**_args)),'
']) @@ -72,7 +74,30 @@ def _dialog (): # _args = {'system':_config['system'],'data':_data} # _html = ( e.render(**_args)) +@_app.route('/api//') +def _getproxy(module,name) : + """ + This endpoint will load a module and make a function call + :_module entry specified in plugins of the configuration + :_name name of the function to execute + """ + global _config + uri = '/'.join(['api',module,name]) + if uri not in _config['plugins'] : + _data = {} + _code = 404 + else: + pointer = _config['plugins'][uri] + _data = pointer () + _code = 200 + + + return _data,_code +@_app.route('/version') +def _version (): + global _config + return _config['system']['version'] @_app.route('/page',methods=['POST']) def cms_page(): """ @@ -84,8 +109,8 @@ def cms_page(): _html = cms.components.html(_uri,_id) e = Environment(loader=BaseLoader()).from_string(_html) - _data = cms.components.data(_config) - _args = {'system':_config['system'],'data':_data} + # _data = {} #cms.components.data(_config) + _args = {'system':_config['system']} _html = ( e.render(**_args)) return _html,200 @@ -120,7 +145,12 @@ if __name__ == '__main__' : _root = _config['layout']['root'] _config['layout']['menu'] = cms.components.menu(_root,_config) # _config['data'] = cms.components.data(_config) - + # + # Let us load the plugins if any are available + if 'plugins' in _config : + _map = cms.components.plugins(_config) + if _map : + _config['plugins'] = _map _args = _config['system']['app'] _app.run(**_args) else: diff --git a/static/js/menu.js b/static/js/menu.js index 7ca6e42..0a55384 100644 --- a/static/js/menu.js +++ b/static/js/menu.js @@ -19,7 +19,7 @@ menu.apply = function (uri,id,pid){ httpclient.setHeader('uri',uri) httpclient.setHeader('dom',id) - httpclient.post('/cms/page',function(x){ + httpclient.post('/page',function(x){ var _html = x.responseText var template = document.createElement('template'); template.innerHTML = _html.trim(); @@ -75,7 +75,7 @@ menu.apply_link =function(_args){ http.setHeader('uri',_args.uri) http.setHeader('dom','dialog') // http.setHeader('dom',_args.text) - http.get('/cms/dialog',function(x){ + http.get('/dialog',function(x){ jx.modal.show({html:x.responseText,id:'dialog'}) }) diff --git a/templates/index.html b/templates/index.html index a913a7c..8350737 100644 --- a/templates/index.html +++ b/templates/index.html @@ -24,7 +24,7 @@ Vanderbilt University Medical Center - +