5050<http://initd.org/psycopg/docs/cursor.html>`_ while still taking advantage of
5151connection pooling:
5252
53- >>> with db.get_cursor('SELECT * FROM foo ORDER BY bar') as cursor:
54- ... results = cursor.fetchall()
53+ >>> with db.get_cursor() as cursor:
54+ ... cursor.execute("SELECT * FROM foo ORDER BY bar")
55+ ... cursor.fetchall()
56+ [{"bar": "baz"}, {"bar": "buz"}]
5557
5658A 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
59+ :py:attr:` autocommit` turned on for its connection, so every call you make
60+ using such a cursor will be isolated in a separate transaction. Need to include
61+ multiple calls in a single transaction? Use the
6062:py:func:`~postgres.Postgres.get_transaction` context manager:
6163
6264 >>> with db.get_transaction() as txn:
7274 [{"bar": "baz"}, {"bar": "blam"}, {"bar": "buz"}]
7375
7476The :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:
77+ with :py:attr:` autocommit` turned off on its connection. If the block under
78+ management raises, the connection is rolled back. Otherwise it's committed.
79+ Use this when you want a series of statements to be part of one transaction,
80+ but you don't need fine-grained control over the transaction. For fine-grained
81+ control, use :py:func:`~postgres.Postgres.get_connection` to get a connection
82+ straight from the connection pool:
8183
8284 >>> with db.get_connection() as connection:
8385 ... cursor = connection.cursor()
84- ... cursor.execute(' SELECT * FROM foo ORDER BY bar' )
86+ ... cursor.execute(" SELECT * FROM foo ORDER BY bar" )
8587 ... cursor.fetchall()
8688 [{"bar": "baz"}, {"bar": "buz"}]
8789
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.
90+ A connection gotten in this way will have :py:attr:` autocommit` turned off, and
91+ it'll never be implicitly committed otherwise. It'll actually be rolled back
92+ when you're done with it, so it's up to you to explicitly commit as needed.
9193
9294
9395API
122124
123125# A Helper
124126# ========
127+ # Heroku gives us an URL, psycopg2 wants a DSN. Convert!
125128
126- # Teach urlparse about postgres:// URLs.
127129if 'postgres' not in urlparse .uses_netloc :
130+ # Teach urlparse about postgres:// URLs.
128131 urlparse .uses_netloc .append ('postgres' )
129132
130-
131133def url_to_dsn (url ):
132- """Heroku gives us an URL, psycopg2 wants a DSN. Convert!
133- """
134134 parsed = urlparse .urlparse (url )
135135 dbname = parsed .path [1 :] # /foobar
136136 user = parsed .username
@@ -148,18 +148,20 @@ def url_to_dsn(url):
148148# ==============
149149
150150class Postgres (object ):
151- """Interact with a `PostgreSQL <http://www.postgresql.org/>`_ datastore .
151+ """Interact with a `PostgreSQL <http://www.postgresql.org/>`_ database .
152152
153153 :param unicode url: A ``postgres://`` URL or a `PostgreSQL connection string <http://www.postgresql.org/docs/current/static/libpq-connect.html>`_
154154 :param int minconn: The minimum size of the connection pool
155155 :param int maxconn: The minimum size of the connection pool
156156
157157 This is the main object that :py:mod:`postgres` provides, and you should
158- have one instance per process. When instantiated, this object creates a
159- `thread-safe connection pool
158+ have one instance per process for each database your process needs to talk
159+ to. When instantiated, this object creates a `thread-safe connection pool
160160 <http://initd.org/psycopg/docs/pool.html#psycopg2.pool.ThreadedConnectionPool>`_,
161- which opens ``minconn`` connections immediately and up to ``maxconn``
162- according to demand.
161+ which opens :py:attr:`minconn` connections immediately, and up to
162+ :py:attr:`maxconn` according to demand. The fundamental value of a
163+ :py:class:`~postgres.Postgres` instance is that it runs everything through
164+ its connection pool.
163165
164166 Features:
165167
@@ -180,68 +182,67 @@ def __init__(self, url, minconn=1, maxconn=10):
180182 def execute (self , * a , ** kw ):
181183 """Execute the query and discard any results.
182184 """
183- with self .get_cursor (* a , ** kw ) :
184- pass
185+ with self .get_cursor () as cursor :
186+ cursor . execute ( * a , ** kw )
185187
186188 def fetchone (self , * a , ** kw ):
187189 """Execute the query and return a single result (``dict`` or ``None``).
188190 """
189- with self .get_cursor (* a , ** kw ) as cursor :
191+ with self .get_cursor () as cursor :
192+ cursor .execute (* a , ** kw )
190193 return cursor .fetchone ()
191194
192195 def fetchall (self , * a , ** kw ):
193196 """Execute the query and yield the results (``dict``).
194197 """
195- with self .get_cursor (* a , ** kw ) as cursor :
198+ with self .get_cursor () as cursor :
199+ cursor .execute (* a , ** kw )
196200 for row in cursor :
197201 yield row
198202
199203 def get_cursor (self , * a , ** kw ):
200- """Execute the query and return a context manager wrapping the cursor .
204+ """Return a :py:class:`~postgres.CursorContextManager` that uses our connection pool .
201205
202- The cursor is a psycopg2 RealDictCursor. The connection underlying the
203- cursor will be checked out of the connection pool and checked back in
204- upon both successful and exceptional executions against the cursor.
206+ This is what :py:meth:`~postgres.Postgres.execute`,
207+ :py:meth:`~postgres.Postgres.fetchone`, and
208+ :py:meth:`~postgres.Postgres.fetchall` use under the hood. It's
209+ probably less directly useful than
210+ :py:meth:`~postgres.Postgres.get_transaction` and
211+ :py:meth:`~postgres.Postgres.get_connection`.
205212
206213 """
207214 return CursorContextManager (self .pool , * a , ** kw )
208215
209216 def get_transaction (self , * a , ** kw ):
210- """Return a context manager wrapping a transactional cursor .
217+ """Return a :py:class:`~postgres.TransactionContextManager` that uses our connection pool .
211218
212- This manager returns a cursor with autocommit turned off on its
213- connection. If the block under management raises then the connection is
214- rolled back. Otherwise it's committed. Use this when you want a series
215- of statements to be part of one transaction, but you don't need
216- fine-grained control over the transaction.
219+ Use this when you want a series of statements to be part of one
220+ transaction, but you don't need fine-grained control over the
221+ transaction.
217222
218223 """
219224 return TransactionContextManager (self .pool , * a , ** kw )
220225
221226 def get_connection (self ):
222- """Return a context manager wrapping a :py:class:`postgres.Connection` .
227+ """Return a :py:class:`~ postgres.ConnectionContextManager` that uses our connection pool .
223228
224- This manager turns autocommit off, and back on when you're done with
225- the connection. The connection is rolled back on exit, so be sure to
226- call commit as needed. The idea is that you'd use this when you want
227- full fine-grained transaction control.
229+ Use this when you want to take advantage of connection pooling, but
230+ otherwise need full control, for example, to do complex things with
231+ transactions.
228232
229233 """
230234 return ConnectionContextManager (self .pool )
231235
232236
233237class Connection (psycopg2 .extensions .connection ):
234- """This is a subclass of psycopg2.extensions.connection.
238+ """This is a subclass of :py:class:` psycopg2.extensions.connection` .
235239
236- Changes:
240+ This class is used as the :py:attr:`connection_factory` for the connection
241+ pool in :py:class:`Postgres`. Here are the differences from the base class:
237242
238- - The DB-API 2.0 spec calls for transactions to be left open by
239- default. I don't think we want this. We set autocommit to
240- :py:class:True.
241-
242- - We enforce UTF-8.
243-
244- - We use RealDictCursor.
243+ - We set :py:attr:`autocommit` to :py:const:`True`.
244+ - We set the client encoding to ``UTF-8``.
245+ - We use :py:class:`psycopg2.extras.RealDictCursor`.
245246
246247 """
247248
@@ -260,7 +261,15 @@ def cursor(self, *a, **kw):
260261# ================
261262
262263class CursorContextManager (object ):
263- """Instantiated once per cursor-level db access.
264+ """Instantiated once per :py:func:`~postgres.Postgres.get_cursor` call.
265+
266+ The return value of :py:func:`CursorContextManager.__enter__` is a
267+ :py:class:`psycopg2.extras.RealDictCursor`. Any positional and keyword
268+ arguments to our constructor are passed through to the cursor constructor.
269+ The :py:class:`~postgres.Connection` underlying the cursor is checked
270+ out of the connection pool when the block starts, and checked back in when
271+ the block ends.
272+
264273 """
265274
266275 def __init__ (self , pool , * a , ** kw ):
@@ -273,16 +282,7 @@ def __enter__(self):
273282 """Get a connection from the pool.
274283 """
275284 self .conn = self .pool .getconn ()
276- cursor = self .conn .cursor ()
277- try :
278- cursor .execute (* self .a , ** self .kw )
279- except :
280- # If we get an exception from execute (like, the query fails:
281- # pretty common), then the __exit__ clause is not triggered. We
282- # trigger it ourselves to avoid draining the pool.
283- self .__exit__ ()
284- raise
285- return cursor
285+ return self .conn .cursor (* self .a , ** self .kw )
286286
287287 def __exit__ (self , * exc_info ):
288288 """Put our connection back in the pool.
@@ -291,19 +291,32 @@ def __exit__(self, *exc_info):
291291
292292
293293class TransactionContextManager (object ):
294- """Instantiated once per db.get_transaction call.
294+ """Instantiated once per :py:func:`~postgres.Postgres.get_transaction` call.
295+
296+ The return value of :py:func:`TransactionContextManager.__enter__` is a
297+ :py:class:`psycopg2.extras.RealDictCursor`. Any positional and keyword
298+ arguments to our constructor are passed through to the cursor constructor.
299+ When the block starts, the :py:class:`~postgres.Connection` underlying the
300+ cursor is checked out of the connection pool and :py:attr:`autocommit` is
301+ set to :py:const:`False`. If the block raises an exception, the
302+ :py:class:`~postgres.Connection` is rolled back. Otherwise it's committed.
303+ In either case, :py:attr:`autocommit` is restored to :py:const:`True` and
304+ the :py:class:`~postgres.Connection` is put back in the pool.
305+
295306 """
296307
297308 def __init__ (self , pool , * a , ** kw ):
298309 self .pool = pool
310+ self .a = a
311+ self .kw = kw
299312 self .conn = None
300313
301- def __enter__ (self , * a , ** kw ):
314+ def __enter__ (self ):
302315 """Get a connection from the pool.
303316 """
304317 self .conn = self .pool .getconn ()
305318 self .conn .autocommit = False
306- return self .conn .cursor (* a , ** kw )
319+ return self .conn .cursor (* self . a , ** self . kw )
307320
308321 def __exit__ (self , * exc_info ):
309322 """Put our connection back in the pool.
@@ -317,10 +330,19 @@ def __exit__(self, *exc_info):
317330
318331
319332class ConnectionContextManager (object ):
320- """Instantiated once per db.get_connection call.
333+ """Instantiated once per :py:func:`~postgres.Postgres.get_connection` call.
334+
335+ The return value of :py:func:`ConnectionContextManager.__enter__` is a
336+ :py:class:`postgres.Connection`. When the block starts, a
337+ :py:class:`~postgres.Connection` is checked out of the connection pool and
338+ :py:attr:`autocommit` is set to :py:const:`False`. When the block ends,
339+ :py:attr:`autocommit` is restored to :py:const:`True` and the
340+ :py:class:`~postgres.Connection` is rolled back before being put back in
341+ the pool.
342+
321343 """
322344
323- def __init__ (self , pool , * a , ** kw ):
345+ def __init__ (self , pool ):
324346 self .pool = pool
325347 self .conn = None
326348
0 commit comments