From 771f30092f2aec2aea05d07a75242a80905cab95 Mon Sep 17 00:00:00 2001 From: Christophe de Vienne Date: Wed, 18 Jan 2012 17:57:58 +0100 Subject: [PATCH] Add a per-call transaction management --- doc/changes.rst | 2 ++ wsme/root.py | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/doc/changes.rst b/doc/changes.rst index 58a48b4..c5a393c 100644 --- a/doc/changes.rst +++ b/doc/changes.rst @@ -4,6 +4,8 @@ Changes next ---- +* Per-call database transaction handling. + * :class:`Unset` is now imported in the wsme module * Attributes of complex types can now have a different name in diff --git a/wsme/root.py b/wsme/root.py index 55cdc90..8ced5c5 100644 --- a/wsme/root.py +++ b/wsme/root.py @@ -25,22 +25,56 @@ html_body = """ """ +class DummyTransaction: + def commit(self): + pass + + def abort(self): + pass + + class WSRoot(object): """ Root controller for webservices. :param protocols: A list of protocols to enable (see :meth:`addprotocol`) :param webpath: The web path where the webservice is published. + + :type transaction: A `transaction + `_-like + object or ``True``. + :param transaction: If specified, a transaction will be created and + handled on a per-call base. + + This option *can* be enabled along with `repoze.tm2 + `_ + (it will only make it void). + + If ``True``, the default :mod:`transaction` + module will be imported and used. + """ - def __init__(self, protocols=[], webpath=''): + def __init__(self, protocols=[], webpath='', transaction=None): self._debug = True self._webpath = webpath self.protocols = [] + + self.transaction = transaction + if self.transaction is True: + import transaction + self.transaction = transaction + for protocol in protocols: self.addprotocol(protocol) self._api = None + def begin(self): + if self.transaction: + return self.transaction.begin() + else: + return DummyTransaction() + def addprotocol(self, protocol, **options): """ Enable a new protocol on the controller. @@ -104,7 +138,13 @@ class WSRoot(object): if arg.mandatory and arg.name not in kw: raise exc.MissingArgument(arg.name) - result = context.func(**kw) + txn = self.begin() + try: + result = context.func(**kw) + txn.commit() + except: + txn.abort() + raise if context.funcdef.protocol_specific \ and context.funcdef.return_type is None: