/usr/share/pyshared/paste/transaction.py is in python-paste 1.7.5.1-4.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
# (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.
.. note::
This is experimental, and will change in the future.
"""
from paste.httpexceptions import HTTPException
from wsgilib import catch_errors
class TransactionManagerMiddleware(object):
def __init__(self, application):
self.application = application
def __call__(self, environ, start_response):
environ['paste.transaction_manager'] = manager = Manager()
# This makes sure nothing else traps unexpected exceptions:
environ['paste.throw_errors'] = True
return catch_errors(self.application, environ, start_response,
error_callback=manager.error,
ok_callback=manager.finish)
class Manager(object):
def __init__(self):
self.aborted = False
self.transactions = []
def abort(self):
self.aborted = True
def error(self, exc_info):
self.aborted = True
self.finish()
def finish(self):
for trans in self.transactions:
if self.aborted:
trans.rollback()
else:
trans.commit()
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=None):
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(exc_info=None):
if exc_info:
if isinstance(exc_info[1], HTTPException):
should_commit.append(exc_info[1].code)
if should_commit.pop() < 400:
conn.commit()
else:
try:
conn.rollback()
except:
# TODO: check if rollback has already happened
return
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)
return catch_errors(application, environ, basictrans_start_response,
finalizer, finalizer)
return basic_transaction
__all__ = ['ConnectionFactory', 'BasicTransactionHandler']
if '__main__' == __name__ and False:
from pyPgSQL import PgSQL
factory = ConnectionFactory(PgSQL, database="testing")
conn = factory()
curr = conn.cursor()
curr.execute("SELECT now(), %s" % conn.quote("B'n\\'gles"))
(time, bing) = curr.fetchone()
print bing, time
|