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}
+%block>
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>
<%block name="extra_header">
@@ -77,28 +78,30 @@ lang_selected=session['lang']