From 6a4ff65b49cd87d699ba7efcdc6ead56405b8d2b Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 13 Feb 2010 02:10:51 +0000 Subject: [PATCH] Added documentation for the extras module. --- doc/extras.rst | 133 ++++++++++++++++++++++++++++++++++++++++++++++++- doc/usage.rst | 4 +- lib/extras.py | 49 ++++++++++-------- 3 files changed, 164 insertions(+), 22 deletions(-) diff --git a/doc/extras.rst b/doc/extras.rst index f11c47aa..a885895c 100644 --- a/doc/extras.rst +++ b/doc/extras.rst @@ -8,4 +8,135 @@ This module is a generic place used to hold little helper functions and classes until a better place in the distribution is found. -.. todo:: psycopg2.extras + +.. index:: + pair: Cursor; Dictionary + +.. _dict-cursor: + +Dictionary-like cursor +---------------------- + +The dict cursors allow to access to the retrieved records using an iterface +similar to the Python dictionaries instead of the tuples. You can use it +either passing :class:`DictConnection` as :obj:`!connection_factory` argument +to the :func:`~psycopg2.connect` function or passing :class:`DictCursor` as +the :class:`!cursor_factory` argument to the :meth:`~connection.cursor` method +of a regular :class:`connection`. :: + + >>> conn = psycopg2.connect(database='test') + >>> cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + >>> cur.execute("SELECT * FROM test") + >>> rec['id'] + 1 + >>> rec['num'] + 100 + >>> rec['data'] + "abc'def" + + # The records still support indexing as the original tuple + >>> rec[2] + "abc'def" + + +.. autoclass:: DictCursor + +.. autoclass:: DictConnection + +.. autoclass:: DictRow + + +Real dictionary cursor +^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: RealDictCursor + +.. autoclass:: RealDictConnection + +.. autoclass:: RealDictRow + + + +.. index:: + pair: Cursor; Logging + +Logging cursor +-------------- + +.. autoclass:: LoggingConnection + :members: initialize,filter + +.. autoclass:: LoggingCursor + + +.. autoclass:: MinTimeLoggingConnection + :members: initialize,filter + +.. autoclass:: MinTimeLoggingCursor + + + +.. index:: + pair: UUID; Data types + +UUID data type +-------------- + +.. versionadded:: 2.0.9 +.. versionchanged:: 2.0.13 added UUID array support. + +:: + + >>> psycopg2.extras.register_uuid() + + # Python UUID can be used in SQL queries + >>> psycopg2.extensions.adapt(uuid.uuid4()).getquoted() + "'1ad2b180-c17e-46ad-ad94-e1f0dfc7c34b'::uuid" + + # PostgreSQL UUID are transformed into Python UUID objects. + >>> conn = psycopg2.connect(database='test') + >>> cur = conn.cursor() + >>> cur.execute("SELECT 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid") + >>> cur.fetchone()[0] + UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11') + + +.. autofunction:: register_uuid + +.. autoclass:: UUID_adapter + + + +.. index:: + pair: INET; Data types + +INET data type +-------------- +:: + + >>> psycopg2.extras.register_inet() + + >>> conn = psycopg2.connect(database='test') + >>> cur = conn.cursor() + >>> cur.execute("SELECT '192.168.0.1'::inet") + >>> cur.fetchone()[0].addr + '192.168.0.1' + +.. autofunction:: register_inet() + +.. autoclass:: Inet + +.. todo:: Adapter non registered: how to register it? + + + +.. index:: + single: Time zones; Fractional + +Fractional time zones +--------------------- + +.. versionadded:: 2.0.10 + +.. autofunction:: register_tstz_w_secs + diff --git a/doc/usage.rst b/doc/usage.rst index 6d301010..e7212d98 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -227,7 +227,9 @@ Many standards Python types are adapted into SQL and returned as Python objects when a query is executed. If you need to convert other Python types to and from PostgreSQL data types, -see :ref:`adapting-new-types` and :ref:`type-casting-from-sql-to-python`. +see :ref:`adapting-new-types` and :ref:`type-casting-from-sql-to-python`. You +can also find a few other specialized adapters in the :mod:`psycopg2.extras` +module. In the following examples the method :meth:`~cursor.mogrify` is used to show the SQL string that would be sent to the database. diff --git a/lib/extras.py b/lib/extras.py index cefa802d..83dbb7a8 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -97,7 +97,7 @@ class DictCursorBase(_cursor): return res class DictConnection(_connection): - """A connection that uses DictCursor automatically.""" + """A connection that uses :class:`DictCursor` automatically.""" def cursor(self, name=None): if name is None: return _connection.cursor(self, cursor_factory=DictCursor) @@ -180,7 +180,7 @@ class DictRow(list): return self._index.__contains__(x) class RealDictConnection(_connection): - """A connection that uses RealDictCursor automatically.""" + """A connection that uses :class:`RealDictCursor` automatically.""" def cursor(self, name=None): if name is None: return _connection.cursor(self, cursor_factory=RealDictCursor) @@ -193,7 +193,7 @@ class RealDictCursor(DictCursorBase): Note that this cursor is extremely specialized and does not allow the normal access (using integer indices) to fetched data. If you need to access database rows both as a dictionary and a list, then use - the generic DictCursor instead of RealDictCursor. + the generic :class:`DictCursor` instead of :class:`!RealDictCursor`. """ def __init__(self, *args, **kwargs): @@ -218,6 +218,7 @@ class RealDictCursor(DictCursorBase): self._query_executed = 0 class RealDictRow(dict): + """A ``dict`` subclass representing a data record.""" __slots__ = ('_column_mapping') @@ -232,13 +233,16 @@ class RealDictRow(dict): class LoggingConnection(_connection): - """A connection that logs all queries to a file or logger object.""" + """A connection that logs all queries to a file or logger__ object. + + .. __: http://docs.python.org/library/logging.html + """ def initialize(self, logobj): - """Initialize the connection to log to `logobj`. + """Initialize the connection to log to ``logobj``. - The `logobj` parameter can be an open file object or a Logger instance - from the standard logging module. + The ``logobj`` parameter can be an open file object or a Logger + instance from the standard logging module. """ self._logobj = logobj if logging and isinstance(logobj, logging.Logger): @@ -294,12 +298,13 @@ class LoggingCursor(_cursor): class MinTimeLoggingConnection(LoggingConnection): """A connection that logs queries based on execution time. - This is just an example of how to sub-class LoggingConnection to provide - some extra filtering for the logged queries. Both the `.inizialize()` and - `.filter()` methods are overwritten to make sure that only queries - executing for more than `mintime` ms are logged. + This is just an example of how to sub-class :class:`LoggingConnection` to + provide some extra filtering for the logged queries. Both the + :meth:`inizialize` and :meth:`filter` methods are overwritten to make sure + that only queries executing for more than ``mintime`` ms are logged. - Note that this connection uses the specialized cursor MinTimeLoggingCursor. + Note that this connection uses the specialized cursor + :class:`MinTimeLoggingCursor`. """ def initialize(self, logobj, mintime=0): LoggingConnection.initialize(self, logobj) @@ -318,7 +323,7 @@ class MinTimeLoggingConnection(LoggingConnection): return _connection.cursor(self, name, cursor_factory=MinTimeLoggingCursor) class MinTimeLoggingCursor(LoggingCursor): - """The cursor sub-class companion to MinTimeLoggingConnection.""" + """The cursor sub-class companion to :class:`MinTimeLoggingConnection`.""" def execute(self, query, vars=None, async=0): self.timestamp = time.time() @@ -335,7 +340,11 @@ try: import uuid class UUID_adapter(object): - """Adapt Python's uuid.UUID type to PostgreSQL's uuid.""" + """Adapt Python's uuid.UUID__ type to PostgreSQL's uuid__. + + .. __: http://docs.python.org/library/uuid.html + .. __: http://www.postgresql.org/docs/8.4/static/datatype-uuid.html + """ def __init__(self, uuid): self._uuid = uuid @@ -440,7 +449,7 @@ def _convert_tstz_w_secs(s, cursor): return DATETIME(s[:-3], cursor) def register_tstz_w_secs(oids=None, conn_or_curs=None): - """Register alternate type caster for TIMESTAMP WITH TIME ZONE. + """Register alternate type caster for :sql:`TIMESTAMP WITH TIME ZONE`. The Python datetime module cannot handle time zones with seconds in the UTC offset. There are, however, historical @@ -451,16 +460,16 @@ def register_tstz_w_secs(oids=None, conn_or_curs=None): timestamp you likely want to try this type caster. It truncates the seconds from the time zone data and retries casting the timestamp. Note that this will generate timestamps - which are INACCURATE by the number of seconds truncated + which are **inaccurate** by the number of seconds truncated (unless the seconds were 00). - + :param oids: which OIDs to use this type caster for, - defaults to TIMESTAMP WITH TIME ZONE - + defaults to :sql:`TIMESTAMP WITH TIME ZONE` + :param conn_or_curs: a cursor or connection if you want to attach this type caster to that only, defaults to - None meaning all connections and cursors + ``None`` meaning all connections and cursors """ if oids is None: oids = (1184,) # hardcoded from PostgreSQL headers