zmc
2023-08-08 e792e9a60d958b93aef96050644f369feb25d61b
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
U
M±dåfã@sˆdZddlZddlmZz eefZWnek
r<eZYnXGdd„deƒZ    Gdd„de    ƒZ
dd
d „Z Gd d „d ƒZ Gdd„dƒZ dS)aå SteadyDB - hardened DB-API 2 connections.
 
Implements steady connections to a database based on an
arbitrary DB-API 2 compliant database interface module.
 
The connections are transparently reopened when they are
closed or the database connection has been lost or when
they are used more often than an optional usage limit.
Database cursors are transparently reopened as well when
the execution of a database operation cannot be performed
due to a lost connection.  Only if the connection is lost
after the execution, when rows are already fetched from the
database, this will give an error and the cursor will not
be reopened automatically, because there is no reliable way
to recover the state of the cursor in such a situation.
Connections which have been marked as being in a transaction
with a begin() call will not be silently replaced either.
 
A typical situation where database connections are lost
is when the database server or an intervening firewall is
shutdown and restarted for maintenance reasons.  In such a
case, all database connections would become unusable, even
though the database service may be already available again.
 
The "hardened" connections provided by this module will
make the database connections immediately available again.
 
This approach results in a steady database connection that
can be used by PooledDB or PersistentDB to create pooled or
persistent connections to a database in a threaded environment
such as the application server of "Webware for Python."
Note, however, that the connections themselves may not be
thread-safe (depending on the used DB-API module).
 
For the Python DB-API 2 specification, see:
    https://www.python.org/dev/peps/pep-0249/
For information on Webware for Python, see:
    https://webwareforpython.github.io/w4py/
 
Usage:
 
You can use the connection constructor connect() in the same
way as you would use the connection constructor of a DB-API 2
module if you specify the DB-API 2 module to be used as the
first parameter, or alternatively you can specify an arbitrary
constructor function returning new DB-API 2 compliant connection
objects as the first parameter.  Passing just a function allows
implementing failover mechanisms and load balancing strategies.
 
You may also specify a usage limit as the second parameter
(set it to None if you prefer unlimited usage), an optional
list of commands that may serve to prepare the session as a
third parameter, the exception classes for which the failover
mechanism shall be applied, and you can specify whether is is
allowed to close the connection (by default this is true).
When the connection to the database is lost or has been used
too often, it will be transparently reset in most situations,
without further notice.
 
    import pgdb  # import used DB-API 2 module
    from dbutils.steady_db import connect
    db = connect(pgdb, 10000, ["set datestyle to german"],
        host=..., database=..., user=..., ...)
    ...
    cursor = db.cursor()
    ...
    cursor.execute('select ...')
    result = cursor.fetchall()
    ...
    cursor.close()
    ...
    db.close()
 
 
Ideas for improvement:
 
* Alternatively to the maximum number of uses,
  implement a maximum time to live for connections.
* Optionally log usage and loss of connection.
 
 
Copyright, credits and license:
 
* Contributed as supplement for Webware for Python and PyGreSQL
  by Christoph Zwerschke in September 2005
* Allowing creator functions as first parameter as in SQLAlchemy
  suggested by Ezio Vernacotola in December 2006
 
Licensed under the MIT license.
éNé)Ú __version__c@seZdZdZdS)Ú SteadyDBErrorzGeneral SteadyDB error.N©Ú__name__Ú
__module__Ú __qualname__Ú__doc__©r
r
úHd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\dbutils/steady_db.pyrfsrc@seZdZdZdS)Ú InvalidCursorzDatabase cursor is invalid.Nrr
r
r
r r jsr TcOst||||||f|ž|ŽS)a–A tough version of the connection constructor of a DB-API 2 module.
 
    creator: either an arbitrary function returning new DB-API 2 compliant
        connection objects or a DB-API 2 compliant database module
    maxusage: maximum usage limit for the underlying DB-API 2 connection
        (number of database operations, 0 or None means unlimited usage)
        callproc(), execute() and executemany() count as one operation.
        When the limit is reached, the connection is automatically reset.
    setsession: an optional list of SQL commands that may serve to prepare
        the session, e.g. ["set datestyle to german", "set time zone mez"]
    failures: an optional exception class or a tuple of exception classes
        for which the failover mechanism shall be applied, if the default
        (OperationalError, InternalError) is not adequate
    ping: determines when the connection should be checked with ping()
        (0 = None = never, 1 = default = when _ping_check() is called,
        2 = whenever a cursor is created, 4 = when a query is executed,
        7 = always, and all other bit combinations of these values)
    closeable: if this is set to false, then closing the connection will
        be silently ignored, but by default the connection can be closed
    args, kwargs: the parameters that shall be passed to the creator
        function or the connection constructor of the DB-API 2 module
    )ÚSteadyDBConnection)ÚcreatorÚmaxusageÚ
setsessionÚfailuresÚpingÚ    closeableÚargsÚkwargsr
r
r Úconnectnsþþþrc@s¼eZdZdZeZd.dd„Zdd„Zd    d
„Zd d „Z    d/d d„Z
dd„Z dd„Z d0dd„Z d1dd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Zd(d)„Zd*d+„Zd,d-„ZdS)2r z*A "tough" version of DB-API 2 connections.NrTc    Osžd|_d|_z|j|_||_Wn~tk
rœ||_z |j|_WnVtk
r–z"tj|j    |_|jj|krpt‚Wntt
fk
rd|_YnXYnXYnXz |j |_ Wn>tk
rèz|jj |_ Wntk
râd|_ YnXYnXt |jƒstd|fƒ‚|dkrd}t|tƒs&tdƒ‚||_||_|dk    r\t|tƒs\t|tƒs\tdƒ‚||_t|tƒrr|nd|_||_|||_|_| | ¡¡dS)z%Create a "tough" DB-API 2 connection.NTz %r is not a connection provider.rz$'maxusage' must be an integer value.z)'failures' must be a tuple of exceptions.)Ú_conÚ_closedrÚ_creatorÚ_dbapiÚAttributeErrorÚdbapiÚsysÚmodulesrÚKeyErrorÚ threadsafetyÚ _threadsafetyÚcallableÚ    TypeErrorÚ
isinstanceÚbaseintÚ    _maxusageÚ_setsession_sqlÚtupleÚ
issubclassÚ    ExceptionÚ    _failuresÚintÚ_pingÚ
_closeableÚ_argsÚ_kwargsÚ_storeÚ_create)    Úselfrrrrrrrrr
r
r Ú__init__‘sV
 
  ÿÿzSteadyDBConnection.__init__cCs|S)z4Enter the runtime context for the connection object.r
©r3r
r
r Ú    __enter__ÀszSteadyDBConnection.__enter__cGs:|ddkr.|ddkr.|ddkr.| ¡n| ¡dS)z„Exit the runtime context for the connection object.
 
        This does not close the connection, but it ends a transaction.
        rNré)ÚcommitÚrollback©r3Úexcr
r
r Ú__exit__Äs$
zSteadyDBConnection.__exit__cCsÞ|j|j|jŽ}zzz|jj|jkr(t‚Wn>tk
rjz
|j}Wntk
r`d}YnX|rÊz tj||_t    |jjƒs„t‚Wntt
fk
ržYnXqf|  d¡}|dkr¼d}qb|d|…}qbz |j j}Wntk
rîd}YnX|r`z"tj||_t    |jjƒst‚Wntt
fk
r2YnXqf|  d¡}|dkrRd}qð|d|…}qðd|_YnX|j dkrÂz|jj|_ Wn:tk
rÀz |j|_ Wntk
rºYnXYnX|jdkr\z|jj |jjf|_Wnvtk
rZz|jj |jjf|_WnHtk
rTz|j |jf|_Wntk
rNtdƒ‚YnXYnXYnXt|jtƒrx|jd|_n|j|_| |¡WnLtk
rØ}z,z | ¡Wntk
rÂYnX|‚W5d}~XYnX|S)z3Create a new connection using the creator function.NÚ.rzNCould not determine failure exceptions (please set failures or creator.dbapi).)rr/r0rrrrrrr"rÚrfindZOperationalErrorr!r r+Z InternalErrorr$r(Ú_failureÚ _setsessionr*Úclose)r3ÚconÚmodÚiÚerrorr
r
r r2Îsš
 
 
 
 
 
 
     þ
þ
ÿ
ÿ zSteadyDBConnection._createcCs>|dkr|j}|jr:| ¡}|jD]}| |¡q"| ¡dS)z1Execute the SQL commands for session preparation.N)rr'ÚcursorÚexecuterA)r3rBrFZsqlr
r
r r@'s
 zSteadyDBConnection._setsessioncCs||_d|_d|_d|_dS)z/Store a database connection for subsequent use.FrN)rÚ _transactionrÚ_usage)r3rBr
r
r r11szSteadyDBConnection._storecCs:|js6z|j ¡Wntk
r(YnXd|_d|_dS)z§Close the tough connection.
 
        You can always close a tough connection with this method
        and it will not complain if you close it more than once.
        FTN)rrrAr*rHr5r
r
r Ú_close8szSteadyDBConnection._closeFcCs6|js2|s|jr2z | ¡Wntk
r0YnXdS)zfReset a tough connection.
 
        Rollback if forced or the connection was in a transaction.
        N)rrHr9r*)r3Úforcer
r
r Ú_resetFs
 zSteadyDBConnection._resetc CsÞ||j@rÚz4z|j d¡}Wntk
r:|j ¡}YnXWn@ttttfk
rhd|_d}d}Yn,tk
r~d}YnX|dkrŒd}|r”d}|rÖ|jsÖz |     ¡}Wntk
r¾YnX| 
¡|  |¡d}|SdS)aCheck whether the connection is still alive using ping().
 
        If the the underlying connection is not active and the ping
        parameter is set accordingly, the connection will be recreated
        unless the connection is currently inside a transaction.
        FrNT) r-rrr#rÚ
IndexErrorÚ
ValueErrorr*rHr2rJr1)r3rZ    reconnectÚaliverBr
r
r Ú _ping_checkQs2
 
 
 
zSteadyDBConnection._ping_checkcCs|jdkrtdƒ‚|jS)z8Return the underlying DB-API 2 module of the connection.Nz?Could not determine DB-API 2 module (please set creator.dbapi).)rrr5r
r
r rts
 
ÿzSteadyDBConnection.dbapicCs&|jdkr |jdkrtdƒ‚dS|jS)z1Return the thread safety level of the connection.NzTCould not determine threadsafety (please set creator.dbapi or creator.threadsafety).r)r!rrr5r
r
r r |s
 
ÿzSteadyDBConnection.threadsafetycCs"|jr| ¡n|jr| ¡dS)a]Close the tough connection.
 
        You are allowed to close a tough connection by default
        and it will not complain if you close it more than once.
 
        You can disallow closing connections by setting
        the closeable parameter to something false.  In this case,
        closing tough connections will be silently ignored.
        N)r.rJrHrLr5r
r
r rA†s
 
zSteadyDBConnection.closecOs6d|_z |jj}Wntk
r&Yn X|||ŽdS)aHIndicate the beginning of a transaction.
 
        During a transaction, connections won't be transparently
        replaced, and all errors will be raised to the application.
 
        If the underlying driver supports this method, it will be called
        with the given parameters (e.g. for distributed transactions).
        TN)rHrÚbeginr)r3rrrQr
r
r rQ•s      zSteadyDBConnection.beginc Csvd|_z|j ¡Wn\|jk
rp}z<z | ¡}Wntk
rHYnX| ¡| |¡|‚W5d}~XYnXdS)zCommit any pending transaction.FN)rHrr8r+r2r*rJr1©r3rErBr
r
r r8¦s 
zSteadyDBConnection.commitc Csvd|_z|j ¡Wn\|jk
rp}z<z | ¡}Wntk
rHYnX| ¡| |¡|‚W5d}~XYnXdS)zRollback pending transaction.FN)rHrr9r+r2r*rJr1rRr
r
r r9µs 
zSteadyDBConnection.rollbackcCs2d|_z |jj}Wntk
r&YnX|ƒdS)zvCancel a long-running transaction.
 
        If the underlying driver supports this method, it will be called.
        FN)rHrÚcancelr)r3rSr
r
r rSÄs  zSteadyDBConnection.cancelcOs|jj||ŽS)zPing connection.)rr©r3rrr
r
r rÑszSteadyDBConnection.pingc Os |j}|s| d¡z.|jr2|j|jkr2|s2|j‚|jj||Ž}WnÄ|jk
r}z¢z | ¡}Wnt    k
rxYnpXz|j||Ž}Wnt    k
ržYn(X| 
¡|  |¡|rº|‚|WY¢6Sz |  ¡Wnt    k
ræYnX|ròd|_|‚W5d}~XYnX|S)z)A "tough" version of the method cursor().r7FN) rHrPr&rIr?rrFr+r2r*rJr1rA)r3rrÚ transactionrFrErBr
r
r Ú_cursorÕs>
ÿ 
  zSteadyDBConnection._cursorcOst|f|ž|ŽS)z0Return a new Cursor Object using the connection.)ÚSteadyDBCursorrTr
r
r rFûszSteadyDBConnection.cursorcCs&z | ¡Wntk
r YnXdS)zDelete the steady connection.N)rJr*r5r
r
r Ú__del__ÿs zSteadyDBConnection.__del__)NNNrT)N)F)rT)rrrr    rÚversionr4r6r<r2r@r1rJrLrPrr rArQr8r9rSrrVrFrXr
r
r
r r Œs6þ
/
Y
 
 
 
#
 &r c@sleZdZdZdd„Zdd„Zdd„Zdd    „Zdd d „Zd d„Z    ddd„Z
dd„Z dd„Z dd„Z dd„Zd
S)rWz&A "tough" version of DB-API 2 cursors.cOshd|_d|_||_|||_|_| ¡z|j||Ž|_Wn"tk
r\td|fƒ‚YnXd|_dS)z!Create a "tough" DB-API 2 cursor.NTz%r is not a SteadyDBConnection.F)rVrrr/r0Ú _clearsizesrr#)r3rBrrr
r
r r4
szSteadyDBCursor.__init__cCs|S)z0Enter the runtime context for the cursor object.r
r5r
r
r r6szSteadyDBCursor.__enter__cGs | ¡dS)z/Exit the runtime context for the cursor object.N)rAr:r
r
r r<szSteadyDBCursor.__exit__cCs
||_dS)z6Store input sizes in case cursor needs to be reopened.N)Ú _inputsizes)r3Úsizesr
r
r Ú setinputsizes!szSteadyDBCursor.setinputsizesNcCs||j|<dS)z7Store output sizes in case cursor needs to be reopened.N)Ú _outputsizes)r3ÚsizeÚcolumnr
r
r Ú setoutputsize%szSteadyDBCursor.setoutputsizecCsg|_i|_dS)z$Clear stored input and output sizes.N)r[r^r5r
r
r rZ)szSteadyDBCursor._clearsizescCsX|dkr|j}|jr | |j¡|j ¡D](\}}|dkrF| |¡q*| ||¡q*dS)z7Set stored input and output sizes for cursor execution.N)rVr[r]r^Úitemsra)r3rFr`r_r
r
r Ú    _setsizes.s  zSteadyDBCursor._setsizescCs4|js0z|j ¡Wntk
r(YnXd|_dS)z^Close the tough cursor.
 
        It will not complain if you close it more than once.
        TN)rrVrAr*r5r
r
r rA:s zSteadyDBCursor.closecs‡‡fdd„}|S)z4Return a "tough" version of the given cursor method.c s&ˆ d¡}ˆj}|j}|s$| d¡zP|jrB|j|jkrB|sB|j‚|rNˆ ¡tˆj    ˆƒ}|||Ž}|rpˆ 
¡Wnš|j k
r}zv|sTz|j    ˆj ˆj Ž}Wntk
rºYnšXz2|r̈ |¡t|ˆƒ}|||Ž}|r술
¡Wntk
rYn,Xˆ ¡|ˆ_    |jd7_|WY¢ÔSz | ¡Wntk
rRYnXz | ¡}    Wntk
rxYnvXz|    jˆj ˆj Ž}Wntk
r¦Yn$X|r҈ ¡| ¡| |    ¡|ˆ_    |‚d}
z6|r舠|¡t|ˆƒ} | ||Ž}|r
ˆ 
¡WnJ|jk
r,d} |}
Yn0tk
rV}z d} |}
W5d}~XYnXd} | r¦ˆ ¡| ¡| |    ¡|ˆ_    |jd7_|
rš|
‚|WY¢^Sz | ¡Wntk
rÈYnXz |     ¡Wntk
rìYnX|rúdˆ_|‚W5d}~XYnX|jd7_|SdS)NrGérFT)Ú
startswithrrHrPr&rIr?rcÚgetattrrVrZr+r/r0r*rAr2rFrJr1Ú    __class__) rrrGrBrUÚmethodÚresultrEZcursor2Zcon2Zerror2Zmethod2Zuse2©Únamer3r
r Ú tough_methodHsÀ
 
ÿ 
ÿ
 
 
   ÿ
 
 
 
 
   z6SteadyDBCursor._get_tough_method.<locals>.tough_methodr
)r3rkrlr
rjr Ú_get_tough_methodFscz SteadyDBCursor._get_tough_methodcCs0|jr(| d¡r| |¡St|j|ƒSnt‚dS)z4Inherit methods and attributes of underlying cursor.)rGÚcallN)rVrermrfr )r3rkr
r
r Ú __getattr__­s
 
 
zSteadyDBCursor.__getattr__cCs&z | ¡Wntk
r YnXdS)zDelete the steady cursor.N)rAr*r5r
r
r rX¸s zSteadyDBCursor.__del__)N)N)rrrr    r4r6r<r]rarZrcrArmrorXr
r
r
r rWs
 
 g rW)NNNrT)r    rÚrr,Úlongr%Ú    NameErrorr*rr rr rWr
r
r
r Ú<module>s$[  
þ
}