66
66
Eighty percent of your database usage should be covered by the simple
67
67
:py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.all`,
68
68
:py:meth:`~postgres.Postgres.one_or_zero` API introduced above. For the other
69
- 20%, :py:mod:`postgres` provides context managers for working at increasingly
70
- lower levels of abstraction. The lowest level of abstraction in
69
+ 20%, :py:mod:`postgres` provides two context managers for working at
70
+ increasingly lower levels of abstraction. The lowest level of abstraction in
71
71
:py:mod:`postgres` is a :py:mod:`psycopg2` `connection pool
72
72
<http://initd.org/psycopg/docs/pool.html>`_ that we configure and manage for
73
73
you. Everything in :py:mod:`postgres`, both the simple API and the context
74
74
managers, uses this connection pool.
75
75
76
- Here's how to work directly with a :py:mod:`psycogpg2` `cursor
76
+ Use the :py:func:`~postgres.Postgres.get_transaction` context manager to work
77
+ directly with a :py:mod:`psycogpg2` `cursor
77
78
<http://initd.org/psycopg/docs/cursor.html>`_ while still taking advantage of
78
- connection pooling:
79
-
80
- >>> with db.get_cursor() as cursor:
81
- ... cursor.execute("SELECT * FROM foo ORDER BY bar")
82
- ... cursor.fetchall()
83
- ...
84
- [{'bar': 'baz'}, {'bar': 'buz'}]
85
-
86
- A cursor you get from :py:func:`~postgres.Postgres.get_cursor` has
87
- :py:attr:`autocommit` turned on for its connection, so every call you make
88
- using such a cursor will be isolated in a separate transaction. Need to include
89
- multiple calls in a single transaction? Use the
90
- :py:func:`~postgres.Postgres.get_transaction` context manager:
79
+ connection pooling and automatic transaction management:
91
80
92
81
>>> with db.get_transaction() as txn:
93
82
... txn.execute("INSERT INTO foo VALUES ('blam')")
@@ -222,8 +211,6 @@ class Postgres(object):
222
211
:param int minconn: The minimum size of the connection pool
223
212
:param int maxconn: The maximum size of the connection pool
224
213
:param cursor_factory: Defaults to :py:class:`~psycopg2.extras.RealDictCursor`
225
- :param strict_one: The default :py:attr:`strict` parameter for :py:meth:`~postgres.Postgres.one`
226
- :type strict_one: :py:class:`bool`
227
214
228
215
This is the main object that :py:mod:`postgres` provides, and you should
229
216
have one instance per process for each PostgreSQL database your process
@@ -252,7 +239,7 @@ class Postgres(object):
252
239
:py:meth:`~postgres.Postgres.all`, and
253
240
:py:meth:`~postgres.Postgres.one_or_zero`, were chosen to be short and
254
241
memorable, and to not conflict with the DB-API 2.0 :py:meth:`execute`,
255
- :py:meth:`fetchone `, and :py:meth:`fetchall ` methods, which have slightly
242
+ :py:meth:`fetchall `, and :py:meth:`fetchone ` methods, which have slightly
256
243
different semantics (under DB-API 2.0 you call :py:meth:`execute` on a
257
244
cursor and then call one of the :py:meth:`fetch*` methods on the same
258
245
cursor to retrieve rows; with our simple API there is no second
@@ -261,15 +248,15 @@ class Postgres(object):
261
248
:py:meth:`get_` to set them apart from the simple-case API. Note that when
262
249
working inside a block under one of the context managers, you're using
263
250
DB-API 2.0 (:py:meth:`execute` + :py:meth:`fetch*`), not our simple API
264
- (:py:meth:`~postgres.Postgres.run` / :py:meth:`~postgres.Postgres.one` /
265
- :py:meth:`~postgres.Postgres.all `).
251
+ (:py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.all`,
252
+ :py:meth:`~postgres.Postgres.one_or_zero `).
266
253
267
254
.. _this ticket: https://github.com/gittip/postgres.py/issues/16
268
255
269
256
"""
270
257
271
258
def __init__ (self , url , minconn = 1 , maxconn = 10 , \
272
- cursor_factory = RealDictCursor , strict_one = None ):
259
+ cursor_factory = RealDictCursor ):
273
260
if url .startswith ("postgres://" ):
274
261
dsn = url_to_dsn (url )
275
262
@@ -281,10 +268,6 @@ def __init__(self, url, minconn=1, maxconn=10, \
281
268
, connection_factory = Connection
282
269
)
283
270
284
- if strict_one not in (True , False , None ):
285
- raise ValueError ("strict_one must be True, False, or None." )
286
- self .strict_one = strict_one
287
-
288
271
289
272
def run (self , sql , parameters = None ):
290
273
"""Execute a query and discard any results.
@@ -299,8 +282,8 @@ def run(self, sql, parameters=None):
299
282
>>> db.run("INSERT INTO foo VALUES ('buz')")
300
283
301
284
"""
302
- with self .get_cursor () as cursor :
303
- cursor .execute (sql , parameters )
285
+ with self .get_transaction () as txn :
286
+ txn .execute (sql , parameters )
304
287
305
288
306
289
def all (self , sql , parameters = None ):
@@ -318,9 +301,9 @@ def all(self, sql, parameters=None):
318
301
buz
319
302
320
303
"""
321
- with self .get_cursor () as cursor :
322
- cursor .execute (sql , parameters )
323
- return cursor .fetchall ()
304
+ with self .get_transaction () as txn :
305
+ txn .execute (sql , parameters )
306
+ return txn .fetchall ()
324
307
325
308
326
309
def one_or_zero (self , sql , parameters = None , zero = None ):
@@ -366,25 +349,6 @@ def _some(self, sql, parameters=None, lo=0, hi=1):
366
349
367
350
return txn .fetchone ()
368
351
369
-
370
- def get_cursor (self , * a , ** kw ):
371
- """Return a :py:class:`~postgres.CursorContextManager` that uses our
372
- connection pool.
373
-
374
- This gets you a cursor with :py:attr:`autocommit` turned on on its
375
- connection. The context manager closes the cursor when the block ends.
376
-
377
- Use this when you want a simple cursor.
378
-
379
- >>> with db.get_cursor() as cursor:
380
- ... cursor.execute("SELECT * FROM foo")
381
- ... cursor.rowcount
382
- ...
383
- 2
384
-
385
- """
386
- return CursorContextManager (self .pool , * a , ** kw )
387
-
388
352
def get_transaction (self , * a , ** kw ):
389
353
"""Return a :py:class:`~postgres.TransactionContextManager` that uses
390
354
our connection pool.
@@ -431,11 +395,9 @@ class Connection(psycopg2.extensions.connection):
431
395
"""This is a subclass of :py:class:`psycopg2.extensions.connection`.
432
396
433
397
:py:class:`Postgres` uses this class as the :py:attr:`connection_factory`
434
- for its connection pool. Here are the differences from the base class:
435
-
436
- - We set :py:attr:`autocommit` to :py:const:`True`.
437
- - We set the client encoding to ``UTF-8``.
438
- - We use :py:attr:`self.cursor_factory`.
398
+ for its connection pool. We use this subclass to support the
399
+ :py:attr:`cursor_factory` parameter to the :py:class:`Postgres`
400
+ constructor, and to ensure that the client encoding is ``UTF-8``.
439
401
440
402
"""
441
403
@@ -444,7 +406,6 @@ class Connection(psycopg2.extensions.connection):
444
406
def __init__ (self , * a , ** kw ):
445
407
psycopg2 .extensions .connection .__init__ (self , * a , ** kw )
446
408
self .set_client_encoding ('UTF-8' )
447
- self .autocommit = True
448
409
449
410
def cursor (self , * a , ** kw ):
450
411
if 'cursor_factory' not in kw :
@@ -455,38 +416,6 @@ def cursor(self, *a, **kw):
455
416
# Context Managers
456
417
# ================
457
418
458
- class CursorContextManager (object ):
459
- """Instantiated once per :py:func:`~postgres.Postgres.get_cursor` call.
460
-
461
- The return value of :py:func:`CursorContextManager.__enter__` is a
462
- :py:class:`psycopg2.extras.RealDictCursor`. Any positional and keyword
463
- arguments to our constructor are passed through to the cursor constructor.
464
- The :py:class:`~postgres.Connection` underlying the cursor is checked
465
- out of the connection pool when the block starts, and checked back in when
466
- the block ends. Also when the block ends, the cursor is closed.
467
-
468
- """
469
-
470
- def __init__ (self , pool , * a , ** kw ):
471
- self .pool = pool
472
- self .a = a
473
- self .kw = kw
474
- self .conn = None
475
-
476
- def __enter__ (self ):
477
- """Get a connection from the pool.
478
- """
479
- self .conn = self .pool .getconn ()
480
- self .cursor = self .conn .cursor (* self .a , ** self .kw )
481
- return self .cursor
482
-
483
- def __exit__ (self , * exc_info ):
484
- """Put our connection back in the pool.
485
- """
486
- self .cursor .close ()
487
- self .pool .putconn (self .conn )
488
-
489
-
490
419
class TransactionContextManager (object ):
491
420
"""Instantiated once per :py:func:`~postgres.Postgres.get_transaction`
492
421
call.
@@ -497,10 +426,9 @@ class TransactionContextManager(object):
497
426
When the block starts, the :py:class:`~postgres.Connection` underlying the
498
427
cursor is checked out of the connection pool and :py:attr:`autocommit` is
499
428
set to :py:const:`False`. If the block raises an exception, the
500
- :py:class:`~postgres.Connection` is rolled back. Otherwise it's committed.
501
- In either case, the cursor is closed, :py:attr:`autocommit` is restored to
502
- :py:const:`True`, and the :py:class:`~postgres.Connection` is put back in
503
- the pool.
429
+ :py:class:`~postgres.Connection` is rolled back. Otherwise, it's committed.
430
+ In either case, the cursor is closed, and the
431
+ :py:class:`~postgres.Connection` is put back in the pool.
504
432
505
433
"""
506
434
@@ -526,7 +454,7 @@ def __exit__(self, *exc_info):
526
454
else :
527
455
self .conn .rollback ()
528
456
self .cursor .close ()
529
- self .conn .autocommit = True
457
+ self .conn .autocommit = False
530
458
self .pool .putconn (self .conn )
531
459
532
460
@@ -536,8 +464,7 @@ class ConnectionContextManager(object):
536
464
The return value of :py:func:`ConnectionContextManager.__enter__` is a
537
465
:py:class:`postgres.Connection`. When the block starts, a
538
466
:py:class:`~postgres.Connection` is checked out of the connection pool and
539
- :py:attr:`autocommit` is set to :py:const:`False`. When the block ends,
540
- :py:attr:`autocommit` is restored to :py:const:`True` and the
467
+ :py:attr:`autocommit` is set to :py:const:`False`. When the block ends, the
541
468
:py:class:`~postgres.Connection` is rolled back before being put back in
542
469
the pool.
543
470
@@ -558,5 +485,5 @@ def __exit__(self, *exc_info):
558
485
"""Put our connection back in the pool.
559
486
"""
560
487
self .conn .rollback ()
561
- self .conn .autocommit = True
488
+ self .conn .autocommit = False
562
489
self .pool .putconn (self .conn )
0 commit comments