parameciofm/paramecio/app.py
2025-04-11 01:33:31 +02:00

261 lines
7.4 KiB
Python

import os, sys, traceback, inspect, resource
from importlib import import_module
from bottle import route, get, post, run, default_app, abort, request, response, static_file, load, hook, error, debug, redirect, template
from settings import config
#from beaker.middleware import SessionMiddleware
from mimetypes import guess_type
from paramecio.libraries.db.webmodel import WebModel
from paramecio.libraries.datetime import set_timezone
#from itsdangerous import JSONWebSignatureSerializer
from paramecio.libraries.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
from paramecio.wsgiapp import app
#from paramecio.libraries.sessions import after_session
modules_pass=False
#app.reset()
#from paramecio.libraries.sessions import generate_session
#Prepare links for static.
#WARNING: only use this feature in development, not in production.
#def create_app():
workdir=os.getcwd()
arr_module_path={}
if config.session_enabled==True:
#Create dir for sessions
if 'session.data_dir' in config.session_opts:
if not os.path.isdir(config.session_opts['session.data_dir']):
os.makedirs(config.session_opts['session.data_dir'], 0o700, True)
"""
@app.hook('after_request')
def clean_session():
after_session()
"""
error_reporting=False
if hasattr(config, 'error_reporting'):
error_reporting=config.error_reporting
def prepare_app():
# In mod_wsgi, make strange thing with reloading.
app.reset()
def print_memory():
print(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
routes={}
module_loaded=None
#Getting paths for loaded modules for use in media load files
"""
for module in config.modules:
#controller_path=sys.modules[module]
controller_base=sys.modules[module].__path__[0]
base_module=module.split('.')[-1]
arr_module_path[base_module]=controller_base
"""
#app.add_hook('before_request', print_memory)
"""
for added_app in config.apps:
a=import_module(added_app)
#print(added_app, file=sys.stdout)
app_name=getattr(a, config.apps[added_app][0])
app.mount(config.apps[added_app][1], app_name)
#print(added_app)
#print(a.__path__[0])
"""
app_mounts={}
for key_app, added_app in config.apps.items():
controller_path=import_module(added_app[0])
controller_base=os.path.dirname(controller_path.__file__)
#print(controller_base)
dir_controllers=os.listdir(controller_base)
for controller in dir_controllers:
if controller.find('.py')!=-1 and controller.find('__init__')==-1:
controller_py=controller.replace('.py', '')
module_app=added_app[0]+'.'+controller_py
a=import_module(module_app)
if added_app[1]!='':
app_name=getattr(a, added_app[1])
app_mounts[added_app[2]]=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)
set_timezone()
if error_reporting:
from paramecio.libraries.error_reporting import ErrorReportingPlugin
app.install(ErrorReportingPlugin())
if hasattr(config, 'plugins_app'):
for p in config.plugins_app:
app.install(p())
# Clean last slash
@app.hook('before_request')
def strip_path():
request.environ['PATH_INFO'] = request.environ['PATH_INFO'].rstrip('/')
# Set error screen if not debug setted
if config.debug==False:
@app.error(404)
def error404(error):
return 'Error: page not found'
debug(config.debug)
#Prepare app
application=app
# Load modules
try:
#from settings import modules
prepare_app()
except:
app.reset()
@app.route('/')
def catch_errors(all='/'):
try:
from pathlib import Path
#from settings import modules
import time
prepare_app()
p=Path('app.py')
p.touch()
time.sleep(1)
except:
raise
redirect(request.url)
catch_errors=app.route('/<all:path>')(catch_errors)
# Prepare static routes
if config.yes_static==True:
@app.route('/media/<filename:path>')
def send_static(filename):
mimetype=guess_type(workdir+'/themes/'+config.theme+'/media/'+filename)
return static_file(filename, root=workdir+'/themes/'+config.theme+'/media/', mimetype=mimetype[0])
#def add_func_static_module(module):
@app.route('/mediafrom/<module>/<filename:path>')
def send_static_module(module, filename):
path_module=arr_module_path[module]+'/media/'
file_path_module=path_module+filename
path=workdir+'/themes/'+config.theme+'/media/'+module
file_path=path+'/'+filename
if os.path.isfile(file_path):
mimetype=guess_type(path+'/'+filename)
return static_file(filename, root=path, mimetype=mimetype[0])
else:
mimetype=guess_type(path_module+'/'+filename)
return static_file(filename, root=path_module, mimetype=mimetype[0])
def error_handler_500(e):
tpl_error="""
%try:
%from bottle import DEBUG, request
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>Error: {{e.status}}</title>
<style type="text/css">
html {background-color: #e8eff0; font-family: sans;}
body {background-color: #fbfbfb; border: 1px solid #ddd;
padding: 15px; margin: 15px;}
pre {background-color: #e0f6fa; border: 1px solid #ddd; padding: 5px;}
</style>
</head>
<body>
<h1>Error: {{e.status}}</h1>
<p>Sorry, the requested URL <tt>{{repr(request.url)}}</tt>
caused an error:</p>
<pre>{{e.body}}</pre>
%if DEBUG and e.exception:
<h2>Exception:</h2>
%try:
%exc = repr(e.exception)
%except:
%exc = '<unprintable %s object>' % type(e.exception).__name__
%end
<pre>{{exc}}</pre>
%end
%if DEBUG and e.traceback:
<h2>Traceback:</h2>
<pre>{{e.traceback}}</pre>
%end
</body>
</html>
%except ImportError:
<b>ImportError:</b> Could not generate the error page. Please add bottle to
the import path.
%end
"""
return template(tpl_error, e=e)
app.error(code=500, callback=error_handler_500)
def run_app(app):
if config.server_used!='cherrypy':
run(app=app, host=config.host, server=config.server_used, port=config.port, debug=config.debug, reloader=config.reloader)
else:
from paramecio.cherry import run_cherrypy_server
run_cherrypy_server()