Completed
Push — master ( d9b99a...978de0 )
by Daniel
01:01
created

WebApplication.init_flask()   B

Complexity

Conditions 2

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
1
import os
2
import logging
3
from flask import Flask, render_template
4
from docutils.core import publish_parts
5
6
from groundwork.patterns import GwBasePattern
7
8
from groundwork_web.patterns.gw_web_pattern.server import ServerManagerApplication, ServerManagerPlugin
9
from groundwork_web.patterns.gw_web_pattern.context import ContextManagerApplication, ContextManagerPlugin
10
from groundwork_web.patterns.gw_web_pattern.route import RouteManagerApplication, RouteManagerPlugin
11
from groundwork_web.patterns.gw_web_pattern.menu import MenuApplication, MenuPlugin
12
13
14
class GwWebPattern(GwBasePattern):
15
16
    def __init__(self, *args, **kwargs):
17
        super().__init__(*args, **kwargs)
18
        if not hasattr(self.app, "web"):
19
            self.app.web = WebApplication(self.app)
20
21
        #: Instance of :class:`~.WebPlugin`.
22
        #: Provides functions to manage web based objects
23
        self.web = WebPlugin(self)
24
25
26
class WebPlugin:
27
    def __init__(self, plugin):
28
        self.plugin = plugin
29
        self.app = plugin.app
30
        self.log = plugin.log
31
32
        self.servers = ServerManagerPlugin(plugin)
33
        self.contexts = ContextManagerPlugin(plugin)
34
        self.routes = RouteManagerPlugin(plugin)
35
        self.menus = MenuPlugin(plugin)
36
37
        self.plugin.signals.connect(receiver="%s_flask_activation" % self.plugin.name,
38
                                    signal="plugin_activate_pre",
39
                                    function=self.__init_flask,
40
                                    description="Initialised flask during plugin activation of %s" % self.plugin.name,
41
                                    sender=self.plugin)
42
43
    @property
44
    def flask(self):
45
        return self.app.web.flask
46
47
    @flask.setter
48
    def flask(self, value):
49
        self.app.web.flask = value
50
51
    def __init_flask(self, plugin, *args, **kwargs):
52
        self.app.web.init_flask()
53
54
    def render(self, template, plugin=None, **kwargs):
55
        if plugin is None:
56
            plugin = self.plugin
57
58
        return self.app.web.render(template, plugin, **kwargs)
59
60
61
class WebApplication:
62
    def __init__(self, app):
63
        self.app = app
64
        self.log = logging.getLogger(__name__)
65
        self.flask = None
66
67
        self.servers = ServerManagerApplication(app)
68
        self.contexts = ContextManagerApplication(app)
69
        self.routes = RouteManagerApplication(app)
70
        self.menus = MenuApplication(app)
71
72
    def init_flask(self):
73
        """
74
        Initialises and configures flask, is not already done,.
75
        :return: None
76
        """
77
        if self.flask is None:
78
            self.flask = Flask(self.app.name)
79
80
            # Inject send_signal() to jinja templates
81
            # Use it like {{ send_signal("my_signal") }}
82
            self.flask.jinja_env.globals.update(send_signal=self.app.signals.send)
83
84
            self.flask.jinja_env.globals.update(app=self.app)
85
86
            self.flask.jinja_env.globals.update(get_menu=self.__get_menu)
87
            self.flask.jinja_env.globals.update(get_config=self.app.config.get)
88
            self.flask.jinja_env.globals.update(rst2html=self.__rst2html)
89
90
            # Lets set the secret key for flask. This should be set in configuration files, so that
91
            # signed cookies are still valid if the server got restarted.
92
            # If there is no such parameter available, we create a temporary key, which is only
93
            # available during server runtime.
94
            self.flask.secret_key = self.app.config.get("FLASK_SECRET_KEY", os.urandom(24))
95
96
            self.flask.config["SERVER_NAME"] = self.app.config.get("FLASK_SERVER_NAME", "localhost")
97
98
    def __get_menu(self, cluster="base"):
99
        return self.menus.get(cluster=cluster)
100
101
    def __rst2html(self, document, part="body"):
102
        if document is not None and type(document) == str:
103
            doc_rendered = publish_parts(document, writer_name="html")
104
            if part not in doc_rendered.keys():
105
                raise KeyError("%s is not a valid key for part parameter of rst2html.\nValid options: " %
106
                               (part, ",".join(doc_rendered.keys())))
107
            return doc_rendered[part]
108
        return document
109
110
    def render(self, template, plugin=None, **kwargs):
111
        """
112
        Renders a template and returns a strings, which represents the rendered data.
113
114
        Internally render_template() from flask is used.
115
116
        :param template: Name of the template
117
        :param kwargs: Optional key-word arguments, which get passed to the template engine.
118
        :return: Rendered template as string
119
        """
120
121
        return render_template(template, app=self.app, plugin=plugin, **kwargs)
122
123