Coverage for .tox/coverage/lib/python3.11/site-packages/wuttaweb/app.py: 100%
45 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-26 14:40 -0500
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-26 14:40 -0500
1# -*- coding: utf-8; -*-
2################################################################################
3#
4# wuttaweb -- Web App for Wutta Framework
5# Copyright © 2024 Lance Edgar
6#
7# This file is part of Wutta Framework.
8#
9# Wutta Framework is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by the Free
11# Software Foundation, either version 3 of the License, or (at your option) any
12# later version.
13#
14# Wutta Framework is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17# more details.
18#
19# You should have received a copy of the GNU General Public License along with
20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21#
22################################################################################
23"""
24Application
25"""
27import os
29from wuttjamaican.app import AppProvider
30from wuttjamaican.conf import make_config
32from pyramid.config import Configurator
34import wuttaweb.db
35from wuttaweb.auth import WuttaSecurityPolicy
38class WebAppProvider(AppProvider):
39 """
40 The :term:`app provider` for WuttaWeb. This adds some methods to
41 the :term:`app handler`, which are specific to web apps.
42 """
43 email_templates = 'wuttaweb:email/templates'
45 def get_web_handler(self, **kwargs):
46 """
47 Get the configured "web" handler for the app.
49 Specify a custom handler in your config file like this:
51 .. code-block:: ini
53 [wutta]
54 web.handler_spec = poser.web.handler:PoserWebHandler
56 :returns: Instance of :class:`~wuttaweb.handler.WebHandler`.
57 """
58 if 'web_handler' not in self.__dict__:
59 spec = self.config.get(f'{self.appname}.web.handler_spec',
60 default='wuttaweb.handler:WebHandler')
61 self.web_handler = self.app.load_object(spec)(self.config)
62 return self.web_handler
65def make_wutta_config(settings, config_maker=None, **kwargs):
66 """
67 Make a WuttaConfig object from the given settings.
69 Note that ``settings`` dict will (typically) correspond to the
70 ``[app:main]`` section of your config file.
72 Regardless, the ``settings`` must contain a special key/value
73 which is needed to identify the location of the config file.
74 Assuming the typical scenario then, your config file should have
75 an entry like this:
77 .. code-block:: ini
79 [app:main]
80 wutta.config = %(__file__)s
82 The ``%(__file__)s`` is auto-replaced with the config file path,
83 so ultimately ``settings`` would contain something like (at
84 minimum)::
86 {'wutta.config': '/path/to/config/file'}
88 If this config file path cannot be discovered, an error is raised.
89 """
90 # validate config file path
91 path = settings.get('wutta.config')
92 if not path or not os.path.exists(path):
93 raise ValueError("Please set 'wutta.config' in [app:main] "
94 "section of config to the path of your "
95 "config file. Lame, but necessary.")
97 # make config, add to settings
98 config_maker = config_maker or make_config
99 wutta_config = config_maker(path, **kwargs)
100 settings['wutta_config'] = wutta_config
102 # configure database sessions
103 if hasattr(wutta_config, 'appdb_engine'):
104 wuttaweb.db.Session.configure(bind=wutta_config.appdb_engine)
106 return wutta_config
109def make_pyramid_config(settings):
110 """
111 Make and return a Pyramid config object from the given settings.
113 The config is initialized with certain features deemed useful for
114 all apps.
116 :returns: Instance of
117 :class:`pyramid:pyramid.config.Configurator`.
118 """
119 settings.setdefault('fanstatic.versioning', 'true')
120 settings.setdefault('mako.directories', ['wuttaweb:templates'])
121 settings.setdefault('pyramid_deform.template_search_path',
122 'wuttaweb:templates/deform')
124 pyramid_config = Configurator(settings=settings)
126 # configure user authorization / authentication
127 pyramid_config.set_security_policy(WuttaSecurityPolicy())
129 # require CSRF token for POST
130 pyramid_config.set_default_csrf_options(require_csrf=True,
131 token='_csrf',
132 header='X-CSRF-TOKEN')
134 pyramid_config.include('pyramid_beaker')
135 pyramid_config.include('pyramid_deform')
136 pyramid_config.include('pyramid_fanstatic')
137 pyramid_config.include('pyramid_mako')
138 pyramid_config.include('pyramid_tm')
140 # add some permissions magic
141 pyramid_config.add_directive('add_wutta_permission_group',
142 'wuttaweb.auth.add_permission_group')
143 pyramid_config.add_directive('add_wutta_permission',
144 'wuttaweb.auth.add_permission')
146 return pyramid_config
149def main(global_config, **settings):
150 """
151 This function returns a Pyramid WSGI application.
153 Typically there is no need to call this function directly, but it
154 may be configured as the web app entry point like so:
156 .. code-block:: ini
158 [app:main]
159 use = egg:wuttaweb
161 The app returned by this function is quite minimal, so most apps
162 will need to define their own ``main()`` function, and use that
163 instead.
164 """
165 wutta_config = make_wutta_config(settings)
166 pyramid_config = make_pyramid_config(settings)
168 pyramid_config.include('wuttaweb.static')
169 pyramid_config.include('wuttaweb.subscribers')
170 pyramid_config.include('wuttaweb.views')
172 return pyramid_config.make_wsgi_app()