Added support for "hooks" which are like a simpler form of middleware.

This commit is contained in:
Jonathan LaCour
2010-09-28 16:06:23 -04:00
parent 1aca32f9ff
commit 6cacf43415
2 changed files with 82 additions and 23 deletions

44
pecan/hooks.py Normal file
View File

@@ -0,0 +1,44 @@
class PecanHook(object):
def before(self, state):
pass
def after(self, state):
pass
def on_error(self, state):
pass
class TransactionHook(PecanHook):
def __init__(self, start, start_ro, commit, rollback, clear):
self.start = start
self.start_ro = start_ro
self.commit = commit
self.rollback = rollback
self.clear = clear
def is_transactional(self, state):
if state.request.method not in ('GET', 'HEAD'):
return True
return False
def before(self, state):
state.request.error = False
if self.is_transactional(state):
state.request.transactional = True
self.start()
else:
state.request.transactional = False
self.start_ro()
def on_error(self, state):
state.request.error = True
self.rollback()
def after(self, state):
if state.request.transactional:
if state.request.error:
self.rollback()
else:
self.commit()
self.clear()

View File

@@ -23,10 +23,11 @@ def override_template(template):
class Pecan(object):
def __init__(self, root, renderers=renderers, default_renderer='genshi'):
def __init__(self, root, renderers=renderers, default_renderer='genshi', hooks=[]):
self.root = root
self.renderers = renderers
self.default_renderer = default_renderer
self.hooks = hooks
self.translate = string.maketrans(
string.punctuation,
'_' * len(string.punctuation)
@@ -109,7 +110,12 @@ class Pecan(object):
response.status = 404
return response(environ, start_response)
# get the result from the controller
# handle "before" hooks
for hook in self.hooks:
hook.before(state)
# get the result from the controller, properly handling wrap hooks
try:
result = controller(**dict(state.request.str_params))
# pull the template out based upon content type
@@ -131,7 +137,16 @@ class Pecan(object):
response = Response(result)
if content_type:
response.content_type = content_type
del state.request
except Exception, e:
# handle "error" hooks
for hook in self.hooks:
hook.on_error(state, e)
raise
else:
# handle "after" hooks
for hook in self.hooks:
hook.after(state)
return response(environ, start_response)
finally:
del state.request