Source code for thekraf.flaskapp

"""
thekraf.flaskapp
================

Flask web backend app
"""
from datetime import datetime
import os
import flask
from flask_bootstrap import Bootstrap
# from flask_mail import Mail
from flask_misaka import Misaka
from flask_principal import Principal
from flask_security import Security, SQLAlchemyUserDatastore
from flask_sqlalchemy import SQLAlchemy
# from flask_sslify import SSLify
from werkzeug.datastructures import ImmutableDict
from thekraf import Multilogr
import thekraf.config as cfg
import thekraf.db.models as mdls
from thekraf.flaskapp.baseview import ViewBase
from thekraf.flaskapp.forms import LoginUserForm, RegisterUserForm

logr = Multilogr.get_logr(cfg.FlaskAppConfig.LOGGER_NAME)


[docs]class FlaskWithHamlish(flask.Flask): """Adds support for Hamlish-Jinja to Flask""" jinja_options = ImmutableDict( extensions=flask.Flask.jinja_options['extensions'] + [ 'hamlish_jinja.HamlishExtension' ] )
[docs]class JSONEncoderWrapper(object): """Add support for more types to the json encoder if `default` and `for_json` are used, then if an object has a `for_json` attribute, it will be used. Otherwise, it will fallback on `default` flask uses a `TaggedJSONSerializer` on sessions which will be try converting various types before giving `default` a try. """ def __new__(cls, *args, **kwargs): kwargs.update(dict( default=cls.default_override, for_json=True, )) return flask.json.JSONEncoder(*args, **kwargs) @staticmethod
[docs] def default_override(o): # Create a dict of object instance variables and properties try: # Include instance variables d = dict(o.__dict__) # Include properties d.update({k: getattr(o, k) for k, v in o.__class__.__dict__.items() if isinstance(v, property)}) except (AttributeError, TypeError): pass else: return d if isinstance(o, set): return list(o) if isinstance(o, datetime): return str(o) # If this method couldn't convert the object raise TypeError(repr(o) + " is not JSON serializable")
[docs]def create_app(config_obj=cfg.FlaskAppConfig): """Flask app factory Returns: flask.app: An app configured for various extensions """ app = FlaskWithHamlish(__name__) app.config.from_object(config_obj) app.json_encoder = JSONEncoderWrapper # Override the flask logger # Note that logging the web server underneath has to be done separately app._logger = logr # Config hamlish app.jinja_env.hamlish_mode = 'debug' app.jinja_env.hamlish_file_extensions = ('.hamlish',) app.jinja_env.hamlish_enable_div_shortcut = True # Create a random secret key used for session security, unless already set if not os.path.exists(cfg.SECRET_KEY_PATH): with open(cfg.SECRET_KEY_PATH, 'wb') as fp: fp.write(os.urandom(24)) with open(cfg.SECRET_KEY_PATH, 'rb') as fp: app.secret_key = fp.read() # SSLify(app) Bootstrap(app) # mail = Mail(app) sqla_db = SQLAlchemy(app) user_ds = SQLAlchemyUserDatastore(sqla_db, mdls.User, mdls.Role) security = Security(app, user_ds, register_form=RegisterUserForm, login_form=LoginUserForm) security.register_context_processor(ViewBase.ctx_processor) security.login_context_processor(ViewBase.ctx_processor) Principal(app) Misaka(app) return app