Refactor app module to promote code sharing.

Hopefully this is a good approach, we'll see.
This commit is contained in:
Lance Edgar 2015-02-13 21:22:01 -06:00
parent 937a55c14d
commit ae5ff89c7f

View file

@ -27,64 +27,110 @@ Application Entry Point
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
import logging
from sqlalchemy import engine_from_config
import edbob import edbob
from edbob.pyramid.forms.formalchemy import TemplateEngine from edbob.pyramid.forms.formalchemy import TemplateEngine
import rattail.db
from rattail.config import RattailConfig
from rattail.exceptions import ConfigurationError
from rattail.db.util import get_engines
from rattail.db.continuum import configure_versioning
from rattail.db.types import GPCType from rattail.db.types import GPCType
import formalchemy import formalchemy
from pyramid.config import Configurator from pyramid.config import Configurator
from pyramid.authentication import SessionAuthenticationPolicy from pyramid.authentication import SessionAuthenticationPolicy
from zope.sqlalchemy import ZopeTransactionExtension
from tailbone.db import Session import tailbone.db
from tailbone.auth import TailboneAuthorizationPolicy from tailbone.auth import TailboneAuthorizationPolicy
from tailbone.forms import GPCFieldRenderer from tailbone.forms import GPCFieldRenderer
def main(global_config, **settings): log = logging.getLogger(__name__)
"""
This function returns a Pyramid WSGI application.
"""
# Use Tailbone templates by default.
settings.setdefault('mako.directories', ['tailbone:templates'])
# Make two attempts when "retryable" errors happen during transactions. def make_rattail_config(settings):
# This is intended to gracefully handle database restarts. """
Make a Rattail config object from the given settings.
"""
# Initialize rattail config and embed it in the settings dict, to make it
# available to web requests later.
path = settings.get('edbob.config')
if not path or not os.path.exists(path):
raise ConfigurationError("Please set 'edbob.config' in [app:main] section of config "
"to the path of your config file. Lame, but necessary.")
edbob.init('rattail', path)
log.info("using rattail config file: {0}".format(path))
rattail_config = RattailConfig(edbob.config)
settings['rattail_config'] = rattail_config
# Load all Rattail database engines from config, and store in settings
# dict. This is necessary e.g. in the case of a host server, to have
# access to its subordinate store servers.
rattail_engines = get_engines(rattail_config)
settings['rattail_engines'] = rattail_engines
# Configure the database session classes. Note that most of the time we'll
# be using the Tailbone Session, but occasionally (e.g. within batch
# processing threads) we want the Rattail Session. The reason is that
# during normal request processing, the Tailbone Session is preferable as
# it includes Zope Transaction magic. Within an explicitly-spawned thread
# however, this is *not* desirable.
rattail.db.Session.configure(bind=rattail_engines['default'])
tailbone.db.Session.configure(bind=rattail_engines['default'])
# Configure (or not) Continuum versioning.
configure_versioning(rattail_config)
return rattail_config
def provide_postgresql_settings(settings):
"""
Add some PostgreSQL-specific settings to the app config. Specifically,
this enables retrying transactions a second time, in an attempt to
gracefully handle database restarts.
"""
settings.setdefault('tm.attempts', 2) settings.setdefault('tm.attempts', 2)
def make_pyramid_config(settings):
"""
Make a Pyramid config object from the given settings.
"""
config = Configurator(settings=settings) config = Configurator(settings=settings)
# Initialize edbob, dammit.
edbob.init('rattail', os.path.abspath(settings['edbob.config']))
edbob.init_modules(['edbob.time'])
# Configure the primary database session.
engine = engine_from_config(settings)
Session.configure(bind=engine)
Session.configure(extension=ZopeTransactionExtension())
# Configure user authentication / authorization. # Configure user authentication / authorization.
config.set_authentication_policy(SessionAuthenticationPolicy()) config.set_authentication_policy(SessionAuthenticationPolicy())
config.set_authorization_policy(TailboneAuthorizationPolicy()) config.set_authorization_policy(TailboneAuthorizationPolicy())
# Bring in some Pyramid goodies. # Bring in some Pyramid goodies.
config.include('pyramid_beaker') config.include('pyramid_beaker')
config.include('pyramid_mako')
config.include('pyramid_tm') config.include('pyramid_tm')
# Bring in the rest of Tailbone.
config.include('tailbone')
# Configure FormAlchemy. # Configure FormAlchemy.
formalchemy.config.engine = TemplateEngine() formalchemy.config.engine = TemplateEngine()
formalchemy.FieldSet.default_renderers[GPCType] = GPCFieldRenderer formalchemy.FieldSet.default_renderers[GPCType] = GPCFieldRenderer
# Consider PostgreSQL server restart errors to be "retryable." return config
config.add_tween('edbob.pyramid.tweens.sqlerror_tween_factory',
under='pyramid_tm.tm_tween_factory')
return config.make_wsgi_app()
def configure_postgresql(pyramid_config):
"""
Add some PostgreSQL-specific tweaks to the final app config. Specifically,
adds the tween necessary for graceful handling of database restarts.
"""
pyramid_config.add_tween('edbob.pyramid.tweens.sqlerror_tween_factory',
under='pyramid_tm.tm_tween_factory')
def main(global_config, **settings):
"""
This function returns a Pyramid WSGI application.
"""
rattail_config = make_rattail_config(settings)
pyramid_config = make_pyramid_config(settings)
return pyramid_config.make_wsgi_app()