hawq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [26/28] incubator-hawq git commit: HAWQ-837. Add python modules into HAWQ code
Date Tue, 21 Jun 2016 02:41:42 GMT
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/ext/pg8000/protocol.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/protocol.py b/tools/bin/ext/pg8000/protocol.py
new file mode 100644
index 0000000..377074b
--- /dev/null
+++ b/tools/bin/ext/pg8000/protocol.py
@@ -0,0 +1,1340 @@
+# vim: sw=4:expandtab:foldmethod=marker
+#
+# Copyright (c) 2007-2009, Mathieu Fenniak
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+__author__ = "Mathieu Fenniak"
+
+import socket
+import select
+import threading
+import struct
+import hashlib
+from cStringIO import StringIO
+
+from errors import *
+from util import MulticastDelegate
+import types
+
+##
+# An SSLRequest message.  To initiate an SSL-encrypted connection, an
+# SSLRequest message is used rather than a {@link StartupMessage
+# StartupMessage}.  A StartupMessage is still sent, but only after SSL
+# negotiation (if accepted).
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class SSLRequest(object):
+    def __init__(self):
+        pass
+
+    # Int32(8) - Message length, including self.<br>
+    # Int32(80877103) - The SSL request code.<br>
+    def serialize(self):
+        return struct.pack("!ii", 8, 80877103)
+
+
+##
+# A StartupMessage message.  Begins a DB session, identifying the user to be
+# authenticated as and the database to connect to.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class StartupMessage(object):
+    # Greenplum utility mode
+    def __init__(self, user, database=None, options=None):
+        self.user = user
+        self.database = database
+        self.options = options
+
+    # Int32 - Message length, including self.
+    # Int32(196608) - Protocol version number.  Version 3.0.
+    # Any number of key/value pairs, terminated by a zero byte:
+    #   String - A parameter name (user, database, or options)
+    #   String - Parameter value
+    def serialize(self):
+        protocol = 196608
+        val = struct.pack("!i", protocol)
+        val += "user\x00" + self.user + "\x00"
+        if self.database:
+            val += "database\x00" + self.database + "\x00"
+        if self.options:
+            val += "options\x00" + self.options + "\x00"
+        val += "\x00"
+        val = struct.pack("!i", len(val) + 4) + val
+        return val
+
+
+##
+# Parse message.  Creates a prepared statement in the DB session.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+#
+# @param ps         Name of the prepared statement to create.
+# @param qs         Query string.
+# @param type_oids  An iterable that contains the PostgreSQL type OIDs for
+#                   parameters in the query string.
+class Parse(object):
+    def __init__(self, ps, qs, type_oids):
+        self.ps = ps
+        self.qs = qs
+        self.type_oids = type_oids
+
+    def __repr__(self):
+        return "<Parse ps=%r qs=%r>" % (self.ps, self.qs)
+
+    # Byte1('P') - Identifies the message as a Parse command.
+    # Int32 -   Message length, including self.
+    # String -  Prepared statement name.  An empty string selects the unnamed
+    #           prepared statement.
+    # String -  The query string.
+    # Int16 -   Number of parameter data types specified (can be zero).
+    # For each parameter:
+    #   Int32 - The OID of the parameter data type.
+    def serialize(self):
+        val = self.ps + "\x00" + self.qs + "\x00"
+        val = val + struct.pack("!h", len(self.type_oids))
+        for oid in self.type_oids:
+            # Parse message doesn't seem to handle the -1 type_oid for NULL
+            # values that other messages handle.  So we'll provide type_oid 705,
+            # the PG "unknown" type.
+            if oid == -1: oid = 705
+            val = val + struct.pack("!i", oid)
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "P" + val
+        return val
+
+
+##
+# Bind message.  Readies a prepared statement for execution.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+#
+# @param portal     Name of the destination portal.
+# @param ps         Name of the source prepared statement.
+# @param in_fc      An iterable containing the format codes for input
+#                   parameters.  0 = Text, 1 = Binary.
+# @param params     The parameters.
+# @param out_fc     An iterable containing the format codes for output
+#                   parameters.  0 = Text, 1 = Binary.
+# @param kwargs     Additional arguments to pass to the type conversion
+#                   methods.
+class Bind(object):
+    def __init__(self, portal, ps, in_fc, params, out_fc, **kwargs):
+        self.portal = portal
+        self.ps = ps
+        self.in_fc = in_fc
+        self.params = []
+        for i in range(len(params)):
+            if len(self.in_fc) == 0:
+                fc = 0
+            elif len(self.in_fc) == 1:
+                fc = self.in_fc[0]
+            else:
+                fc = self.in_fc[i]
+            self.params.append(types.pg_value(params[i], fc, **kwargs))
+        self.out_fc = out_fc
+
+    def __repr__(self):
+        return "<Bind p=%r s=%r>" % (self.portal, self.ps)
+
+    # Byte1('B') - Identifies the Bind command.
+    # Int32 - Message length, including self.
+    # String - Name of the destination portal.
+    # String - Name of the source prepared statement.
+    # Int16 - Number of parameter format codes.
+    # For each parameter format code:
+    #   Int16 - The parameter format code.
+    # Int16 - Number of parameter values.
+    # For each parameter value:
+    #   Int32 - The length of the parameter value, in bytes, not including this
+    #           this length.  -1 indicates a NULL parameter value, in which no
+    #           value bytes follow.
+    #   Byte[n] - Value of the parameter.
+    # Int16 - The number of result-column format codes.
+    # For each result-column format code:
+    #   Int16 - The format code.
+    def serialize(self):
+        retval = StringIO()
+        retval.write(self.portal + "\x00")
+        retval.write(self.ps + "\x00")
+        retval.write(struct.pack("!h", len(self.in_fc)))
+        for fc in self.in_fc:
+            retval.write(struct.pack("!h", fc))
+        retval.write(struct.pack("!h", len(self.params)))
+        for param in self.params:
+            if param == None:
+                # special case, NULL value
+                retval.write(struct.pack("!i", -1))
+            else:
+                retval.write(struct.pack("!i", len(param)))
+                retval.write(param)
+        retval.write(struct.pack("!h", len(self.out_fc)))
+        for fc in self.out_fc:
+            retval.write(struct.pack("!h", fc))
+        val = retval.getvalue()
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "B" + val
+        return val
+
+
+##
+# A Close message, used for closing prepared statements and portals.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+#
+# @param typ    'S' for prepared statement, 'P' for portal.
+# @param name   The name of the item to close.
+class Close(object):
+    def __init__(self, typ, name):
+        if len(typ) != 1:
+            raise InternalError("Close typ must be 1 char")
+        self.typ = typ
+        self.name = name
+
+    # Byte1('C') - Identifies the message as a close command.
+    # Int32 - Message length, including self.
+    # Byte1 - 'S' for prepared statement, 'P' for portal.
+    # String - The name of the item to close.
+    def serialize(self):
+        val = self.typ + self.name + "\x00"
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "C" + val
+        return val
+
+
+##
+# A specialized Close message for a portal.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class ClosePortal(Close):
+    def __init__(self, name):
+        Close.__init__(self, "P", name)
+
+
+##
+# A specialized Close message for a prepared statement.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class ClosePreparedStatement(Close):
+    def __init__(self, name):
+        Close.__init__(self, "S", name)
+
+
+##
+# A Describe message, used for obtaining information on prepared statements
+# and portals.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+#
+# @param typ    'S' for prepared statement, 'P' for portal.
+# @param name   The name of the item to close.
+class Describe(object):
+    def __init__(self, typ, name):
+        if len(typ) != 1:
+            raise InternalError("Describe typ must be 1 char")
+        self.typ = typ
+        self.name = name
+
+    # Byte1('D') - Identifies the message as a describe command.
+    # Int32 - Message length, including self.
+    # Byte1 - 'S' for prepared statement, 'P' for portal.
+    # String - The name of the item to close.
+    def serialize(self):
+        val = self.typ + self.name + "\x00"
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "D" + val
+        return val
+
+
+##
+# A specialized Describe message for a portal.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class DescribePortal(Describe):
+    def __init__(self, name):
+        Describe.__init__(self, "P", name)
+
+    def __repr__(self):
+        return "<DescribePortal %r>" % (self.name)
+
+
+##
+# A specialized Describe message for a prepared statement.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class DescribePreparedStatement(Describe):
+    def __init__(self, name):
+        Describe.__init__(self, "S", name)
+
+    def __repr__(self):
+        return "<DescribePreparedStatement %r>" % (self.name)
+
+
+##
+# A Flush message forces the backend to deliver any data pending in its
+# output buffers.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class Flush(object):
+    # Byte1('H') - Identifies the message as a flush command.
+    # Int32(4) - Length of message, including self.
+    def serialize(self):
+        return 'H\x00\x00\x00\x04'
+
+    def __repr__(self):
+        return "<Flush>"
+
+##
+# Causes the backend to close the current transaction (if not in a BEGIN/COMMIT
+# block), and issue ReadyForQuery.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class Sync(object):
+    # Byte1('S') - Identifies the message as a sync command.
+    # Int32(4) - Length of message, including self.
+    def serialize(self):
+        return 'S\x00\x00\x00\x04'
+
+    def __repr__(self):
+        return "<Sync>"
+
+
+##
+# Transmits a password.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class PasswordMessage(object):
+    def __init__(self, pwd):
+        self.pwd = pwd
+
+    # Byte1('p') - Identifies the message as a password message.
+    # Int32 - Message length including self.
+    # String - The password.  Password may be encrypted.
+    def serialize(self):
+        val = self.pwd + "\x00"
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "p" + val
+        return val
+
+
+##
+# Requests that the backend execute a portal and retrieve any number of rows.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+# @param row_count  The number of rows to return.  Can be zero to indicate the
+#                   backend should return all rows. If the portal represents a
+#                   query that does not return rows, no rows will be returned
+#                   no matter what the row_count.
+class Execute(object):
+    def __init__(self, portal, row_count):
+        self.portal = portal
+        self.row_count = row_count
+
+    # Byte1('E') - Identifies the message as an execute message.
+    # Int32 -   Message length, including self.
+    # String -  The name of the portal to execute.
+    # Int32 -   Maximum number of rows to return, if portal contains a query that
+    #           returns rows.  0 = no limit.
+    def serialize(self):
+        val = self.portal + "\x00" + struct.pack("!i", self.row_count)
+        val = struct.pack("!i", len(val) + 4) + val
+        val = "E" + val
+        return val
+
+
+##
+# Informs the backend that the connection is being closed.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class Terminate(object):
+    def __init__(self):
+        pass
+
+    # Byte1('X') - Identifies the message as a terminate message.
+    # Int32(4) - Message length, including self.
+    def serialize(self):
+        return 'X\x00\x00\x00\x04'
+
+##
+# Base class of all Authentication[*] messages.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class AuthenticationRequest(object):
+    def __init__(self, data):
+        pass
+
+    # Byte1('R') - Identifies the message as an authentication request.
+    # Int32(8) - Message length, including self.
+    # Int32 -   An authentication code that represents different
+    #           authentication messages:
+    #               0 = AuthenticationOk
+    #               5 = MD5 pwd
+    #               2 = Kerberos v5 (not supported by pg8000)
+    #               3 = Cleartext pwd (not supported by pg8000)
+    #               4 = crypt() pwd (not supported by pg8000)
+    #               6 = SCM credential (not supported by pg8000)
+    #               7 = GSSAPI (not supported by pg8000)
+    #               8 = GSSAPI data (not supported by pg8000)
+    #               9 = SSPI (not supported by pg8000)
+    # Some authentication messages have additional data following the
+    # authentication code.  That data is documented in the appropriate class.
+    def createFromData(data):
+        ident = struct.unpack("!i", data[:4])[0]
+        klass = authentication_codes.get(ident, None)
+        if klass != None:
+            return klass(data[4:])
+        else:
+            raise NotSupportedError("authentication method %r not supported" % (ident,))
+    createFromData = staticmethod(createFromData)
+
+    def ok(self, conn, user, **kwargs):
+        raise InternalError("ok method should be overridden on AuthenticationRequest instance")
+
+##
+# A message representing that the backend accepting the provided username
+# without any challenge.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class AuthenticationOk(AuthenticationRequest):
+    def ok(self, conn, user, **kwargs):
+        return True
+
+
+##
+# A message representing the backend requesting an MD5 hashed password
+# response.  The response will be sent as md5(md5(pwd + login) + salt).
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class AuthenticationMD5Password(AuthenticationRequest):
+    # Additional message data:
+    #  Byte4 - Hash salt.
+    def __init__(self, data):
+        self.salt = "".join(struct.unpack("4c", data))
+
+    def ok(self, conn, user, password=None, **kwargs):
+        if password == None:
+            raise InterfaceError("server requesting MD5 password authentication, but no password was provided")
+        pwd = "md5" + hashlib.md5(hashlib.md5(password + user).hexdigest() + self.salt).hexdigest()
+        conn._send(PasswordMessage(pwd))
+        conn._flush()
+
+        reader = MessageReader(conn)
+        reader.add_message(AuthenticationRequest, lambda msg, reader: reader.return_value(msg.ok(conn, user)), reader)
+        reader.add_message(ErrorResponse, self._ok_error)
+        return reader.handle_messages()
+
+    def _ok_error(self, msg):
+        if msg.code == "28000":
+            raise InterfaceError("md5 password authentication failed")
+        else:
+            raise msg.createException()
+
+authentication_codes = {
+    0: AuthenticationOk,
+    5: AuthenticationMD5Password,
+}
+
+
+##
+# ParameterStatus message sent from backend, used to inform the frotnend of
+# runtime configuration parameter changes.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class ParameterStatus(object):
+    def __init__(self, key, value):
+        self.key = key
+        self.value = value
+
+    # Byte1('S') - Identifies ParameterStatus
+    # Int32 - Message length, including self.
+    # String - Runtime parameter name.
+    # String - Runtime parameter value.
+    def createFromData(data):
+        key = data[:data.find("\x00")]
+        value = data[data.find("\x00")+1:-1]
+        return ParameterStatus(key, value)
+    createFromData = staticmethod(createFromData)
+
+
+##
+# BackendKeyData message sent from backend.  Contains a connection's process
+# ID and a secret key.  Can be used to terminate the connection's current
+# actions, such as a long running query.  Not supported by pg8000 yet.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class BackendKeyData(object):
+    def __init__(self, process_id, secret_key):
+        self.process_id = process_id
+        self.secret_key = secret_key
+
+    # Byte1('K') - Identifier.
+    # Int32(12) - Message length, including self.
+    # Int32 - Process ID.
+    # Int32 - Secret key.
+    def createFromData(data):
+        process_id, secret_key = struct.unpack("!2i", data)
+        return BackendKeyData(process_id, secret_key)
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing a query with no data.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class NoData(object):
+    # Byte1('n') - Identifier.
+    # Int32(4) - Message length, including self.
+    def createFromData(data):
+        return NoData()
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing a successful Parse.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class ParseComplete(object):
+    # Byte1('1') - Identifier.
+    # Int32(4) - Message length, including self.
+    def createFromData(data):
+        return ParseComplete()
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing a successful Bind.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class BindComplete(object):
+    # Byte1('2') - Identifier.
+    # Int32(4) - Message length, including self.
+    def createFromData(data):
+        return BindComplete()
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing a successful Close.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class CloseComplete(object):
+    # Byte1('3') - Identifier.
+    # Int32(4) - Message length, including self.
+    def createFromData(data):
+        return CloseComplete()
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing data from an Execute has been received, but more data
+# exists in the portal.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class PortalSuspended(object):
+    # Byte1('s') - Identifier.
+    # Int32(4) - Message length, including self.
+    def createFromData(data):
+        return PortalSuspended()
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Message representing the backend is ready to process a new query.
+# <p>
+# Stability: This is an internal class.  No stability guarantee is made.
+class ReadyForQuery(object):
+    def __init__(self, status):
+        self._status = status
+
+    ##
+    # I = Idle, T = Idle in Transaction, E = idle in failed transaction.
+    status = property(lambda self: self._status)
+
+    def __repr__(self):
+        return "<ReadyForQuery %s>" % \
+                {"I": "Idle", "T": "Idle in Transaction", "E": "Idle in Failed Transaction"}[self.status]
+
+    # Byte1('Z') - Identifier.
+    # Int32(5) - Message length, including self.
+    # Byte1 -   Status indicator.
+    def createFromData(data):
+        return ReadyForQuery(data)
+    createFromData = staticmethod(createFromData)
+
+
+##
+# Represents a notice sent from the server.  This is not the same as a
+# notification.  A notice is just additional information about a query, such
+# as a notice that a primary key has automatically been created for a table.
+# <p>
+# A NoticeResponse instance will have properties containing the data sent
+# from the server:
+# <ul>
+# <li>severity -- "ERROR", "FATAL', "PANIC", "WARNING", "NOTICE", "DEBUG",
+# "INFO", or "LOG".  Always present.</li>
+# <li>code -- the SQLSTATE code for the error.  See Appendix A of the
+# PostgreSQL documentation for specific error codes.  Always present.</li>
+# <li>msg -- human-readable error message.  Always present.</li>
+# <li>detail -- Optional additional information.</li>
+# <li>hint -- Optional suggestion about what to do about the issue.</li>
+# <li>position -- Optional index into the query string.</li>
+# <li>where -- Optional context.</li>
+# <li>file -- Source-code file.</li>
+# <li>line -- Source-code line.</li>
+# <li>routine -- Source-code routine.</li>
+# </ul>
+# <p>
+# Stability: Added in pg8000 v1.03.  Required properties severity, code, and
+# msg are guaranteed for v1.xx.  Other properties should be checked with
+# hasattr before accessing.
+class NoticeResponse(object):
+    responseKeys = {
+        "S": "severity",  # always present
+        "C": "code",      # always present
+        "M": "msg",       # always present
+        "D": "detail",
+        "H": "hint",
+        "P": "position",
+        "p": "_position",
+        "q": "_query",
+        "W": "where",
+        "F": "file",
+        "L": "line",
+        "R": "routine",
+    }
+
+    def __init__(self, **kwargs):
+        for arg, value in kwargs.items():
+            setattr(self, arg, value)
+
+    def __repr__(self):
+        return "<NoticeResponse %s %s %r>" % (self.severity, self.code, self.msg)
+
+    def dataIntoDict(data):
+        retval = {}
+        for s in data.split("\x00"):
+            if not s: continue
+            key, value = s[0], s[1:]
+            key = NoticeResponse.responseKeys.get(key, key)
+            retval[key] = value
+        return retval
+    dataIntoDict = staticmethod(dataIntoDict)
+
+    # 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 createFromData(data):
+        return NoticeResponse(**NoticeResponse.dataIntoDict(data))
+    createFromData = staticmethod(createFromData)
+
+
+##
+# A message sent in case of a server-side error.  Contains the same properties
+# that {@link NoticeResponse NoticeResponse} contains.
+# <p>
+# Stability: Added in pg8000 v1.03.  Required properties severity, code, and
+# msg are guaranteed for v1.xx.  Other properties should be checked with
+# hasattr before accessing.
+class ErrorResponse(object):
+    def __init__(self, **kwargs):
+        for arg, value in kwargs.items():
+            setattr(self, arg, value)
+
+    def __repr__(self):
+        return "<ErrorResponse %s %s %r>" % (self.severity, self.code, self.msg)
+
+    def createException(self):
+        return ProgrammingError(self.severity, self.code, self.msg)
+
+    def createFromData(data):
+        return ErrorResponse(**NoticeResponse.dataIntoDict(data))
+    createFromData = staticmethod(createFromData)
+
+
+##
+# A message sent if this connection receives a NOTIFY that it was LISTENing for.
+# <p>
+# Stability: Added in pg8000 v1.03.  When limited to accessing properties from
+# a notification event dispatch, stability is guaranteed for v1.xx.
+class NotificationResponse(object):
+    def __init__(self, backend_pid, condition, additional_info):
+        self._backend_pid = backend_pid
+        self._condition = condition
+        self._additional_info = additional_info
+
+    ##
+    # An integer representing the process ID of the backend that triggered
+    # the NOTIFY.
+    # <p>
+    # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx.
+    backend_pid = property(lambda self: self._backend_pid)
+
+    ##
+    # The name of the notification fired.
+    # <p>
+    # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx.
+    condition = property(lambda self: self._condition)
+
+    ##
+    # Currently unspecified by the PostgreSQL documentation as of v8.3.1.
+    # <p>
+    # Stability: Added in pg8000 v1.03, stability guaranteed for v1.xx.
+    additional_info = property(lambda self: self._additional_info)
+
+    def __repr__(self):
+        return "<NotificationResponse %s %s %r>" % (self.backend_pid, self.condition, self.additional_info)
+
+    def createFromData(data):
+        backend_pid = struct.unpack("!i", data[:4])[0]
+        data = data[4:]
+        null = data.find("\x00")
+        condition = data[:null]
+        data = data[null+1:]
+        null = data.find("\x00")
+        additional_info = data[:null]
+        return NotificationResponse(backend_pid, condition, additional_info)
+    createFromData = staticmethod(createFromData)
+
+
+class ParameterDescription(object):
+    def __init__(self, type_oids):
+        self.type_oids = type_oids
+    def createFromData(data):
+        count = struct.unpack("!h", data[:2])[0]
+        type_oids = struct.unpack("!" + "i"*count, data[2:])
+        return ParameterDescription(type_oids)
+    createFromData = staticmethod(createFromData)
+
+
+class RowDescription(object):
+    def __init__(self, fields):
+        self.fields = fields
+
+    def createFromData(data):
+        count = struct.unpack("!h", data[:2])[0]
+        data = data[2:]
+        fields = []
+        for i in range(count):
+            null = data.find("\x00")
+            field = {"name": data[:null]}
+            data = data[null+1:]
+            field["table_oid"], field["column_attrnum"], field["type_oid"], field["type_size"], field["type_modifier"], field["format"] = struct.unpack("!ihihih", data[:18])
+            data = data[18:]
+            fields.append(field)
+        return RowDescription(fields)
+    createFromData = staticmethod(createFromData)
+
+class CommandComplete(object):
+    def __init__(self, command, rows=None, oid=None):
+        self.command = command
+        self.rows = rows
+        self.oid = oid
+
+    def createFromData(data):
+        values = data[:-1].split(" ")
+        args = {}
+        args['command'] = values[0]
+        if args['command'] in ("INSERT", "DELETE", "UPDATE", "MOVE", "FETCH", "COPY"):
+            args['rows'] = int(values[-1])
+            if args['command'] == "INSERT":
+                args['oid'] = int(values[1])
+        else:
+            args['command'] = data[:-1]
+        return CommandComplete(**args)
+    createFromData = staticmethod(createFromData)
+
+
+class DataRow(object):
+    def __init__(self, fields):
+        self.fields = fields
+
+    def createFromData(data):
+        count = struct.unpack("!h", data[:2])[0]
+        data = data[2:]
+        fields = []
+        for i in range(count):
+            val_len = struct.unpack("!i", data[:4])[0]
+            data = data[4:]
+            if val_len == -1:
+                fields.append(None)
+            else:
+                fields.append(data[:val_len])
+                data = data[val_len:]
+        return DataRow(fields)
+    createFromData = staticmethod(createFromData)
+
+
+class CopyData(object):
+    # "d": CopyData,
+    def __init__(self, data):
+        self.data = data
+
+    def createFromData(data):
+        return CopyData(data)
+    createFromData = staticmethod(createFromData)
+    
+    def serialize(self):
+        return 'd' + struct.pack('!i', len(self.data) + 4) + self.data
+
+
+class CopyDone(object):
+    # Byte1('c') - Identifier.
+    # Int32(4) - Message length, including self.
+
+    def createFromData(data):
+        return CopyDone()
+
+    createFromData = staticmethod(createFromData)
+    
+    def serialize(self):
+        return 'c\x00\x00\x00\x04'
+
+class CopyOutResponse(object):
+    # Byte1('H')
+    # Int32(4) - Length of message contents in bytes, including self.
+    # Int8(1) - 0 textual, 1 binary
+    # Int16(2) - Number of columns
+    # Int16(N) - Format codes for each column (0 text, 1 binary)
+
+    def __init__(self, is_binary, column_formats):
+        self.is_binary = is_binary
+        self.column_formats = column_formats
+    
+    def createFromData(data):
+        is_binary, num_cols = struct.unpack('!bh', data[:3])
+        column_formats = struct.unpack('!' + ('h' * num_cols), data[3:])
+        return CopyOutResponse(is_binary, column_formats)
+
+    createFromData = staticmethod(createFromData)
+
+
+class CopyInResponse(object):
+    # Byte1('G')
+    # Otherwise the same as CopyOutResponse
+    
+    def __init__(self, is_binary, column_formats):
+        self.is_binary = is_binary
+        self.column_formats = column_formats
+    
+    def createFromData(data):
+        is_binary, num_cols = struct.unpack('!bh', data[:3])
+        column_formats = struct.unpack('!' + ('h' * num_cols), data[3:])
+        return CopyInResponse(is_binary, column_formats)
+
+    createFromData = staticmethod(createFromData)
+
+class SSLWrapper(object):
+    def __init__(self, sslobj):
+        self.sslobj = sslobj
+    def send(self, data):
+        self.sslobj.write(data)
+    def recv(self, num):
+        return self.sslobj.read(num)
+
+
+class MessageReader(object):
+    def __init__(self, connection):
+        self._conn = connection
+        self._msgs = []
+
+        # If true, raise exception from an ErrorResponse after messages are
+        # processed.  This can be used to leave the connection in a usable
+        # state after an error response, rather than having unconsumed
+        # messages that won't be understood in another context.
+        self.delay_raising_exception = False
+
+        self.ignore_unhandled_messages = False
+
+    def add_message(self, msg_class, handler, *args, **kwargs):
+        self._msgs.append((msg_class, handler, args, kwargs))
+
+    def clear_messages(self):
+        self._msgs = []
+
+    def return_value(self, value):
+        self._retval = value
+    
+    def handle_messages(self):
+        exc = None
+        while 1:
+            msg = self._conn._read_message()
+            msg_handled = False
+            for (msg_class, handler, args, kwargs) in self._msgs:
+                if isinstance(msg, msg_class):
+                    msg_handled = True
+                    retval = handler(msg, *args, **kwargs)
+                    if retval:
+                        # The handler returned a true value, meaning that the
+                        # message loop should be aborted.
+                        if exc != None:
+                            raise exc
+                        return retval
+                    elif hasattr(self, "_retval"):
+                        # The handler told us to return -- used for non-true
+                        # return values
+                        if exc != None:
+                            raise exc
+                        return self._retval
+            if msg_handled:
+                continue
+            elif isinstance(msg, ErrorResponse):
+                exc = msg.createException()
+                if not self.delay_raising_exception:
+                    raise exc
+            elif isinstance(msg, NoticeResponse):
+                self._conn.handleNoticeResponse(msg)
+            elif isinstance(msg, ParameterStatus):
+                self._conn.handleParameterStatus(msg)
+            elif isinstance(msg, NotificationResponse):
+                self._conn.handleNotificationResponse(msg)
+            elif not self.ignore_unhandled_messages:
+                raise InternalError("Unexpected response msg %r" % (msg))
+
+def sync_on_error(fn):
+    def _fn(self, *args, **kwargs):
+        try:
+            self._sock_lock.acquire()
+            return fn(self, *args, **kwargs)
+        except:
+            self._sync()
+            raise
+        finally:
+            self._sock_lock.release()
+    return _fn
+
+class Connection(object):
+    def __init__(self, unix_sock=None, host=None, port=5432, socket_timeout=60, ssl=False, records=False):
+        self._client_encoding = "ascii"
+        self._integer_datetimes = False
+        self._record_field_names = {}
+        self._sock_buf = ""
+        self._sock_buf_pos = 0
+        self._send_sock_buf = []
+        self._block_size = 8192
+        self.user_wants_records = records
+        if unix_sock == None and host != None:
+            self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        elif unix_sock != None:
+            if not hasattr(socket, "AF_UNIX"):
+                raise InterfaceError("attempt to connect to unix socket on unsupported platform")
+            self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        else:
+            raise ProgrammingError("one of host or unix_sock must be provided")
+        if unix_sock == None and host != None:
+            self._sock.connect((host, port))
+        elif unix_sock != None:
+            self._sock.connect(unix_sock)
+        if ssl:
+            self._send(SSLRequest())
+            self._flush()
+            resp = self._sock.recv(1)
+            if resp == 'S':
+                self._sock = SSLWrapper(socket.ssl(self._sock))
+            else:
+                raise InterfaceError("server refuses SSL")
+        else:
+            # settimeout causes ssl failure, on windows.  Python bug 1462352.
+            self._sock.settimeout(socket_timeout)
+        self._state = "noauth"
+        self._backend_key_data = None
+        self._sock_lock = threading.Lock()
+
+        self.NoticeReceived = MulticastDelegate()
+        self.ParameterStatusReceived = MulticastDelegate()
+        self.NotificationReceived = MulticastDelegate()
+
+        self.ParameterStatusReceived += self._onParameterStatusReceived
+
+    def verifyState(self, state):
+        if self._state != state:
+            raise InternalError("connection state must be %s, is %s" % (state, self._state))
+
+    def _send(self, msg):
+        assert self._sock_lock.locked()
+        #print "_send(%r)" % msg
+        data = msg.serialize()
+        self._send_sock_buf.append(data)
+    
+    def _flush(self):
+        assert self._sock_lock.locked()
+        self._sock.sendall("".join(self._send_sock_buf))
+        del self._send_sock_buf[:]
+
+    def _read_bytes(self, byte_count):
+        retval = []
+        bytes_read = 0
+        while bytes_read < byte_count:
+            if self._sock_buf_pos == len(self._sock_buf):
+                self._sock_buf = self._sock.recv(1024)
+                self._sock_buf_pos = 0
+            rpos = min(len(self._sock_buf), self._sock_buf_pos + (byte_count - bytes_read))
+            addt_data = self._sock_buf[self._sock_buf_pos:rpos]
+            bytes_read += (rpos - self._sock_buf_pos)
+            assert bytes_read <= byte_count
+            self._sock_buf_pos = rpos
+            retval.append(addt_data)
+        return "".join(retval)
+
+    def _read_message(self):
+        assert self._sock_lock.locked()
+        bytes = self._read_bytes(5)
+        message_code = bytes[0]
+        data_len = struct.unpack("!i", bytes[1:])[0] - 4
+        bytes = self._read_bytes(data_len)
+        assert len(bytes) == data_len
+        msg = message_types[message_code].createFromData(bytes)
+        #print "_read_message() -> %r" % msg
+        return msg
+
+    def authenticate(self, user, **kwargs):
+        self.verifyState("noauth")
+        self._sock_lock.acquire()
+        try:
+            self._send(StartupMessage(user, database=kwargs.get("database",None), options=kwargs.get("options", None)))
+            self._flush()
+            msg = self._read_message()
+            if isinstance(msg, ErrorResponse):
+                raise msg.createException()
+            if not isinstance(msg, AuthenticationRequest):
+                raise InternalError("StartupMessage was responded to with non-AuthenticationRequest msg %r" % msg)
+            if not msg.ok(self, user, **kwargs):
+                raise InterfaceError("authentication method %s failed" % msg.__class__.__name__)
+
+            self._state = "auth"
+
+            reader = MessageReader(self)
+            reader.add_message(ReadyForQuery, self._ready_for_query)
+            reader.add_message(BackendKeyData, self._receive_backend_key_data)
+            reader.handle_messages()
+        finally:
+            self._sock_lock.release()
+
+        self._cache_record_attnames()
+
+    def _ready_for_query(self, msg):
+        self._state = "ready"
+        return True
+
+    def _receive_backend_key_data(self, msg):
+        self._backend_key_data = msg
+
+    def _cache_record_attnames(self):
+        if not self.user_wants_records:
+            return
+
+        parse_retval = self.parse("",
+            """SELECT
+                pg_type.oid, attname
+            FROM
+                pg_type
+                INNER JOIN pg_attribute ON (attrelid = pg_type.typrelid)
+                                  WHERE typreceive = 'record_recv'::regproc
+            ORDER BY pg_type.oid, attnum""",
+            [])
+        row_desc, cmd = self.bind("tmp", "", (), parse_retval, None)
+        eod, rows = self.fetch_rows("tmp", 0, row_desc)
+
+        self._record_field_names = {}
+        typoid, attnames = None, []
+        for row in rows:
+            new_typoid, attname = row
+            if new_typoid != typoid and typoid != None:
+                self._record_field_names[typoid] = attnames
+                attnames = []
+            typoid = new_typoid
+            attnames.append(attname)
+        self._record_field_names[typoid] = attnames
+
+    @sync_on_error
+    def parse(self, statement, qs, param_types):
+        self.verifyState("ready")
+
+        type_info = [types.pg_type_info(x) for x in param_types]
+        param_types, param_fc = [x[0] for x in type_info], [x[1] for x in type_info] # zip(*type_info) -- fails on empty arr
+        self._send(Parse(statement, qs, param_types))
+        self._send(DescribePreparedStatement(statement))
+        self._send(Flush())
+        self._flush()
+
+        reader = MessageReader(self)
+
+        # ParseComplete is good.
+        reader.add_message(ParseComplete, lambda msg: 0)
+
+        # Well, we don't really care -- we're going to send whatever we
+        # want and let the database deal with it.  But thanks anyways!
+        reader.add_message(ParameterDescription, lambda msg: 0)
+
+        # We're not waiting for a row description.  Return something
+        # destinctive to let bind know that there is no output.
+        reader.add_message(NoData, lambda msg: (None, param_fc))
+
+        # Common row description response
+        reader.add_message(RowDescription, lambda msg: (msg, param_fc))
+
+        return reader.handle_messages()
+
+    @sync_on_error
+    def bind(self, portal, statement, params, parse_data, copy_stream):
+        self.verifyState("ready")
+
+        row_desc, param_fc = parse_data
+        if row_desc == None:
+            # no data coming out
+            output_fc = ()
+        else:
+            # We've got row_desc that allows us to identify what we're going to
+            # get back from this statement.
+            output_fc = [types.py_type_info(f, self._record_field_names) for f in row_desc.fields]
+        self._send(Bind(portal, statement, param_fc, params, output_fc, client_encoding = self._client_encoding, integer_datetimes = self._integer_datetimes))
+        # We need to describe the portal after bind, since the return
+        # format codes will be different (hopefully, always what we
+        # requested).
+        self._send(DescribePortal(portal))
+        self._send(Flush())
+        self._flush()
+
+        # Read responses from server...
+        reader = MessageReader(self)
+
+        # BindComplete is good -- just ignore
+        reader.add_message(BindComplete, lambda msg: 0)
+
+        # NoData in this case means we're not executing a query.  As a
+        # result, we won't be fetching rows, so we'll never execute the
+        # portal we just created... unless we execute it right away, which
+        # we'll do.
+        reader.add_message(NoData, self._bind_nodata, portal, reader, copy_stream)
+
+        # Return the new row desc, since it will have the format types we
+        # asked the server for
+        reader.add_message(RowDescription, lambda msg: (msg, None))
+
+        return reader.handle_messages()
+
+    def _copy_in_response(self, copyin, fileobj, old_reader):
+        if fileobj == None:
+            raise CopyQueryWithoutStreamError()
+        while True:
+            data = fileobj.read(self._block_size)
+            if not data:
+                break
+            self._send(CopyData(data))
+            self._flush()
+        self._send(CopyDone())
+        self._send(Sync())
+        self._flush()
+
+    def _copy_out_response(self, copyout, fileobj, old_reader):
+        if fileobj == None:
+            raise CopyQueryWithoutStreamError()
+        reader = MessageReader(self)
+        reader.add_message(CopyData, self._copy_data, fileobj)
+        reader.add_message(CopyDone, lambda msg: 1)
+        reader.handle_messages()
+
+    def _copy_data(self, copydata, fileobj):
+        fileobj.write(copydata.data)
+
+    def _bind_nodata(self, msg, portal, old_reader, copy_stream):
+        # Bind message returned NoData, causing us to execute the command.
+        self._send(Execute(portal, 0))
+        self._send(Sync())
+        self._flush()
+
+        output = {}
+        reader = MessageReader(self)
+        reader.add_message(CopyOutResponse, self._copy_out_response, copy_stream, reader)
+        reader.add_message(CopyInResponse, self._copy_in_response, copy_stream, reader)
+        reader.add_message(CommandComplete, lambda msg, out: out.setdefault('msg', msg) and False, output)
+        reader.add_message(ReadyForQuery, lambda msg: 1)
+        reader.delay_raising_exception = True
+        reader.handle_messages()
+
+        old_reader.return_value((None, output['msg']))
+
+    @sync_on_error
+    def fetch_rows(self, portal, row_count, row_desc):
+        self.verifyState("ready")
+
+        self._send(Execute(portal, row_count))
+        self._send(Flush())
+        self._flush()
+        rows = []
+
+        reader = MessageReader(self)
+        reader.add_message(DataRow, self._fetch_datarow, rows, row_desc)
+        reader.add_message(PortalSuspended, lambda msg: 1)
+        reader.add_message(CommandComplete, self._fetch_commandcomplete, portal)
+        retval = reader.handle_messages()
+
+        # retval = 2 when command complete, indicating that we've hit the
+        # end of the available data for this command
+        return (retval == 2), rows
+
+    def _fetch_datarow(self, msg, rows, row_desc):
+        rows.append(
+            [
+                types.py_value(
+                    msg.fields[i],
+                    row_desc.fields[i],
+                    client_encoding=self._client_encoding,
+                    integer_datetimes=self._integer_datetimes,
+                    record_field_names=self._record_field_names
+                )
+                for i in range(len(msg.fields))
+            ]
+        )
+
+    def _fetch_commandcomplete(self, msg, portal):
+        self._send(ClosePortal(portal))
+        self._send(Sync())
+        self._flush()
+
+        reader = MessageReader(self)
+        reader.add_message(ReadyForQuery, self._fetch_commandcomplete_rfq)
+        reader.add_message(CloseComplete, lambda msg: False)
+        reader.handle_messages()
+
+        return 2  # signal end-of-data
+
+    def _fetch_commandcomplete_rfq(self, msg):
+        self._state = "ready"
+        return True
+
+    # Send a Sync message, then read and discard all messages until we
+    # receive a ReadyForQuery message.
+    def _sync(self):
+        # it is assumed _sync is called from sync_on_error, which holds
+        # a _sock_lock throughout the call
+        self._send(Sync())
+        self._flush()
+        reader = MessageReader(self)
+        reader.ignore_unhandled_messages = True
+        reader.add_message(ReadyForQuery, lambda msg: True)
+        reader.handle_messages()
+
+    def close_statement(self, statement):
+        if self._state == "closed":
+            return
+        self.verifyState("ready")
+        self._sock_lock.acquire()
+        try:
+            self._send(ClosePreparedStatement(statement))
+            self._send(Sync())
+            self._flush()
+
+            reader = MessageReader(self)
+            reader.add_message(CloseComplete, lambda msg: 0)
+            reader.add_message(ReadyForQuery, lambda msg: 1)
+            reader.handle_messages()
+        finally:
+            self._sock_lock.release()
+
+    def close_portal(self, portal):
+        if self._state == "closed":
+            return
+        self.verifyState("ready")
+        self._sock_lock.acquire()
+        try:
+            self._send(ClosePortal(portal))
+            self._send(Sync())
+            self._flush()
+
+            reader = MessageReader(self)
+            reader.add_message(CloseComplete, lambda msg: 0)
+            reader.add_message(ReadyForQuery, lambda msg: 1)
+            reader.handle_messages()
+        finally:
+            self._sock_lock.release()
+
+    def close(self):
+        self._sock_lock.acquire()
+        try:
+            self._send(Terminate())
+            self._flush()
+            self._sock.close()
+            self._state = "closed"
+        finally:
+            self._sock_lock.release()
+
+    def _onParameterStatusReceived(self, msg):
+        if msg.key == "client_encoding":
+            self._client_encoding = msg.value
+        elif msg.key == "integer_datetimes":
+            self._integer_datetimes = (msg.value == "on")
+
+    def handleNoticeResponse(self, msg):
+        self.NoticeReceived(msg)
+
+    def handleParameterStatus(self, msg):
+        self.ParameterStatusReceived(msg)
+
+    def handleNotificationResponse(self, msg):
+        self.NotificationReceived(msg)
+
+    def fileno(self):
+        # This should be safe to do without a lock
+        return self._sock.fileno()
+    
+    def isready(self):
+        self._sock_lock.acquire()
+        try:
+            rlst, _wlst, _xlst = select.select([self], [], [], 0)
+            if not rlst:
+                return False
+                
+            self._sync()
+            return True
+        finally:
+            self._sock_lock.release()
+
+message_types = {
+    "N": NoticeResponse,
+    "R": AuthenticationRequest,
+    "S": ParameterStatus,
+    "K": BackendKeyData,
+    "Z": ReadyForQuery,
+    "T": RowDescription,
+    "E": ErrorResponse,
+    "D": DataRow,
+    "C": CommandComplete,
+    "1": ParseComplete,
+    "2": BindComplete,
+    "3": CloseComplete,
+    "s": PortalSuspended,
+    "n": NoData,
+    "t": ParameterDescription,
+    "A": NotificationResponse,
+    "c": CopyDone,
+    "d": CopyData,
+    "G": CopyInResponse,
+    "H": CopyOutResponse,
+    }
+
+

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/ext/pg8000/types.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/types.py b/tools/bin/ext/pg8000/types.py
new file mode 100644
index 0000000..c622a7d
--- /dev/null
+++ b/tools/bin/ext/pg8000/types.py
@@ -0,0 +1,687 @@
+# vim: sw=4:expandtab:foldmethod=marker
+#
+# Copyright (c) 2007-2009, Mathieu Fenniak
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+__author__ = "Mathieu Fenniak"
+
+import datetime
+import decimal
+import struct
+import math
+from errors import (NotSupportedError, ArrayDataParseError, InternalError,
+        ArrayContentEmptyError, ArrayContentNotHomogenousError,
+        ArrayContentNotSupportedError, ArrayDimensionsNotConsistentError)
+
+try:
+    from pytz import utc
+except ImportError:
+    ZERO = datetime.timedelta(0)
+    class UTC(datetime.tzinfo):
+        def utcoffset(self, dt):
+            return ZERO
+        def tzname(self, dt):
+            return "UTC"
+        def dst(self, dt):
+            return ZERO
+    utc = UTC()
+
+class Bytea(str):
+    pass
+
+class Interval(object):
+    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, int) and not isinstance(value, long):
+            raise TypeError("microseconds must be an int or long")
+        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, int) and not isinstance(value, long):
+            raise TypeError("days must be an int or long")
+        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, int) and not isinstance(value, long):
+            raise TypeError("months must be an int or long")
+        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 __cmp__(self, other):
+        if other == None: return -1
+        c = cmp(self.months, other.months)
+        if c != 0: return c
+        c = cmp(self.days, other.days)
+        if c != 0: return c
+        return cmp(self.microseconds, other.microseconds)
+
+def pg_type_info(typ):
+    value = None
+    if isinstance(typ, dict):
+        value = typ["value"]
+        typ = typ["type"]
+
+    data = py_types.get(typ)
+    if data == None:
+        raise NotSupportedError("type %r not mapped to pg type" % typ)
+
+    # permit the type data to be determined by the value, if provided
+    inspect_func = data.get("inspect")
+    if value != None and inspect_func != None:
+        data = inspect_func(value)
+
+    type_oid = data.get("typeoid")
+    if type_oid == None:
+        raise InternalError("type %r has no type_oid" % typ)
+    elif type_oid == -1:
+        # special case: NULL values
+        return type_oid, 0
+
+    # prefer bin, but go with whatever exists
+    if data.get("bin_out"):
+        format = 1
+    elif data.get("txt_out"):
+        format = 0
+    else:
+        raise InternalError("no conversion fuction for type %r" % typ)
+
+    return type_oid, format
+
+def pg_value(value, fc, **kwargs):
+    typ = type(value)
+    data = py_types.get(typ)
+    if data == None:
+        raise NotSupportedError("type %r not mapped to pg type" % typ)
+
+    # permit the type conversion to be determined by the value, if provided
+    inspect_func = data.get("inspect")
+    if value != None and inspect_func != None:
+        data = inspect_func(value)
+
+    # special case: NULL values
+    if data.get("typeoid") == -1:
+        return None
+
+    if fc == 0:
+        func = data.get("txt_out")
+    elif fc == 1:
+        func = data.get("bin_out")
+    else:
+        raise InternalError("unrecognized format code %r" % fc)
+    if func == None:
+        raise NotSupportedError("type %r, format code %r not supported" % (typ, fc))
+    return func(value, **kwargs)
+
+def py_type_info(description, record_field_names):
+    type_oid = description['type_oid']
+    data = pg_types.get(type_oid)
+    if data == None:
+        record_data = record_field_names.get(type_oid)
+        if record_data != None:
+            # records are in bin format
+            return 1
+        raise NotSupportedError("type oid %r not mapped to py type" % type_oid)
+    # prefer bin, but go with whatever exists
+    if data.get("bin_in"):
+        format = 1
+    elif data.get("txt_in"):
+        format = 0
+    else:
+        raise InternalError("no conversion fuction for type oid %r" % type_oid)
+    return format
+
+def py_value(v, description, record_field_names, **kwargs):
+    if v == None:
+        # special case - NULL value
+        return None
+    type_oid = description['type_oid']
+    format = description['format']
+    data = pg_types.get(type_oid)
+    if data == None:
+        record_data = record_field_names.get(type_oid)
+        if record_data != None:
+            data = {"bin_in": record_recv(record_data)}
+    if data == None:
+        raise NotSupportedError("type oid %r not supported" % type_oid)
+    if format == 0:
+        func = data.get("txt_in")
+    elif format == 1:
+        func = data.get("bin_in")
+    else:
+        raise NotSupportedError("format code %r not supported" % format)
+    if func == None:
+        raise NotSupportedError("data response format %r, type %r not supported" % (format, type_oid))
+    return func(v, **kwargs)
+
+def voidrecv(data, **kwargs):
+    return None
+
+def voidsend(v, **kwargs):
+    return None
+
+def boolrecv(data, **kwargs):
+    return data == "\x01"
+
+def boolsend(v, **kwargs):
+    if v:
+        return "\x01"
+    else:
+        return "\x00"
+
+min_int2, max_int2 = -2 ** 15, 2 ** 15
+min_int4, max_int4 = -2 ** 31, 2 ** 31
+min_int8, max_int8 = -2 ** 63, 2 ** 63
+
+def int_inspect(value):
+    if min_int2 < value < max_int2:
+        return {"typeoid": 21, "bin_out": int2send}
+    elif min_int4 < value < max_int4:
+        return {"typeoid": 23, "bin_out": int4send}
+    elif min_int8 < value < max_int8:
+        return {"typeoid": 20, "bin_out": int8send}
+    else:
+        return {"typeoid": 1700, "bin_out": numeric_send}
+
+def int2recv(data, **kwargs):
+    return struct.unpack("!h", data)[0]
+
+def int2send(v, **kwargs):
+    return struct.pack("!h", v)
+
+def int4recv(data, **kwargs):
+    return struct.unpack("!i", data)[0]
+
+def int4send(v, **kwargs):
+    return struct.pack("!i", v)
+
+def int8recv(data, **kwargs):
+    return struct.unpack("!q", data)[0]
+
+def int8send(v, **kwargs):
+    return struct.pack("!q", v)
+
+def float4recv(data, **kwargs):
+    return struct.unpack("!f", data)[0]
+
+def float8recv(data, **kwargs):
+    return struct.unpack("!d", data)[0]
+
+def float8send(v, **kwargs):
+    return struct.pack("!d", v)
+
+def datetime_inspect(value):
+    if value.tzinfo != None:
+        # send as timestamptz if timezone is provided
+        return {"typeoid": 1184, "bin_out": timestamptz_send}
+    else:
+        # otherwise send as timestamp
+        return {"typeoid": 1114, "bin_out": timestamp_send}
+
+def timestamp_recv(data, integer_datetimes, **kwargs):
+    if integer_datetimes:
+        # data is 64-bit integer representing milliseconds since 2000-01-01
+        val = struct.unpack("!q", data)[0]
+        return datetime.datetime(2000, 1, 1) + datetime.timedelta(microseconds = val)
+    else:
+        # data is double-precision float representing seconds since 2000-01-01
+        val = struct.unpack("!d", data)[0]
+        return datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds = val)
+
+# return a timezone-aware datetime instance if we're reading from a
+# "timestamp with timezone" type.  The timezone returned will always be UTC,
+# but providing that additional information can permit conversion to local.
+def timestamptz_recv(data, **kwargs):
+    return timestamp_recv(data, **kwargs).replace(tzinfo=utc)
+
+def timestamp_send(v, integer_datetimes, **kwargs):
+    delta = v - datetime.datetime(2000, 1, 1)
+    val = delta.microseconds + (delta.seconds * 1000000) + (delta.days * 86400000000)
+    if integer_datetimes:
+        # data is 64-bit integer representing milliseconds since 2000-01-01
+        return struct.pack("!q", val)
+    else:
+        # data is double-precision float representing seconds since 2000-01-01
+        return struct.pack("!d", val / 1000.0 / 1000.0)
+
+def timestamptz_send(v, **kwargs):
+    # timestamps should be sent as UTC.  If they have zone info,
+    # convert them.
+    return timestamp_send(v.astimezone(utc).replace(tzinfo=None), **kwargs)
+
+def date_in(data, **kwargs):
+    year = int(data[0:4])
+    month = int(data[5:7])
+    day = int(data[8:10])
+    return datetime.date(year, month, day)
+
+def date_out(v, **kwargs):
+    return v.isoformat()
+
+def time_in(data, **kwargs):
+    hour = int(data[0:2])
+    minute = int(data[3:5])
+    sec = decimal.Decimal(data[6:])
+    return datetime.time(hour, minute, int(sec), int((sec - int(sec)) * 1000000))
+
+def time_out(v, **kwargs):
+    return v.isoformat()
+
+def numeric_in(data, **kwargs):
+    if data.find(".") == -1:
+        return int(data)
+    else:
+        return decimal.Decimal(data)
+
+def numeric_recv(data, **kwargs):
+    num_digits, weight, sign, scale = struct.unpack("!hhhh", data[:8])
+    data = data[8:]
+    digits = struct.unpack("!" + ("h" * num_digits), data)
+    weight = decimal.Decimal(weight)
+    retval = 0
+    for d in digits:
+        d = decimal.Decimal(d)
+        retval += d * (10000 ** weight)
+        weight -= 1
+    if sign:
+        retval *= -1
+    return retval
+
+def numeric_send(v, **kwargs):
+    sign = 0
+    if v < 0:
+        sign = 16384
+        v *= -1
+    max_weight = decimal.Decimal(int(math.floor(math.log(v) / math.log(10000))))
+    weight = max_weight
+    digits = []
+    while v != 0:
+        digit = int(math.floor(v / (10000 ** weight)))
+        v = v - (digit * (10000 ** weight))
+        weight -= 1
+        digits.append(digit)
+    retval = struct.pack("!hhhh", len(digits), max_weight, sign, 0)
+    retval += struct.pack("!" + ("h" * len(digits)), *digits)
+    return retval
+
+def numeric_out(v, **kwargs):
+    return str(v)
+
+# PostgreSQL encodings:
+#   http://www.postgresql.org/docs/8.3/interactive/multibyte.html
+# Python encodings:
+#   http://www.python.org/doc/2.4/lib/standard-encodings.html
+#
+# Commented out encodings don't require a name change between PostgreSQL and
+# Python.  If the py side is None, then the encoding isn't supported.
+pg_to_py_encodings = {
+    # Not supported:
+    "mule_internal": None,
+    "euc_tw": None,
+
+    # Name fine as-is:
+    #"euc_jp",
+    #"euc_jis_2004",
+    #"euc_kr",
+    #"gb18030",
+    #"gbk",
+    #"johab",
+    #"sjis",
+    #"shift_jis_2004",
+    #"uhc",
+    #"utf8",
+
+    # Different name:
+    "euc_cn": "gb2312",
+    "iso_8859_5": "is8859_5",
+    "iso_8859_6": "is8859_6",
+    "iso_8859_7": "is8859_7",
+    "iso_8859_8": "is8859_8",
+    "koi8": "koi8_r",
+    "latin1": "iso8859-1",
+    "latin2": "iso8859_2",
+    "latin3": "iso8859_3",
+    "latin4": "iso8859_4",
+    "latin5": "iso8859_9",
+    "latin6": "iso8859_10",
+    "latin7": "iso8859_13",
+    "latin8": "iso8859_14",
+    "latin9": "iso8859_15",
+    "sql_ascii": "ascii",
+    "win866": "cp886",
+    "win874": "cp874",
+    "win1250": "cp1250",
+    "win1251": "cp1251",
+    "win1252": "cp1252",
+    "win1253": "cp1253",
+    "win1254": "cp1254",
+    "win1255": "cp1255",
+    "win1256": "cp1256",
+    "win1257": "cp1257",
+    "win1258": "cp1258",
+}
+
+def encoding_convert(encoding):
+    return pg_to_py_encodings.get(encoding.lower(), encoding)
+
+def varcharin(data, client_encoding, **kwargs):
+    return unicode(data, encoding_convert(client_encoding))
+
+def textout(v, client_encoding, **kwargs):
+    return v.encode(encoding_convert(client_encoding))
+
+def byteasend(v, **kwargs):
+    return str(v)
+
+def bytearecv(data, **kwargs):
+    return Bytea(data)
+
+# interval support does not provide a Python-usable interval object yet
+def interval_recv(data, integer_datetimes, **kwargs):
+    if integer_datetimes:
+        microseconds, days, months = struct.unpack("!qii", data)
+    else:
+        seconds, days, months = struct.unpack("!dii", data)
+        microseconds = int(seconds * 1000 * 1000)
+    return Interval(microseconds, days, months)
+
+def interval_send(data, integer_datetimes, **kwargs):
+    if integer_datetimes:
+        return struct.pack("!qii", data.microseconds, data.days, data.months)
+    else:
+        return struct.pack("!dii", data.microseconds / 1000.0 / 1000.0, data.days, data.months)
+
+def array_recv(data, **kwargs):
+    dim, hasnull, typeoid = struct.unpack("!iii", data[:12])
+    data = data[12:]
+
+    # get type conversion method for typeoid
+    conversion = pg_types[typeoid]["bin_in"]
+
+    # Read dimension info
+    dim_lengths = []
+    element_count = 1
+    for idim in range(dim):
+        dim_len, dim_lbound = struct.unpack("!ii", data[:8])
+        data = data[8:]
+        dim_lengths.append(dim_len)
+        element_count *= dim_len
+
+    # Read all array values
+    array_values = []
+    for i in range(element_count):
+        element_len, = struct.unpack("!i", data[:4])
+        data = data[4:]
+        if element_len == -1:
+            array_values.append(None)
+        else:
+            array_values.append(conversion(data[:element_len], **kwargs))
+            data = data[element_len:]
+    if data != "":
+        raise ArrayDataParseError("unexpected data left over after array read")
+
+    # at this point, {{1,2,3},{4,5,6}}::int[][] looks like [1,2,3,4,5,6].
+    # go through the dimensions and fix up the array contents to match
+    # expected dimensions
+    for dim_length in reversed(dim_lengths[1:]):
+        val = []
+        while array_values:
+            val.append(array_values[:dim_length])
+            array_values = array_values[dim_length:]
+        array_values = val
+
+    return array_values
+
+def array_inspect(value):
+    # Check if array has any values.  If not, we can't determine the proper
+    # array typeoid.
+    first_element = array_find_first_element(value)
+    if first_element == None:
+        raise ArrayContentEmptyError("array has no values")
+
+    # supported array output
+    typ = type(first_element)
+    if issubclass(typ, int) or issubclass(typ, long):
+        # special int array support -- send as smallest possible array type
+        special_int_support = True
+        int2_ok, int4_ok, int8_ok = True, True, True
+        for v in array_flatten(value):
+            if v == None:
+                continue
+            if min_int2 < v < max_int2:
+                continue
+            int2_ok = False
+            if min_int4 < v < max_int4:
+                continue
+            int4_ok = False
+            if min_int8 < v < max_int8:
+                continue
+            int8_ok = False
+        if int2_ok:
+            array_typeoid = 1005 # INT2[]
+        elif int4_ok:
+            array_typeoid = 1007 # INT4[]
+        elif int8_ok:
+            array_typeoid = 1016 # INT8[]
+        else:
+            raise ArrayContentNotSupportedError("numeric not supported as array contents")
+    else:
+        special_int_support = False
+        array_typeoid = py_array_types.get(typ)
+        if array_typeoid == None:
+            raise ArrayContentNotSupportedError("type %r not supported as array contents" % typ)
+
+    # check for homogenous array
+    for v in array_flatten(value):
+        if v != None and not (isinstance(v, typ) or (typ == long and isinstance(v, int)) or (typ == int and isinstance(v, long))):
+            raise ArrayContentNotHomogenousError("not all array elements are of type %r" % typ)
+
+    # check that all array dimensions are consistent
+    array_check_dimensions(value)
+
+    type_data = py_types[typ]
+    if special_int_support:
+        if array_typeoid == 1005:
+            type_data = {"typeoid": 21, "bin_out": int2send}
+        elif array_typeoid == 1007:
+            type_data = {"typeoid": 23, "bin_out": int4send}
+        elif array_typeoid == 1016:
+            type_data = {"typeoid": 20, "bin_out": int8send}
+    else:
+        type_data = py_types[typ]
+    return {
+        "typeoid": array_typeoid,
+        "bin_out": array_send(type_data["typeoid"], type_data["bin_out"])
+    }
+
+def array_find_first_element(arr):
+    for v in array_flatten(arr):
+        if v != None:
+            return v
+    return None
+
+def array_flatten(arr):
+    for v in arr:
+        if isinstance(v, list):
+            for v2 in array_flatten(v):
+                yield v2
+        else:
+            yield v
+
+def array_check_dimensions(arr):
+    v0 = arr[0]
+    if isinstance(v0, list):
+        req_len = len(v0)
+        req_inner_lengths = array_check_dimensions(v0)
+        for v in arr:
+            inner_lengths = array_check_dimensions(v)
+            if len(v) != req_len or inner_lengths != req_inner_lengths:
+                raise ArrayDimensionsNotConsistentError("array dimensions not consistent")
+        retval = [req_len]
+        retval.extend(req_inner_lengths)
+        return retval
+    else:
+        # make sure nothing else at this level is a list
+        for v in arr:
+            if isinstance(v, list):
+                raise ArrayDimensionsNotConsistentError("array dimensions not consistent")
+        return []
+
+def array_has_null(arr):
+    for v in array_flatten(arr):
+        if v == None:
+            return True
+    return False
+
+def array_dim_lengths(arr):
+    v0 = arr[0]
+    if isinstance(v0, list):
+        retval = [len(v0)]
+        retval.extend(array_dim_lengths(v0))
+    else:
+        return [len(arr)]
+
+class array_send(object):
+    def __init__(self, typeoid, bin_out_func):
+        self.typeoid = typeoid
+        self.bin_out_func = bin_out_func
+
+    def __call__(self, arr, **kwargs):
+        has_null = array_has_null(arr)
+        dim_lengths = array_dim_lengths(arr)
+        data = struct.pack("!iii", len(dim_lengths), has_null, self.typeoid)
+        for i in dim_lengths:
+            data += struct.pack("!ii", i, 1)
+        for v in array_flatten(arr):
+            if v == None:
+                data += struct.pack("!i", -1)
+            else:
+                inner_data = self.bin_out_func(v, **kwargs)
+                data += struct.pack("!i", len(inner_data))
+                data += inner_data
+        return data
+
+class record_recv(object):
+    def __init__(self, record_field_names):
+        self.record_field_names = record_field_names
+
+    def __call__(self, data, **kwargs):
+        num_fields, = struct.unpack("!i", data[:4])
+        data = data[4:]
+        retval = {}
+        for i in range(num_fields):
+            typeoid, size = struct.unpack("!ii", data[:8])
+            data = data[8:]
+            conversion = pg_types[typeoid]["bin_in"]
+            value = conversion(data[:size], **kwargs)
+            data = data[size:]
+            retval[self.record_field_names[i]] = value
+        return retval
+
+py_types = {
+    bool: {"typeoid": 16, "bin_out": boolsend},
+    int: {"inspect": int_inspect},
+    long: {"inspect": int_inspect},
+    str: {"typeoid": 25, "bin_out": textout},
+    unicode: {"typeoid": 25, "bin_out": textout},
+    float: {"typeoid": 701, "bin_out": float8send},
+    decimal.Decimal: {"typeoid": 1700, "bin_out": numeric_send},
+    Bytea: {"typeoid": 17, "bin_out": byteasend},
+    datetime.datetime: {"typeoid": 1114, "bin_out": timestamp_send, "inspect": datetime_inspect},
+    datetime.date: {"typeoid": 1082, "txt_out": date_out},
+    datetime.time: {"typeoid": 1083, "txt_out": time_out},
+    Interval: {"typeoid": 1186, "bin_out": interval_send},
+    type(None): {"typeoid": -1},
+    list: {"inspect": array_inspect},
+}
+
+# py type -> pg array typeoid
+py_array_types = {
+    float: 1022,
+    bool: 1000,
+    str: 1009,      # TEXT[]
+    unicode: 1009,  # TEXT[]
+    decimal.Decimal: 1231, # NUMERIC[]
+}
+
+pg_types = {
+    16: {"bin_in": boolrecv},
+    17: {"bin_in": bytearecv},
+    18: {"txt_in": varcharin}, # char type (Greenplum)
+    19: {"bin_in": varcharin}, # name type
+    20: {"bin_in": int8recv},
+    21: {"bin_in": int2recv},
+    23: {"bin_in": int4recv},
+    24: {"txt_in": varcharin}, # regproc    (Greenplum)
+    25: {"bin_in": varcharin}, # TEXT type
+    26: {"txt_in": numeric_in}, # oid type
+    28: {"txt_in": numeric_in}, # xid type  (Greenplum)
+    700: {"bin_in": float4recv},
+    701: {"bin_in": float8recv},
+    829: {"txt_in": varcharin}, # MACADDR type
+    1000: {"bin_in": array_recv}, # BOOL[]
+    1003: {"bin_in": array_recv}, # NAME[]
+    1005: {"bin_in": array_recv}, # INT2[]
+    1007: {"bin_in": array_recv}, # INT4[]
+    1009: {"bin_in": array_recv}, # TEXT[]
+    1014: {"bin_in": array_recv}, # CHAR[]
+    1015: {"bin_in": array_recv}, # VARCHAR[]
+    1016: {"bin_in": array_recv}, # INT8[]
+    1021: {"bin_in": array_recv}, # FLOAT4[]
+    1022: {"bin_in": array_recv}, # FLOAT8[]
+    1042: {"bin_in": varcharin}, # CHAR type
+    1043: {"bin_in": varcharin}, # VARCHAR type
+    1082: {"txt_in": date_in},
+    1083: {"txt_in": time_in},
+    1114: {"bin_in": timestamp_recv},
+    1184: {"bin_in": timestamptz_recv}, # timestamp w/ tz
+    1186: {"bin_in": interval_recv},
+    1231: {"bin_in": array_recv}, # NUMERIC[]
+    1263: {"bin_in": array_recv}, # cstring[]
+    1700: {"bin_in": numeric_recv},
+    2275: {"bin_in": varcharin}, # cstring
+    2278: {"txt_in": voidrecv}, # void - This is to allow the code to handle the situation where a SQL function returns void
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/ext/pg8000/util.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/util.py b/tools/bin/ext/pg8000/util.py
new file mode 100644
index 0000000..d99421e
--- /dev/null
+++ b/tools/bin/ext/pg8000/util.py
@@ -0,0 +1,20 @@
+
+class MulticastDelegate(object):
+    def __init__(self):
+        self.delegates = []
+
+    def __iadd__(self, delegate):
+        self.add(delegate)
+        return self
+
+    def add(self, delegate):
+        self.delegates.append(delegate)
+
+    def __isub__(self, delegate):
+        self.delegates.remove(delegate)
+        return self
+
+    def __call__(self, *args, **kwargs):
+        for d in self.delegates:
+            d(*args, **kwargs)
+

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/ext/simplejson/__init__.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/simplejson/__init__.py b/tools/bin/ext/simplejson/__init__.py
new file mode 100755
index 0000000..6f0f605
--- /dev/null
+++ b/tools/bin/ext/simplejson/__init__.py
@@ -0,0 +1,303 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+r"""
+A simple, fast, extensible JSON encoder and decoder
+
+JSON (JavaScript Object Notation) <http://json.org> is a subset of
+JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
+interchange format.
+
+simplejson exposes an API familiar to uses of the standard library
+marshal and pickle modules.
+
+Encoding basic Python object hierarchies::
+    
+    >>> import simplejson
+    >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
+    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
+    >>> print simplejson.dumps("\"foo\bar")
+    "\"foo\bar"
+    >>> print simplejson.dumps(u'\u1234')
+    "\u1234"
+    >>> print simplejson.dumps('\\')
+    "\\"
+    >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
+    {"a": 0, "b": 0, "c": 0}
+    >>> from StringIO import StringIO
+    >>> io = StringIO()
+    >>> simplejson.dump(['streaming API'], io)
+    >>> io.getvalue()
+    '["streaming API"]'
+
+Compact encoding::
+
+    >>> import simplejson
+    >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
+    '[1,2,3,{"4":5,"6":7}]'
+
+Pretty printing::
+
+    >>> import simplejson
+    >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
+    {
+        "4": 5, 
+        "6": 7
+    }
+
+Decoding JSON::
+    
+    >>> import simplejson
+    >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
+    [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
+    >>> simplejson.loads('"\\"foo\\bar"')
+    u'"foo\x08ar'
+    >>> from StringIO import StringIO
+    >>> io = StringIO('["streaming API"]')
+    >>> simplejson.load(io)
+    [u'streaming API']
+
+Specializing JSON object decoding::
+
+    >>> import simplejson
+    >>> def as_complex(dct):
+    ...     if '__complex__' in dct:
+    ...         return complex(dct['real'], dct['imag'])
+    ...     return dct
+    ... 
+    >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}',
+    ...     object_hook=as_complex)
+    (1+2j)
+
+Extending JSONEncoder::
+    
+    >>> import simplejson
+    >>> class ComplexEncoder(simplejson.JSONEncoder):
+    ...     def default(self, obj):
+    ...         if isinstance(obj, complex):
+    ...             return [obj.real, obj.imag]
+    ...         return simplejson.JSONEncoder.default(self, obj)
+    ... 
+    >>> dumps(2 + 1j, cls=ComplexEncoder)
+    '[2.0, 1.0]'
+    >>> ComplexEncoder().encode(2 + 1j)
+    '[2.0, 1.0]'
+    >>> list(ComplexEncoder().iterencode(2 + 1j))
+    ['[', '2.0', ', ', '1.0', ']']
+    
+
+Note that the JSON produced by this module's default settings
+is a subset of YAML, so it may be used as a serializer for that as well.
+"""
+__version__ = '1.7.3'
+__all__ = [
+    'dump', 'dumps', 'load', 'loads',
+    'JSONDecoder', 'JSONEncoder',
+]
+
+from decoder import JSONDecoder
+from encoder import JSONEncoder
+
+_default_encoder = JSONEncoder(
+    skipkeys=False,
+    ensure_ascii=True,
+    check_circular=True,
+    allow_nan=True,
+    indent=None,
+    separators=None,
+    encoding='utf-8'
+)
+
+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
+        allow_nan=True, cls=None, indent=None, separators=None,
+        encoding='utf-8', **kw):
+    """
+    Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
+    ``.write()``-supporting file-like object).
+
+    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 
+    will be skipped instead of raising a ``TypeError``.
+
+    If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
+    may be ``unicode`` instances, subject to normal Python ``str`` to
+    ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
+    understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
+    to cause an error.
+
+    If ``check_circular`` is ``False``, then the circular reference check
+    for container types will be skipped and a circular reference will
+    result in an ``OverflowError`` (or worse).
+
+    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
+    in strict compliance of the JSON specification, instead of using the
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+    If ``indent`` is a non-negative integer, then JSON array elements and object
+    members will be pretty-printed with that indent level. An indent level
+    of 0 will only insert newlines. ``None`` is the most compact representation.
+
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
+    then it will be used instead of the default ``(', ', ': ')`` separators.
+    ``(',', ':')`` is the most compact JSON representation.
+
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
+
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+    ``.default()`` method to serialize additional types), specify it with
+    the ``cls`` kwarg.
+    """
+    # cached encoder
+    if (skipkeys is False and ensure_ascii is True and
+        check_circular is True and allow_nan is True and
+        cls is None and indent is None and separators is None and
+        encoding == 'utf-8' and not kw):
+        iterable = _default_encoder.iterencode(obj)
+    else:
+        if cls is None:
+            cls = JSONEncoder
+        iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+            separators=separators, encoding=encoding, **kw).iterencode(obj)
+    # could accelerate with writelines in some versions of Python, at
+    # a debuggability cost
+    for chunk in iterable:
+        fp.write(chunk)
+
+
+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
+        allow_nan=True, cls=None, indent=None, separators=None,
+        encoding='utf-8', **kw):
+    """
+    Serialize ``obj`` to a JSON formatted ``str``.
+
+    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 
+    will be skipped instead of raising a ``TypeError``.
+
+    If ``ensure_ascii`` is ``False``, then the return value will be a
+    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
+    coercion rules instead of being escaped to an ASCII ``str``.
+
+    If ``check_circular`` is ``False``, then the circular reference check
+    for container types will be skipped and a circular reference will
+    result in an ``OverflowError`` (or worse).
+
+    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
+    strict compliance of the JSON specification, instead of using the
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+    If ``indent`` is a non-negative integer, then JSON array elements and
+    object members will be pretty-printed with that indent level. An indent
+    level of 0 will only insert newlines. ``None`` is the most compact
+    representation.
+
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
+    then it will be used instead of the default ``(', ', ': ')`` separators.
+    ``(',', ':')`` is the most compact JSON representation.
+
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
+
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+    ``.default()`` method to serialize additional types), specify it with
+    the ``cls`` kwarg.
+    """
+    # cached encoder
+    if (skipkeys is False and ensure_ascii is True and
+        check_circular is True and allow_nan is True and
+        cls is None and indent is None and separators is None and
+        encoding == 'utf-8' and not kw):
+        return _default_encoder.encode(obj)
+    if cls is None:
+        cls = JSONEncoder
+    return cls(
+        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+        separators=separators, encoding=encoding,
+        **kw).encode(obj)
+
+_default_decoder = JSONDecoder(encoding=None, object_hook=None)
+
+def load(fp, encoding=None, cls=None, object_hook=None, **kw):
+    """
+    Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
+    a JSON document) to a Python object.
+
+    If the contents of ``fp`` is encoded with an ASCII based encoding other
+    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
+    be specified. Encodings that are not ASCII based (such as UCS-2) are
+    not allowed, and should be wrapped with
+    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
+    object and passed to ``loads()``
+
+    ``object_hook`` is an optional function that will be called with the
+    result of any object literal decode (a ``dict``). The return value of
+    ``object_hook`` will be used instead of the ``dict``. This feature
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+    
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+    kwarg.
+    """
+    return loads(fp.read(),
+        encoding=encoding, cls=cls, object_hook=object_hook, **kw)
+
+def loads(s, encoding=None, cls=None, object_hook=None, **kw):
+    """
+    Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
+    document) to a Python object.
+
+    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
+    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
+    must be specified. Encodings that are not ASCII based (such as UCS-2)
+    are not allowed and should be decoded to ``unicode`` first.
+
+    ``object_hook`` is an optional function that will be called with the
+    result of any object literal decode (a ``dict``). The return value of
+    ``object_hook`` will be used instead of the ``dict``. This feature
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+    kwarg.
+    """
+    if cls is None and encoding is None and object_hook is None and not kw:
+        return _default_decoder.decode(s)
+    if cls is None:
+        cls = JSONDecoder
+    if object_hook is not None:
+        kw['object_hook'] = object_hook
+    return cls(encoding=encoding, **kw).decode(s)
+
+def read(s):
+    """
+    json-py API compatibility hook. Use loads(s) instead.
+    """
+    import warnings
+    warnings.warn("simplejson.loads(s) should be used instead of read(s)",
+        DeprecationWarning)
+    return loads(s)
+
+def write(obj):
+    """
+    json-py API compatibility hook. Use dumps(s) instead.
+    """
+    import warnings
+    warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
+        DeprecationWarning)
+    return dumps(obj)
+
+


Mime
View raw message