Added support for "hooks" which are like a simpler form of middleware.
This commit is contained in:
44
pecan/hooks.py
Normal file
44
pecan/hooks.py
Normal 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()
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user