You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by rl...@apache.org on 2016/01/06 09:56:12 UTC
[11/13] incubator-hawq git commit: HAWQ-271. Remove external python
modules.
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0672292f/tools/bin/ext/pg8000/protocol.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/protocol.py b/tools/bin/ext/pg8000/protocol.py
deleted file mode 100644
index 377074b..0000000
--- a/tools/bin/ext/pg8000/protocol.py
+++ /dev/null
@@ -1,1340 +0,0 @@
-# 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/0672292f/tools/bin/ext/pg8000/types.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/types.py b/tools/bin/ext/pg8000/types.py
deleted file mode 100644
index c622a7d..0000000
--- a/tools/bin/ext/pg8000/types.py
+++ /dev/null
@@ -1,687 +0,0 @@
-# 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/0672292f/tools/bin/ext/pg8000/util.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pg8000/util.py b/tools/bin/ext/pg8000/util.py
deleted file mode 100644
index d99421e..0000000
--- a/tools/bin/ext/pg8000/util.py
+++ /dev/null
@@ -1,20 +0,0 @@
-
-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/0672292f/tools/bin/ext/pygresql/__init__.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/pygresql/__init__.py b/tools/bin/ext/pygresql/__init__.py
deleted file mode 100644
index e69de29..0000000
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0672292f/tools/bin/ext/simplejson/__init__.py
----------------------------------------------------------------------
diff --git a/tools/bin/ext/simplejson/__init__.py b/tools/bin/ext/simplejson/__init__.py
deleted file mode 100755
index 6f0f605..0000000
--- a/tools/bin/ext/simplejson/__init__.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# 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)
-
-