Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/creactiweb/_templates/lib/flask/module.py
blob: 4e719a4e93dc67448e3be437f399deb2d3888ce4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# -*- coding: utf-8 -*-
"""
    flask.module
    ~~~~~~~~~~~~

    Implements a class that represents module blueprints.

    :copyright: (c) 2010 by Armin Ronacher.
    :license: BSD, see LICENSE for more details.
"""

from .helpers import _PackageBoundObject, _endpoint_from_view_func


def _register_module(module, static_path):
    """Internal helper function that returns a function for recording
    that registers the `send_static_file` function for the module on
    the application if necessary.  It also registers the module on
    the application.
    """
    def _register(state):
        state.app.modules[module.name] = module
        # do not register the rule if the static folder of the
        # module is the same as the one from the application.
        if state.app.root_path == module.root_path:
            return
        path = static_path
        if path is None:
            path = state.app.static_path
        if state.url_prefix:
            path = state.url_prefix + path
        state.app.add_url_rule(path + '/<path:filename>',
                               endpoint='%s.static' % module.name,
                               view_func=module.send_static_file,
                               subdomain=state.subdomain)
    return _register


class _ModuleSetupState(object):

    def __init__(self, app, url_prefix=None, subdomain=None):
        self.app = app
        self.url_prefix = url_prefix
        self.subdomain = subdomain


class Module(_PackageBoundObject):
    """Container object that enables pluggable applications.  A module can
    be used to organize larger applications.  They represent blueprints that,
    in combination with a :class:`Flask` object are used to create a large
    application.

    A module is like an application bound to an `import_name`.  Multiple
    modules can share the same import names, but in that case a `name` has
    to be provided to keep them apart.  If different import names are used,
    the rightmost part of the import name is used as name.

    Here's an example structure for a larger application::

        /myapplication
            /__init__.py
            /views
                /__init__.py
                /admin.py
                /frontend.py

    The `myapplication/__init__.py` can look like this::

        from flask import Flask
        from myapplication.views.admin import admin
        from myapplication.views.frontend import frontend

        app = Flask(__name__)
        app.register_module(admin, url_prefix='/admin')
        app.register_module(frontend)

    And here's an example view module (`myapplication/views/admin.py`)::

        from flask import Module

        admin = Module(__name__)

        @admin.route('/')
        def index():
            pass

        @admin.route('/login')
        def login():
            pass

    For a gentle introduction into modules, checkout the
    :ref:`working-with-modules` section.

    .. versionadded:: 0.5
       The `static_path` parameter was added and it's now possible for
       modules to refer to their own templates and static files.  See
       :ref:`modules-and-resources` for more information.

    .. versionadded:: 0.6
       The `subdomain` parameter was added.

    :param import_name: the name of the Python package or module
                        implementing this :class:`Module`.
    :param name: the internal short name for the module.  Unless specified
                 the rightmost part of the import name
    :param url_prefix: an optional string that is used to prefix all the
                       URL rules of this module.  This can also be specified
                       when registering the module with the application.
    :param subdomain: used to set the subdomain setting for URL rules that
                      do not have a subdomain setting set.
    :param static_path: can be used to specify a different path for the
                        static files on the web.  Defaults to ``/static``.
                        This does not affect the folder the files are served
                        *from*.
    """

    def __init__(self, import_name, name=None, url_prefix=None,
                 static_path=None, subdomain=None):
        if name is None:
            assert '.' in import_name, 'name required if package name ' \
                'does not point to a submodule'
            name = import_name.rsplit('.', 1)[1]
        _PackageBoundObject.__init__(self, import_name)
        self.name = name
        self.url_prefix = url_prefix
        self.subdomain = subdomain
        self._register_events = [_register_module(self, static_path)]

    def route(self, rule, **options):
        """Like :meth:`Flask.route` but for a module.  The endpoint for the
        :func:`url_for` function is prefixed with the name of the module.
        """
        def decorator(f):
            self.add_url_rule(rule, f.__name__, f, **options)
            return f
        return decorator

    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        """Like :meth:`Flask.add_url_rule` but for a module.  The endpoint for
        the :func:`url_for` function is prefixed with the name of the module.

        .. versionchanged:: 0.6
           The `endpoint` argument is now optional and will default to the
           function name to consistent with the function of the same name
           on the application object.
        """
        def register_rule(state):
            the_rule = rule
            if state.url_prefix:
                the_rule = state.url_prefix + rule
            options.setdefault('subdomain', state.subdomain)
            the_endpoint = endpoint
            if the_endpoint is None:
                the_endpoint = _endpoint_from_view_func(view_func)
            state.app.add_url_rule(the_rule, '%s.%s' % (self.name,
                                                        the_endpoint),
                                   view_func, **options)
        self._record(register_rule)

    def before_request(self, f):
        """Like :meth:`Flask.before_request` but for a module.  This function
        is only executed before each request that is handled by a function of
        that module.
        """
        self._record(lambda s: s.app.before_request_funcs
            .setdefault(self.name, []).append(f))
        return f

    def before_app_request(self, f):
        """Like :meth:`Flask.before_request`.  Such a function is executed
        before each request, even if outside of a module.
        """
        self._record(lambda s: s.app.before_request_funcs
            .setdefault(None, []).append(f))
        return f

    def after_request(self, f):
        """Like :meth:`Flask.after_request` but for a module.  This function
        is only executed after each request that is handled by a function of
        that module.
        """
        self._record(lambda s: s.app.after_request_funcs
            .setdefault(self.name, []).append(f))
        return f

    def after_app_request(self, f):
        """Like :meth:`Flask.after_request` but for a module.  Such a function
        is executed after each request, even if outside of the module.
        """
        self._record(lambda s: s.app.after_request_funcs
            .setdefault(None, []).append(f))
        return f

    def context_processor(self, f):
        """Like :meth:`Flask.context_processor` but for a module.  This
        function is only executed for requests handled by a module.
        """
        self._record(lambda s: s.app.template_context_processors
            .setdefault(self.name, []).append(f))
        return f

    def app_context_processor(self, f):
        """Like :meth:`Flask.context_processor` but for a module.  Such a
        function is executed each request, even if outside of the module.
        """
        self._record(lambda s: s.app.template_context_processors
            .setdefault(None, []).append(f))
        return f

    def app_errorhandler(self, code):
        """Like :meth:`Flask.errorhandler` but for a module.  This
        handler is used for all requests, even if outside of the module.

        .. versionadded:: 0.4
        """
        def decorator(f):
            self._record(lambda s: s.app.errorhandler(code)(f))
            return f
        return decorator

    def _record(self, func):
        self._register_events.append(func)