summaryrefslogtreecommitdiff
path: root/pecan/hooks.py
diff options
context:
space:
mode:
authorAlfredo Deza <alfredodeza@gmail.com>2011-06-24 15:56:27 -0400
committerAlfredo Deza <alfredodeza@gmail.com>2011-06-24 15:56:27 -0400
commit83fb416542f478aaa70fdb7ac5076a09fe93061c (patch)
tree0647bd3ced048c4c320c898e58d9b4efc0cdeb9b /pecan/hooks.py
parent4ab82d3e3b0d9e327165704847057eed4e62c169 (diff)
downloadpecan-83fb416542f478aaa70fdb7ac5076a09fe93061c.tar.gz
Adds the RequestViewer Hook (from pecan-raw)
Diffstat (limited to 'pecan/hooks.py')
-rw-r--r--pecan/hooks.py137
1 files changed, 133 insertions, 4 deletions
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
+
+