Skip to content

Commit 0cf933e

Browse files
committed
Document the context managers
1 parent b55ad8f commit 0cf933e

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
#default_role = None
7171

7272
# If true, '()' will be appended to :func: etc. cross-reference text.
73-
#add_function_parentheses = True
73+
add_function_parentheses = False
7474

7575
# If true, the current module name will be prepended to all description
7676
# unit titles (such as .. function::).

postgres.py

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,60 @@
3535
>>> db.fetchone("SELECT * FROM foo WHERE bar='blam'")
3636
None
3737
38-
Work with a cursor directly:
38+
39+
Context Managers
40+
++++++++++++++++
41+
42+
Eighty percent of your database usage should be covered by the simple API
43+
above. For the other 20%, :py:mod:`postgres` provides context managers for
44+
working at increasingly lower levels of abstraction. The lowest level of
45+
abstraction in :py:mod:`postgres` is a :py:mod:`psycopg2` connection pool that
46+
we configure and manage for you. Everything in :py:mod:`postgres`, both the
47+
simple API and the context managers, uses this connection pool.
48+
49+
Here's how to work directly with a `psycogpg2 cursor
50+
<http://initd.org/psycopg/docs/cursor.html>`_ while still taking advantage of
51+
connection pooling:
3952
4053
>>> with db.get_cursor('SELECT * FROM foo ORDER BY bar') as cursor:
4154
... results = cursor.fetchall()
4255
56+
A cursor you get from :py:func:`~postgres.Postgres.get_cursor` has
57+
``autocommit`` turned on for its connection, so every call you make using such
58+
a cursor will be isolated in a separate transaction. Need to include multiple
59+
calls in a single transaction? Use the
60+
:py:func:`~postgres.Postgres.get_transaction` context manager:
61+
62+
>>> with db.get_transaction() as txn:
63+
... txn.execute("INSERT INTO foo VALUES ('blam')")
64+
... txn.execute("SELECT * FROM foo ORDER BY bar")
65+
... txn.fetchall()
66+
[{"bar": "baz"}, {"bar": "blam"}, {"bar": "buz"}]
67+
...
68+
... db.fetchall("SELECT * FROM foo ORDER BY bar")
69+
[{"bar": "baz"}, {"bar": "buz"}]
70+
...
71+
... db.fetchall("SELECT * FROM foo ORDER BY bar")
72+
[{"bar": "baz"}, {"bar": "blam"}, {"bar": "buz"}]
73+
74+
The :py:func:`~postgres.Postgres.get_transaction` manager gives you a cursor
75+
with ``autocommit`` turned off on its connection. If the block under management
76+
raises, the connection is rolled back. Otherwise it's committed. Use this when
77+
you want a series of statements to be part of one transaction, but you don't
78+
need fine-grained control over the transaction. For fine-grained control, use
79+
:py:func:`~postgres.Postgres.get_connection` to get a connection straight from
80+
the connection pool:
81+
82+
>>> with db.get_connection() as connection:
83+
... cursor = connection.cursor()
84+
... cursor.execute('SELECT * FROM foo ORDER BY bar')
85+
... cursor.fetchall()
86+
[{"bar": "baz"}, {"bar": "buz"}]
87+
88+
A connection gotten in this way will have ``autocommit`` turned off, and it'll
89+
never be implicitly committed otherwise. It'll actually be rolled back when
90+
you're done with it, so it's up to you to explicitly commit as needed.
91+
4392
4493
API
4594
---
@@ -150,15 +199,23 @@ def get_cursor(self, *a, **kw):
150199

151200
def get_transaction(self, *a, **kw):
152201
"""Return a context manager wrapping a transactional cursor.
202+
203+
This manager returns a cursor with autocommit turned off on its
204+
connection. If the block under management raises then the connection is
205+
rolled back. Otherwise it's committed. Use this when you want a series
206+
of statements to be part of one transaction, but you don't need
207+
fine-grained control over the transaction.
208+
153209
"""
154210
return PostgresTransactionContextManager(self.pool, *a, **kw)
155211

156212
def get_connection(self):
157213
"""Return a context manager wrapping a PostgresConnection.
158214
159-
The manager turns autocommit off for you and then turns it on again
160-
when you're done with it. Use this when you need fine-grained
161-
transaction control.
215+
This manager turns autocommit off, and back on when you're done with
216+
the connection. The connection is rolled back on exit, so be sure to
217+
call commit as needed. The idea is that you'd use this when you want
218+
full fine-grained transaction control.
162219
163220
"""
164221
return PostgresConnectionContextManager(self.pool)
@@ -192,13 +249,6 @@ def cursor(self, *a, **kw):
192249

193250
class PostgresTransactionContextManager(object):
194251
"""Instantiated once per db.get_transaction call.
195-
196-
This manager gives you a cursor with autocommit turned off on its
197-
connection. If the block under management raises then the connection is
198-
rolled back. Otherwise it's committed. Use this when you want a series of
199-
statements to be part of one transaction, but you don't need fine-grained
200-
control over the transaction.
201-
202252
"""
203253

204254
def __init__(self, pool, *a, **kw):
@@ -225,12 +275,6 @@ def __exit__(self, *exc_info):
225275

226276
class PostgresConnectionContextManager(object):
227277
"""Instantiated once per db.get_connection call.
228-
229-
This manager turns autocommit off, and back on when you're done with it.
230-
The connection is rolled back on exit, so be sure to call commit as needed.
231-
The idea is that you'd use this when you want full fine-grained transaction
232-
control.
233-
234278
"""
235279

236280
def __init__(self, pool, *a, **kw):

0 commit comments

Comments
 (0)