updated pg8000 imports

This commit is contained in:
ilvalle
2015-02-01 17:56:30 +01:00
parent 0f9fe09a15
commit 7bbeb669b9
4 changed files with 108 additions and 85 deletions
+15 -6
View File
@@ -38,7 +38,7 @@ for fmt in (
import datetime
import time
from pg8000.six import binary_type, integer_types, PY2
from .six import binary_type, integer_types, PY2
min_int2, max_int2 = -2 ** 15, 2 ** 15
min_int4, max_int4 = -2 ** 31, 2 ** 31
@@ -274,7 +274,7 @@ class Interval(object):
def __neq__(self, other):
return not self.__eq__(other)
import pg8000.core
from .core import Connection
def connect(
@@ -291,6 +291,10 @@ def connect(
provided, pg8000 looks first for the PGUSER then the USER environment
variables.
If your server character encoding is not ``ascii`` or ``utf8``, then
you need to provide ``user`` as bytes, eg.
``"my_name".encode('EUC-JP')``.
:keyword host:
The hostname of the PostgreSQL server to connect with. Providing this
parameter is necessary for TCP/IP connections. One of either ``host``
@@ -311,6 +315,10 @@ def connect(
optional; if omitted, the PostgreSQL server will assume the database
name is the same as the username.
If your server character encoding is not ``ascii`` or ``utf8``, then
you need to provide ``database`` as bytes, eg.
``"my_db".encode('EUC-JP')``.
:keyword password:
The user password to connect to the server with. This parameter is
optional; if omitted and the database server requests password-based
@@ -324,7 +332,7 @@ def connect(
:rtype:
A :class:`Connection` object.
"""
return pg8000.core.Connection(
return Connection(
user, host, unix_sock, port, database, password, ssl)
apilevel = "2.0"
@@ -472,7 +480,7 @@ def Binary(value):
return value
from pg8000.core import utc, Connection, Cursor
from .core import utc, Cursor
__all__ = [
Warning, Bytea, DataError, DatabaseError, connect, InterfaceError,
@@ -481,10 +489,11 @@ __all__ = [
ArrayDimensionsNotConsistentError, ArrayContentNotSupportedError, utc,
Connection, Cursor]
from ._version import get_versions
__version__ = get_versions()['version']
"""Version string for pg8000.
.. versionadded:: 1.9.11
"""
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
+45 -43
View File
@@ -1,20 +1,26 @@
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (build by setup.py sdist) and build
# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.10 (https://github.com/warner/python-versioneer)
# versioneer-0.12 (https://github.com/warner/python-versioneer)
# these strings will be replaced by git during git-archive
git_refnames = "$Format:%d$"
git_full = "$Format:%H$"
# these strings are filled in when 'setup.py versioneer' creates _version.py
tag_prefix = ""
parentdir_prefix = "pg8000-"
versionfile_source = "pg8000/_version.py"
import subprocess
import os
import sys
import re
import subprocess
import errno
@@ -50,38 +56,49 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
return stdout
import re
import os.path
def versions_from_parentdir(parentdir_prefix, root, verbose=False):
# Source tarballs conventionally unpack into a directory that includes
# both the project name and a version string.
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
print(
"guessing rootdir is '%s', but '%s' doesn't start with "
"prefix '%s'" % (root, dirname, parentdir_prefix))
return None
return {"version": dirname[len(parentdir_prefix):], "full": ""}
def get_expanded_variables(versionfile_abs):
def git_get_keywords(versionfile_abs):
# the code embedded in _version.py can just fetch the value of these
# variables. When used from setup.py, we don't want to import
# _version.py, so we do it with a regexp instead. This function is not
# used from _version.py.
variables = {}
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
# _version.py.
keywords = {}
try:
f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
variables["refnames"] = mo.group(1)
keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
variables["full"] = mo.group(1)
keywords["full"] = mo.group(1)
f.close()
except EnvironmentError:
pass
return variables
return keywords
def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
refnames = variables["refnames"].strip()
def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
if not keywords:
return {} # keyword-finding function failed to find keywords
refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
print("variables are unexpanded, not using")
print("keywords are unexpanded, not using")
return {} # unexpanded, so not in an unpacked git-archive tarball
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
@@ -107,18 +124,20 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return {"version": r, "full": variables["full"].strip()}
return {
"version": r,
"full": keywords["full"].strip()}
# no suitable tags, so we use the full revision id
if verbose:
print("no suitable tags, using full revision id")
return {
"version": variables["full"].strip(),
"full": variables["full"].strip()}
"version": keywords["full"].strip(),
"full": keywords["full"].strip()}
def versions_from_vcs(tag_prefix, root, verbose=False):
def git_versions_from_vcs(tag_prefix, root, verbose=False):
# this runs 'git' from the root of the source tree. This only gets called
# if the git-archive 'subst' variables were *not* expanded, and
# if the git-archive 'subst' keywords were *not* expanded, and
# _version.py hasn't already been rewritten with a short version string,
# meaning we're inside a checked out source tree.
@@ -150,31 +169,14 @@ def versions_from_vcs(tag_prefix, root, verbose=False):
return {"version": tag, "full": full}
def versions_from_parentdir(parentdir_prefix, root, verbose=False):
# Source tarballs conventionally unpack into a directory that includes
# both the project name and a version string.
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
print(
"guessing rootdir is '%s', but '%s' doesn't start with prefix "
"'%s'" % (root, dirname, parentdir_prefix))
return None
return {"version": dirname[len(parentdir_prefix):], "full": ""}
tag_prefix = ""
parentdir_prefix = "pg8000-"
versionfile_source = "pg8000/_version.py"
def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
# case we can only use expanded variables.
# case we can only use expanded keywords.
variables = {"refnames": git_refnames, "full": git_full}
ver = versions_from_expanded_variables(variables, tag_prefix, verbose)
keywords = {"refnames": git_refnames, "full": git_full}
ver = git_versions_from_keywords(keywords, tag_prefix, verbose)
if ver:
return ver
@@ -183,11 +185,11 @@ def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
# versionfile_source is the relative path from the top of the source
# tree (where the .git directory might live) to this file. Invert
# this to find the root from __file__.
for i in range(len(versionfile_source.split("/"))):
for i in range(len(versionfile_source.split(os.sep))):
root = os.path.dirname(root)
except NameError:
return default
return (versions_from_vcs(tag_prefix, root, verbose)
return (git_versions_from_vcs(tag_prefix, root, verbose)
or versions_from_parentdir(parentdir_prefix, root, verbose)
or default)
+45 -32
View File
@@ -29,7 +29,7 @@ __author__ = "Mathieu Fenniak"
import datetime
from datetime import timedelta
from pg8000 import (
from . import (
Interval, min_int2, max_int2, min_int4, max_int4, min_int8, max_int8,
Bytea, NotSupportedError, ProgrammingError, InternalError, IntegrityError,
OperationalError, DatabaseError, InterfaceError, Error,
@@ -45,11 +45,10 @@ import threading
from struct import pack
from hashlib import md5
from decimal import Decimal
import pg8000
from collections import deque, defaultdict
from itertools import count, islice
from pg8000.six.moves import map
from pg8000.six import b, PY2, integer_types, next, PRE_26, text_type, u
from .six.moves import map
from .six import b, PY2, integer_types, next, PRE_26, text_type, u
from sys import exc_info
from uuid import UUID
from copy import deepcopy
@@ -57,6 +56,12 @@ from calendar import timegm
import os
from distutils.version import LooseVersion
try:
from json import loads
except ImportError:
pass # Can only use JSON with Python 2.6 and above
ZERO = timedelta(0)
@@ -891,7 +896,7 @@ class Connection(object):
return error
def __init__(self, user, host, unix_sock, port, database, password, ssl):
self._client_encoding = "ascii"
self._client_encoding = "utf8"
self._commands_with_count = (
b("INSERT"), b("DELETE"), b("UPDATE"), b("MOVE"),
b("FETCH"), b("COPY"), b("SELECT"))
@@ -911,6 +916,9 @@ class Connection(object):
else:
self.user = user
if isinstance(self.user, text_type):
self.user = self.user.encode('utf8')
self.password = password
self.autocommit = False
self._xid = None
@@ -1085,6 +1093,10 @@ class Connection(object):
def bool_recv(d, o, l):
return d[o] == "\x01"
def json_in(data, offset, length):
return loads(unicode( # noqa
data[offset: offset + length], self._client_encoding))
else:
def text_recv(data, offset, length):
return str(
@@ -1093,6 +1105,10 @@ class Connection(object):
def bool_recv(data, offset, length):
return data[offset] == 1
def json_in(data, offset, length):
return loads(
str(data[offset: offset + length], self._client_encoding))
def time_in(data, offset, length):
hour = int(data[offset:offset + 2])
minute = int(data[offset + 3:offset + 5])
@@ -1131,6 +1147,7 @@ class Connection(object):
25: (FC_BINARY, text_recv), # TEXT type
26: (FC_TEXT, int_in), # oid
28: (FC_TEXT, int_in), # xid
114: (FC_TEXT, json_in), # json
700: (FC_BINARY, float4_recv), # float4
701: (FC_BINARY, float8_recv), # float8
705: (FC_BINARY, text_recv), # unknown
@@ -1157,6 +1174,7 @@ class Connection(object):
1700: (FC_TEXT, numeric_in), # NUMERIC
2275: (FC_BINARY, text_recv), # cstring
2950: (FC_BINARY, uuid_recv), # uuid
3802: (FC_TEXT, json_in), # jsonb
})
self.py_types = {
@@ -1183,7 +1201,7 @@ class Connection(object):
}
if PY2:
self.py_types[pg8000.Bytea] = (17, FC_BINARY, bytea_send) # bytea
self.py_types[Bytea] = (17, FC_BINARY, bytea_send) # bytea
self.py_types[text_type] = (705, FC_TEXT, text_out) # unknown
self.py_types[long] = (705, FC_TEXT, unknown_out) # noqa
@@ -1242,11 +1260,12 @@ class Connection(object):
# String - A parameter name (user, database, or options)
# String - Parameter value
protocol = 196608
val = bytearray(i_pack(protocol) + b("user\x00"))
val.extend(user.encode("ascii") + NULL_BYTE)
val = bytearray(
i_pack(protocol) + b("user\x00") + self.user + NULL_BYTE)
if database is not None:
val.extend(
b("database\x00") + database.encode("ascii") + NULL_BYTE)
if isinstance(database, text_type):
database = database.encode('utf8')
val.extend(b("database\x00") + database + NULL_BYTE)
val.append(0)
self._write(i_pack(len(val) + 4))
self._write(val)
@@ -1421,9 +1440,9 @@ class Connection(object):
self._usock.close()
self._sock = None
except AttributeError:
raise pg8000.InterfaceError("connection is closed")
raise InterfaceError("connection is closed")
except ValueError:
raise pg8000.InterfaceError("connection is closed")
raise InterfaceError("connection is closed")
def close(self):
"""Closes the database connection.
@@ -1478,10 +1497,8 @@ class Connection(object):
"server requesting MD5 password authentication, but no "
"password was provided")
pwd = b("md5") + md5(
md5(
self.password.encode("ascii") +
self.user.encode("ascii")).hexdigest().encode("ascii") +
salt).hexdigest().encode("ascii")
md5(self.password.encode("ascii") + self.user).
hexdigest().encode("ascii") + salt).hexdigest().encode("ascii")
# Byte1('p') - Identifies the message as a password message.
# Int32 - Message length including self.
# String - The password. Password may be encrypted.
@@ -1529,26 +1546,22 @@ class Connection(object):
count = h_unpack(data)[0]
idx = 2
for i in range(count):
field = {'name': data[idx:data.find(NULL_BYTE, idx)]}
idx += len(field['name']) + 1
field.update(
dict(zip((
"table_oid", "column_attrnum", "type_oid",
"type_size", "type_modifier", "format"),
ihihih_unpack(data, idx))))
name = data[idx:data.find(NULL_BYTE, idx)]
idx += len(name) + 1
field = dict(
zip((
"table_oid", "column_attrnum", "type_oid", "type_size",
"type_modifier", "format"), ihihih_unpack(data, idx)))
field['name'] = name
idx += 18
cursor.ps['row_desc'].append(field)
try:
field['pg8000_fc'], field['func'] = self.pg_types[
field['type_oid']]
except KeyError:
raise NotSupportedError(
"type oid " + exc_info()[1] + " not supported")
field['pg8000_fc'], field['func'] = \
self.pg_types[field['type_oid']]
def execute(self, cursor, operation, vals):
if vals is None:
vals = ()
paramstyle = pg8000.paramstyle
from . import paramstyle
cache = self._caches[paramstyle]
try:
@@ -1700,11 +1713,11 @@ class Connection(object):
self._write(FLUSH_MSG)
except ValueError:
if str(exc_info()[1]) == "write to closed file":
raise pg8000.InterfaceError("connection is closed")
raise InterfaceError("connection is closed")
else:
raise exc_info()[1]
except AttributeError:
raise pg8000.InterfaceError("connection is closed")
raise InterfaceError("connection is closed")
def send_EXECUTE(self, cursor):
# Byte1('E') - Identifies the message as an execute message.
+3 -4
View File
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from pydal import DAL as pyDAL
from pydal import Field, SQLCustomType, geoPoint, geoLine, geoPolygon
@@ -128,9 +127,9 @@ from pydal.drivers import DRIVERS
if not DRIVERS.get('pymysql'):
from .contrib import pymysql
DRIVERS['pymysql'] = pymysql
#if not DRIVERS.get('pg8000'):
# from .contrib import pg8000
# DRIVERS['pg8000'] = pg8000
if not DRIVERS.get('pg8000'):
from .contrib import pg8000
DRIVERS['pg8000'] = pg8000
if not DRIVERS.get('pyodbc'):
from .contrib import pypyodbc as pyodbc
DRIVERS['pyodbc'] = pyodbc