"""The Quality-Control Web Application entry point""" import os import sys import logging from pathlib import Path from flask import Flask, request from flask_session import Session from uploader.oauth2.client import user_logged_in, authserver_authorise_uri from .entry import entrybp from .upload import upload from .parse import parsebp from .samples import samples from .base_routes import base from .dbinsert import dbinsertbp from .oauth2.views import oauth2 from .errors import register_error_handlers def override_settings_with_envvars( app: Flask, ignore: tuple[str, ...]=tuple()) -> None: """Override settings in `app` with those in ENVVARS""" for setting in (key for key in app.config if key not in ignore): app.config[setting] = os.environ.get(setting) or app.config[setting] def __log_gunicorn__(app: Flask) -> Flask: """Set up logging for the WSGI environment with GUnicorn""" logger = logging.getLogger("gunicorn.error") app.logger.handlers = logger.handlers app.logger.setLevel(logger.level) return app def __log_dev__(app: Flask) -> Flask: """Set up logging for the development environment.""" stderr_handler = logging.StreamHandler(stream=sys.stderr) app.logger.addHandler(stderr_handler) root_logger = logging.getLogger() root_logger.addHandler(stderr_handler) root_logger.setLevel(app.config["LOG_LEVEL"]) return app def setup_logging(app: Flask) -> Flask: """Set up logging for the application.""" software, *_version_and_comments = os.environ.get( "SERVER_SOFTWARE", "").split('/') return __log_gunicorn__(app) if bool(software) else __log_dev__(app) def create_app(): """The application factory""" app = Flask(__name__) app.config.from_pyfile( Path(__file__).parent.joinpath("default_settings.py")) if "UPLOADER_CONF" in os.environ: app.config.from_envvar("UPLOADER_CONF") # Override defaults with instance path override_settings_with_envvars(app, ignore=tuple()) secretsfile = app.config.get("UPLOADER_SECRETS", "").strip() if bool(secretsfile): secretsfile = Path(secretsfile).absolute() app.config["UPLOADER_SECRETS"] = secretsfile if secretsfile.exists(): # Silently ignore secrets if the file does not exist. app.config.from_pyfile(secretsfile) setup_logging(app) # setup jinja2 symbols app.add_template_global(lambda : request.url, name="request_url") app.add_template_global(authserver_authorise_uri) app.add_template_global(lambda: app.config["GN2_SERVER_URL"], name="gn2server_uri") app.add_template_global(user_logged_in) Session(app) # setup blueprints app.register_blueprint(base, url_prefix="/") app.register_blueprint(entrybp, url_prefix="/") app.register_blueprint(parsebp, url_prefix="/parse") app.register_blueprint(oauth2, url_prefix="/oauth2") app.register_blueprint(upload, url_prefix="/upload") app.register_blueprint(dbinsertbp, url_prefix="/dbinsert") app.register_blueprint(samples, url_prefix="/samples") register_error_handlers(app) return app