Flask app minimal structure

This commit is contained in:
Ilona 2024-08-27 02:06:22 +02:00
parent c2f4abf631
commit 4f641f24e6
10 changed files with 242 additions and 0 deletions

15
.gitignore vendored
View File

@ -160,3 +160,18 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# Mac OSX OS generated files
.DS_Store?
Thumbs.db
*.DS_Store
# VS Code
.vscode/
*.code-workspace
# Symlinks static ScoDoc
app/static/links/[0-9]*.*
# Essais locaux
xp/

30
app/__init__.py Normal file
View File

@ -0,0 +1,30 @@
from flask import current_app, g, request
from flask import Flask
from config import DevConfig
class ReverseProxied:
"""Adaptateur wsgi qui nous permet d'avoir toutes les URL calculées en https
sauf quand on est en dev.
La variable HTTP_X_FORWARDED_PROTO est positionnée par notre config nginx"""
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
scheme = environ.get("HTTP_X_FORWARDED_PROTO")
if scheme:
environ["wsgi.url_scheme"] = scheme # ou forcer à https ici ?
return self.app(environ, start_response)
def create_app(config_class=DevConfig):
app = Flask(__name__, static_url_path="/AutoSco/static", static_folder="static")
app.config.from_object(config_class)
app.wsgi_app = ReverseProxied(app.wsgi_app)
from app.views import bp
app.register_blueprint(bp)
return app

7
app/cli.py Normal file
View File

@ -0,0 +1,7 @@
# -*- coding: UTF-8 -*
import os
import click
def register(app):
pass

27
app/templates/base.j2 Normal file
View File

@ -0,0 +1,27 @@
{%- block doc -%}<!DOCTYPE html>{# Base de toutes les pages AutoSco #}
<html{% block html_attribs %}{% endblock html_attribs %}>
{%- block html %}
<head>
{%- block head %}
<title>{% block title %}{{title|default}}{% endblock title %}</title>
{%- block metas %}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{%- endblock metas %}
{%- endblock head %}
</head>
<body{% block body_attribs %}{% endblock body_attribs %}>
{% block body -%}
{% block navbar %}
{%- endblock navbar %}
{% block content -%}
{%- endblock content %}
{% block scripts %}
{%- endblock scripts %}
{%- endblock body %}
</body>
{%- endblock html %}
</html>
{% endblock doc -%}

10
app/utils/utils.py Normal file
View File

@ -0,0 +1,10 @@
"""AutoSco / utils.py
"""
import os
import version
# le répertoire static, lié à chaque release pour éviter les problèmes de caches
STATIC_DIR = (
os.environ.get("SCRIPT_NAME", "") + "/AutoSco/static/links/" + version.VERSION
)

8
app/views/__init__.py Normal file
View File

@ -0,0 +1,8 @@
"""AutoSco Flask views"""
from flask import Blueprint
from flask import g, current_app, request
bp = Blueprint("autosco", __name__)
from app.views import views

9
app/views/views.py Normal file
View File

@ -0,0 +1,9 @@
"""AutoSco / views
"""
from app.views import bp
@bp.route("/")
def index():
return "hello"

51
autosco.py Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python
"""Application Flask: AutoSco"""
import os
from pprint import pprint as pp
import click
import flask
from flask.cli import with_appcontext
from flask.templating import render_template
import app as mapp
from app import create_app, cli
from app.utils import utils as scu
from config import RunningConfig
app = create_app(RunningConfig)
cli.register(app)
@app.context_processor
def inject_utils():
"Make scu available in all Jinja templates"
# if modified, put the same in conftest.py#27
return {
"DEBUG": flask.current_app.config["DEBUG"],
"scu": scu,
}
@app.shell_context_processor
def make_shell_context():
import app as mapp # le package app
from app.utils import sco_utils as scu
return {
"ctx": app.test_request_context(),
"current_app": flask.current_app,
"current_user": current_user,
"datetime": datetime,
"flask": flask,
"mapp": mapp,
"pp": pp,
"scu": scu,
}
if __name__ == "__main__":
port = os.environ.get("PORT", 5001)
app.run(debug=True, port=port)

82
config.py Normal file
View File

@ -0,0 +1,82 @@
import os
import logging
from dotenv import load_dotenv
BASEDIR = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(BASEDIR, ".env"))
class Config:
"""General configuration. Mostly loaded from environment via .env"""
FLASK_ENV = None # # set in subclass
SECRET_KEY = os.environ.get("SECRET_KEY") or "90e01e751977d4276a4c70d98564b425e"
LOG_TO_STDOUT = os.environ.get("LOG_TO_STDOUT")
LOG_LEVEL = getattr(logging, os.environ.get("LOG_LEVEL", "INFO"), "INFO")
MAIL_SERVER = os.environ.get("MAIL_SERVER", "localhost")
LANGUAGES = ["fr", "en"] # unused for now
ADMIN_MAIL = os.environ.get("ADMIN_MAIL")
ADMIN_LOGIN = os.environ.get("ADMIN_LOGIN") or "admin"
ADMINS = [ADMIN_MAIL]
ERR_MAIL = os.environ.get("ERR_MAIL")
# Le "from" des mails émis. Attention: peut être remplacée par la préférence email_from_addr:
MAIL_FROM = os.environ.get("MAIL_FROM") or ("no-reply@" + MAIL_SERVER)
AUTOSCO_DIR = os.environ.get("AUTOSCO_DIR", "/opt/autosco")
AUTOSCO_VAR_DIR = os.environ.get("AUTOSCO_VAR_DIR", "/opt/autosco-data")
AUTOSCO_LOG_FILE = os.path.join(AUTOSCO_VAR_DIR, "log", "autosco.log")
# evite confusion avec le log nginx scodoc_error.log:
AUTOSCO_ERR_FILE = os.path.join(AUTOSCO_VAR_DIR, "log", "autosco_exc.log")
#
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # Flask uploads (16Mo, en ligne avec nginx)
# flask_json:
JSON_ADD_STATUS = False
JSON_USE_ENCODE_METHODS = True
JSON_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z" # "%Y-%m-%dT%H:%M:%S"
class ProdConfig(Config):
"mode production, normalement derrière nginx/gunicorn"
FLASK_ENV = "production"
DEBUG = False
TESTING = False
PREFERRED_URL_SCHEME = "https"
class DevConfig(Config):
"mode développement"
FLASK_ENV = "development"
DEBUG = True
TESTING = False
SECRET_KEY = os.environ.get("DEV_SECRET_KEY") or "cc4fbec7d9a34eb69a7e3e710087d87a"
class TestConfig(DevConfig):
"Pour les tests unitaires"
TESTING = True
DEBUG = False
SERVER_NAME = os.environ.get("AUTOSCO_TEST_SERVER_NAME") or "autotest.gr"
SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "c8ecff5db1592c308f563ff30e0f6bbc"
class TestAPIConfig(Config):
"Pour les tests de l'API"
FLASK_ENV = "test_api"
TESTING = False
DEBUG = True
SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "d8ecff5db15946789Hhahbh88aja276"
mode = os.environ.get("FLASK_ENV", "production")
if mode == "production":
RunningConfig = ProdConfig
elif mode == "development":
RunningConfig = DevConfig
elif mode == "test":
RunningConfig = TestConfig
elif mode == "test_api":
RunningConfig = TestAPIConfig

3
version.py Normal file
View File

@ -0,0 +1,3 @@
VERSION = "0.0.0"
NAME = "AutoSco"