Context objects now use a contextmanager (and update gmg shell to use it)
authorChristopher Allan Webber <cwebber@dustycloud.org>
Sun, 30 Nov 2014 22:14:05 +0000 (16:14 -0600)
committerChristopher Allan Webber <cwebber@dustycloud.org>
Wed, 3 Dec 2014 21:40:57 +0000 (15:40 -0600)
This means that we have a really convenient way to make sure that you
have a context/request that threads its way through the application,
where everything needed gets "shut down" appropriately by the end.

You always get a context object via a context manager!  And by the time
you're done with it, things should be cleaned up.

mediagoblin/app.py
mediagoblin/gmg_commands/shell.py

index c04585961f8066260c6695bbd0519442ec22dddf..3142224d963f5271f77e03cedbb19a263c8c5e02 100644 (file)
@@ -16,6 +16,7 @@
 
 import os
 import logging
+from contextlib import contextmanager
 
 from mediagoblin.routing import get_url_map
 from mediagoblin.tools.routing import endpoint_to_controller
@@ -172,6 +173,7 @@ class MediaGoblinApp(object):
         self.meddleware = [common.import_component(m)(self)
                            for m in meddleware.ENABLED_MEDDLEWARE]
 
+    @contextmanager
     def gen_context(self, ctx=None):
         """
         Attach contextual information to request, or generate a context object
@@ -180,6 +182,13 @@ class MediaGoblinApp(object):
         information (current translation, etc) are attached to this
         object.
         """
+        if DISABLE_GLOBALS:
+            with self.db_manager.session_scope() as db:
+                yield self._gen_context(db, ctx)
+        else:
+            yield self._gen_context(self.db, ctx)
+
+    def _gen_context(self, db, ctx):
         # Set up context
         # --------------
 
@@ -194,8 +203,7 @@ class MediaGoblinApp(object):
         # Also attach a few utilities from request.app for convenience?
         ctx.app = self
 
-        if not DISABLE_GLOBALS:
-            ctx.db = self.db
+        ctx.db = db
 
         ctx.staticdirect = self.staticdirector
 
@@ -264,8 +272,10 @@ class MediaGoblinApp(object):
             environ.pop('HTTPS')
 
         ## Attach utilities to the request object
-        request = self.gen_context(request)
+        with self.gen_context(request) as request:
+            return self._finish_call_backend(request, environ, start_response)
 
+    def _finish_call_backend(self, request, environ, start_response):
         # Log user out if authentication_disabled
         no_auth_logout(request)
 
@@ -305,11 +315,7 @@ class MediaGoblinApp(object):
 
         # get the Http response from the controller
         try:
-            if DISABLE_GLOBALS:
-                with self.db_manager.session_scope() as request.db:
-                    response = controller(request)
-            else:
-                response = controller(request)
+            response = controller(request)
         except HTTPException as e:
             response = render_http_exception(
                 request, e, e.get_description(environ))
index 70e1140449d0ef2027a28c32f18aa7a66bc3d42f..4d3ec241ba6eb4215d91abc1c41c3d180e51517a 100644 (file)
@@ -35,7 +35,8 @@ if DISABLE_GLOBALS:
         "----------------------\n"
         "Available vars:\n"
         " - app: instantiated mediagoblin application\n"
-        " - db: database session\n")
+        " - db: database session\n"
+        " - ctx: context object\n")
 else:
     SHELL_BANNER = (
         "GNU MediaGoblin shell!\n"
@@ -43,7 +44,8 @@ else:
         "Available vars:\n"
         " - app: instantiated mediagoblin application\n"
         " - mg_globals: mediagoblin.globals\n"
-        " - db: database instance\n")
+        " - db: database instance\n"
+        " - ctx: context object\n")
 
 def py_shell(**user_namespace):
     """
@@ -75,11 +77,12 @@ def shell(args):
     """
     app = commands_util.setup_app(args)
 
-    def run_shell(db):
+    def run_shell(db, ctx):
         user_namespace = {
             'mg_globals': mg_globals,
             'app': app,
-            'db': db}
+            'db': db,
+            "ctx": ctx}
 
         if args.ipython:
             ipython_shell(**user_namespace)
@@ -88,8 +91,6 @@ def shell(args):
             if not ipython_shell(**user_namespace):
                 py_shell(**user_namespace)
 
-    if DISABLE_GLOBALS:
-        with app.db_manager.session_scope() as db:
-            run_shell(db)
-    else:
-        run_shell(mg_globals.database)
+    with app.gen_context() as ctx:
+        db = ctx.db
+        run_shell(db, ctx)