mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-29 20:23:45 +03:00
commit
3e52b5445b
|
@ -15,7 +15,7 @@ environment:
|
||||||
# http://www.appveyor.com/docs/installed-software#python
|
# http://www.appveyor.com/docs/installed-software#python
|
||||||
|
|
||||||
# Py 2.7 = VS Ver. 9.0 (VS 2008)
|
# Py 2.7 = VS Ver. 9.0 (VS 2008)
|
||||||
# Py 3.3, 3.4 = VS Ver. 10.0 (VS 2010)
|
# Py 3.4 = VS Ver. 10.0 (VS 2010)
|
||||||
# Py 3.5, 3.6 = VS Ver. 14.0 (VS 2015)
|
# Py 3.5, 3.6 = VS Ver. 14.0 (VS 2015)
|
||||||
|
|
||||||
- PYTHON: C:\Python27-x64
|
- PYTHON: C:\Python27-x64
|
||||||
|
@ -51,15 +51,6 @@ environment:
|
||||||
PYTHON_ARCH: 32
|
PYTHON_ARCH: 32
|
||||||
VS_VER: 10.0
|
VS_VER: 10.0
|
||||||
|
|
||||||
- PYTHON: C:\Python33-x64
|
|
||||||
DISTUTILS_USE_SDK: '1'
|
|
||||||
PYTHON_ARCH: 64
|
|
||||||
VS_VER: 10.0
|
|
||||||
|
|
||||||
- PYTHON: C:\Python33
|
|
||||||
PYTHON_ARCH: 32
|
|
||||||
VS_VER: 10.0
|
|
||||||
|
|
||||||
PSYCOPG2_TESTDB: psycopg2_test
|
PSYCOPG2_TESTDB: psycopg2_test
|
||||||
PSYCOPG2_TESTDB_USER: postgres
|
PSYCOPG2_TESTDB_USER: postgres
|
||||||
PSYCOPG2_TESTDB_PASSWORD: Password12!
|
PSYCOPG2_TESTDB_PASSWORD: Password12!
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -11,6 +11,7 @@ doc/html/*
|
||||||
doc/psycopg2.txt
|
doc/psycopg2.txt
|
||||||
scripts/pypi_docs_upload.py
|
scripts/pypi_docs_upload.py
|
||||||
env
|
env
|
||||||
|
.idea
|
||||||
.tox
|
.tox
|
||||||
/rel
|
/rel
|
||||||
/wheels
|
/wheels
|
||||||
|
|
|
@ -7,11 +7,8 @@ language: python
|
||||||
python:
|
python:
|
||||||
- 2.7
|
- 2.7
|
||||||
- 3.6
|
- 3.6
|
||||||
- 2.6
|
|
||||||
- 3.5
|
- 3.5
|
||||||
- 3.4
|
- 3.4
|
||||||
- 3.3
|
|
||||||
- 3.2
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- python setup.py install
|
- python setup.py install
|
||||||
|
|
8
NEWS
8
NEWS
|
@ -1,6 +1,14 @@
|
||||||
Current release
|
Current release
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
What's new in psycopg 2.8
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
|
||||||
|
- Dropped support for Python 2.6, 3.2, 3.3.
|
||||||
|
|
||||||
|
|
||||||
What's new in psycopg 2.7.4
|
What's new in psycopg 2.7.4
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ between 8.1 and 10 are included in the module.
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
... cur.execute("SELECT ouch FROM aargh;")
|
... cur.execute("SELECT ouch FROM aargh;")
|
||||||
... except Exception, e:
|
... except Exception as e:
|
||||||
... pass
|
... pass
|
||||||
...
|
...
|
||||||
>>> errorcodes.lookup(e.pgcode[:2])
|
>>> errorcodes.lookup(e.pgcode[:2])
|
||||||
|
|
|
@ -17,8 +17,8 @@ The current `!psycopg2` implementation supports:
|
||||||
..
|
..
|
||||||
NOTE: keep consistent with setup.py and the /features/ page.
|
NOTE: keep consistent with setup.py and the /features/ page.
|
||||||
|
|
||||||
- Python 2 versions from 2.6 to 2.7
|
- Python version 2.7
|
||||||
- Python 3 versions from 3.2 to 3.6
|
- Python 3 versions from 3.4 to 3.6
|
||||||
- PostgreSQL server versions from 7.4 to 10
|
- PostgreSQL server versions from 7.4 to 10
|
||||||
- PostgreSQL client library version from 9.1
|
- PostgreSQL client library version from 9.1
|
||||||
|
|
||||||
|
|
|
@ -457,14 +457,12 @@ the connection or globally: see the function
|
||||||
Binary adaptation
|
Binary adaptation
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Python types representing binary objects are converted into
|
Python types representing binary objects are converted into PostgreSQL binary
|
||||||
PostgreSQL binary string syntax, suitable for :sql:`bytea` fields. Such
|
string syntax, suitable for :sql:`bytea` fields. Such types are `buffer`
|
||||||
types are `buffer` (only available in Python 2), `memoryview` (available
|
(only available in Python 2), `memoryview`, `bytearray`, and `bytes` (only in
|
||||||
from Python 2.7), `bytearray` (available from Python 2.6) and `bytes`
|
Python 3: the name is available in Python 2 but it's only an alias for the
|
||||||
(only from Python 3: the name is available from Python 2.6 but it's only an
|
type `!str`). Any object implementing the `Revised Buffer Protocol`__ should
|
||||||
alias for the type `!str`). Any object implementing the `Revised Buffer
|
be usable as binary type. Received data is returned as `!buffer` (in Python 2)
|
||||||
Protocol`__ should be usable as binary type where the protocol is supported
|
|
||||||
(i.e. from Python 2.6). Received data is returned as `!buffer` (in Python 2)
|
|
||||||
or `!memoryview` (in Python 3).
|
or `!memoryview` (in Python 3).
|
||||||
|
|
||||||
.. __: http://www.python.org/dev/peps/pep-3118/
|
.. __: http://www.python.org/dev/peps/pep-3118/
|
||||||
|
|
|
@ -27,9 +27,9 @@ import psycopg2
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
DSN = sys.argv[1]
|
DSN = sys.argv[1]
|
||||||
|
|
||||||
print "Opening connection using dsn:", DSN
|
print("Opening connection using dsn:", DSN)
|
||||||
conn = psycopg2.connect(DSN)
|
conn = psycopg2.connect(DSN)
|
||||||
print "Encoding for this connection is", conn.encoding
|
print("Encoding for this connection is", conn.encoding)
|
||||||
|
|
||||||
curs = conn.cursor()
|
curs = conn.cursor()
|
||||||
try:
|
try:
|
||||||
|
@ -51,16 +51,16 @@ io.close()
|
||||||
|
|
||||||
io = open('copy_from.txt', 'r')
|
io = open('copy_from.txt', 'r')
|
||||||
curs.copy_from(io, 'test_copy')
|
curs.copy_from(io, 'test_copy')
|
||||||
print "1) Copy %d records from file object " % len(data) + \
|
print("1) Copy %d records from file object " % len(data) +
|
||||||
"using defaults (sep: \\t and null = \\N)"
|
"using defaults (sep: \\t and null = \\N)")
|
||||||
io.close()
|
io.close()
|
||||||
|
|
||||||
curs.execute("SELECT * FROM test_copy")
|
curs.execute("SELECT * FROM test_copy")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
print " Select returned %d rows" % len(rows)
|
print(" Select returned %d rows" % len(rows))
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
print(" %s %s\t%s" % (r[0], r[1], r[2]))
|
||||||
curs.execute("delete from test_copy")
|
curs.execute("delete from test_copy")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
@ -75,15 +75,15 @@ io.close()
|
||||||
|
|
||||||
io = open('copy_from.txt', 'r')
|
io = open('copy_from.txt', 'r')
|
||||||
curs.copy_from(io, 'test_copy', ':')
|
curs.copy_from(io, 'test_copy', ':')
|
||||||
print "2) Copy %d records from file object using sep = :" % len(data)
|
print("2) Copy %d records from file object using sep = :" % len(data))
|
||||||
io.close()
|
io.close()
|
||||||
|
|
||||||
curs.execute("SELECT * FROM test_copy")
|
curs.execute("SELECT * FROM test_copy")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
print " Select returned %d rows" % len(rows)
|
print(" Select returned %d rows" % len(rows))
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
print(" %s %s\t%s" % (r[0], r[1], r[2]))
|
||||||
curs.execute("delete from test_copy")
|
curs.execute("delete from test_copy")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
@ -98,15 +98,15 @@ io.close()
|
||||||
|
|
||||||
io = open('copy_from.txt', 'r')
|
io = open('copy_from.txt', 'r')
|
||||||
curs.copy_from(io, 'test_copy', null='NULL')
|
curs.copy_from(io, 'test_copy', null='NULL')
|
||||||
print "3) Copy %d records from file object using null = NULL" % len(data)
|
print("3) Copy %d records from file object using null = NULL" % len(data))
|
||||||
io.close()
|
io.close()
|
||||||
|
|
||||||
curs.execute("SELECT * FROM test_copy")
|
curs.execute("SELECT * FROM test_copy")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
print " Select using cursor returned %d rows" % len(rows)
|
print(" Select using cursor returned %d rows" % len(rows))
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
print(" %s %s\t%s" % (r[0], r[1], r[2]))
|
||||||
curs.execute("delete from test_copy")
|
curs.execute("delete from test_copy")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
@ -119,16 +119,16 @@ io.close()
|
||||||
|
|
||||||
io = open('copy_from.txt', 'r')
|
io = open('copy_from.txt', 'r')
|
||||||
curs.copy_from(io, 'test_copy', ':', 'NULL')
|
curs.copy_from(io, 'test_copy', ':', 'NULL')
|
||||||
print "4) Copy %d records from file object " % len(data) + \
|
print("4) Copy %d records from file object " % len(data) +
|
||||||
"using sep = : and null = NULL"
|
"using sep = : and null = NULL")
|
||||||
io.close()
|
io.close()
|
||||||
|
|
||||||
curs.execute("SELECT * FROM test_copy")
|
curs.execute("SELECT * FROM test_copy")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
print " Select using cursor returned %d rows" % len(rows)
|
print(" Select using cursor returned %d rows" % len(rows))
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
print(" %s %s\t%s" % (r[0], r[1], r[2]))
|
||||||
curs.execute("delete from test_copy")
|
curs.execute("delete from test_copy")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
@ -141,20 +141,20 @@ data.write('\n'.join(['Tom\tJenkins\t37',
|
||||||
data.seek(0)
|
data.seek(0)
|
||||||
|
|
||||||
curs.copy_from(data, 'test_copy')
|
curs.copy_from(data, 'test_copy')
|
||||||
print "5) Copy 3 records from StringIO object using defaults"
|
print("5) Copy 3 records from StringIO object using defaults")
|
||||||
|
|
||||||
curs.execute("SELECT * FROM test_copy")
|
curs.execute("SELECT * FROM test_copy")
|
||||||
rows = curs.fetchall()
|
rows = curs.fetchall()
|
||||||
print " Select using cursor returned %d rows" % len(rows)
|
print(" Select using cursor returned %d rows" % len(rows))
|
||||||
|
|
||||||
for r in rows:
|
for r in rows:
|
||||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
print(" %s %s\t%s" % (r[0], r[1], r[2]))
|
||||||
curs.execute("delete from test_copy")
|
curs.execute("delete from test_copy")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
# simple error test
|
# simple error test
|
||||||
|
|
||||||
print "6) About to raise an error"
|
print("6) About to raise an error")
|
||||||
data = StringIO.StringIO()
|
data = StringIO.StringIO()
|
||||||
data.write('\n'.join(['Tom\tJenkins\t37',
|
data.write('\n'.join(['Tom\tJenkins\t37',
|
||||||
'Madonna\t\N\t45',
|
'Madonna\t\N\t45',
|
||||||
|
@ -163,9 +163,9 @@ data.seek(0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
curs.copy_from(data, 'test_copy')
|
curs.copy_from(data, 'test_copy')
|
||||||
except StandardError, err:
|
except StandardError as err:
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
print " Caught error (as expected):\n", err
|
print(" Caught error (as expected):\n", err)
|
||||||
|
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ import psycopg2.extensions
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
DSN = sys.argv[1]
|
DSN = sys.argv[1]
|
||||||
|
|
||||||
print "Opening connection using dsn:", DSN
|
print("Opening connection using dsn:", DSN)
|
||||||
conn = psycopg2.connect(DSN)
|
conn = psycopg2.connect(DSN)
|
||||||
print "Encoding for this connection is", conn.encoding
|
print("Encoding for this connection is", conn.encoding)
|
||||||
|
|
||||||
|
|
||||||
class NoDataError(psycopg2.ProgrammingError):
|
class NoDataError(psycopg2.ProgrammingError):
|
||||||
|
@ -52,12 +52,12 @@ class Cursor(psycopg2.extensions.cursor):
|
||||||
|
|
||||||
curs = conn.cursor(cursor_factory=Cursor)
|
curs = conn.cursor(cursor_factory=Cursor)
|
||||||
curs.execute("SELECT 1 AS foo")
|
curs.execute("SELECT 1 AS foo")
|
||||||
print "Result of fetchone():", curs.fetchone()
|
print("Result of fetchone():", curs.fetchone())
|
||||||
|
|
||||||
# now let's raise the exception
|
# now let's raise the exception
|
||||||
try:
|
try:
|
||||||
curs.fetchone()
|
curs.fetchone()
|
||||||
except NoDataError, err:
|
except NoDataError as err:
|
||||||
print "Exception caught:", err
|
print("Exception caught:", err)
|
||||||
|
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
|
|
|
@ -84,7 +84,7 @@ def insert_func(conn_or_pool, rows):
|
||||||
try:
|
try:
|
||||||
c.execute("INSERT INTO test_threads VALUES (%s, %s, %s)",
|
c.execute("INSERT INTO test_threads VALUES (%s, %s, %s)",
|
||||||
(str(i), i, float(i)))
|
(str(i), i, float(i)))
|
||||||
except psycopg2.ProgrammingError, err:
|
except psycopg2.ProgrammingError as err:
|
||||||
print name, ": an error occurred; skipping this insert"
|
print name, ": an error occurred; skipping this insert"
|
||||||
print err
|
print err
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
@ -112,10 +112,10 @@ def select_func(conn_or_pool, z):
|
||||||
if MODE == 1:
|
if MODE == 1:
|
||||||
conn_or_pool.putconn(conn)
|
conn_or_pool.putconn(conn)
|
||||||
s = name + ": number of rows fetched: " + str(len(l))
|
s = name + ": number of rows fetched: " + str(len(l))
|
||||||
print s
|
print(s)
|
||||||
except psycopg2.ProgrammingError, err:
|
except psycopg2.ProgrammingError as err:
|
||||||
print name, ": an error occurred; skipping this select"
|
print(name, ": an error occurred; skipping this select")
|
||||||
print err
|
print(err)
|
||||||
|
|
||||||
## create the connection pool or the connections
|
## create the connection pool or the connections
|
||||||
if MODE == 0:
|
if MODE == 0:
|
||||||
|
@ -129,14 +129,14 @@ else:
|
||||||
## create the threads
|
## create the threads
|
||||||
threads = []
|
threads = []
|
||||||
|
|
||||||
print "Creating INSERT threads:"
|
print("Creating INSERT threads:")
|
||||||
for name in INSERT_THREADS:
|
for name in INSERT_THREADS:
|
||||||
t = threading.Thread(None, insert_func, 'Thread-'+name,
|
t = threading.Thread(None, insert_func, 'Thread-'+name,
|
||||||
(conn_insert, ROWS))
|
(conn_insert, ROWS))
|
||||||
t.setDaemon(0)
|
t.setDaemon(0)
|
||||||
threads.append(t)
|
threads.append(t)
|
||||||
|
|
||||||
print "Creating SELECT threads:"
|
print("Creating SELECT threads:")
|
||||||
for name in SELECT_THREADS:
|
for name in SELECT_THREADS:
|
||||||
t = threading.Thread(None, select_func, 'Thread-'+name,
|
t = threading.Thread(None, select_func, 'Thread-'+name,
|
||||||
(conn_select, SELECT_DIV))
|
(conn_select, SELECT_DIV))
|
||||||
|
@ -150,12 +150,12 @@ for t in threads:
|
||||||
# and wait for them to finish
|
# and wait for them to finish
|
||||||
for t in threads:
|
for t in threads:
|
||||||
t.join()
|
t.join()
|
||||||
print t.getName(), "exited OK"
|
print(t.getName(), "exited OK")
|
||||||
|
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
curs.execute("SELECT count(name) FROM test_threads")
|
curs.execute("SELECT count(name) FROM test_threads")
|
||||||
print "Inserted", curs.fetchone()[0], "rows."
|
print("Inserted", curs.fetchone()[0], "rows.")
|
||||||
|
|
||||||
curs.execute("DROP TABLE test_threads")
|
curs.execute("DROP TABLE test_threads")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
|
@ -194,7 +194,7 @@ def _get_json_oids(conn_or_curs, name='json'):
|
||||||
r = curs.fetchone()
|
r = curs.fetchone()
|
||||||
|
|
||||||
# revert the status of the connection as before the command
|
# revert the status of the connection as before the command
|
||||||
if (conn_status != STATUS_IN_TRANSACTION and not conn.autocommit):
|
if conn_status != STATUS_IN_TRANSACTION and not conn.autocommit:
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
|
|
||||||
if not r:
|
if not r:
|
||||||
|
|
|
@ -181,11 +181,8 @@ class Range(object):
|
||||||
return self.__gt__(other)
|
return self.__gt__(other)
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return dict(
|
return {slot: getattr(self, slot)
|
||||||
(slot, getattr(self, slot))
|
for slot in self.__slots__ if hasattr(self, slot)}
|
||||||
for slot in self.__slots__
|
|
||||||
if hasattr(self, slot)
|
|
||||||
)
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
for slot, value in state.items():
|
for slot, value in state.items():
|
||||||
|
|
|
@ -163,7 +163,7 @@ def make_dsn(dsn=None, **kwargs):
|
||||||
kwargs['dbname'] = kwargs.pop('database')
|
kwargs['dbname'] = kwargs.pop('database')
|
||||||
|
|
||||||
# Drop the None arguments
|
# Drop the None arguments
|
||||||
kwargs = dict((k, v) for (k, v) in kwargs.iteritems() if v is not None)
|
kwargs = {k: v for (k, v) in kwargs.iteritems() if v is not None}
|
||||||
|
|
||||||
if dsn is not None:
|
if dsn is not None:
|
||||||
tmp = parse_dsn(dsn)
|
tmp = parse_dsn(dsn)
|
||||||
|
|
|
@ -264,7 +264,7 @@ class RealDictCursor(DictCursorBase):
|
||||||
class RealDictRow(dict):
|
class RealDictRow(dict):
|
||||||
"""A `!dict` subclass representing a data record."""
|
"""A `!dict` subclass representing a data record."""
|
||||||
|
|
||||||
__slots__ = ('_column_mapping')
|
__slots__ = ('_column_mapping',)
|
||||||
|
|
||||||
def __init__(self, cursor):
|
def __init__(self, cursor):
|
||||||
dict.__init__(self)
|
dict.__init__(self)
|
||||||
|
@ -280,7 +280,7 @@ class RealDictRow(dict):
|
||||||
return dict.__setitem__(self, name, value)
|
return dict.__setitem__(self, name, value)
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return (self.copy(), self._column_mapping[:])
|
return self.copy(), self._column_mapping[:]
|
||||||
|
|
||||||
def __setstate__(self, data):
|
def __setstate__(self, data):
|
||||||
self.update(data[0])
|
self.update(data[0])
|
||||||
|
|
12
lib/sql.py
12
lib/sql.py
|
@ -203,12 +203,12 @@ class SQL(Composable):
|
||||||
:rtype: `Composed`
|
:rtype: `Composed`
|
||||||
|
|
||||||
The method is similar to the Python `str.format()` method: the string
|
The method is similar to the Python `str.format()` method: the string
|
||||||
template supports auto-numbered (``{}``, only available from Python
|
template supports auto-numbered (``{}``), numbered (``{0}``,
|
||||||
2.7), numbered (``{0}``, ``{1}``...), and named placeholders
|
``{1}``...), and named placeholders (``{name}``), with positional
|
||||||
(``{name}``), with positional arguments replacing the numbered
|
arguments replacing the numbered placeholders and keywords replacing
|
||||||
placeholders and keywords replacing the named ones. However placeholder
|
the named ones. However placeholder modifiers (``{0!r}``, ``{0:<10}``)
|
||||||
modifiers (``{0!r}``, ``{0:<10}``) are not supported. Only
|
are not supported. Only `!Composable` objects can be passed to the
|
||||||
`!Composable` objects can be passed to the template.
|
template.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class FixedOffsetTimezone(datetime.tzinfo):
|
||||||
|
|
||||||
def __getinitargs__(self):
|
def __getinitargs__(self):
|
||||||
offset_mins = self._offset.seconds // 60 + self._offset.days * 24 * 60
|
offset_mins = self._offset.seconds // 60 + self._offset.days * 24 * 60
|
||||||
return (offset_mins, self._name)
|
return offset_mins, self._name
|
||||||
|
|
||||||
def utcoffset(self, dt):
|
def utcoffset(self, dt):
|
||||||
return self._offset
|
return self._offset
|
||||||
|
|
|
@ -31,8 +31,10 @@
|
||||||
#include <stringobject.h>
|
#include <stringobject.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x02060000
|
#if ((PY_VERSION_HEX < 0x02070000) \
|
||||||
# error "psycopg requires Python >= 2.6"
|
|| ((PY_VERSION_HEX >= 0x03000000) \
|
||||||
|
&& (PY_VERSION_HEX < 0x03040000)) )
|
||||||
|
# error "psycopg requires Python 2.7 or 3.4+"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* hash() return size changed around version 3.2a4 on 64bit platforms. Before
|
/* hash() return size changed around version 3.2a4 on 64bit platforms. Before
|
||||||
|
@ -44,14 +46,6 @@ typedef long Py_hash_t;
|
||||||
typedef unsigned long Py_uhash_t;
|
typedef unsigned long Py_uhash_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Macros defined in Python 2.6 */
|
|
||||||
#ifndef Py_REFCNT
|
|
||||||
#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
|
|
||||||
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
|
|
||||||
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
|
|
||||||
#define PyVarObject_HEAD_INIT(x,n) PyObject_HEAD_INIT(x) n,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* FORMAT_CODE_PY_SSIZE_T is for Py_ssize_t: */
|
/* FORMAT_CODE_PY_SSIZE_T is for Py_ssize_t: */
|
||||||
#define FORMAT_CODE_PY_SSIZE_T "%" PY_FORMAT_SIZE_T "d"
|
#define FORMAT_CODE_PY_SSIZE_T "%" PY_FORMAT_SIZE_T "d"
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,15 @@ def sleep(curs):
|
||||||
# DECLARE zz INSENSITIVE SCROLL CURSOR WITH HOLD FOR
|
# DECLARE zz INSENSITIVE SCROLL CURSOR WITH HOLD FOR
|
||||||
# SELECT now();
|
# SELECT now();
|
||||||
# FOR READ ONLY;""", async = 1)
|
# FOR READ ONLY;""", async = 1)
|
||||||
curs.execute("SELECT now() AS foo", async=1);
|
curs.execute("SELECT now() AS foo", async=1)
|
||||||
sleep(curs)
|
sleep(curs)
|
||||||
print curs.fetchall()
|
print curs.fetchall()
|
||||||
|
|
||||||
#curs.execute("""
|
#curs.execute("""
|
||||||
# FETCH FORWARD 1 FROM zz;""", async = 1)
|
# FETCH FORWARD 1 FROM zz;""", async = 1)
|
||||||
curs.execute("SELECT now() AS bar", async=1);
|
curs.execute("SELECT now() AS bar", async=1)
|
||||||
print curs.fetchall()
|
print curs.fetchall()
|
||||||
|
|
||||||
curs.execute("SELECT now() AS bar");
|
curs.execute("SELECT now() AS bar")
|
||||||
sleep(curs)
|
sleep(curs)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ class B(object):
|
||||||
print "ga called", attr
|
print "ga called", attr
|
||||||
return object.__getattribute__(self, attr)
|
return object.__getattribute__(self, attr)
|
||||||
def _sqlquote(self):
|
def _sqlquote(self):
|
||||||
if self._o == True:
|
if self._o:
|
||||||
return 'It is True'
|
return 'It is True'
|
||||||
else:
|
else:
|
||||||
return 'It is False'
|
return 'It is False'
|
||||||
|
|
|
@ -43,7 +43,7 @@ def main():
|
||||||
dump(i, opt)
|
dump(i, opt)
|
||||||
|
|
||||||
f1 = open('debug-%02d.txt' % (opt.nruns - 1)).readlines()
|
f1 = open('debug-%02d.txt' % (opt.nruns - 1)).readlines()
|
||||||
f2 = open('debug-%02d.txt' % (opt.nruns)).readlines()
|
f2 = open('debug-%02d.txt' % opt.nruns).readlines()
|
||||||
for line in difflib.unified_diff(f1, f2,
|
for line in difflib.unified_diff(f1, f2,
|
||||||
"run %d" % (opt.nruns - 1), "run %d" % opt.nruns):
|
"run %d" % (opt.nruns - 1), "run %d" % opt.nruns):
|
||||||
sys.stdout.write(line)
|
sys.stdout.write(line)
|
||||||
|
@ -52,7 +52,7 @@ def main():
|
||||||
|
|
||||||
if opt.objs:
|
if opt.objs:
|
||||||
f1 = open('objs-%02d.txt' % (opt.nruns - 1)).readlines()
|
f1 = open('objs-%02d.txt' % (opt.nruns - 1)).readlines()
|
||||||
f2 = open('objs-%02d.txt' % (opt.nruns)).readlines()
|
f2 = open('objs-%02d.txt' % opt.nruns).readlines()
|
||||||
for line in difflib.unified_diff(f1, f2,
|
for line in difflib.unified_diff(f1, f2,
|
||||||
"run %d" % (opt.nruns - 1), "run %d" % opt.nruns):
|
"run %d" % (opt.nruns - 1), "run %d" % opt.nruns):
|
||||||
sys.stdout.write(line)
|
sys.stdout.write(line)
|
||||||
|
|
25
setup.py
25
setup.py
|
@ -76,11 +76,8 @@ License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
|
||||||
License :: OSI Approved :: Zope Public License
|
License :: OSI Approved :: Zope Public License
|
||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
Programming Language :: Python :: 2
|
Programming Language :: Python :: 2
|
||||||
Programming Language :: Python :: 2.6
|
|
||||||
Programming Language :: Python :: 2.7
|
Programming Language :: Python :: 2.7
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3.2
|
|
||||||
Programming Language :: Python :: 3.3
|
|
||||||
Programming Language :: Python :: 3.4
|
Programming Language :: Python :: 3.4
|
||||||
Programming Language :: Python :: 3.5
|
Programming Language :: Python :: 3.5
|
||||||
Programming Language :: Python :: 3.6
|
Programming Language :: Python :: 3.6
|
||||||
|
@ -215,8 +212,7 @@ or with the pg_config option in 'setup.cfg'.
|
||||||
|
|
||||||
# Support unicode paths, if this version of Python provides the
|
# Support unicode paths, if this version of Python provides the
|
||||||
# necessary infrastructure:
|
# necessary infrastructure:
|
||||||
if sys.version_info[0] < 3 \
|
if sys.version_info[0] < 3:
|
||||||
and hasattr(sys, 'getfilesystemencoding'):
|
|
||||||
pg_config_path = pg_config_path.encode(
|
pg_config_path = pg_config_path.encode(
|
||||||
sys.getfilesystemencoding())
|
sys.getfilesystemencoding())
|
||||||
|
|
||||||
|
@ -297,7 +293,7 @@ class psycopg_build_ext(build_ext):
|
||||||
|
|
||||||
# For Python versions that use MSVC compiler 2008, re-insert the
|
# For Python versions that use MSVC compiler 2008, re-insert the
|
||||||
# manifest into the resulting .pyd file.
|
# manifest into the resulting .pyd file.
|
||||||
if self.compiler_is_msvc() and sysVer in ((2, 6), (2, 7), (3, 0), (3, 1), (3, 2)):
|
if self.compiler_is_msvc() and sysVer == (2, 7):
|
||||||
platform = get_platform()
|
platform = get_platform()
|
||||||
# Default to the x86 manifest
|
# Default to the x86 manifest
|
||||||
manifest = '_psycopg.vc9.x86.manifest'
|
manifest = '_psycopg.vc9.x86.manifest'
|
||||||
|
@ -319,7 +315,6 @@ class psycopg_build_ext(build_ext):
|
||||||
|
|
||||||
def finalize_win32(self):
|
def finalize_win32(self):
|
||||||
"""Finalize build system configuration on win32 platform."""
|
"""Finalize build system configuration on win32 platform."""
|
||||||
sysVer = sys.version_info[:2]
|
|
||||||
|
|
||||||
# Add compiler-specific arguments:
|
# Add compiler-specific arguments:
|
||||||
extra_compiler_args = []
|
extra_compiler_args = []
|
||||||
|
@ -335,17 +330,6 @@ class psycopg_build_ext(build_ext):
|
||||||
# API code.
|
# API code.
|
||||||
extra_compiler_args.append('-fno-strict-aliasing')
|
extra_compiler_args.append('-fno-strict-aliasing')
|
||||||
|
|
||||||
# Force correct C runtime library linkage:
|
|
||||||
if sysVer <= (2, 3):
|
|
||||||
# Yes: 'msvcr60', rather than 'msvcrt', is the correct value
|
|
||||||
# on the line below:
|
|
||||||
self.libraries.append('msvcr60')
|
|
||||||
elif sysVer in ((2, 4), (2, 5)):
|
|
||||||
self.libraries.append('msvcr71')
|
|
||||||
# Beyond Python 2.5, we take our chances on the default C runtime
|
|
||||||
# library, because we don't know what compiler those future
|
|
||||||
# versions of Python will use.
|
|
||||||
|
|
||||||
for extension in ext: # ext is a global list of Extension objects
|
for extension in ext: # ext is a global list of Extension objects
|
||||||
extension.extra_compile_args.extend(extra_compiler_args)
|
extension.extra_compile_args.extend(extra_compiler_args)
|
||||||
# End of add-compiler-specific arguments section.
|
# End of add-compiler-specific arguments section.
|
||||||
|
@ -414,7 +398,7 @@ class psycopg_build_ext(build_ext):
|
||||||
# *at least* PostgreSQL 7.4 is available (this is the only
|
# *at least* PostgreSQL 7.4 is available (this is the only
|
||||||
# 7.x series supported by psycopg 2)
|
# 7.x series supported by psycopg 2)
|
||||||
pgversion = pg_config_helper.query("version").split()[1]
|
pgversion = pg_config_helper.query("version").split()[1]
|
||||||
except:
|
except Exception:
|
||||||
pgversion = "7.4.0"
|
pgversion = "7.4.0"
|
||||||
|
|
||||||
verre = re.compile(
|
verre = re.compile(
|
||||||
|
@ -619,7 +603,7 @@ try:
|
||||||
f = open("README.rst")
|
f = open("README.rst")
|
||||||
readme = f.read()
|
readme = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
except:
|
except Exception:
|
||||||
print("failed to read readme: ignoring...")
|
print("failed to read readme: ignoring...")
|
||||||
readme = __doc__
|
readme = __doc__
|
||||||
|
|
||||||
|
@ -633,6 +617,7 @@ setup(name="psycopg2",
|
||||||
download_url=download_url,
|
download_url=download_url,
|
||||||
license="LGPL with exceptions or ZPL",
|
license="LGPL with exceptions or ZPL",
|
||||||
platforms=["any"],
|
platforms=["any"],
|
||||||
|
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
|
||||||
description=readme.split("\n")[0],
|
description=readme.split("\n")[0],
|
||||||
long_description="\n".join(readme.split("\n")[2:]).lstrip(),
|
long_description="\n".join(readme.split("\n")[2:]).lstrip(),
|
||||||
classifiers=[x for x in classifiers.split("\n") if x],
|
classifiers=[x for x in classifiers.split("\n") if x],
|
||||||
|
|
|
@ -762,7 +762,7 @@ class DatabaseAPI20Test(unittest.TestCase):
|
||||||
names=cur.fetchall()
|
names=cur.fetchall()
|
||||||
assert len(names) == len(self.samples)
|
assert len(names) == len(self.samples)
|
||||||
s=cur.nextset()
|
s=cur.nextset()
|
||||||
assert s == None,'No more return sets, should return None'
|
assert s is None, 'No more return sets, should return None'
|
||||||
finally:
|
finally:
|
||||||
self.help_nextset_tearDown(cur)
|
self.help_nextset_tearDown(cur)
|
||||||
|
|
||||||
|
|
|
@ -352,8 +352,7 @@ class ParseDsnTestCase(ConnectingTestCase):
|
||||||
"DSN with quoting parsed")
|
"DSN with quoting parsed")
|
||||||
|
|
||||||
# Can't really use assertRaisesRegexp() here since we need to
|
# Can't really use assertRaisesRegexp() here since we need to
|
||||||
# make sure that secret is *not* exposed in the error messgage
|
# make sure that secret is *not* exposed in the error message.
|
||||||
# (and it also requires python >= 2.7).
|
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
# unterminated quote after dbname:
|
# unterminated quote after dbname:
|
||||||
|
|
|
@ -463,9 +463,9 @@ def _has_lo64(conn):
|
||||||
% conn.server_version)
|
% conn.server_version)
|
||||||
|
|
||||||
if 'lo64' not in psycopg2.__version__:
|
if 'lo64' not in psycopg2.__version__:
|
||||||
return (False, "this psycopg build doesn't support the lo64 API")
|
return False, "this psycopg build doesn't support the lo64 API"
|
||||||
|
|
||||||
return (True, "this server and build support the lo64 API")
|
return True, "this server and build support the lo64 API"
|
||||||
|
|
||||||
|
|
||||||
def skip_if_no_lo64(f):
|
def skip_if_no_lo64(f):
|
||||||
|
|
|
@ -32,7 +32,6 @@ from psycopg2 import sql
|
||||||
|
|
||||||
|
|
||||||
class SqlFormatTests(ConnectingTestCase):
|
class SqlFormatTests(ConnectingTestCase):
|
||||||
@skip_before_python(2, 7)
|
|
||||||
def test_pos(self):
|
def test_pos(self):
|
||||||
s = sql.SQL("select {} from {}").format(
|
s = sql.SQL("select {} from {}").format(
|
||||||
sql.Identifier('field'), sql.Identifier('table'))
|
sql.Identifier('field'), sql.Identifier('table'))
|
||||||
|
@ -91,7 +90,6 @@ class SqlFormatTests(ConnectingTestCase):
|
||||||
def test_compose_badnargs(self):
|
def test_compose_badnargs(self):
|
||||||
self.assertRaises(IndexError, sql.SQL("select {0};").format)
|
self.assertRaises(IndexError, sql.SQL("select {0};").format)
|
||||||
|
|
||||||
@skip_before_python(2, 7)
|
|
||||||
def test_compose_badnargs_auto(self):
|
def test_compose_badnargs_auto(self):
|
||||||
self.assertRaises(IndexError, sql.SQL("select {};").format)
|
self.assertRaises(IndexError, sql.SQL("select {};").format)
|
||||||
self.assertRaises(ValueError, sql.SQL("select {} {1};").format, 10, 20)
|
self.assertRaises(ValueError, sql.SQL("select {} {1};").format, 10, 20)
|
||||||
|
|
|
@ -295,7 +295,6 @@ class TypesBasicTests(ConnectingTestCase):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(memoryview, type(o2))
|
self.assertEqual(memoryview, type(o2))
|
||||||
|
|
||||||
@testutils.skip_before_python(2, 7)
|
|
||||||
def testAdaptMemoryview(self):
|
def testAdaptMemoryview(self):
|
||||||
o1 = memoryview(bytearray(range(256)))
|
o1 = memoryview(bytearray(range(256)))
|
||||||
o2 = self.execute("select %s;", (o1,))
|
o2 = self.execute("select %s;", (o1,))
|
||||||
|
|
|
@ -365,9 +365,7 @@ class HstoreTestCase(ConnectingTestCase):
|
||||||
from psycopg2.extras import register_hstore
|
from psycopg2.extras import register_hstore
|
||||||
register_hstore(self.conn)
|
register_hstore(self.conn)
|
||||||
|
|
||||||
ds = []
|
ds = [{}, {'a': 'b', 'c': None}]
|
||||||
ds.append({})
|
|
||||||
ds.append({'a': 'b', 'c': None})
|
|
||||||
|
|
||||||
ab = map(chr, range(32, 128))
|
ab = map(chr, range(32, 128))
|
||||||
ds.append(dict(zip(ab, ab)))
|
ds.append(dict(zip(ab, ab)))
|
||||||
|
|
|
@ -32,38 +32,6 @@ from functools import wraps
|
||||||
from testconfig import dsn, repl_dsn
|
from testconfig import dsn, repl_dsn
|
||||||
|
|
||||||
|
|
||||||
if hasattr(unittest, 'skipIf'):
|
|
||||||
skip = unittest.skip
|
|
||||||
skipIf = unittest.skipIf
|
|
||||||
|
|
||||||
else:
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
def skipIf(cond, msg):
|
|
||||||
def skipIf_(f):
|
|
||||||
@wraps(f)
|
|
||||||
def skipIf__(self):
|
|
||||||
if cond:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter('always', UserWarning)
|
|
||||||
warnings.warn(msg)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
return f(self)
|
|
||||||
return skipIf__
|
|
||||||
return skipIf_
|
|
||||||
|
|
||||||
def skip(msg):
|
|
||||||
return skipIf(True, msg)
|
|
||||||
|
|
||||||
def skipTest(self, msg):
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter('always', UserWarning)
|
|
||||||
warnings.warn(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
unittest.TestCase.skipTest = skipTest
|
|
||||||
|
|
||||||
# Silence warnings caused by the stubbornness of the Python unittest
|
# Silence warnings caused by the stubbornness of the Python unittest
|
||||||
# maintainers
|
# maintainers
|
||||||
# http://bugs.python.org/issue9424
|
# http://bugs.python.org/issue9424
|
||||||
|
|
Loading…
Reference in New Issue
Block a user