Package wtf :: Package ext :: Package db :: Module _decorators
[hide private]
[frames] | no frames]

Source Code for Module wtf.ext.db._decorators

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2010-2012 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 17  """ 
 18  ========== 
 19   DB stuff 
 20  ========== 
 21   
 22  DB stuff. 
 23  """ 
 24  __author__ = u"Andr\xe9 Malo" 
 25  __docformat__ = "restructuredtext en" 
 26   
 27  import sys as _sys 
 28   
 29  from wtf import util as _wtf_util 
 30  from wtf.ext.db import _connection 
31 32 33 -class WTFConnection(object):
34 """ Connection wrapper """ 35 # pylint: disable = W0212, C0111
36 - def __init__(self, dbname, conn):
37 in_transaction = False 38 self.__next_broken = None 39 while isinstance(conn, WTFConnection): 40 dbname = conn.__dbname 41 in_transaction = conn.__in_transaction 42 if not self.__next_broken: 43 self.__next_broken = conn.__mark_broken 44 conn = conn.__conn 45 self.__conn = conn 46 self.__dbname = dbname 47 self.__in_transaction = in_transaction 48 self.__initiated_transaction = False 49 self.__broken = False
50 - def __getattr__(self, name):
51 return getattr(self.__conn, name)
52 - def __mark_broken(self, how, who=None):
53 if who is None: 54 who = set() 55 if id(self) not in who: 56 who.add(id(self)) 57 self.__broken = bool(how) 58 if self.__next_broken: 59 self.__next_broken(how, who)
60 - def begin(self):
61 if not self.__in_transaction: 62 _connection.driver(self.__dbname).begin(self.__conn) 63 self.__mark_broken(False) 64 self.__initiated_transaction = True 65 return self
66 - def commit(self):
67 if self.__initiated_transaction and not self.__broken: 68 _connection.driver(self.__dbname).commit(self.__conn) 69 _connection.driver(self.__dbname).autocommit(self.__conn, True)
70 - def rollback(self):
71 if self.__in_transaction: 72 self.__mark_broken(True) 73 _connection.driver(self.__dbname).rollback(self.__conn) 74 _connection.driver(self.__dbname).autocommit(self.__conn, False)
75
76 77 -def connection(dbname, arg=None, translate_exceptions=True):
78 """ 79 Create decorator to inject SA connection into function 80 81 :Parameters: 82 `dbname` : ``str`` 83 DB name 84 85 `arg` : ``str`` 86 Argument name. If omitted or ``None``, ``'db'`` is used. 87 88 `translate_exceptions` : ``bool`` 89 Translate adapter exceptions to our ones? 90 91 :Return: Decorator function 92 :Rtype: ``callable`` 93 """ 94 if arg is None: 95 arg = 'db' 96 def con(oldval): 97 """ Create connection """ 98 if oldval is None: 99 this_con = _connection.connect(dbname) 100 _connection.driver(dbname).autocommit(this_con, True) 101 return True, WTFConnection(dbname, this_con) 102 return False, WTFConnection(dbname, oldval)
103 104 def inner(func): 105 """ 106 Actual decorator 107 108 :Parameters: 109 `func` : ``callable`` 110 Function to decorate 111 112 :Return: Decorated function 113 :Rtype: ``callable`` 114 """ 115 setarg = _wtf_util.make_setarg(arg, func) 116 117 @_wtf_util.decorating(func) 118 def proxy(*args, **kwargs): 119 """ Proxy """ 120 drv = _connection.driver(dbname) 121 try: 122 (created, opened), args, kwargs = setarg(args, kwargs, con) 123 try: 124 return func(*args, **kwargs) 125 finally: 126 if created: 127 opened.close() 128 except drv.adapter.Error: 129 if translate_exceptions: 130 drv.translate_exception() 131 raise 132 return proxy 133 return inner 134
135 136 -def transaction(arg=None):
137 """ 138 Create decorator to wrap a connection into a transaction 139 140 :Parameters: 141 `arg` : ``str`` 142 Argument name. If omitted or ``None``, ``'db'`` is used. 143 144 :Return: Decorator function 145 :Rtype: ``callable`` 146 """ 147 if arg is None: 148 func, arg = None, 'db' 149 elif callable(arg): 150 func, arg = arg, 'db' 151 else: 152 func = None 153 154 def make_trans(oldval): 155 """ Create transaction """ 156 return False, oldval.begin()
157 158 def inner(func): 159 """ 160 Actual decorator 161 162 :Parameters: 163 `func` : ``callable`` 164 Function to decorate 165 166 :Return: Decorated function 167 :Rtype: ``callable`` 168 """ 169 setarg = _wtf_util.make_setarg(arg, func) 170 171 @_wtf_util.decorating(func) 172 def proxy(*args, **kwargs): 173 """ Proxy """ 174 (_, trans), args, kwargs = setarg(args, kwargs, make_trans) 175 try: 176 res = func(*args, **kwargs) 177 except: # pylint: disable = W0702 178 e = _sys.exc_info() 179 try: 180 trans.rollback() 181 finally: 182 try: 183 raise e[0], e[1], e[2] 184 finally: 185 del e 186 trans.commit() 187 return res 188 return proxy 189 190 if func is not None: 191 return inner(func) 192 return inner 193