From 83fb416542f478aaa70fdb7ac5076a09fe93061c Mon Sep 17 00:00:00 2001 From: Alfredo Deza Date: Fri, 24 Jun 2011 15:56:27 -0400 Subject: Adds the RequestViewer Hook (from pecan-raw) --- pecan/hooks.py | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 4 deletions(-) (limited to 'pecan/hooks.py') diff --git a/pecan/hooks.py b/pecan/hooks.py index c1d0037..4343174 100644 --- a/pecan/hooks.py +++ b/pecan/hooks.py @@ -1,8 +1,9 @@ -from inspect import getmembers -from webob.exc import HTTPFound - -from util import iscontroller, _cfg +import sys +from inspect import getmembers +from webob.exc import HTTPFound +from util import iscontroller, _cfg +from routing import lookup_controller __all__ = ['PecanHook', 'TransactionHook', 'HookController'] @@ -164,3 +165,131 @@ class TransactionHook(PecanHook): for action in actions: action() self.clear() + +class RequestViewerHook(PecanHook): + ''' + Returns some information about what is going on in a single request. It + accepts specific items to report on but uses a default list of items when + none are passed in. Based on the requested ``url``, items can also be + blacklisted. + Configuration is flexible, can be passed in (or not) and can contain some or + all the keys supported. + + ``items`` + --------- + This key holds the items that this hook will display. When this key is passed + only the items in the list will be used. + Valid items are *any* item that the ``request`` object holds, by default it uses + the following: + + * url + * method + * response + * method + * context + * params + * hooks + + .. :note:: + This key should always use a ``list`` of items to use. + + ``blacklist`` + ------------- + This key holds items that will be blacklisted based on ``url``. If there is a need + to ommit urls that start with `/javascript`, then this key would look like:: + + 'blacklist': ['/javascript'] + + As many blacklisting items can be contained in the list. The hook will + verify that the url is not starting with items in this list to display + results, otherwise it will get ommited. + + .. :note:: + This key should always use a ``list`` of items to use. + + ''' + + available = [ + 'url', + 'method', + 'response', + 'method', + 'context', + 'params', + 'hooks', + ] + + def __init__(self, config=None, writer=sys.stdout): + ''' + :param config: A (optional) dictionary that can hold ``items`` and/or + ``blacklist`` keys. + :param writer: The stream writer to use. Can redirect output to other + streams as long as the passed in stream has a ``write`` + callable method. + ''' + if not config: + self.config = {'items' : self.available} + else: + self.config = config + self.writer = writer + self.items = self.config.get('items', self.available) + self.blacklist = self.config.get('blacklist', []) + + def after(self, state): + responses = { + 'method' : lambda self, state: state.request.method, + 'response' : lambda self, state: state.response.status, + 'url' : lambda self, state: state.request.path, + 'controller' : lambda self, state: self.get_controller(state), + 'context' : lambda self, state: state.request.context, + 'params' : lambda self, state: state.request.str_params.items(), + 'hooks' : lambda self, state: self.format_hooks(state.app.hooks), + } + + is_available = [ + i for i in self.items + if i in self.available or hasattr(state.request, i) + ] + out = [] + will_skip = [i for i in self.blacklist if state.request.path.startswith(i)] + + if will_skip: + return + + for request_info in is_available: + try: + value = responses.get(request_info) + if not value: + value = getattr(state.request, request_info) + else: + value = value(self, state) + out.append("%-12s - %s\n" % (request_info, value)) + except Exception, e: + out.append("%-12s - %s\n" % (request_info, e)) + + self.writer.write(''.join(out)) + self.writer.write('\n\n') + + def get_controller(self, state): + ''' + Retrieves the actual controller name from the application + Specific to Pecan (not available in the request object) + ''' + path = state.request.pecan['routing_path'].split('/')[1:] + controller, reminder = lookup_controller(state.app.root, path) + return controller.__str__().split()[2] + + def format_hooks(self, hooks): + ''' + Tries to format the hook objects to be more readable + Specific to Pecan (not available in the request object) + ''' + try: + str_hooks = [str(i).split()[0].strip('<') for i in hooks] + f_hooks = [i.split('.')[-1] for i in str_hooks if '.' in i] + except: + f_hooks = hooks + + return f_hooks + + -- cgit v1.2.1