Parent: [9b2830] (diff)

Child: [e18ac4] (diff)

Download this file

base.py    143 lines (115 with data), 4.6 kB

  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
# -*- coding: utf-8 -*-
"""The base Controller API."""
from tg import TGController, tmpl_context, config
from tg.render import render
from pylons.i18n import _, ungettext, N_
from pylons import c, g
from tw.api import WidgetBunch
from paste.deploy.converters import asbool
import pkg_resources
from webob import exc
import ming
from threading import local
__all__ = ['BaseController']
class Environ(object):
_local = local()
def set_environment(self, environ):
self._local.environ = environ
def __getitem__(self, name):
try:
return self._local.environ[name]
except AttributeError:
self._local.environ = {}
raise KeyError, name
def __setitem__(self, name, value):
try:
self._local.environ[name] = value
except AttributeError:
self._local.environ = {name:value}
def __delitem__(self, name):
try:
del self._local.environ[name]
except AttributeError:
self._local.environ = {}
raise KeyError, name
def __getattr__(self, name):
return getattr(self._local.environ, name)
def __repr__(self):
return repr(self._local.environ)
environ = _environ = Environ()
class BaseController(TGController):
"""
Base class for the controllers in the application.
Your web application should have one of these. The root of
your application is used to compute URLs used by your app.
"""
def __call__(self, environ, start_response):
"""This is the basic WSGI callable that wraps and dispatches forge controllers.
It peforms a number of functions:
* displays the forge index page
* sets up and cleans up the Ming/MongoDB Session
* persists all Ming object changes to Mongo
"""
_environ.set_environment(environ)
if asbool(environ.get('HTTP_X_SFINC_SSL', 'false')):
environ['wsgi.url_scheme'] = 'https'
app = self._wsgi_handler(environ)
if app is None:
"""Invoke the Controller"""
# TGController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
app = lambda e,s: TGController.__call__(self, e, s)
magical_c = MagicalC(c._current_obj())
try:
c._push_object(magical_c)
self._setup_request()
result = app(environ, start_response)
if not isinstance(result, list):
return self._cleanup_iterator(result)
else:
self._cleanup_request()
return result
except exc.HTTPRedirection:
self._cleanup_request()
raise
except:
ming.orm.ormsession.ThreadLocalORMSession.close_all()
raise
finally:
c._pop_object(magical_c)
def _wsgi_handler(self, environ):
import pyforge.model as model
host = environ['HTTP_HOST'].lower()
if host == config['oembed.host']:
return OEmbedController()
neighborhood = model.Neighborhood.query.get(url_prefix='//' + host + '/')
if neighborhood:
return HostNeighborhoodController(neighborhood.name, neighborhood.shortname_prefix)
if environ['PATH_INFO'].startswith('/_wsgi_/'):
for ep in pkg_resources.iter_entry_points('pyforge'):
App = ep.load()
if App.wsgi and App.wsgi.handles(environ): return App.wsgi
def _setup_request(self):
'''Responsible for setting all the values we need to be set on pylons.c'''
raise NotImplementedError, '_setup_request'
def _cleanup_request(self):
ming.orm.ormsession.ThreadLocalORMSession.flush_all()
ming.orm.ormsession.ThreadLocalORMSession.close_all()
class MagicalC(object):
'''Magically saves various attributes to the environ'''
_saved_attrs = set(['project', 'app', 'queued_messages'])
def __init__(self, old_c):
self._old_c = old_c
def __getattr__(self, name):
return getattr(self._old_c, name)
def __setattr__(self, name, value):
if name in MagicalC._saved_attrs:
environ['allura.' + name] = value
if name != '_old_c':
setattr(self._old_c, name, value)
object.__setattr__(self, name, value)
def __delattr__(self, name):
if name != '_old_c':
delattr(self._old_c, name)
object.__delattr__(self, name)