Compare commits

...

36 Commits

Author SHA1 Message Date
Daniele Varrazzo
4f1e4a03d1 Bump version for release 2.5.2 2014-01-07 12:00:28 +00:00
Daniele Varrazzo
8aaa4eabca Fixed dealloc of lobject->smode
I put it by mistake into the in the self->conn checked block in the
previous commit.
2013-11-27 12:59:14 +00:00
Daniele Varrazzo
7e9e11ee27 Check connection type in lobject init
Fixes ticket #187.
2013-11-27 12:42:57 +00:00
Daniele Varrazzo
0442fd924f Typo fixes and improvements to new_array_type() docs 2013-10-21 15:26:57 +01:00
Daniele Varrazzo
58c53025d1 Use bytestrings in infinite dates adapter example
Returning strings would result in unclear tracebacks on Py3 (see ticket #163).
2013-10-21 14:35:30 +01:00
Daniele Varrazzo
8d8cc38590 Really test named cursors in test_scroll_named() 2013-10-16 19:09:51 +01:00
Daniele Varrazzo
429ebfc764 Document that named cursors don't raise an exception going out-of-bound
See issue #174 for the details.
2013-10-16 19:08:45 +01:00
Daniele Varrazzo
865b36e005 Document that using %, (, ) in the placeholder name is not supported 2013-10-16 15:36:43 +01:00
Daniele Varrazzo
09cf64dda4 Meaningful connection errors report a meaningful message
Fixes issue #173.
2013-10-16 15:28:16 +01:00
Daniele Varrazzo
0e08fbb20b Fixed pickling of exceptions with no pgerror/pgcode set
Fixes ticket #170.
2013-07-19 16:05:48 +01:00
Daniele Varrazzo
96248d0f09 Fixed titles in newsfile
The first title at the same level of the main releases helps getting a
more regular ToC in the docs main page.
2013-07-19 15:54:35 +01:00
Daniele Varrazzo
bf843fc5f0 Bump to next dev release number 2013-07-19 15:21:16 +01:00
Daniele Varrazzo
68d5d070fe Bump up version for release 2.5.1 2013-06-23 02:01:35 +01:00
Daniele Varrazzo
9b2f4c7d77 Fixed manifest to avoid spurious messages during install
It was a while we were getting::

  no previously-included directories found matching 'doc/src/_build'

at install time. Also avoid a couple of Sphinx build files from sdist
package.
2013-06-23 02:01:35 +01:00
Daniele Varrazzo
468951de25 Fixed doc index entry for infinite dates 2013-06-23 01:24:56 +01:00
Daniele Varrazzo
889b1d826e Untrack the connection before closing to avoid possible double-free
From Gangadharan S.A. Fixes issue #166.
2013-06-20 16:35:01 +01:00
Daniele Varrazzo
9f4b5b37a3 Added doc example to convert date.max to infinity
See issue #163.
2013-06-18 15:01:04 +01:00
Daniele Varrazzo
eb36e75b89 Fixed comparison of Range with non-range objects
Fixes ticket #164.

Patch from Chris Withers on master.
2013-06-18 14:16:06 +01:00
Daniele Varrazzo
8fd228dd28 Added regression test for infinity parsing in dates
...and a couple of typos.
2013-05-11 02:24:25 +01:00
Daniele Varrazzo
1e94018473 Added test to verify copysize handling in copy_expert
Not an original psycopg2 bug but present in pure python implementation,
e.g. ctypes issue #25 and cffi issue #5.

https://github.com/mvantellingen/psycopg2-ctypes/issues/25
https://github.com/chtd/psycopg2cffi/pull/5
2013-05-11 02:24:24 +01:00
Daniele Varrazzo
cc4cabebf0 Skip tests on python implementations without getrefcount()
PyPy is one of these.
2013-05-11 02:24:22 +01:00
Daniele Varrazzo
3a13599a99 A few docs fixes to the usage page 2013-05-01 22:40:39 +01:00
Daniele Varrazzo
c862554fdc Dropped a lot of words from the front matter
Replaced with links to the types adaptation table and the extension docs.
2013-04-26 10:33:06 +01:00
Piotr Kasprzyk
5f320e52f4 Fix multiple misspellings 2013-04-26 10:32:21 +01:00
Daniele Varrazzo
0fc1e3a8c7 Merge branch 'classifiers' into maint_2_5 2013-04-21 21:46:46 +01:00
Daniele Varrazzo
361522cde8 Added explicit Python 2 and Python 3 classifiers
Not sure, but I suspect the "python3" page on PyPy in only based
on the Language :: Python :: 3 classifier, not the more specific ones
2013-04-21 21:46:13 +01:00
Saul Shanabrook
ad5af45ba6 Explicit Python Version Support
Used supported versions from http://initd.org/psycopg/docs/install.html
2013-04-21 21:46:08 +01:00
Daniele Varrazzo
b8fbe599ac Make sure to return a bytes string from numeric range adapter 2013-04-21 20:30:03 +01:00
Daniele Varrazzo
9a1dac6125 Merge branch 'solaris-round' into maint_2_5 2013-04-21 18:43:27 +01:00
Daniele Varrazzo
244a58e5c7 Mention Solaris round fix in NEWS file 2013-04-21 18:43:08 +01:00
Daniele Varrazzo
35086c9ef0 Long ifdef reformatted for readibility 2013-04-21 18:43:08 +01:00
Daniel Enman
e93357ba17 Remove extra || 2013-04-21 18:43:08 +01:00
Daniel Enman
ec4aa95554 Solaris 10+, and illumos distros have round() 2013-04-21 18:43:08 +01:00
Daniele Varrazzo
29e96179f2 The UUID adapter returns bytes instead of str in Python 3
Also added __conform__ method to the adapter.
2013-04-07 22:20:38 +01:00
Daniele Varrazzo
5d3a5c242e Dropped stale entries from MANIFEST.in 2013-04-07 20:05:11 +01:00
Daniele Varrazzo
979c4fc1a6 Bump to next maint release 2013-04-07 18:29:56 +01:00
42 changed files with 286 additions and 1860 deletions

View File

@ -93,7 +93,7 @@ You can compile psycopg under Windows platform with mingw32
Dev-C++ (http://www.bloodshed.net/devcpp.html) and Code::Blocks
(http://www.codeblocks.org). gcc binaries should be in your PATH.
You need a PostgreSQL with include and libary files installed. At least v8.0
You need a PostgreSQL with include and library files installed. At least v8.0
is required.
First you need to create a libpython2X.a as described in

View File

@ -1,16 +1,12 @@
recursive-include psycopg *.c *.h *.manifest
recursive-include lib *.py
recursive-include tests *.py
recursive-include ZPsycopgDA *.py *.gif *.dtml
recursive-include psycopg2da *
recursive-include examples *.py somehackers.jpg whereareyou.jpg
recursive-include debian *
recursive-include doc README HACKING SUCCESS COPYING* ChangeLog-1.x pep-0249.txt
recursive-include doc *.txt *.html *.css *.js Makefile
recursive-include doc/src *.rst *.py *.css Makefile
recursive-include doc/html *
prune doc/src/_build
include doc/Makefile doc/README doc/HACKING doc/SUCCESS doc/COPYING* doc/*.txt
include doc/src/Makefile doc/src/conf.py doc/src/*.rst doc/src/_static/*
recursive-include doc/src/tools *.py
include doc/html/*.html doc/html/*.js doc/html/_sources/*.txt doc/html/_static/*
recursive-include scripts *.py *.sh
include scripts/maketypes.sh scripts/buildtypes.py
include AUTHORS README INSTALL LICENSE NEWS ChangeLog
include AUTHORS README INSTALL LICENSE NEWS
include PKG-INFO MANIFEST.in MANIFEST setup.py setup.cfg Makefile

37
NEWS
View File

@ -1,3 +1,28 @@
Current release
---------------
What's new in psycopg 2.5.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed segfault pickling the exception raised on connection error
(:ticket:`#170`).
- Meaningful connection errors report a meaningful message, thanks to
Alexey Borzenkov (:ticket:`#173`).
- Manually creating `lobject` with the wrong parameter doesn't segfault
(:ticket:`#187`).
What's new in psycopg 2.5.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed build on Solaris 10 and 11 where the round() function is already
declared (:ticket:`#146`).
- Fixed comparison of `Range` with non-range objects (:ticket:`#164`).
Thanks to Chris Withers for the patch.
- Fixed double-free on connection dealloc (:ticket:`#166`). Thanks to
Gangadharan S.A. for the report and fix suggestion.
What's new in psycopg 2.5
-------------------------
@ -181,7 +206,7 @@ New features and changes:
ISO885916, LATIN10, SHIFT_JIS_2004.
- Dropped repeated dictionary lookups with unicode query/parameters.
- Improvements to the named cusors:
- Improvements to the named cursors:
- More efficient iteration on named cursors, fetching 'itersize'
records at time from the backend.
@ -244,7 +269,7 @@ Main new features:
- `dict` to `hstore` adapter and `hstore` to `dict` typecaster, using both
9.0 and pre-9.0 syntax.
- Two-phase commit protocol support as per DBAPI specification.
- Support for payload in notifications received from the backed.
- Support for payload in notifications received from the backend.
- `namedtuple`-returning cursor.
- Query execution cancel.
@ -284,7 +309,7 @@ Bux fixes:
The old register_tstz_w_secs() function is deprecated and will raise a
warning if called.
- Exceptions raised by the column iterator are propagated.
- Exceptions raised by executemany() interators are propagated.
- Exceptions raised by executemany() iterators are propagated.
What's new in psycopg 2.2.1
@ -401,7 +426,7 @@ New features:
Bug fixes:
- Fixed exeception in setup.py.
- Fixed exception in setup.py.
- More robust detection of PostgreSQL development versions.
- Fixed exception in RealDictCursor, introduced in 2.0.10.
@ -783,7 +808,7 @@ What's new in psycopg 1.99.11
* changed 'tuple_factory' cursor attribute name to 'row_factory'.
* the .cursor attribute is gone and connections and cursors are propely
* the .cursor attribute is gone and connections and cursors are properly
gc-managed.
* fixes to the async core.
@ -832,7 +857,7 @@ What's new in psycopg 1.99.8
* now cursors support .fileno() and .isready() methods, to be used in
select() calls.
* .copy_from() and .copy_in() methods are back in (still using the old
protocol, will be updated to use new one in next releasae.)
protocol, will be updated to use new one in next release.)
* fixed memory corruption bug reported on win32 platform.
What's new in psycopg 1.99.7

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ Date: 23 Oct 2001 09:53:11 +0600
We use psycopg and psycopg zope adapter since fisrt public
release (it seems version 0.4). Now it works on 3 our sites and in intranet
applications. We had few problems, but all problems were quckly
applications. We had few problems, but all problems were quickly
solved. The strong side of psycopg is that it's code is well organized
and easy to understand. When I found a problem with non-ISO datestyle in first
version of psycopg, it took for me 15 or 20 minutes to learn code and

View File

@ -255,7 +255,7 @@ Cursor Objects
display_size, internal_size, precision, scale,
null_ok). The first two items (name and type_code) are
mandatory, the other five are optional and must be set to
None if meaningfull values are not provided.
None if meaningful values are not provided.
This attribute will be None for operations that
do not return rows or if the cursor has not had an

View File

@ -678,7 +678,7 @@ The ``connection`` class
Return one of the constants defined in :ref:`poll-constants`. If it
returns `~psycopg2.extensions.POLL_OK` then the connection has been
estabilished or the query results are available on the client.
established or the query results are available on the client.
Otherwise wait until the file descriptor returned by `fileno()` is
ready to read or to write, as explained in :ref:`async-support`.
`poll()` should be also used by the function installed by

View File

@ -332,10 +332,6 @@ The ``cursor`` class
`~psycopg2.ProgrammingError` is raised and the cursor position is
not changed.
The method can be used both for client-side cursors and
:ref:`server-side cursors <server-side-cursors>`. Server-side cursors
can usually scroll backwards only if declared `~cursor.scrollable`.
.. note::
According to the |DBAPI|_, the exception raised for a cursor out
@ -347,6 +343,13 @@ The ``cursor`` class
except (ProgrammingError, IndexError), exc:
deal_with_it(exc)
The method can be used both for client-side cursors and
:ref:`server-side cursors <server-side-cursors>`. Server-side cursors
can usually scroll backwards only if declared `~cursor.scrollable`.
Moving out-of-bound in a server-side cursor doesn't result in an
exception, if the backend doesn't raise any (Postgres doesn't tell us
in a reliable way if we went out of bound).
.. attribute:: arraysize

View File

@ -25,7 +25,7 @@ functionalities defined by the |DBAPI|_.
.. class:: cursor(conn, name=None)
It is the class usually returnded by the `connection.cursor()`
It is the class usually returned by the `connection.cursor()`
method. It is exposed by the `extensions` module in order to allow
subclassing to extend its behaviour: the subclass should be passed to the
`!cursor()` method using the `cursor_factory` parameter. See
@ -352,8 +352,8 @@ details.
`register_type()` to be used.
:param oids: tuple of OIDs of the PostgreSQL type to convert. It should
probably be the oid of the array type (e.g. the ``typarray`` field in
the ``pg_type`` table.
probably contain the oid of the array type (e.g. the ``typarray``
field in the ``pg_type`` table).
:param name: the name of the new type adapter.
:param base_caster: a Psycopg typecaster, e.g. created using the
`new_type()` function. The caster should be able to parse a single
@ -366,11 +366,12 @@ details.
.. note::
The function can be used to create a generic array typecaster,
returning a list of strings: just use the `~psycopg2.STRING` as base
typecaster. For instance, if you want to receive from the database an
array of :sql:`macaddr`, each address represented by string, you can
use::
returning a list of strings: just use `psycopg2.STRING` as base
typecaster. For instance, if you want to receive an array of
:sql:`macaddr` from the database, each address represented by string,
you can use::
# select typarray from pg_type where typname = 'macaddr' -> 1040
psycopg2.extensions.register_type(
psycopg2.extensions.new_array_type(
(1040,), 'MACADDR[]', psycopg2.STRING))
@ -427,7 +428,7 @@ The module exports a few exceptions in addition to the :ref:`standard ones
(subclasses `~psycopg2.OperationalError`)
Error causing transaction rollback (deadlocks, serialisation failures,
Error causing transaction rollback (deadlocks, serialization failures,
etc). It can be trapped specifically to detect a deadlock.
.. versionadded:: 2.0.7
@ -515,7 +516,7 @@ set to one of the following constants:
:sql:`SERIALIZABLE` isolation level. This is the strictest transactions
isolation level, equivalent to having the transactions executed serially
rather than concurrently. However applications using this level must be
prepared to retry reansactions due to serialization failures.
prepared to retry transactions due to serialization failures.
Starting from PostgreSQL 9.1, this mode monitors for conditions which
could make execution of a concurrent set of serializable transactions

View File

@ -41,7 +41,7 @@ If you want to use a `!connection` subclass you can pass it as the
Dictionary-like cursor
^^^^^^^^^^^^^^^^^^^^^^
The dict cursors allow to access to the retrieved records using an iterface
The dict cursors allow to access to the retrieved records using an interface
similar to the Python dictionaries instead of the tuples.
>>> dict_cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
@ -453,6 +453,17 @@ automatically casted into instances of these classes.
.. autoclass:: DateTimeRange
.. autoclass:: DateTimeTZRange
.. note::
Python lacks a representation for :sql:`infinity` date so Psycopg converts
the value to `date.max` and such. When written into the database these
dates will assume their literal value (e.g. :sql:`9999-12-31` instead of
:sql:`infinity`). Check :ref:`infinite-dates-handling` for an example of
an alternative adapter to map `date.max` to :sql:`infinity`. An
alternative dates adapter will be used automatically by the `DateRange`
adapter and so on.
Custom |range| types (created with |CREATE TYPE|_ :sql:`... AS RANGE`) can be
adapted to a custom `Range` subclass:

View File

@ -121,7 +121,7 @@ Psycopg converts :sql:`decimal`\/\ :sql:`numeric` database types into Python `!D
psycopg2.extensions.register_type(DEC2FLOAT)
See :ref:`type-casting-from-sql-to-python` to read the relevant
documentation. If you find `!psycopg2.extensions.DECIMAL` not avalable, use
documentation. If you find `!psycopg2.extensions.DECIMAL` not available, use
`!psycopg2._psycopg.DECIMAL` instead.

View File

@ -15,16 +15,10 @@ Psycopg 2 is mostly implemented in C as a libpq_ wrapper, resulting in being
both efficient and secure. It features client-side and :ref:`server-side
<server-side-cursors>` cursors, :ref:`asynchronous communication
<async-support>` and :ref:`notifications <async-notify>`, |COPY-TO-FROM|__
support, and a flexible :ref:`objects adaptation system
<python-types-adaptation>`. Many basic Python types are supported
out-of-the-box and mapped to matching PostgreSQL data types, such as strings
(both byte strings and Unicode), numbers (ints, longs, floats, decimals),
booleans and date/time objects (both built-in and `mx.DateTime`_), several
types of :ref:`binary objects <adapt-binary>`. Also available are mappings
between lists and PostgreSQL arrays of any supported type, between
:ref:`dictionaries and PostgreSQL hstore <adapt-hstore>`, between
:ref:`tuples/namedtuples and PostgreSQL composite types <adapt-composite>`,
and between Python objects and :ref:`JSON <adapt-json>`.
support. Many Python types are supported out-of-the-box and :ref:`adapted to
matching PostgreSQL data types <python-types-adaptation>`; adaptation can be
extended and customized thanks to a flexible :ref:`objects adaptation system
<adapting-new-types>`.
Psycopg 2 is both Unicode and Python 3 friendly.

View File

@ -100,7 +100,8 @@ many placeholders can use the same values::
... {'int': 10, 'str': "O'Reilly", 'date': datetime.date(2005, 11, 18)})
When parameters are used, in order to include a literal ``%`` in the query you
can use the ``%%`` string.
can use the ``%%`` string. Using characters ``%``, ``(``, ``)`` in the
argument names is not supported.
While the mechanism resembles regular Python strings manipulation, there are a
few subtle differences you should care about when passing parameters to a
@ -298,8 +299,8 @@ proper SQL literals::
Numbers adaptation
^^^^^^^^^^^^^^^^^^
Numeric objects: `int`, `long`, `float`, `~decimal.Decimal` are converted in
the PostgreSQL numerical representation::
Python numeric objects `int`, `long`, `float`, `~decimal.Decimal` are
converted into a PostgreSQL numerical representation::
>>> cur.mogrify("SELECT %s, %s, %s, %s;", (10, 10L, 10.0, Decimal("10.00")))
'SELECT 10, 10, 10.0, 10.00;'
@ -311,7 +312,7 @@ converted into `!Decimal`.
.. note::
Sometimes you may prefer to receive :sql:`numeric` data as `!float`
insted, for performance reason or ease of manipulation: you can configure
instead, for performance reason or ease of manipulation: you can configure
an adapter to :ref:`cast PostgreSQL numeric to Python float <faq-float>`.
This of course may imply a loss of precision.
@ -422,7 +423,7 @@ the connection or globally: see the function
Binary adaptation
^^^^^^^^^^^^^^^^^
Binary types: Python types representing binary objects are converted into
Python types representing binary objects are converted into
PostgreSQL binary string syntax, suitable for :sql:`bytea` fields. Such
types are `buffer` (only available in Python 2), `memoryview` (available
from Python 2.7), `bytearray` (available from Python 2.6) and `bytes`
@ -477,7 +478,7 @@ or `!memoryview` (in Python 3).
Date/Time objects adaptation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Date and time objects: builtin `~datetime.datetime`, `~datetime.date`,
Python builtin `~datetime.datetime`, `~datetime.date`,
`~datetime.time`, `~datetime.timedelta` are converted into PostgreSQL's
:sql:`timestamp[tz]`, :sql:`date`, :sql:`time`, :sql:`interval` data types.
Time zones are supported too. The Egenix `mx.DateTime`_ objects are adapted
@ -496,6 +497,7 @@ the same way::
.. seealso:: `PostgreSQL date/time types
<http://www.postgresql.org/docs/current/static/datatype-datetime.html>`__
.. index::
single: Time Zones
@ -530,6 +532,40 @@ rounded to the nearest minute, with an error of up to 30 seconds.
versions use `psycopg2.extras.register_tstz_w_secs()`.
.. index::
double: Date objects; Infinite
.. _infinite-dates-handling:
Infinite dates handling
'''''''''''''''''''''''
PostgreSQL can store the representation of an "infinite" date, timestamp, or
interval. Infinite dates are not available to Python, so these objects are
mapped to `!date.max`, `!datetime.max`, `!interval.max`. Unfortunately the
mapping cannot be bidirectional so these dates will be stored back into the
database with their values, such as :sql:`9999-12-31`.
It is possible to create an alternative adapter for dates and other objects
to map `date.max` to :sql:`infinity`, for instance::
class InfDateAdapter:
def __init__(self, wrapped):
self.wrapped = wrapped
def getquoted(self):
if self.wrapped == datetime.date.max:
return b"'infinity'::date"
elif self.wrapped == datetime.date.min:
return b"'-infinity'::date"
else:
return psycopg2.extensions.DateFromPy(self.wrapped).getquoted()
psycopg2.extensions.register_adapter(datetime.date, InfDateAdapter)
Of course it will not be possible to write the value of `date.max` in the
database anymore: :sql:`infinity` will be stored instead.
.. _adapt-list:
Lists adaptation
@ -560,7 +596,7 @@ Python lists are converted into PostgreSQL :sql:`ARRAY`\ s::
.. note::
Reading back from PostgreSQL, arrays are converted to lists of Python
objects as expected, but only if the items are of a known known type.
objects as expected, but only if the items are of a known type.
Arrays of unknown types are returned as represented by the database (e.g.
``{a,b,c}``). If you want to convert the items into Python objects you can
easily create a typecaster for :ref:`array of unknown types
@ -576,7 +612,7 @@ Tuples adaptation
double: Tuple; Adaptation
single: IN operator
Python tuples are converted in a syntax suitable for the SQL :sql:`IN`
Python tuples are converted into a syntax suitable for the SQL :sql:`IN`
operator and to represent a composite type::
>>> cur.mogrify("SELECT %s IN %s;", (10, (10, 20, 30)))

View File

@ -79,7 +79,7 @@ for row in curs.fetchall():
print "done"
print " python type of image data is", type(row[0])
# this rollback is required because we can't drop a table with a binary cusor
# this rollback is required because we can't drop a table with a binary cursor
# declared and still open
conn.rollback()

View File

@ -1,4 +1,4 @@
# encoding.py - show to change client enkoding (and test it works)
# encoding.py - show to change client encoding (and test it works)
# -*- encoding: utf8 -*-
#
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>

View File

@ -121,6 +121,8 @@ class Range(object):
return self._bounds is not None
def __eq__(self, other):
if not isinstance(other, Range):
return False
return (self._lower == other._lower
and self._upper == other._upper
and self._bounds == other._bounds)
@ -415,7 +417,7 @@ class NumberRangeAdapter(RangeAdapter):
def getquoted(self):
r = self.adapted
if r.isempty:
return "'empty'"
return b("'empty'")
if not r.lower_inf:
# not exactly: we are relying that none of these object is really
@ -431,8 +433,8 @@ class NumberRangeAdapter(RangeAdapter):
else:
upper = ''
return b("'%s%s,%s%s'" % (
r._bounds[0], lower, upper, r._bounds[1]))
return ("'%s%s,%s%s'" % (
r._bounds[0], lower, upper, r._bounds[1])).encode('ascii')
# TODO: probably won't work with infs, nans and other tricky cases.
register_adapter(NumericRange, NumberRangeAdapter)

View File

@ -82,7 +82,7 @@ STATUS_SYNC = 3 # currently unused
STATUS_ASYNC = 4 # currently unused
STATUS_PREPARED = 5
# This is a usefull mnemonic to check if the connection is in a transaction
# This is a useful mnemonic to check if the connection is in a transaction
STATUS_IN_TRANSACTION = STATUS_BEGIN
"""psycopg asynchronous connection polling values"""

View File

@ -1,7 +1,7 @@
"""Miscellaneous goodies for psycopg2
This module is a generic place used to hold little helper functions
and classes untill a better place in the distribution is found.
and classes until a better place in the distribution is found.
"""
# psycopg/extras.py - miscellaneous extra goodies for psycopg
#
@ -131,7 +131,7 @@ class DictCursor(DictCursorBase):
self._query_executed = 0
class DictRow(list):
"""A row object that allow by-colmun-name access to data."""
"""A row object that allow by-column-name access to data."""
__slots__ = ('_index',)
@ -406,7 +406,7 @@ class MinTimeLoggingConnection(LoggingConnection):
This is just an example of how to sub-class `LoggingConnection` to
provide some extra filtering for the logged queries. Both the
`inizialize()` and `filter()` methods are overwritten to make sure
`initialize()` and `filter()` methods are overwritten to make sure
that only queries executing for more than ``mintime`` ms are logged.
Note that this connection uses the specialized cursor
@ -449,13 +449,15 @@ class UUID_adapter(object):
def __init__(self, uuid):
self._uuid = uuid
def prepare(self, conn):
pass
def __conform__(self, proto):
if proto is _ext.ISQLQuote:
return self
def getquoted(self):
return "'"+str(self._uuid)+"'::uuid"
return b("'%s'::uuid" % self._uuid)
__str__ = getquoted
def __str__(self):
return "'%s'::uuid" % self._uuid
def register_uuid(oids=None, conn_or_curs=None):
"""Create the UUID type and an uuid.UUID adapter.
@ -514,8 +516,8 @@ class Inet(object):
obj.prepare(self._conn)
return obj.getquoted() + b("::inet")
def __conform__(self, foo):
if foo is _ext.ISQLQuote:
def __conform__(self, proto):
if proto is _ext.ISQLQuote:
return self
def __str__(self):

View File

@ -45,7 +45,7 @@ typedef struct {
HIDDEN PyObject *psyco_Binary(PyObject *module, PyObject *args);
#define psyco_Binary_doc \
"Binary(buffer) -> new binary object\n\n" \
"Build an object capable to hold a bynary string value."
"Build an object capable to hold a binary string value."
#ifdef __cplusplus
}

View File

@ -141,7 +141,10 @@ static int pthread_mutex_init(pthread_mutex_t *mutex, void* fake)
#endif
#endif
#if (defined(__FreeBSD__) && __FreeBSD_version < 503000) || (defined(_WIN32) && !defined(__GNUC__)) || defined(__sun__) || defined(sun)
#if (defined(__FreeBSD__) && __FreeBSD_version < 503000) \
|| (defined(_WIN32) && !defined(__GNUC__)) \
|| (defined(sun) || defined(__sun__)) \
&& (defined(__SunOS_5_8) || defined(__SunOS_5_9))
/* what's this, we have no round function either? */
static double round(double num)
{

View File

@ -226,7 +226,7 @@ conn_get_standard_conforming_strings(PGconn *pgconn)
* The presence of the 'standard_conforming_strings' parameter
* means that the server _accepts_ the E'' quote.
*
* If the paramer is off, the PQescapeByteaConn returns
* If the parameter is off, the PQescapeByteaConn returns
* backslash escaped strings (e.g. '\001' -> "\\001"),
* so the E'' quotes are required to avoid warnings
* if 'escape_string_warning' is set.
@ -642,6 +642,7 @@ static int
_conn_poll_connecting(connectionObject *self)
{
int res = PSYCO_POLL_ERROR;
const char *msg;
Dprintf("conn_poll: poll connecting");
switch (PQconnectPoll(self->pgconn)) {
@ -656,7 +657,11 @@ _conn_poll_connecting(connectionObject *self)
break;
case PGRES_POLLING_FAILED:
case PGRES_POLLING_ACTIVE:
PyErr_SetString(OperationalError, "asynchronous connection failed");
msg = PQerrorMessage(self->pgconn);
if (!(msg && *msg)) {
msg = "asynchronous connection failed";
}
PyErr_SetString(OperationalError, msg);
res = PSYCO_POLL_ERROR;
break;
}
@ -1177,7 +1182,7 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
goto endlock;
}
/* no error, we can proceeed and store the new encoding */
/* no error, we can proceed and store the new encoding */
{
char *tmp = self->encoding;
self->encoding = clean_enc;

View File

@ -1128,10 +1128,13 @@ connection_dealloc(PyObject* obj)
{
connectionObject *self = (connectionObject *)obj;
conn_close(self);
/* Make sure to untrack the connection before calling conn_close, which may
* allow a different thread to try and dealloc the connection again,
* resulting in a double-free segfault (ticket #166). */
PyObject_GC_UnTrack(self);
conn_close(self);
if (self->weakreflist) {
PyObject_ClearWeakRefs(obj);
}

View File

@ -109,7 +109,7 @@ _mogrify(PyObject *var, PyObject *fmt, cursorObject *curs, PyObject **new)
/* if we find '%(' then this is a dictionary, we:
1/ find the matching ')' and extract the key name
2/ locate the value in the dictionary (or return an error)
3/ mogrify the value into something usefull (quoting)...
3/ mogrify the value into something useful (quoting)...
4/ ...and add it to the new dictionary to be used as argument
*/
case '(':
@ -314,7 +314,7 @@ _psyco_curs_merge_query_args(cursorObject *self,
"not all arguments converted"
and return the appropriate ProgrammingError. we do that by grabbing
the curren exception (we will later restore it if the type or the
the current exception (we will later restore it if the type or the
strings do not match.) */
if (!(fquery = Bytes_Format(query, args))) {
@ -1822,7 +1822,7 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
}
}
/* FIXME: why does this raise an excpetion on the _next_ line of code?
/* FIXME: why does this raise an exception on the _next_ line of code?
if (PyObject_IsInstance((PyObject*)conn,
(PyObject *)&connectionType) == 0) {
PyErr_SetString(PyExc_TypeError,

View File

@ -163,8 +163,16 @@ psyco_error_reduce(errorObject *self)
if (2 != PyTuple_GET_SIZE(tuple)) { goto exit; }
if (!(dict = PyDict_New())) { goto error; }
if (0 != PyDict_SetItemString(dict, "pgerror", self->pgerror)) { goto error; }
if (0 != PyDict_SetItemString(dict, "pgcode", self->pgcode)) { goto error; }
if (self->pgerror) {
if (0 != PyDict_SetItemString(dict, "pgerror", self->pgerror)) {
goto error;
}
}
if (self->pgcode) {
if (0 != PyDict_SetItemString(dict, "pgcode", self->pgcode)) {
goto error;
}
}
{
PyObject *newtuple;

View File

@ -355,9 +355,11 @@ lobject_dealloc(PyObject* obj)
{
lobjectObject *self = (lobjectObject *)obj;
if (lobject_close(self) < 0)
PyErr_Print();
Py_XDECREF((PyObject*)self->conn);
if (self->conn) { /* if not, init failed */
if (lobject_close(self) < 0)
PyErr_Print();
Py_XDECREF((PyObject*)self->conn);
}
PyMem_Free(self->smode);
Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = "
@ -372,10 +374,11 @@ lobject_init(PyObject *obj, PyObject *args, PyObject *kwds)
int oid = (int)InvalidOid, new_oid = (int)InvalidOid;
const char *smode = "";
const char *new_file = NULL;
PyObject *conn;
PyObject *conn = NULL;
if (!PyArg_ParseTuple(args, "O|iziz",
&conn, &oid, &smode, &new_oid, &new_file))
if (!PyArg_ParseTuple(args, "O!|iziz",
&connectionType, &conn,
&oid, &smode, &new_oid, &new_file))
return -1;
return lobject_setup((lobjectObject *)obj,

View File

@ -1,4 +1,4 @@
/* microporotocols_proto.h - definiton for psycopg's protocols
/* microporotocols_proto.h - definition for psycopg's protocols
*
* Copyright (C) 2003-2010 Federico Di Gregorio <fog@debian.org>
*

View File

@ -25,7 +25,7 @@
/* IMPORTANT NOTE: no function in this file do its own connection locking
except for pg_execute and pq_fetch (that are somehow high-level). This means
that all the othe functions should be called while holding a lock to the
that all the other functions should be called while holding a lock to the
connection.
*/
@ -153,7 +153,7 @@ exception_from_sqlstate(const char *sqlstate)
This function should be called while holding the GIL.
The function passes the ownership of the pgres to the returned exception,
wherer the pgres was the explicit argument or taken from the cursor.
where the pgres was the explicit argument or taken from the cursor.
So, after calling it curs->pgres will be set to null */
RAISES static void
@ -781,7 +781,7 @@ exit:
means that there is data available to be collected. -1 means an error, the
exception will be set accordingly.
this fucntion locks the connection object
this function locks the connection object
this function call Py_*_ALLOW_THREADS macros */
int
@ -974,7 +974,7 @@ pq_execute(cursorObject *curs, const char *query, int async, int no_result)
/* if the execute was sync, we call pq_fetch() immediately,
to respect the old DBAPI-2.0 compatible behaviour */
if (async == 0) {
Dprintf("pq_execute: entering syncronous DBAPI compatibility mode");
Dprintf("pq_execute: entering synchronous DBAPI compatibility mode");
if (pq_fetch(curs, no_result) < 0) return -1;
}
else {
@ -1041,7 +1041,7 @@ pq_get_last_result(connectionObject *conn)
/* pq_fetch - fetch data after a query
this fucntion locks the connection object
this function locks the connection object
this function call Py_*_ALLOW_THREADS macros
return value:
@ -1335,7 +1335,7 @@ _pq_copy_in_v3(cursorObject *curs)
else if (error == 2)
res = PQputCopyEnd(curs->conn->pgconn, "error in PQputCopyData() call");
else
/* XXX would be nice to propagate the exeption */
/* XXX would be nice to propagate the exception */
res = PQputCopyEnd(curs->conn->pgconn, "error in .read() call");
CLEARPGRES(curs->pgres);
@ -1343,7 +1343,7 @@ _pq_copy_in_v3(cursorObject *curs)
Dprintf("_pq_copy_in_v3: copy ended; res = %d", res);
/* if the result is -1 we should not even try to get a result from the
bacause that will lock the current thread forever */
because that will lock the current thread forever */
if (res == -1) {
pq_raise(curs->conn, curs, NULL);
/* FIXME: pq_raise check the connection but for some reason even

View File

@ -59,7 +59,7 @@ extern "C" {
HIDDEN psyco_errors_fill_RETURN psyco_errors_fill psyco_errors_fill_PROTO;
HIDDEN psyco_errors_set_RETURN psyco_errors_set psyco_errors_set_PROTO;
/* global excpetions */
/* global exceptions */
extern HIDDEN PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
*InternalError, *OperationalError, *ProgrammingError,
*IntegrityError, *DataError, *NotSupportedError;
@ -169,7 +169,7 @@ STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
"Error related to SQL query cancellation."
#define TransactionRollbackError_doc \
"Error causing transaction rollback (deadlocks, serialisation failures, etc)."
"Error causing transaction rollback (deadlocks, serialization failures, etc)."
#endif
#ifdef __cplusplus

View File

@ -437,7 +437,7 @@ static struct {
static int
psyco_errors_init(void)
{
/* the names of the exceptions here reflect the oranization of the
/* the names of the exceptions here reflect the organization of the
psycopg2 module and not the fact the the original error objects
live in _psycopg */

View File

@ -61,7 +61,7 @@ chunk_getreadbuffer(chunkObject *self, Py_ssize_t segment, void **ptr)
if (segment != 0)
{
PyErr_SetString(PyExc_SystemError,
"acessing non-existant buffer segment");
"accessing non-existant buffer segment");
return -1;
}
*ptr = self->base;
@ -160,7 +160,7 @@ typecast_BINARY_cast(const char *s, Py_ssize_t l, PyObject *curs)
}
else {
/* This is a buffer in the classic bytea format. So we can handle it
* to the PQunescapeBytea to have it parsed, rignt? ...Wrong. We
* to the PQunescapeBytea to have it parsed, right? ...Wrong. We
* could, but then we'd have to record whether buffer was allocated by
* Python or by the libpq to dispose it properly. Furthermore the
* PQunescapeBytea interface is not the most brilliant as it wants a

View File

@ -74,7 +74,7 @@ typecastObject_initlist typecast_builtins[] = {
FOOTER = """ {NULL, NULL, NULL, NULL}\n};\n"""
# usefull error reporting function
# useful error reporting function
def error(msg):
"""Report an error on stderr."""
sys.stderr.write(msg+'\n')

View File

@ -28,5 +28,5 @@ have_ssl=0
# Statically link against the postgresql client library.
#static_libpq=1
# Add here eventual extra libreries required to link the module.
# Add here eventual extra libraries required to link the module.
#libraries=

View File

@ -21,7 +21,7 @@ and stable as a rock.
psycopg2 is different from the other database adapter because it was
designed for heavily multi-threaded applications that create and destroy
lots of cursors and make a conspicuous number of concurrent INSERTs or
UPDATEs. psycopg2 also provide full asycronous operations and support
UPDATEs. psycopg2 also provide full asynchronous operations and support
for coroutine libraries.
"""
@ -31,7 +31,13 @@ Intended Audience :: Developers
License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
License :: OSI Approved :: Zope Public License
Programming Language :: Python
Programming Language :: Python :: 2.5
Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.1
Programming Language :: Python :: 3.2
Programming Language :: Python :: 3.3
Programming Language :: C
Programming Language :: SQL
Topic :: Database
@ -76,8 +82,7 @@ except ImportError:
# Take a look at http://www.python.org/dev/peps/pep-0386/
# for a consistent versioning pattern.
PSYCOPG_VERSION = '2.5'
PSYCOPG_VERSION = '2.5.2'
version_flags = ['dt', 'dec']
@ -210,7 +215,7 @@ or with the pg_config option in 'setup.cfg'.
class psycopg_build_ext(build_ext):
"""Conditionally complement the setup.cfg options file.
This class configures the include_dirs, libray_dirs, libraries
This class configures the include_dirs, library_dirs, libraries
options as required by the system. Most of the configuration happens
in finalize_options() method.
@ -362,7 +367,7 @@ class psycopg_build_ext(build_ext):
finalize_linux3 = finalize_linux
def finalize_options(self):
"""Complete the build system configuation."""
"""Complete the build system configuration."""
build_ext.finalize_options(self)
pg_config_helper = PostgresConfig(self)

View File

@ -60,7 +60,7 @@ import sys
# - Now a subclass of TestCase, to avoid requiring the driver stub
# to use multiple inheritance
# - Reversed the polarity of buggy test in test_description
# - Test exception heirarchy correctly
# - Test exception hierarchy correctly
# - self.populate is now self._populate(), so if a driver stub
# overrides self.ddl1 this change propogates
# - VARCHAR columns now have a width, which will hopefully make the
@ -188,7 +188,7 @@ class DatabaseAPI20Test(unittest.TestCase):
def test_Exceptions(self):
# Make sure required exceptions exist, and are in the
# defined heirarchy.
# defined hierarchy.
if sys.version[0] == '3': #under Python 3 StardardError no longer exists
self.failUnless(issubclass(self.driver.Warning,Exception))
self.failUnless(issubclass(self.driver.Error,Exception))
@ -504,7 +504,7 @@ class DatabaseAPI20Test(unittest.TestCase):
self.assertRaises(self.driver.Error,cur.fetchone)
# cursor.fetchone should raise an Error if called after
# executing a query that cannnot return rows
# executing a query that cannot return rows
self.executeDDL1(cur)
self.assertRaises(self.driver.Error,cur.fetchone)
@ -516,7 +516,7 @@ class DatabaseAPI20Test(unittest.TestCase):
self.failUnless(cur.rowcount in (-1,0))
# cursor.fetchone should raise an Error if called after
# executing a query that cannnot return rows
# executing a query that cannot return rows
cur.execute("insert into %sbooze values ('Victoria Bitter')" % (
self.table_prefix
))

View File

@ -449,6 +449,16 @@ class AsyncTests(ConnectingTestCase):
self.wait(self.conn)
self.assertEqual(cur.fetchone(), (42,))
def test_async_connection_error_message(self):
try:
cnn = psycopg2.connect('dbname=thisdatabasedoesntexist', async=True)
self.wait(cnn)
except psycopg2.Error, e:
self.assertNotEqual(str(e), "asynchronous connection failed",
"connection error reason lost")
else:
self.fail("no exception raised")
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View File

@ -199,6 +199,20 @@ class CopyTests(ConnectingTestCase):
f.seek(0)
self.assertEqual(f.readline().rstrip(), about)
# same tests with setting size
f = io.StringIO()
f.write(about)
f.seek(0)
exp_size = 123
# hack here to leave file as is, only check size when reading
real_read = f.read
def read(_size, f=f, exp_size=exp_size):
self.assertEqual(_size, exp_size)
return real_read(_size)
f.read = read
curs.copy_expert('COPY tcopy (data) FROM STDIN', f, size=exp_size)
curs.execute("select data from tcopy;")
self.assertEqual(curs.fetchone()[0], abin)
def _copy_from(self, curs, nrecs, srec, copykw):
f = StringIO()

View File

@ -27,7 +27,7 @@ import psycopg2
import psycopg2.extensions
from psycopg2.extensions import b
from testutils import unittest, ConnectingTestCase, skip_before_postgres
from testutils import skip_if_no_namedtuple
from testutils import skip_if_no_namedtuple, skip_if_no_getrefcount
class CursorTests(ConnectingTestCase):
@ -97,6 +97,7 @@ class CursorTests(ConnectingTestCase):
self.assertEqual(b('SELECT 10.3;'),
cur.mogrify("SELECT %s;", (Decimal("10.3"),)))
@skip_if_no_getrefcount
def test_mogrify_leak_on_multiple_reference(self):
# issue #81: reference leak when a parameter value is referenced
# more than once from a dict.
@ -157,6 +158,7 @@ class CursorTests(ConnectingTestCase):
curs = self.conn.cursor()
w = ref(curs)
del curs
import gc; gc.collect()
self.assert_(w() is None)
def test_null_name(self):
@ -400,7 +402,7 @@ class CursorTests(ConnectingTestCase):
@skip_before_postgres(8, 0)
def test_scroll_named(self):
cur = self.conn.cursor()
cur = self.conn.cursor('tmp', scrollable=True)
cur.execute("select generate_series(0,9)")
cur.scroll(2)
self.assertEqual(cur.fetchone(), (2,))
@ -410,8 +412,6 @@ class CursorTests(ConnectingTestCase):
self.assertEqual(cur.fetchone(), (8,))
cur.scroll(9, mode='absolute')
self.assertEqual(cur.fetchone(), (9,))
self.assertRaises((IndexError, psycopg2.ProgrammingError),
cur.scroll, 10, mode='absolute')
def test_suite():

View File

@ -213,6 +213,14 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
self.assertEqual(value.seconds, 41103)
self.assertEqual(value.microseconds, 876544)
def test_parse_infinity(self):
value = self.DATETIME('-infinity', self.curs)
self.assertEqual(str(value), '0001-01-01 00:00:00')
value = self.DATETIME('infinity', self.curs)
self.assertEqual(str(value), '9999-12-31 23:59:59.999999')
value = self.DATE('infinity', self.curs)
self.assertEqual(str(value), '9999-12-31')
def test_adapt_date(self):
from datetime import date
value = self.execute('select (%s)::date::text',
@ -240,7 +248,7 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
self.assertEqual(seconds, 3674096)
self.assertEqual(int(round((value - seconds) * 1000000)), 123456)
def test_adapt_megative_timedelta(self):
def test_adapt_negative_timedelta(self):
from datetime import timedelta
value = self.execute('select extract(epoch from (%s)::interval)',
[timedelta(days=-42, seconds=45296,
@ -428,7 +436,7 @@ class mxDateTimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
self.assertEqual(seconds, 3674096)
self.assertEqual(int(round((value - seconds) * 1000000)), 123456)
def test_adapt_megative_timedelta(self):
def test_adapt_negative_timedelta(self):
from mx.DateTime import DateTimeDeltaFrom
value = self.execute('select extract(epoch from (%s)::interval)',
[DateTimeDeltaFrom(days=-42,

View File

@ -77,6 +77,10 @@ class LargeObjectTests(LargeObjectTestCase):
self.assertNotEqual(lo, None)
self.assertEqual(lo.mode[0], "w")
def test_connection_needed(self):
self.assertRaises(TypeError,
psycopg2.extensions.lobject, [])
def test_open_non_existent(self):
# By creating then removing a large object, we get an Oid that
# should be unused.

View File

@ -199,7 +199,7 @@ class ExceptionsTestCase(ConnectingTestCase):
self.assertEqual(diag.sqlstate, '42P01')
del diag
gc.collect()
gc.collect(); gc.collect()
assert(w() is None)
@skip_copy_if_green
@ -279,6 +279,21 @@ class ExceptionsTestCase(ConnectingTestCase):
self.assertEqual(e.pgcode, e1.pgcode)
self.assert_(e1.cursor is None)
@skip_before_python(2, 5)
def test_pickle_connection_error(self):
# segfaults on psycopg 2.5.1 - see ticket #170
import pickle
try:
psycopg2.connect('dbname=nosuchdatabasemate')
except psycopg2.Error, exc:
e = exc
e1 = pickle.loads(pickle.dumps(e))
self.assertEqual(e.pgerror, e1.pgerror)
self.assertEqual(e.pgcode, e1.pgcode)
self.assert_(e1.cursor is None)
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View File

@ -1212,6 +1212,19 @@ class RangeTestCase(unittest.TestCase):
assert_not_equal(Range(10, 20), Range(11, 20))
assert_not_equal(Range(10, 20, '[)'), Range(10, 20, '[]'))
def test_eq_wrong_type(self):
from psycopg2.extras import Range
self.assertNotEqual(Range(10, 20), ())
def test_eq_subclass(self):
from psycopg2.extras import Range, NumericRange
class IntRange(NumericRange): pass
class PositiveIntRange(IntRange): pass
self.assertEqual(Range(10, 20), IntRange(10, 20))
self.assertEqual(PositiveIntRange(10, 20), IntRange(10, 20))
def test_not_ordered(self):
from psycopg2.extras import Range
self.assertRaises(TypeError, lambda: Range(empty=True) < Range(0,4))

View File

@ -293,6 +293,15 @@ def skip_if_green(reason):
skip_copy_if_green = skip_if_green("copy in async mode currently not supported")
def skip_if_no_getrefcount(f):
@wraps(f)
def skip_if_no_getrefcount_(self):
if not hasattr(sys, 'getrefcount'):
return self.skipTest('skipped, no sys.getrefcount()')
else:
return f(self)
return skip_if_no_getrefcount_
def script_to_py3(script):
"""Convert a script to Python3 syntax if required."""
if sys.version_info[0] < 3: