summaryrefslogtreecommitdiff
path: root/lib/extras.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/extras.py')
-rw-r--r--lib/extras.py100
1 files changed, 63 insertions, 37 deletions
diff --git a/lib/extras.py b/lib/extras.py
index 7a3a925..fe74d38 100644
--- a/lib/extras.py
+++ b/lib/extras.py
@@ -40,10 +40,23 @@ from psycopg2 import extensions as _ext
from psycopg2.extensions import cursor as _cursor
from psycopg2.extensions import connection as _connection
from psycopg2.extensions import adapt as _A, quote_ident
-from psycopg2._psycopg import REPLICATION_PHYSICAL, REPLICATION_LOGICAL
-from psycopg2._psycopg import ReplicationConnection as _replicationConnection
-from psycopg2._psycopg import ReplicationCursor as _replicationCursor
-from psycopg2._psycopg import ReplicationMessage
+
+from psycopg2._psycopg import ( # noqa
+ REPLICATION_PHYSICAL, REPLICATION_LOGICAL,
+ ReplicationConnection as _replicationConnection,
+ ReplicationCursor as _replicationCursor,
+ ReplicationMessage)
+
+
+# expose the json adaptation stuff into the module
+from psycopg2._json import ( # noqa
+ json, Json, register_json, register_default_json, register_default_jsonb)
+
+
+# Expose range-related objects
+from psycopg2._range import ( # noqa
+ Range, NumericRange, DateRange, DateTimeRange, DateTimeTZRange,
+ register_range, RangeAdapter, RangeCaster)
class DictCursorBase(_cursor):
@@ -109,6 +122,7 @@ class DictConnection(_connection):
kwargs.setdefault('cursor_factory', DictCursor)
return super(DictConnection, self).cursor(*args, **kwargs)
+
class DictCursor(DictCursorBase):
"""A cursor that keeps a list of column name -> index mappings."""
@@ -133,6 +147,7 @@ class DictCursor(DictCursorBase):
self.index[self.description[i][0]] = i
self._query_executed = 0
+
class DictRow(list):
"""A row object that allow by-column-name access to data."""
@@ -195,10 +210,10 @@ class DictRow(list):
# drop the crusty Py2 methods
if _sys.version_info[0] > 2:
- items = iteritems; del iteritems
- keys = iterkeys; del iterkeys
- values = itervalues; del itervalues
- del has_key
+ items = iteritems # noqa
+ keys = iterkeys # noqa
+ values = itervalues # noqa
+ del iteritems, iterkeys, itervalues, has_key
class RealDictConnection(_connection):
@@ -207,6 +222,7 @@ class RealDictConnection(_connection):
kwargs.setdefault('cursor_factory', RealDictCursor)
return super(RealDictConnection, self).cursor(*args, **kwargs)
+
class RealDictCursor(DictCursorBase):
"""A cursor that uses a real dict as the base type for rows.
@@ -236,6 +252,7 @@ class RealDictCursor(DictCursorBase):
self.column_mapping.append(self.description[i][0])
self._query_executed = 0
+
class RealDictRow(dict):
"""A `!dict` subclass representing a data record."""
@@ -268,6 +285,7 @@ class NamedTupleConnection(_connection):
kwargs.setdefault('cursor_factory', NamedTupleCursor)
return super(NamedTupleConnection, self).cursor(*args, **kwargs)
+
class NamedTupleCursor(_cursor):
"""A cursor that generates results as `~collections.namedtuple`.
@@ -372,11 +390,13 @@ class LoggingConnection(_connection):
def _logtofile(self, msg, curs):
msg = self.filter(msg, curs)
- if msg: self._logobj.write(msg + _os.linesep)
+ if msg:
+ self._logobj.write(msg + _os.linesep)
def _logtologger(self, msg, curs):
msg = self.filter(msg, curs)
- if msg: self._logobj.debug(msg)
+ if msg:
+ self._logobj.debug(msg)
def _check(self):
if not hasattr(self, '_logobj'):
@@ -388,6 +408,7 @@ class LoggingConnection(_connection):
kwargs.setdefault('cursor_factory', LoggingCursor)
return super(LoggingConnection, self).cursor(*args, **kwargs)
+
class LoggingCursor(_cursor):
"""A cursor that logs queries using its connection logging facilities."""
@@ -428,6 +449,7 @@ class MinTimeLoggingConnection(LoggingConnection):
kwargs.setdefault('cursor_factory', MinTimeLoggingCursor)
return LoggingConnection.cursor(self, *args, **kwargs)
+
class MinTimeLoggingCursor(LoggingCursor):
"""The cursor sub-class companion to `MinTimeLoggingConnection`."""
@@ -479,18 +501,23 @@ class ReplicationCursor(_replicationCursor):
if slot_type == REPLICATION_LOGICAL:
if output_plugin is None:
- raise psycopg2.ProgrammingError("output plugin name is required to create logical replication slot")
+ raise psycopg2.ProgrammingError(
+ "output plugin name is required to create "
+ "logical replication slot")
command += "LOGICAL %s" % quote_ident(output_plugin, self)
elif slot_type == REPLICATION_PHYSICAL:
if output_plugin is not None:
- raise psycopg2.ProgrammingError("cannot specify output plugin name when creating physical replication slot")
+ raise psycopg2.ProgrammingError(
+ "cannot specify output plugin name when creating "
+ "physical replication slot")
command += "PHYSICAL"
else:
- raise psycopg2.ProgrammingError("unrecognized replication type: %s" % repr(slot_type))
+ raise psycopg2.ProgrammingError(
+ "unrecognized replication type: %s" % repr(slot_type))
self.execute(command)
@@ -513,7 +540,8 @@ class ReplicationCursor(_replicationCursor):
if slot_name:
command += "SLOT %s " % quote_ident(slot_name, self)
else:
- raise psycopg2.ProgrammingError("slot name is required for logical replication")
+ raise psycopg2.ProgrammingError(
+ "slot name is required for logical replication")
command += "LOGICAL "
@@ -523,28 +551,32 @@ class ReplicationCursor(_replicationCursor):
# don't add "PHYSICAL", before 9.4 it was just START_REPLICATION XXX/XXX
else:
- raise psycopg2.ProgrammingError("unrecognized replication type: %s" % repr(slot_type))
+ raise psycopg2.ProgrammingError(
+ "unrecognized replication type: %s" % repr(slot_type))
if type(start_lsn) is str:
lsn = start_lsn.split('/')
lsn = "%X/%08X" % (int(lsn[0], 16), int(lsn[1], 16))
else:
- lsn = "%X/%08X" % ((start_lsn >> 32) & 0xFFFFFFFF, start_lsn & 0xFFFFFFFF)
+ lsn = "%X/%08X" % ((start_lsn >> 32) & 0xFFFFFFFF,
+ start_lsn & 0xFFFFFFFF)
command += lsn
if timeline != 0:
if slot_type == REPLICATION_LOGICAL:
- raise psycopg2.ProgrammingError("cannot specify timeline for logical replication")
+ raise psycopg2.ProgrammingError(
+ "cannot specify timeline for logical replication")
command += " TIMELINE %d" % timeline
if options:
if slot_type == REPLICATION_PHYSICAL:
- raise psycopg2.ProgrammingError("cannot specify output plugin options for physical replication")
+ raise psycopg2.ProgrammingError(
+ "cannot specify output plugin options for physical replication")
command += " ("
- for k,v in options.iteritems():
+ for k, v in options.iteritems():
if not command.endswith('('):
command += ", "
command += "%s %s" % (quote_ident(k, self), _A(str(v)))
@@ -579,6 +611,7 @@ class UUID_adapter(object):
def __str__(self):
return "'%s'::uuid" % self._uuid
+
def register_uuid(oids=None, conn_or_curs=None):
"""Create the UUID type and an uuid.UUID adapter.
@@ -643,6 +676,7 @@ class Inet(object):
def __str__(self):
return str(self.addr)
+
def register_inet(oid=None, conn_or_curs=None):
"""Create the INET type and an Inet adapter.
@@ -862,8 +896,9 @@ WHERE typname = 'hstore';
return tuple(rv0), tuple(rv1)
+
def register_hstore(conn_or_curs, globally=False, unicode=False,
- oid=None, array_oid=None):
+ oid=None, array_oid=None):
"""Register adapter and typecaster for `!dict`\-\ |hstore| conversions.
:param conn_or_curs: a connection or cursor: the typecaster will be
@@ -942,8 +977,8 @@ class CompositeCaster(object):
self.oid = oid
self.array_oid = array_oid
- self.attnames = [ a[0] for a in attrs ]
- self.atttypes = [ a[1] for a in attrs ]
+ self.attnames = [a[0] for a in attrs]
+ self.atttypes = [a[1] for a in attrs]
self._create_type(name, self.attnames)
self.typecaster = _ext.new_type((oid,), name, self.parse)
if array_oid:
@@ -962,8 +997,8 @@ class CompositeCaster(object):
"expecting %d components for the type %s, %d found instead" %
(len(self.atttypes), self.name, len(tokens)))
- values = [ curs.cast(oid, token)
- for oid, token in zip(self.atttypes, tokens) ]
+ values = [curs.cast(oid, token)
+ for oid, token in zip(self.atttypes, tokens)]
return self.make(values)
@@ -1057,11 +1092,12 @@ ORDER BY attnum;
type_oid = recs[0][0]
array_oid = recs[0][1]
- type_attrs = [ (r[2], r[3]) for r in recs ]
+ type_attrs = [(r[2], r[3]) for r in recs]
return self(tname, type_oid, type_attrs,
array_oid=array_oid, schema=schema)
+
def register_composite(name, conn_or_curs, globally=False, factory=None):
"""Register a typecaster to convert a composite type into a tuple.
@@ -1084,17 +1120,7 @@ def register_composite(name, conn_or_curs, globally=False, factory=None):
_ext.register_type(caster.typecaster, not globally and conn_or_curs or None)
if caster.array_typecaster is not None:
- _ext.register_type(caster.array_typecaster, not globally and conn_or_curs or None)
+ _ext.register_type(
+ caster.array_typecaster, not globally and conn_or_curs or None)
return caster
-
-
-# expose the json adaptation stuff into the module
-from psycopg2._json import json, Json, register_json
-from psycopg2._json import register_default_json, register_default_jsonb
-
-
-# Expose range-related objects
-from psycopg2._range import Range, NumericRange
-from psycopg2._range import DateRange, DateTimeRange, DateTimeTZRange
-from psycopg2._range import register_range, RangeAdapter, RangeCaster