diff options
author | ianb <devnull@localhost> | 2005-12-13 07:00:20 +0000 |
---|---|---|
committer | ianb <devnull@localhost> | 2005-12-13 07:00:20 +0000 |
commit | 4e73bff9da87e35c7154ab1cc923bb4f9d40711d (patch) | |
tree | d2e4c92965398700457280d5829dfaa5cdf5b4fb /paste/transaction.py | |
parent | 55b404e53bc834daf3852069af6de9b1fca4c742 (diff) | |
download | paste-4e73bff9da87e35c7154ab1cc923bb4f9d40711d.tar.gz |
Merged changes from cce branch (r3727:HEAD/4008); the branch is now in sync with trunk
Diffstat (limited to 'paste/transaction.py')
-rw-r--r-- | paste/transaction.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/paste/transaction.py b/paste/transaction.py new file mode 100644 index 0000000..17b434d --- /dev/null +++ b/paste/transaction.py @@ -0,0 +1,79 @@ +# (c) 2005 Clark C. Evans +# This module is part of the Python Paste Project and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php +""" +Middleware related to transactions and database connections. + +At this time it is very basic; but will eventually sprout all that +two-phase commit goodness that I don't need. +""" +from paste.httpexceptions import HTTPError, HTTPException + +class ConnectionFactory(object): + """ + Provides a callable interface for connecting to ADBAPI databases in + a WSGI style (using the environment). More advanced connection + factories might use the REMOTE_USER and/or other environment + variables to make the connection returned depend upon the request. + """ + def __init__(self, module, *args, **kwargs): + #assert getattr(module,'threadsaftey',0) > 0 + self.module = module + self.args = args + self.kwargs = kwargs + + # deal with database string quoting issues + self.quote = lambda s: "'%s'" % s.replace("'","''") + if hasattr(self.module,'PgQuoteString'): + self.quote = self.module.PgQuoteString + + def __call__(self, environ): + conn = self.module.connect(*self.args,**self.kwargs) + conn.__dict__['module'] = self.module + conn.__dict__['quote'] = self.quote + return conn + +def BasicTransactionHandler(application, factory): + """ + Provides a simple mechanism for starting a transaction based on the + factory; and for either committing or rolling back the transaction + depending on the result. It checks for the response's current + status code either through the latest call to start_response; or + through a HTTPException's code. If it is a 100, 200, or 300; the + transaction is committed; otherwise it is rolled back. + """ + + def basic_transaction(environ, start_response): + conn = factory(environ) + environ['paste.connection'] = conn + should_commit = [500] + def finalizer(): + if should_commit.pop() < 400: + conn.commit() + else: + conn.rollback() + conn.close() + def basictrans_start_response(status, headers, exc_info = None): + should_commit.append(int(status.split(" ")[0])) + return start_response(status, headers, exc_info) + try: + for chunk in application(environ, basictrans_start_response): + yield chunk + except Exception, e: + if isinstance(e,HTTPException): + should_commit.append(e.code) + finalizer() + raise + finalizer() + return basic_transaction + +__all__ = ['ConnectionFactory','BasicTransactionHandler'] + +if '__main__' == __name__ and False: + from pyPgSQL import PgSQL + factory = ConnectionFactory(PgSQL,database="testing") + conn = factory(None) + curr = conn.cursor() + curr.execute("SELECT now(), %s" % conn.quote("B'n\\'gles")) + (time,bing) = curr.fetchone() + print bing, time |