modern #2

Merged
absurdo merged 38 commits from modern into master 2025-03-15 00:00:11 +00:00
2 changed files with 154 additions and 18 deletions
Showing only changes of commit e93adee075 - Show all commits

View file

@ -1,10 +1,29 @@
#!/usr/bin/python
"""
Parameciofm is a series of wrappers for Bottle.py, mako and others and construct a simple headless cms.
Copyright (C) 2024 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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 <https://www.gnu.org/licenses/>.
"""
from bottle import hook
from mako.template import Template
from mako.lookup import TemplateLookup
from paramecio.citoplasma.urls import make_url, make_url_domain, make_media_url, make_media_url_module, add_get_parameters
from paramecio.citoplasma.i18n import I18n
from paramecio.citoplasma.i18n import I18n, PGetText
from paramecio.citoplasma.sessions import get_session
from paramecio.citoplasma.adminutils import make_admin_url
from paramecio.cromosoma.formsutils import csrf_token
@ -17,6 +36,22 @@ from collections import OrderedDict
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
Args:
module (str): The module where the templates can be founded
cache_enabled (boolean): If True then mako template cache is enabled, is False, mako template cache is disabled.
cache_args (dict): Cache Args dict parameter for TemplateLookup function from Mako templates. View Mako Templates documentation.
module_directory (str): Module directory parameter for TemplateLookup function from Mako templates. View Mako Templates documentation.
Returns:
template (TemplateLookup): Return TemplateLookup object
"""
ext=module[len(module)-3:]
if ext=='.py':
@ -51,11 +86,28 @@ def preload_templates(template_files, env):
return templates
class PTemplate:
"""A class used how shortcuts for Mako template functions.
"""
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.
Args:
environment (TemplateLookup): A TemplateLookup object generated with env_theme function
Attributes:
autoescape_ext (set): A set of extensions file where automatic autoescape is used
environment (TemplateLookup): A TemplateLookup object generated with env_theme function
filters (list): A list of functions used for add filters to your templates.
js (list): A list of javascript sources for generate js html load tags.
"""
# A simple method used in internal things of paramecio
self.show_basic_template=True
@ -130,6 +182,20 @@ class PTemplate:
self.env=environment
# Loading language domain for gettext in templates
base_name=path.dirname(path.realpath(__file__))
module_env=self.env.directories[1].replace('/templates', '')
self.l=PGetText(module_env+'/index.py')
self.add_filter(self._)
def _(self, text):
return self.l.gettext(text)
#self.auto_reload=True
# Clean HeaderHTML
@ -144,6 +210,12 @@ class PTemplate:
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
@ -180,6 +252,18 @@ class PTemplate:
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
Args:
template_file (str): The name of template file. The template is searched using configuration defined in self.env
**arguments (mixed): Extra arguments with variables passed to template
Returns:
template (str): Return a template rendered using mako class from self.env
"""
template = self.env.get_template(template_file)
arguments.update(self.filters)
@ -190,6 +274,18 @@ class PTemplate:
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
Args:
template_file (str): The name of template file. The template is searched using configuration defined in self.env
**arguments (mixed): Extra arguments with variables passed to template
Returns:
dummy (str): Dummy return necessary because mako expect return something
"""
if not str(self.env.directories)+'/'+template_file in PTemplate.templates_loaded:
PTemplate.templates_loaded[str(self.env.directories)+'/'+template_file]=self.env.get_template(template_file)

View file

@ -12,6 +12,14 @@ import traceback
engine=None
class SqlClass:
"""Class used how interface to sqlalchemy for connect to mysql engine
Attributes:
cursors_connect (pymysql.cursors.DictCursor): Cursor dict connection to database
disable_pool (boolean): If True then not exists mysql pool, if False, use sql pool for better connections.
pymsql_install (boolean): If True, pymysql is used how mysqldb classic python module.
pool_size (int): The size of the mysql pool.
"""
cursors_connect=None
disable_pool=False
@ -19,8 +27,18 @@ class SqlClass:
pool_size=15
def __init__(self, connection):
"""
Args:
connection (dict): A dict with the configurations of SqlClass connection
Attributes:
error_connection (str): A string where errors are saved
connection (dict): A dict with the configurations of SqlClass connection
conn (MySQL Connection): A PyMySQL or Mysqldb connection
connected (bool): Simple bool for check if was connected to mysql
pool_recycle (int): Time limite for recycle the pool by inactivity
"""
self.max_overflow=-1
#self.max_overflow=-1
self.error_connection=""
# Data of connection
self.connection=connection
@ -28,11 +46,13 @@ class SqlClass:
self.conn=None
self.connected=False
self.pool_recycle=3600
self.connect()
self.last_query=''
self.connect()
def connect(self):
"""Method for connect to mysql db using pymysql or mysqldb
"""
global engine
@ -45,7 +65,8 @@ class SqlClass:
if self.connection['db_type']=='pymysql':
import pymysql.cursors
pymysql.install_as_MySQLdb
SqlClass.pymysql_install=True
SqlClass.cursors_connect=pymysql.cursors.DictCursor
else:
import MySQLdb.cursors
@ -53,6 +74,9 @@ class SqlClass:
engine=create_engine("mysql+%s://%s:%s@%s/%s?charset=utf8mb4" % (self.connection['db_type'], self.connection['user'], self.connection['password'], self.connection['host'], self.connection['db']), pool_recycle=self.pool_recycle, echo_pool=True, pool_size=self.pool_size, pool_pre_ping=True)
#Postgre
#engine = create_engine("postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase")
except:
e = sys.exc_info()[0]
v = sys.exc_info()[1]
@ -77,18 +101,22 @@ class SqlClass:
pymysql.install_as_MySQLdb
SqlClass.pymysql_install=True
self.conn=pymysql.connect(self.connection['host'],
user=self.connection['user'],
passwd=self.connection['password'],
db=self.connection['db'],
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
"""
connection = pymysql.connect(host='localhost',
user='user',
password='passwd',
database='db',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
"""
self.conn=pymysql.connect(host=self.connection['host'], user=self.connection['user'], passwd=self.connection['password'], db=self.connection['db'], charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)
else:
import MySQLdb.cursors
self.conn=MySQLdb.connect(self.connection['host'],
self.conn=MySQLdb.connect(host=self.connection['host'],
user=self.connection['user'],
passwd=self.connection['password'],
db=self.connection['db'],
@ -132,26 +160,34 @@ class SqlClass:
#Make def query more simple if not debugging.
def query(self, sql_query, arguments=[], name_connection="default"):
"""Method for send a sql query to mysql server
Args:
sql_query (str): The sql sentence to execute. For data you should use %s character.
arguments (list): The data used in sql sentence. This data substitute the %s characters.
name_connection (str): The name of dict element with the configuration of connection, without used in this moment.
"""
cursor=self.conn.cursor(SqlClass.cursors_connect)
try:
cursor.execute(sql_query, arguments)
self.conn.commit()
if hasattr(cursor, '_last_executed'):
self.last_query=cursor._last_executed
self.conn.commit()
#if hasattr(cursor, '_executed'):
# self.last_query=cursor._executed
return cursor
except:
e = sys.exc_info()[0]
v = sys.exc_info()[1]
if hasattr(cursor, '_last_executed'):
sql_query=cursor._last_executed
#if hasattr(cursor, '_executed'):
# self.last_query=cursor._executed
self.error_connection="Error in query ||%s||Values: %s" % (sql_query, str(arguments))
self.error_connection="Error in query ||%s||Values: %s" % (self.last_query, str(arguments))
self.conn.close()
@ -196,12 +232,16 @@ class SqlClass:
#return cursor.fetchone()
def __del__(self):
"""Typical method used when class is deleted from memory. Close the connextion if exists.
"""
if self.conn:
self.conn.close()
def close(self, name_connection="default"):
"""Method used for close the connection if you want close connection and open other.
"""
if self.conn: