1st trial

This commit is contained in:
niphlod
2016-10-03 22:16:55 +02:00
parent 4f68c418f8
commit 15769857cb
5 changed files with 1217 additions and 714 deletions
+481 -162
View File
@@ -1,3 +1,23 @@
import datetime
from datetime import timedelta
from warnings import warn
import socket
import threading
from struct import pack
from hashlib import md5
from decimal import Decimal
from collections import deque, defaultdict
from itertools import count, islice
from .six.moves import map
from .six import b, PY2, integer_types, next, text_type, u, binary_type
from uuid import UUID
from copy import deepcopy
from calendar import timegm
from distutils.version import LooseVersion
from struct import Struct
import time
# Copyright (c) 2007-2009, Mathieu Fenniak
# All rights reserved.
#
@@ -27,34 +47,6 @@
__author__ = "Mathieu Fenniak"
import datetime
from datetime import timedelta
from . import (
Interval, min_int2, max_int2, min_int4, max_int4, min_int8, max_int8,
Bytea, NotSupportedError, ProgrammingError, InternalError, IntegrityError,
OperationalError, DatabaseError, InterfaceError, Error,
ArrayContentNotHomogenousError, ArrayContentEmptyError,
ArrayDimensionsNotConsistentError, ArrayContentNotSupportedError, Warning,
i_unpack, ii_unpack, iii_unpack, h_pack, d_unpack, q_unpack, d_pack,
f_unpack, q_pack, i_pack, h_unpack, dii_unpack, qii_unpack, ci_unpack,
bh_unpack, ihihih_unpack, cccc_unpack, ii_pack, iii_pack, dii_pack,
qii_pack)
from warnings import warn
import socket
import threading
from struct import pack
from hashlib import md5
from decimal import Decimal
from collections import deque, defaultdict
from itertools import count, islice
from .six.moves import map
from .six import b, PY2, integer_types, next, PRE_26, text_type, u
from sys import exc_info
from uuid import UUID
from copy import deepcopy
from calendar import timegm
import os
from distutils.version import LooseVersion
try:
from json import loads
@@ -78,9 +70,350 @@ class UTC(datetime.tzinfo):
utc = UTC()
if PRE_26:
bytearray = list
class Interval(object):
"""An Interval represents a measurement of time. In PostgreSQL, an
interval is defined in the measure of months, days, and microseconds; as
such, the pg8000 interval type represents the same information.
Note that values of the :attr:`microseconds`, :attr:`days` and
:attr:`months` properties are independently measured and cannot be
converted to each other. A month may be 28, 29, 30, or 31 days, and a day
may occasionally be lengthened slightly by a leap second.
.. attribute:: microseconds
Measure of microseconds in the interval.
The microseconds value is constrained to fit into a signed 64-bit
integer. Any attempt to set a value too large or too small will result
in an OverflowError being raised.
.. attribute:: days
Measure of days in the interval.
The days value is constrained to fit into a signed 32-bit integer.
Any attempt to set a value too large or too small will result in an
OverflowError being raised.
.. attribute:: months
Measure of months in the interval.
The months value is constrained to fit into a signed 32-bit integer.
Any attempt to set a value too large or too small will result in an
OverflowError being raised.
"""
def __init__(self, microseconds=0, days=0, months=0):
self.microseconds = microseconds
self.days = days
self.months = months
def _setMicroseconds(self, value):
if not isinstance(value, integer_types):
raise TypeError("microseconds must be an integer type")
elif not (min_int8 < value < max_int8):
raise OverflowError(
"microseconds must be representable as a 64-bit integer")
else:
self._microseconds = value
def _setDays(self, value):
if not isinstance(value, integer_types):
raise TypeError("days must be an integer type")
elif not (min_int4 < value < max_int4):
raise OverflowError(
"days must be representable as a 32-bit integer")
else:
self._days = value
def _setMonths(self, value):
if not isinstance(value, integer_types):
raise TypeError("months must be an integer type")
elif not (min_int4 < value < max_int4):
raise OverflowError(
"months must be representable as a 32-bit integer")
else:
self._months = value
microseconds = property(lambda self: self._microseconds, _setMicroseconds)
days = property(lambda self: self._days, _setDays)
months = property(lambda self: self._months, _setMonths)
def __repr__(self):
return "<Interval %s months %s days %s microseconds>" % (
self.months, self.days, self.microseconds)
def __eq__(self, other):
return other is not None and isinstance(other, Interval) and \
self.months == other.months and self.days == other.days and \
self.microseconds == other.microseconds
def __neq__(self, other):
return not self.__eq__(other)
def pack_funcs(fmt):
struc = Struct('!' + fmt)
return struc.pack, struc.unpack_from
i_pack, i_unpack = pack_funcs('i')
h_pack, h_unpack = pack_funcs('h')
q_pack, q_unpack = pack_funcs('q')
d_pack, d_unpack = pack_funcs('d')
f_pack, f_unpack = pack_funcs('f')
iii_pack, iii_unpack = pack_funcs('iii')
ii_pack, ii_unpack = pack_funcs('ii')
qii_pack, qii_unpack = pack_funcs('qii')
dii_pack, dii_unpack = pack_funcs('dii')
ihihih_pack, ihihih_unpack = pack_funcs('ihihih')
ci_pack, ci_unpack = pack_funcs('ci')
bh_pack, bh_unpack = pack_funcs('bh')
cccc_pack, cccc_unpack = pack_funcs('cccc')
Struct('!i')
min_int2, max_int2 = -2 ** 15, 2 ** 15
min_int4, max_int4 = -2 ** 31, 2 ** 31
min_int8, max_int8 = -2 ** 63, 2 ** 63
class Warning(Exception):
"""Generic exception raised for important database warnings like data
truncations. This exception is not currently used by pg8000.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class Error(Exception):
"""Generic exception that is the base exception of all other error
exceptions.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class InterfaceError(Error):
"""Generic exception raised for errors that are related to the database
interface rather than the database itself. For example, if the interface
attempts to use an SSL connection but the server refuses, an InterfaceError
will be raised.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class DatabaseError(Error):
"""Generic exception raised for errors that are related to the database.
This exception is currently never raised by pg8000.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class DataError(DatabaseError):
"""Generic exception raised for errors that are due to problems with the
processed data. This exception is not currently raised by pg8000.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class OperationalError(DatabaseError):
"""
Generic exception raised for errors that are related to the database's
operation and not necessarily under the control of the programmer. This
exception is currently never raised by pg8000.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class IntegrityError(DatabaseError):
"""
Generic exception raised when the relational integrity of the database is
affected. This exception is not currently raised by pg8000.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class InternalError(DatabaseError):
"""Generic exception raised when the database encounters an internal error.
This is currently only raised when unexpected state occurs in the pg8000
interface itself, and is typically the result of a interface bug.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class ProgrammingError(DatabaseError):
"""Generic exception raised for programming errors. For example, this
exception is raised if more parameter fields are in a query string than
there are available parameters.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class NotSupportedError(DatabaseError):
"""Generic exception raised in case a method or database API was used which
is not supported by the database.
This exception is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
pass
class ArrayContentNotSupportedError(NotSupportedError):
"""
Raised when attempting to transmit an array where the base type is not
supported for binary data transfer by the interface.
"""
pass
class ArrayContentNotHomogenousError(ProgrammingError):
"""
Raised when attempting to transmit an array that doesn't contain only a
single type of object.
"""
pass
class ArrayContentEmptyError(ProgrammingError):
"""Raised when attempting to transmit an empty array. The type oid of an
empty array cannot be determined, and so sending them is not permitted.
"""
pass
class ArrayDimensionsNotConsistentError(ProgrammingError):
"""
Raised when attempting to transmit an array that has inconsistent
multi-dimension sizes.
"""
pass
class Bytea(binary_type):
"""Bytea is a str-derived class that is mapped to a PostgreSQL byte array.
This class is only used in Python 2, the built-in ``bytes`` type is used in
Python 3.
"""
pass
def Date(year, month, day):
"""Constuct an object holding a date value.
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.date`
"""
return datetime.date(year, month, day)
def Time(hour, minute, second):
"""Construct an object holding a time value.
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.time`
"""
return datetime.time(hour, minute, second)
def Timestamp(year, month, day, hour, minute, second):
"""Construct an object holding a timestamp value.
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.datetime`
"""
return datetime.datetime(year, month, day, hour, minute, second)
def DateFromTicks(ticks):
"""Construct an object holding a date value from the given ticks value
(number of seconds since the epoch).
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.date`
"""
return Date(*time.localtime(ticks)[:3])
def TimeFromTicks(ticks):
"""Construct an objet holding a time value from the given ticks value
(number of seconds since the epoch).
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.time`
"""
return Time(*time.localtime(ticks)[3:6])
def TimestampFromTicks(ticks):
"""Construct an object holding a timestamp value from the given ticks value
(number of seconds since the epoch).
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`datetime.datetime`
"""
return Timestamp(*time.localtime(ticks)[:6])
def Binary(value):
"""Construct an object holding binary data.
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
:rtype: :class:`pg8000.types.Bytea` for Python 2, otherwise :class:`bytes`
"""
if PY2:
return Bytea(value)
else:
return value
if PY2:
BINARY = Bytea
else:
BINARY = bytes
FC_TEXT = 0
FC_BINARY = 1
@@ -271,13 +604,13 @@ def timestamp_recv_integer(data, offset, length):
micros = q_unpack(data, offset)[0]
try:
return EPOCH + timedelta(microseconds=micros)
except OverflowError:
except OverflowError as e:
if micros == INFINITY_MICROSECONDS:
return datetime.datetime.max
elif micros == MINUS_INFINITY_MICROSECONDS:
return datetime.datetime.min
else:
raise exc_info()[1]
raise e
# data is double-precision float representing seconds since 2000-01-01
@@ -299,7 +632,7 @@ def timestamp_send_integer(v):
# data is double-precision float representing seconds since 2000-01-01
def timestamp_send_float(v):
return d_pack(timegm(v.timetuple) + v.microsecond / 1e6 - EPOCH_SECONDS)
return d_pack(timegm(v.timetuple()) + v.microsecond / 1e6 - EPOCH_SECONDS)
def timestamptz_send_integer(v):
@@ -325,13 +658,13 @@ def timestamptz_recv_integer(data, offset, length):
micros = q_unpack(data, offset)[0]
try:
return EPOCH_TZ + timedelta(microseconds=micros)
except OverflowError:
except OverflowError as e:
if micros == INFINITY_MICROSECONDS:
return DATETIME_MAX_TZ
elif micros == MINUS_INFINITY_MICROSECONDS:
return DATETIME_MIN_TZ
else:
raise exc_info()[1]
raise e
def timestamptz_recv_float(data, offset, length):
@@ -565,21 +898,19 @@ class Cursor():
.. versionadded:: 1.9.11
"""
try:
self._c._lock.acquire()
self.stream = stream
with self._c._lock:
self.stream = stream
if not self._c.in_transaction and not self._c.autocommit:
self._c.execute(self, "begin transaction", None)
self._c.execute(self, operation, args)
except AttributeError:
if not self._c.in_transaction and not self._c.autocommit:
self._c.execute(self, "begin transaction", None)
self._c.execute(self, operation, args)
except AttributeError as e:
if self._c is None:
raise InterfaceError("Cursor closed")
elif self._c._sock is None:
raise InterfaceError("connection is closed")
else:
raise exc_info()[1]
finally:
self._c._lock.release()
raise e
def executemany(self, operation, param_sets):
"""Prepare a database operation, and then execute it against all
@@ -690,28 +1021,26 @@ class Cursor():
pass
def __next__(self):
try:
self._c._lock.acquire()
return self._cached_rows.popleft()
except IndexError:
if self.portal_suspended:
self._c.send_EXECUTE(self)
self._c._write(SYNC_MSG)
self._c._flush()
self._c.handle_messages(self)
if not self.portal_suspended:
self._c.close_portal(self)
with self._c._lock:
try:
return self._cached_rows.popleft()
except IndexError:
if self.ps is None:
raise ProgrammingError("A query hasn't been issued.")
elif len(self.ps['row_desc']) == 0:
raise ProgrammingError("no result set")
else:
raise StopIteration()
finally:
self._c._lock.release()
if self.portal_suspended:
self._c.send_EXECUTE(self)
self._c._write(SYNC_MSG)
self._c._flush()
self._c.handle_messages(self)
if not self.portal_suspended:
self._c.close_portal(self)
try:
return self._cached_rows.popleft()
except IndexError:
if self.ps is None:
raise ProgrammingError("A query hasn't been issued.")
elif len(self.ps['row_desc']) == 0:
raise ProgrammingError("no result set")
else:
raise StopIteration()
if PY2:
Cursor.next = Cursor.__next__
@@ -737,6 +1066,7 @@ COPY_DONE = b("c")
COPY_DATA = b("d")
COPY_IN_RESPONSE = b("G")
COPY_OUT_RESPONSE = b("H")
EMPTY_QUERY_RESPONSE = b("I")
BIND = b("B")
PARSE = b("P")
@@ -776,14 +1106,6 @@ IDLE_IN_TRANSACTION = b("T")
IDLE_IN_FAILED_TRANSACTION = b("E")
# Byte1('N') - Identifier
# Int32 - Message length
# Any number of these, followed by a zero byte:
# Byte1 - code identifying the field type (see responseKeys)
# String - field value
def data_into_dict(data):
return dict((s[0:1], s[1:]) for s in data.split(NULL_BYTE))
arr_trans = dict(zip(map(ord, u("[] 'u")), list(u('{}')) + [None] * 3))
@@ -895,7 +1217,9 @@ class Connection(object):
error.__name__, stacklevel=3)
return error
def __init__(self, user, host, unix_sock, port, database, password, ssl):
def __init__(
self, user, host, unix_sock, port, database, password, ssl,
timeout):
self._client_encoding = "utf8"
self._commands_with_count = (
b("INSERT"), b("DELETE"), b("UPDATE"), b("MOVE"),
@@ -903,23 +1227,19 @@ class Connection(object):
self._lock = threading.Lock()
if user is None:
try:
self.user = os.environ['PGUSER']
except KeyError:
try:
self.user = os.environ['USER']
except KeyError:
raise InterfaceError(
"The 'user' connection parameter was omitted, and "
"neither the PGUSER or USER environment variables "
"were set.")
raise InterfaceError(
"The 'user' connection parameter cannot be None")
if isinstance(user, text_type):
self.user = user.encode('utf8')
else:
self.user = user
if isinstance(self.user, text_type):
self.user = self.user.encode('utf8')
if isinstance(password, text_type):
self.password = password.encode('utf8')
else:
self.password = password
self.password = password
self.autocommit = False
self._xid = None
@@ -939,41 +1259,38 @@ class Connection(object):
else:
raise ProgrammingError(
"one of host or unix_sock must be provided")
if not PY2 and timeout is not None:
self._usock.settimeout(timeout)
if unix_sock is None and host is not None:
self._usock.connect((host, port))
elif unix_sock is not None:
self._usock.connect(unix_sock)
if ssl:
try:
self._lock.acquire()
import ssl as sslmodule
# Int32(8) - Message length, including self.
# Int32(80877103) - The SSL request code.
self._usock.sendall(ii_pack(8, 80877103))
resp = self._usock.recv(1)
if resp == b('S'):
self._usock = sslmodule.wrap_socket(self._usock)
else:
raise InterfaceError("Server refuses SSL")
except ImportError:
raise InterfaceError(
"SSL required but ssl module not available in "
"this python installation")
finally:
self._lock.release()
with self._lock:
try:
import ssl as sslmodule
# Int32(8) - Message length, including self.
# Int32(80877103) - The SSL request code.
self._usock.sendall(ii_pack(8, 80877103))
resp = self._usock.recv(1)
if resp == b('S'):
self._usock = sslmodule.wrap_socket(self._usock)
else:
raise InterfaceError("Server refuses SSL")
except ImportError:
raise InterfaceError(
"SSL required but ssl module not available in "
"this python installation")
self._sock = self._usock.makefile(mode="rwb")
except socket.error:
except socket.error as e:
self._usock.close()
raise InterfaceError("communication error", exc_info()[1])
raise InterfaceError("communication error", e)
self._flush = self._sock.flush
self._read = self._sock.read
if PRE_26:
self._write = self._sock.writelines
else:
self._write = self._sock.write
self._write = self._sock.write
self._backend_key_data = None
##
@@ -1182,7 +1499,6 @@ class Connection(object):
bool: (16, FC_BINARY, bool_send),
int: (705, FC_TEXT, unknown_out),
float: (701, FC_BINARY, d_pack), # float8
str: (705, FC_TEXT, text_out), # unknown
datetime.date: (1082, FC_TEXT, date_out), # date
datetime.time: (1083, FC_TEXT, time_out), # time
1114: (1114, FC_BINARY, timestamp_send_integer), # timestamp
@@ -1203,10 +1519,12 @@ class Connection(object):
if PY2:
self.py_types[Bytea] = (17, FC_BINARY, bytea_send) # bytea
self.py_types[text_type] = (705, FC_TEXT, text_out) # unknown
self.py_types[str] = (705, FC_TEXT, bytea_send) # unknown
self.py_types[long] = (705, FC_TEXT, unknown_out) # noqa
else:
self.py_types[bytes] = (17, FC_BINARY, bytea_send) # bytea
self.py_types[str] = (705, FC_TEXT, text_out) # unknown
try:
from ipaddress import (
@@ -1240,6 +1558,7 @@ class Connection(object):
READY_FOR_QUERY: self.handle_READY_FOR_QUERY,
ROW_DESCRIPTION: self.handle_ROW_DESCRIPTION,
ERROR_RESPONSE: self.handle_ERROR_RESPONSE,
EMPTY_QUERY_RESPONSE: self.handle_EMPTY_QUERY_RESPONSE,
DATA_ROW: self.handle_DATA_ROW,
COMMAND_COMPLETE: self.handle_COMMAND_COMPLETE,
PARSE_COMPLETE: self.handle_PARSE_COMPLETE,
@@ -1272,32 +1591,37 @@ class Connection(object):
self._flush()
self._cursor = self.cursor()
try:
self._lock.acquire()
code = self.error = None
while code not in (READY_FOR_QUERY, ERROR_RESPONSE):
code, data_len = ci_unpack(self._read(5))
self.message_types[code](self._read(data_len - 4), None)
if self.error is not None:
raise self.error
except:
self._close()
raise
finally:
self._lock.release()
with self._lock:
try:
code = self.error = None
while code not in (READY_FOR_QUERY, ERROR_RESPONSE):
code, data_len = ci_unpack(self._read(5))
self.message_types[code](self._read(data_len - 4), None)
if self.error is not None:
raise self.error
except Exception as e:
try:
self._close()
except Exception:
pass
raise e
self.in_transaction = False
self.notifies = []
self.notifies_lock = threading.Lock()
def handle_ERROR_RESPONSE(self, data, ps):
msg_dict = data_into_dict(data)
responses = tuple(
(s[0:1], s[1:].decode(self._client_encoding)) for s in
data.split(NULL_BYTE))
msg_dict = dict(responses)
if msg_dict[RESPONSE_CODE] == "28000":
self.error = InterfaceError("md5 password authentication failed")
else:
self.error = ProgrammingError(
msg_dict[RESPONSE_SEVERITY], msg_dict[RESPONSE_CODE],
msg_dict[RESPONSE_MSG])
self.error = ProgrammingError(*tuple(v for k, v in responses))
def handle_EMPTY_QUERY_RESPONSE(self, data, ps):
self.error = ProgrammingError("query was empty")
def handle_CLOSE_COMPLETE(self, data, ps):
pass
@@ -1391,11 +1715,8 @@ class Connection(object):
# additional_info = data[idx:idx + null]
# psycopg2 compatible notification interface
try:
self.notifies_lock.acquire()
with self.notifies_lock:
self.notifies.append((backend_pid, condition))
finally:
self.notifies_lock.release()
def cursor(self):
"""Creates a :class:`Cursor` object bound to this
@@ -1412,11 +1733,8 @@ class Connection(object):
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
try:
self._lock.acquire()
with self._lock:
self.execute(self._cursor, "commit", None)
finally:
self._lock.release()
def rollback(self):
"""Rolls back the current database transaction.
@@ -1424,11 +1742,8 @@ class Connection(object):
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
try:
self._lock.acquire()
with self._lock:
self.execute(self._cursor, "rollback", None)
finally:
self._lock.release()
def _close(self):
try:
@@ -1437,12 +1752,15 @@ class Connection(object):
self._write(TERMINATE_MSG)
self._flush()
self._sock.close()
self._usock.close()
self._sock = None
except AttributeError:
raise InterfaceError("connection is closed")
except ValueError:
raise InterfaceError("connection is closed")
except socket.error as e:
raise OperationalError(str(e))
finally:
self._usock.close()
self._sock = None
def close(self):
"""Closes the database connection.
@@ -1450,11 +1768,8 @@ class Connection(object):
This function is part of the `DBAPI 2.0 specification
<http://www.python.org/dev/peps/pep-0249/>`_.
"""
try:
self._lock.acquire()
with self._lock:
self._close()
finally:
self._lock.release()
def handle_AUTHENTICATION_REQUEST(self, data, cursor):
assert self._lock.locked()
@@ -1463,7 +1778,7 @@ class Connection(object):
# 0 = AuthenticationOk
# 5 = MD5 pwd
# 2 = Kerberos v5 (not supported by pg8000)
# 3 = Cleartext pwd (not supported by pg8000)
# 3 = Cleartext pwd
# 4 = crypt() pwd (not supported by pg8000)
# 6 = SCM credential (not supported by pg8000)
# 7 = GSSAPI (not supported by pg8000)
@@ -1480,8 +1795,7 @@ class Connection(object):
raise InterfaceError(
"server requesting password authentication, but no "
"password was provided")
self._send_message(
PASSWORD, self.password.encode("ascii") + NULL_BYTE)
self._send_message(PASSWORD, self.password + NULL_BYTE)
self._flush()
elif auth_code == 5:
##
@@ -1497,8 +1811,8 @@ class Connection(object):
"server requesting MD5 password authentication, but no "
"password was provided")
pwd = b("md5") + md5(
md5(self.password.encode("ascii") + self.user).
hexdigest().encode("ascii") + salt).hexdigest().encode("ascii")
md5(self.password + self.user).hexdigest().encode("ascii") +
salt).hexdigest().encode("ascii")
# Byte1('p') - Identifies the message as a password message.
# Int32 - Message length including self.
# String - The password. Password may be encrypted.
@@ -1536,11 +1850,10 @@ class Connection(object):
except KeyError:
try:
params.append(self.inspect_funcs[typ](value))
except KeyError:
except KeyError as e:
raise NotSupportedError(
"type " + str(exc_info()[1]) +
"not mapped to pg type")
return params
"type " + str(e) + "not mapped to pg type")
return tuple(params)
def handle_ROW_DESCRIPTION(self, data, cursor):
count = h_unpack(data)[0]
@@ -1572,8 +1885,7 @@ class Connection(object):
args = make_args(vals)
params = self.make_params(args)
key = tuple(oid for oid, x, y in params), operation
key = operation, params
try:
ps = cache['ps'][key]
@@ -1617,11 +1929,13 @@ class Connection(object):
try:
self._flush()
except AttributeError:
except AttributeError as e:
if self._sock is None:
raise InterfaceError("connection is closed")
else:
raise exc_info()[1]
raise e
except socket.error as e:
raise OperationalError(str(e))
self.handle_messages(cursor)
@@ -1711,11 +2025,11 @@ class Connection(object):
self._write(i_pack(len(data) + 4))
self._write(data)
self._write(FLUSH_MSG)
except ValueError:
if str(exc_info()[1]) == "write to closed file":
except ValueError as e:
if str(e) == "write to closed file":
raise InterfaceError("connection is closed")
else:
raise exc_info()[1]
raise e
except AttributeError:
raise InterfaceError("connection is closed")
@@ -1783,8 +2097,13 @@ class Connection(object):
self._flush()
self.handle_messages(cursor)
# Byte1('N') - Identifier
# Int32 - Message length
# Any number of these, followed by a zero byte:
# Byte1 - code identifying the field type (see responseKeys)
# String - field value
def handle_NOTICE_RESPONSE(self, data, ps):
resp = data_into_dict(data)
resp = dict((s[0:1], s[1:]) for s in data.split(NULL_BYTE))
self.NoticeReceived(resp)
def handle_PARAMETER_STATUS(self, data, ps):