Commits

Robert Brewer committed 0ed886e

New HandlerWrapperTool.

Comments (0)

Files changed (2)

cherrypy/_cptools.py

                                       priority=p, **conf)
 
 
+class HandlerWrapperTool(Tool):
+    """Tool which wraps request.handler in a provided wrapper function.
+    
+    The 'newhandler' arg must be a handler wrapper function that takes a
+    'next_handler' argument, plus *args and **kwargs. Like all page handler
+    functions, it must return an iterable for use as cherrypy.response.body.
+    
+    For example, to allow your 'inner' page handlers to return dicts
+    which then get interpolated into a template:
+    
+        def interpolator(next_handler, *args, **kwargs):
+            filename = cherrypy.request.config.get('template')
+            cherrypy.response.template = env.get_template(filename)
+            response_dict = next_handler(*args, **kwargs)
+            return cherrypy.response.template.render(**response_dict)
+        cherrypy.tools.jinja = HandlerWrapperTool(interpolator)
+    """
+    
+    def __init__(self, newhandler, point='before_handler', name=None, priority=50):
+        self.newhandler = newhandler
+        self._point = point
+        self._name = name
+        self._priority = priority
+    
+    def callable(self):
+        innerfunc = cherrypy.request.handler
+        def wrap(*args, **kwargs):
+            return self.newhandler(innerfunc, *args, **kwargs)
+        cherrypy.request.handler = wrap
+
+
 class ErrorTool(Tool):
     """Tool which is used to replace the default request.error_response."""
     

cherrypy/test/test_tools.py

             r.body = [chr(ord(x) + scale) for x in r.body]
     cherrypy.tools.rotator = cherrypy.Tool('before_finalize', Rotator())
     
+    def stream_handler(next_handler, *args, **kwargs):
+        cherrypy.response.output = o = StringIO.StringIO()
+        try:
+            response = next_handler(*args, **kwargs)
+            # Ignore the response and return our accumulated output instead.
+            return o.getvalue()
+        finally:
+            o.close()
+    cherrypy.tools.streamer = cherrypy._cptools.HandlerWrapperTool(stream_handler)
+    
     class Root:
         def index(self):
             return "Howdy earth!"
         index.exposed = True
         
+        def tarfile(self):
+            cherrypy.response.output.write('I am ')
+            cherrypy.response.output.write('a tarfile')
+        tarfile.exposed = True
+        tarfile._cp_config = {'tools.streamer.on': True}
+        
         def euro(self):
             hooks = list(cherrypy.request.hooks['before_finalize'])
             hooks.sort()
         '/decorated_euro/subpath': {
             'tools.gzip.priority': 10,
         },
+        # Handler wrappers
+        '/tarfile': {'tools.streamer.on': True}
     }
     app = cherrypy.tree.mount(root, config=conf)
     app.request_class.namespaces['myauth'] = myauthtools
                               ("Content-Type", "text/plain")],
                      method="POST", body=content)
         self.assertBody(content)
+    
+    def testHandlerWrapperTool(self):
+        self.getPage("/tarfile")
+        self.assertBody("I am a tarfile")
 
 
 if __name__ == '__main__':
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.