diff --git a/cuchulu/app.py b/cuchulu/app.py index 58da4ab..b7ce2e8 100644 --- a/cuchulu/app.py +++ b/cuchulu/app.py @@ -118,17 +118,21 @@ def prepare_app(): if controller_py=='app': app_name=getattr(a, added_app[1]) - - app_mounts[added_app[2]]=app_name + + if not added_app[2] in app_mounts: + + app_mounts[added_app[2]]=[] + + app_mounts[added_app[2]].append(app_name) arr_module_path[key_app]=os.path.dirname(sys.modules[module_app].__file__) for k_app,v_app in app_mounts.items(): - #print(k_app) - if k_app!='/': - app.mount(k_app, v_app) - elif k_app!='': - app.merge(v_app) + for t_app in v_app: + if k_app!='/': + app.mount(k_app, t_app) + elif k_app!='': + app.merge(t_app) set_timezone() diff --git a/cuchulu/libraries/db/dbadmin.py b/cuchulu/libraries/db/dbadmin.py index d7001db..55c5aa7 100644 --- a/cuchulu/libraries/db/dbadmin.py +++ b/cuchulu/libraries/db/dbadmin.py @@ -34,7 +34,9 @@ sys.path.insert(0, os.path.realpath('.')) try: from settings import config + except ModuleNotFoundError: + print('You need a settings directory with a cuchulu configuration') sys.exit(1) diff --git a/cuchulu/libraries/mtemplates.py b/cuchulu/libraries/mtemplates.py index 599a622..3474252 100644 --- a/cuchulu/libraries/mtemplates.py +++ b/cuchulu/libraries/mtemplates.py @@ -1,9 +1,7 @@ -#!/usr/bin/python - """ -Cuchulufm is a series of wrappers for Bottle.py, mako and others and construct a simple headless cms. +Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms. -Copyright (C) 2024 Antonio de la Rosa Caballero +Copyright (C) 2023 Antonio de la Rosa Caballero This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -15,32 +13,46 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from bottle import hook +# Template frontend from mako. + +#import gettext from mako.template import Template +#from flask import url_for as url_for_flask from mako.lookup import TemplateLookup -from cuchulu.libraries.urls import make_url, make_url_domain, make_media_url, make_media_url_module, add_get_parameters -from cuchulu.libraries.i18n import I18n, PGetText -from cuchulu.libraries.sessionplugin import get_session -from cuchulu.libraries.adminutils import make_admin_url -from cuchulu.libraries.db.formsutils import csrf_token -from cuchulu.libraries.js import make_js_url -from settings import config from os import path -from collections import OrderedDict +try: + from settings import config +except: + class config: + theme='default' + reloader=False + +#import gettext +import sys +from cuchulu.libraries.i18n import I18n, PGetText +from cuchulu.libraries.urls import make_url, make_media_url, add_get_parameters +from cuchulu.libraries.db.formsutils import csrf_token +from cuchulu.libraries.sessionplugin import get_session from cuchulu.wsgiapp import app -gtext=PGetText(__file__) +framework='flask' -_=gtext.gettext +if hasattr(config, 'framework'): + framework=config.framework -# Preparing envs for views of modules, and views of + +""" +def _(text): + + return gettext.gettext(text) +""" def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_directory="./tmp/modules"): - """Function for create an environment for mako templates Function for create an environment for mako templates. Really is a shortcut for TemplateLookup mako function. You can define cache options and module_directory for templates compiled @@ -64,6 +76,8 @@ def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_d module=path.dirname(module) standard_templates=path.dirname(__file__)+'/templates' + + standard_languages=path.dirname(__file__)+'/languages' module_directory+='/'+module @@ -79,20 +93,10 @@ def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_d #Standard templates #print(standard_templates) return TemplateLookup(directories=search_folders, default_filters=['h'], input_encoding='utf-8', encoding_errors='replace', cache_enabled=cache_enabled, cache_impl=cache_impl, cache_args=cache_args, module_directory=module_directory, filesystem_checks=config.reloader) - -def preload_templates(template_files, env): - - templates={} - - for template_file in template_files: - - templates[template_file]=env.get_template(template_file) - - return templates -def url_for(name, **kwargs): +def url_for(url, **kargs): - return app.get_url(name, **kwargs) + return app.get_url(url, **kargs) def get_file(): @@ -105,7 +109,6 @@ class PTemplate: templates_loaded={} def __init__(self, environment): - """A class used how shortcuts for Mako template functions. This class is used to have a set of shortcuts and hooks to Mako templates functions and methods over a series of default options. @@ -121,79 +124,48 @@ class PTemplate: """ - # A simple method used in internal things of cuchulu - - self.show_basic_template=True - """ - ext=module[len(module)-3:] - - if ext=='.py': - - module=path.dirname(module) - """ - self.autoescape_ext=('html', 'htm', 'xml', 'phtml', 'js') - - """ - self.cache_enabled=cache_enabled - - self.cache_impl=cache_impl - - self.cache_args=cache_args - - self.module_directory="./tmp/modules" - """ - - self.inject_folder=None + + self.env=environment self.filters={} - #Place where templates contexts is loaded + self.js={} - self.templates={} - - #Adding basic filters for urls - self.add_filter(make_url) - - self.add_filter(make_url_domain) - - self.add_filter(make_media_url) - - self.add_filter(make_media_url_module) - - self.add_filter(add_get_parameters) - - self.add_filter(csrf_token) - - self.add_filter(make_admin_url) - - self.add_filter(make_js_url) - - I18n_lang=I18n.lang + self.url_for=url_for self.add_filter(I18n.lang) - self.add_filter(I18n.get_default_lang) + self.add_filter(make_url) - self.headerhtml=HeaderHTML() + self.add_filter(make_media_url) + """ + if not url_for_function: + + url_for=url_for_bottle + + self.add_filter(url_for) + + else: + + url_for=url_for_function + + self.add_filter(url_for) + + """ + self.add_filter(self.url_for) - self.add_filter(self.headerhtml.add_css_home) + self.add_filter(csrf_token) - self.add_filter(self.headerhtml.add_js_home) + self.add_filter(add_get_parameters) - self.add_filter(self.headerhtml.add_css_home_local) + self.add_filter(self.add_js) - self.add_filter(self.headerhtml.add_js_home_local) + self.add_filter(self.load_js) - self.add_filter(self.headerhtml.add_header_home) + self.add_filter(show_flash_message) - self.add_filter(qf) - - self.filters['HeaderHTML']=self.headerhtml - - self.filters['show_flash_message']=self.headerhtml.show_flash_message - - self.env=environment + self.add_filter(get_file) # Loading language domain for gettext in templates @@ -201,7 +173,11 @@ class PTemplate: module_env=self.env.directories[1].replace('/templates', '') + #print(path.basename(module_env)+' '+base_name+'/languages/') + self.l=PGetText(module_env+'/app.py') + + self.i18n=I18n(module_env) self.add_filter(self._) @@ -210,75 +186,39 @@ class PTemplate: self.add_filter(self.i18n.slang) self.add_filter(self.i18n.tlang) - - #self.url_for=lambda name: app.get_url(name) - #x = lambda a : a + 10 - #print(self.url_for) - - self.add_filter(url_for) - - self.add_filter(get_file) def _(self, text): return self.l.gettext(text) + + def add_js(self, js, module=''): + """Function for add js to self.js attribute - #self.auto_reload=True - - # Clean HeaderHTML - """ - HeaderHTML.css=[] - HeaderHTML.js=[] - HeaderHTML.header=[] - HeaderHTML.cache_header=[] - HeaderHTML.css_local={} - HeaderHTML.js_local={} - """ - - def guess_autoescape(self, template_name): - - """Simple helper method for get an extension from filename + Add a js file name to an attribute list called self.js with the '.format(make_media_url('js/'+js, module)) + + return "" + def load_js(self): + + return "\n".join(self.js.values()) + + + """ + def gettext(self, text): + return gettext.dgettext(self.domain_gettext, text) + """ + + def load_template(self, template_file, **arguments): """Load a mako template and return the result Load a mako template and return the results with different arguments applied @@ -291,16 +231,40 @@ class PTemplate: template (str): Return a template rendered using mako class from self.env """ + """ + if self.prepare_gettext: + + module_lang_dir=self.env.directories[1].replace('/templates', '/locales') + + module_name=path.basename(module_lang_dir.replace('/locales', '')) + + en = gettext.translation(module_name, localedir=module_lang_dir, languages=['en']) + en.install() + _=en.gettext + + arguments.update({'_': _}) + """ template = self.env.get_template(template_file) - + arguments.update(self.filters) - #arguments['make_media_url']=make_media_url - - return template.render(**arguments) + return template.render(**arguments) - def render_template(self, template_file, **arguments): + def guess_autoescape(self, template_name): + """Simple helper method for get an extension from filename + Args: + template_name (str): The template name + """ + + if template_name is None or '.' not in template_name: + return False + + ext = template_name.rsplit('.', 1)[1] + + return ext in self.autoescape_ext + + def render_template(self, template_file, **arguments): """Experimental method for parse a template Experimental method for parse a template, similar to load_template but try cache the template loaded @@ -321,159 +285,41 @@ class PTemplate: return PTemplate.templates_loaded[str(self.env.directories)+'/'+template_file].render(**arguments) def add_filter(self, filter_name): + """Method for add filters to self.filters attributes + + Method for add filters to self.filters attributes for use in templates + + Args: + filter_name (function): Filter function + """ self.filters[filter_name.__name__]=filter_name - -class STemplate: - - def __init__(html_code): - - return Template(html_code) - -# DEPRECATED, use utilities from mako for personalize headers. - -class HeaderHTML: - - def __init__(self): - - self.css=[] - self.js=[] - self.header=[] - self.cache_header=OrderedDict() - self.css_local=OrderedDict() - self.js_local=OrderedDict() - - def header_home(self): - - final_header="\n".join(self.header) - - self.header=[] - - return final_header - - def js_home(self): - - final_js=[] - - for js in self.js: - final_js.append('') - - for module, arr_js in self.js_local.items(): - for js in arr_js: - final_js.append('') - - self.js=[] - self.js_local=OrderedDict() - - return "\n".join(final_js) - - def css_home(self): - - final_css=[] - - for css in self.css: - final_css.append('') - - for module, arr_css in self.css_local.items(): - - for css in arr_css: - - final_css.append('') - - self.css=[] - self.css_local=OrderedDict() - - return "\n".join(final_css) - - - def add_header_home(self, variable, only_one_time=False): - - - if only_one_time==True: - self.cache_header.get(variable, 0) - - if cache_header[variable]==1: - return '' - #self.cache_header[variable]=1 - - self.header.append(variable) - - return '' - - def add_css_home(self, css): - - if not css in self.css: - self.css.append(css) - - return '' - - def add_js_home(self, js): - - if not js in self.js: - self.js.append(js) - - return '' - - def add_css_home_local(self, css, module): - - if not css in self.css_local: - - self.css_local[module]=self.css_local.get(module, []) - - try: - - self.css_local[module].index(css) - - except: - - self.css_local[module].append(css) - - return '' - - def add_js_home_local(self, js, module): - - if not js in self.js_local: - - self.js_local[module]=self.js_local.get(module, []) - - try: - self.js_local[module].index(js) - - except: - self.js_local[module].append(js) - - return '' - - def show_flash_message(self): - - message="" - - s=get_session() - - s['flash']=s.get('flash', "") - - if s['flash']!="": - message='
'+s['flash']+'
' - - s['flash']='' - - #s.save() - - return message - def set_flash_message(message): - + s=get_session() s['flash']=message s.save() -def qf(text): +def show_flash_message(): - return text.replace('"', '\\"') + s=get_session() + + message=s.get('flash', '') + + s['flash']='' + + s.save() + + return message + +def add_css_home_local(file_css, module): + + pass env=env_theme(__file__) standard_t=PTemplate(env) + diff --git a/cuchulu/libraries/sessionplugin.py b/cuchulu/libraries/sessionplugin.py index 0df0621..a85e279 100644 --- a/cuchulu/libraries/sessionplugin.py +++ b/cuchulu/libraries/sessionplugin.py @@ -6,7 +6,7 @@ try: from settings import config -except: +except ModuleNotFoundError: class config: cookie_name='cuchulu.session' @@ -177,8 +177,8 @@ class SessionPlugin(object): #if 'session' in kwargs: #print(kwargs) - if self.session: - kwargs['session']=session + #if self.session: + # kwargs['session']=session #For compatibility with old sessions server-side style. diff --git a/cuchulu/libraries/templates/utils/admin.phtml b/cuchulu/libraries/templates/utils/admin.phtml index 16bc5db..830a3a4 100644 --- a/cuchulu/libraries/templates/utils/admin.phtml +++ b/cuchulu/libraries/templates/utils/admin.phtml @@ -1,4 +1,2 @@ -${show_flash_message()|n} -

${add_new_item}

${admin.list.show()|n} diff --git a/cuchulu/modules/admin2/__init__.py b/cuchulu/modules/admin2/__init__.py index df801e1..5f72e2b 100644 --- a/cuchulu/modules/admin2/__init__.py +++ b/cuchulu/modules/admin2/__init__.py @@ -1,8 +1,13 @@ from bottle import request, redirect, Bottle from cuchulu.modules.admin2.libraries.loginplugin import check_login from cuchulu.libraries.sessionplugin import SessionPlugin +from cuchulu.libraries.mtemplates import PTemplate, env_theme admin_app=Bottle() splugin=SessionPlugin() admin_app.install(splugin) admin_app.install(check_login) + +env=env_theme(__file__) + +t=PTemplate(env) diff --git a/cuchulu/modules/admin2/ausers.py b/cuchulu/modules/admin2/ausers.py index fdbd52b..ff7f66e 100644 --- a/cuchulu/modules/admin2/ausers.py +++ b/cuchulu/modules/admin2/ausers.py @@ -21,8 +21,6 @@ env=env_theme(__file__) t=PTemplate(env) -#i18n=I18n('admin2') - gtext=PGetText(__file__) _=gtext.gettext @@ -40,8 +38,12 @@ if t.env.directories[1]!=tpl_path: def admin_users(): return _('Admin users') + +def edit_admin_users(): + + return _('Edit Admin users') -modules_admin['admin_app.admin_users']=[admin_users, 'people-circle', ['admin_app.admin_permissions']] +modules_admin['admin_app.admin_users']=[[admin_users, 'people-circle', ''], [edit_admin_users, 'people-circle', ['admin_app.admin_permissions']]] modules_admin_icons['admin_app.admin_users']='' diff --git a/cuchulu/modules/admin2/templates/content.phtml b/cuchulu/modules/admin2/templates/content.phtml new file mode 100644 index 0000000..3d980c2 --- /dev/null +++ b/cuchulu/modules/admin2/templates/content.phtml @@ -0,0 +1,4 @@ +<%inherit file="layout.phtml"/> +<%block name="content"> + ${contents|n} + diff --git a/cuchulu/modules/admin2/templates/layout.phtml b/cuchulu/modules/admin2/templates/layout.phtml index 6ec40b0..19ed286 100644 --- a/cuchulu/modules/admin2/templates/layout.phtml +++ b/cuchulu/modules/admin2/templates/layout.phtml @@ -34,6 +34,7 @@ lang_selected=session['lang'] +${load_js()|n} <%block name="extra_js"> <%block name="extra_header"> @@ -77,28 +78,30 @@ lang_selected=session['lang']