Add context generator: first step towards removing globals from the application
This allows you to generate a "context" object that gets threaded throughout the application... this object should keep track of the same things that currently we use global variables for.
This commit is contained in:
parent
03ff0b368e
commit
d71499004f
@ -46,6 +46,19 @@ from mediagoblin.auth.tools import check_auth_enabled, no_auth_logout
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Context(object):
|
||||
"""
|
||||
MediaGoblin context object.
|
||||
|
||||
If a web request is being used, a Flask Request object is used
|
||||
instead, otherwise (celery tasks, etc), attach things to this
|
||||
object.
|
||||
|
||||
Usually appears as "ctx" in utilities as first argument.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class MediaGoblinApp(object):
|
||||
"""
|
||||
WSGI application of MediaGoblin
|
||||
@ -149,15 +162,79 @@ class MediaGoblinApp(object):
|
||||
self.meddleware = [common.import_component(m)(self)
|
||||
for m in meddleware.ENABLED_MEDDLEWARE]
|
||||
|
||||
def gen_context(self, ctx=None):
|
||||
"""
|
||||
Attach contextual information to request, or generate a context object
|
||||
|
||||
This avoids global variables; various utilities and contextual
|
||||
information (current translation, etc) are attached to this
|
||||
object.
|
||||
"""
|
||||
# Set up context
|
||||
# --------------
|
||||
|
||||
# Is a context provided?
|
||||
if ctx is not None:
|
||||
# Do special things if this is a request
|
||||
if isinstance(ctx, Request):
|
||||
ctx = self._request_only_gen_context(ctx)
|
||||
|
||||
else:
|
||||
ctx = Context()
|
||||
|
||||
# Attach utilities
|
||||
# ----------------
|
||||
|
||||
# Attach self as request.app
|
||||
# Also attach a few utilities from request.app for convenience?
|
||||
ctx.app = self
|
||||
|
||||
ctx.db = self.db
|
||||
ctx.staticdirect = self.staticdirector
|
||||
|
||||
return ctx
|
||||
|
||||
def _request_only_gen_context(self, request):
|
||||
"""
|
||||
Requests get some extra stuff attached to them that's not relevant
|
||||
otherwise.
|
||||
"""
|
||||
# Do we really want to load this via middleware? Maybe?
|
||||
request.session = self.session_manager.load_session_from_cookie(request)
|
||||
|
||||
request.locale = translate.get_locale_from_request(request)
|
||||
|
||||
# This should be moved over for certain, but how to deal with
|
||||
# request.locale?
|
||||
request.template_env = template.get_jinja_env(
|
||||
self.template_loader, request.locale)
|
||||
|
||||
mg_request.setup_user_in_request(request)
|
||||
|
||||
## Routing / controller loading stuff
|
||||
request.map_adapter = self.url_map.bind_to_environ(request.environ)
|
||||
|
||||
def build_proxy(endpoint, **kw):
|
||||
try:
|
||||
qualified = kw.pop('qualified')
|
||||
except KeyError:
|
||||
qualified = False
|
||||
|
||||
return request.map_adapter.build(
|
||||
endpoint,
|
||||
values=dict(**kw),
|
||||
force_external=qualified)
|
||||
|
||||
request.urlgen = build_proxy
|
||||
|
||||
return request
|
||||
|
||||
def call_backend(self, environ, start_response):
|
||||
request = Request(environ)
|
||||
|
||||
# Compatibility with django, use request.args preferrably
|
||||
request.GET = request.args
|
||||
|
||||
## Routing / controller loading stuff
|
||||
map_adapter = self.url_map.bind_to_environ(request.environ)
|
||||
|
||||
# By using fcgi, mediagoblin can run under a base path
|
||||
# like /mediagoblin/. request.path_info contains the
|
||||
# path inside mediagoblin. If the something needs the
|
||||
@ -175,41 +252,14 @@ class MediaGoblinApp(object):
|
||||
environ.pop('HTTPS')
|
||||
|
||||
## Attach utilities to the request object
|
||||
# Do we really want to load this via middleware? Maybe?
|
||||
session_manager = self.session_manager
|
||||
request.session = session_manager.load_session_from_cookie(request)
|
||||
# Attach self as request.app
|
||||
# Also attach a few utilities from request.app for convenience?
|
||||
request.app = self
|
||||
|
||||
request.db = self.db
|
||||
request.staticdirect = self.staticdirector
|
||||
|
||||
request.locale = translate.get_locale_from_request(request)
|
||||
request.template_env = template.get_jinja_env(
|
||||
self.template_loader, request.locale)
|
||||
|
||||
def build_proxy(endpoint, **kw):
|
||||
try:
|
||||
qualified = kw.pop('qualified')
|
||||
except KeyError:
|
||||
qualified = False
|
||||
|
||||
return map_adapter.build(
|
||||
endpoint,
|
||||
values=dict(**kw),
|
||||
force_external=qualified)
|
||||
|
||||
request.urlgen = build_proxy
|
||||
request = self.gen_context(request)
|
||||
|
||||
# Log user out if authentication_disabled
|
||||
no_auth_logout(request)
|
||||
|
||||
mg_request.setup_user_in_request(request)
|
||||
|
||||
request.controller_name = None
|
||||
try:
|
||||
found_rule, url_values = map_adapter.match(return_rule=True)
|
||||
found_rule, url_values = request.map_adapter.match(return_rule=True)
|
||||
request.matchdict = url_values
|
||||
except RequestRedirect as response:
|
||||
# Deal with 301 responses eg due to missing final slash
|
||||
@ -225,6 +275,7 @@ class MediaGoblinApp(object):
|
||||
# used for lazy context modification
|
||||
request.controller_name = found_rule.endpoint
|
||||
|
||||
## TODO: get rid of meddleware, turn it into hooks only
|
||||
# pass the request through our meddleware classes
|
||||
try:
|
||||
for m in self.meddleware:
|
||||
@ -255,7 +306,8 @@ class MediaGoblinApp(object):
|
||||
response = render_http_exception(
|
||||
request, e, e.get_description(environ))
|
||||
|
||||
session_manager.save_session_to_cookie(request.session,
|
||||
self.session_manager.save_session_to_cookie(
|
||||
request.session,
|
||||
request, response)
|
||||
|
||||
return response(environ, start_response)
|
||||
|
Loading…
x
Reference in New Issue
Block a user