"""
:filename: wsgi.py
:author: Brigitte Bigi
:contact: contact@sppas.org
:summary: Example of WSGI response for a WhakerKit-based website or application.
:license: Use of this software is governed by the GNU Affero Public License, version 3.
-----------------------------------------------------------------------------
WSGI entry point for WhakerKit/WhakerPy applications.
- Initializes the site using a JSON configuration;
- Provides a robust error fallback for server deployment.
The WSGI server is searching for an "application(environ, start_response)"
function. It is invoked every time a request is received by either POST,
or GET, or any other method.
Test locally the site/app with:
> uwsgi --http :9090 --wsgi-file wsgi.py
-----------------------------------------------------------------------------
Copyright (C) 2024-2025 Brigitte Bigi, CNRS
Laboratoire Parole et Langage, Aix-en-Provence, France
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/>.
This banner notice must not be removed.
-----------------------------------------------------------------------------
"""
# ---------------------------------------------------------------------------
# Import of python standard libraries
# ---------------------------------------------------------------------------
from __future__ import annotations
import os
import sys
import logging
# ---------------------------------------------------------------------------
# Add current directory into the PYTHONPATH allowing Python to find our
# own packages.
FILENAME = os.path.abspath(__file__)
HERE = os.path.dirname(FILENAME)
sys.path.append(HERE)
# ----------------------------------------------------------------------------
# Manage logging
# ----------------------------------------------------------------------------
# Define the log level for output messages
LOG_LEVEL = 1 # Debug level
# LOG_LEVEL = 15 # Info level
# Name of the file for logger messages
LOG_FILENAME = "wsgi.log"
if LOG_LEVEL < 10:
LOG_FILENAME = "wsgi_debug.log"
# Create formatter and add it to the handler
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# Save logs into a file: create file logger
file_log = logging.FileHandler(HERE + "/" + LOG_FILENAME, mode='a', encoding="utf-8", delay=False)
file_log.setFormatter(formatter)
file_log.setLevel(LOG_LEVEL)
# Add this file logger to the logging system
logging.getLogger().addHandler(file_log)
logging.getLogger().setLevel(LOG_LEVEL)
# ----------------------------------------------------------------------------
# Environment variables
# ----------------------------------------------------------------------------
# Definition of lang, required by wsgi service
os.environ['LC_ALL'] = "en_US.UTF-8"
# os.environ['LC_LANG'] = "fr_FR.UTF-8" # For a website in French
os.environ['LC_LANG'] = "en_EN.UTF-8" # For a website in English
# Define the filepath of this wsgi.py file. Can be used to get the path of
# the project directory with: os.getenv("INSTANCE_ROOT").
os.environ["INSTANCE_ROOT"] = os.path.dirname(os.path.abspath(__file__))
# ----------------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------------
try:
import whakerpy
import whakerkit
# -----------------------------------------------------------------------
# Path to the main JSON configuration for both WhakerPy and WhakerKit.
# !! TO BE MODIFIED FOR YOUR OWN WEBSITE !!
# -----------------------------------------------------------------------
json_filename = "./sample/sample.json"
if os.path.exists(json_filename) is False:
raise Exception(f"The expected JSON configuration file {json_filename} wasn't found.")
# Initialize WhakerKit global settings. This makes all WhakerKit features
# use the chosen configuration file.
whakerkit.initialize(json_filename, os.path.dirname(os.path.abspath(__file__)))
# Import the website data manager (must inherit from whakerpy.WebSiteData).
# It must be imported after whakerkit initialization because it makes use of
# whakerkit.sg which contains specific "pathes" for this website.
from sample.bakery import CustomWebData
# Build the WSGI application, with WhakerKit error handling.
application = whakerkit.WhakerkitErrorMiddleware(whakerpy.WSGIApplication(
default_path="",
default_filename="index.html",
web_page_maker=CustomWebData,
default_web_json=json_filename
))
except Exception as e:
import traceback
# In case of initialization error, log and return a 500 error page.
logging.error(str(e))
logging.error(traceback.format_exc())
# HTML error message, displayed to users on fatal errors.
MSG_ERROR = traceback.format_exc().replace("\n", "<br>")
def application(environ, start_response):
start_response('500 Internal Server Error', [('Content-Type', 'text/html; charset=utf-8')])
HTML_500 = "Internal Server Error"
filename = HERE + "/whakerkit/error/500.html"
if os.path.exists(filename) is True:
with open(filename, "r", encoding="utf-8") as f:
HTML_500 = f.read()
return [line.encode("utf-8") for line in HTML_500.format(ERROR=MSG_ERROR)]