Serve.py 3.93 KB
import os
import sys
import cherrypy
import importlib
import logging.config

from cherrypy.lib.reprconf import Parser

if __name__ == '__main__':

    html_path = os.path.dirname(os.path.abspath(__file__))
    base_path = os.path.join(html_path, '..')
    conf_path = os.path.join(html_path, 'site.config' )

    # Import web framework modules
    from src.plugins import SQLAlchemyPlugin
    from src.tools import Jinja2Tool, SQLAlchemyTool, DebugTool, ResponseHeaders

    # Load config before CherryPy
    p = Parser()
    try:
        conf = p.dict_from_file(conf_path)
    except Exception as e:
        cherrypy.log('Failed loading config file: %s', e)
        sys.exit(1)

    # Register location of application and libraries (git submodules)
    libs_path = conf['path']['libraries']
    sys.path.append(libs_path)
    sys.path.append(base_path)

    #if conf['global']['server.wsgi'] is False:
    #    from cherrypy._cpnative_server import CPHTTPServer
    #    cherrypy.server.httpserver = CPHTTPServer(cherrypy.server)
    #    cherrypy.log('Disabled WSGI Server, using native HTTP server')

    # Load Plugins
    SQLAlchemyPlugin(cherrypy.engine,
                     host = conf['db']['host'],
                     port = conf['db']['port'],
                     name = conf['db']['name'],
                     user = conf['db']['user'],
                     pw   = conf['db']['pass']).subscribe()

    # Load Tools
    cherrypy.tools.render = Jinja2Tool(conf['path']['templates'])
    cherrypy.tools.db = SQLAlchemyTool()
    cherrypy.tools.debug = DebugTool()
    cherrypy.tools.response_headers = ResponseHeaders(conf['response-headers'])

    # Import application modules via config file
    for classname, pair in conf['apps'].items():

        module, script = pair
        module_object = importlib.import_module(module)
        classname = getattr(module_object, classname)

        cherrypy.tree.mount(classname(), script, conf_path)

        cherrypy.log(f'MOUNT from {module} import {classname}')
        cherrypy.log(f"cherrypy.tree.mount({classname}(), '{script}', config={conf_path})")

    # Share logging with application
    LOG_CONF = {
        'version': 1,
        'formatters': {
            'standard': {
                'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
            },
            'basic': {
                'format': '[%(levelname)s] %(message)s'
            },
        },
        'handlers': {
            'default': {
                'level': conf['logs']['level'],
                'class': 'logging.handlers.RotatingFileHandler',
                'formatter': 'basic',
                'filename': conf['logs']['error'],
                'maxBytes': 10485760,
                'backupCount': 20,
                'encoding': 'utf8'
            },
            'cherrypy_access': {
                'level': conf['logs']['level'],
                'class': 'logging.handlers.RotatingFileHandler',
                'formatter': 'basic',
                'filename': conf['logs']['access'],
                'maxBytes': 10485760,
                'backupCount': 20,
                'encoding': 'utf8'
            },
        },
        'loggers': {
            '': {
                'handlers': ['default'],
                'level': conf['logs']['level']
            },
            'cherrypy.access': {
                'handlers': ['cherrypy_access'],
                'level': conf['logs']['level'],
                'propagate': False
            },
            'cherrypy.error': {
                'handlers': ['default'],
                'level': conf['logs']['level'],
                'propagate': False
            },
        }
    }

    # Disable CherryPy logger, replace with standard logging
    cherrypy.engine.unsubscribe('graceful', cherrypy.log.reopen_files)
    logging.config.dictConfig(LOG_CONF)

    # Pass config file location to CherryPy
    cherrypy.config.update(conf_path)

    # Start web server
    cherrypy.engine.start()
    cherrypy.engine.block()