mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-22 17:06:33 +03:00
Merge from 2.0 branch up to r839.
This commit is contained in:
parent
52666ef5bd
commit
96f631d41e
44
ChangeLog
44
ChangeLog
|
@ -1,3 +1,47 @@
|
|||
2006-09-30 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* ZpsycopgDA/DA.py: applied the infinity patch from 1.1 (fixes #122).
|
||||
|
||||
* psycopg/adapter_datetime.py: fixed conversion problem with seconds
|
||||
in the (59,60) range (fixes #131).
|
||||
|
||||
* ZpsycopgDA/DA.py: we now split on GMT+, GMT-, + or -. This should
|
||||
fix bug #129.
|
||||
|
||||
* psycopg/adapter_datetime.py: now TimeFromTicks and
|
||||
TimestampFromTicks both accept fractionary seconds (fixes #130).
|
||||
|
||||
2006-09-23 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* lib/errorcodes.py: added list of all PostgreSQL error codes
|
||||
compiled by Johan Dahlin.
|
||||
|
||||
* psycopg/psycopg.h: applied compatibility macros from PEP 353.
|
||||
|
||||
* Applied patch 1/3 from Piet Delport; from his email:
|
||||
|
||||
psycopg2-Py_ssize_t-input.diff adjusts variables used for parameters
|
||||
and return values. These changes only prevent overflowing on values
|
||||
greater than 32-bits, so they're not as critical as the other two
|
||||
patches. I tried to leave places unchanged where the input size is
|
||||
already constrained to sizeof(int), but i might have missed a few
|
||||
either way, not being too familiar with the codebase.
|
||||
|
||||
* Applied patch 2/3 from Piet Delport; from his email:
|
||||
|
||||
psycopg2-Py_ssize_t-output.diff adjusts variables used as outputs
|
||||
from CPython API calls: without it the calls try to write 64 bits
|
||||
to 32 bit locations, trampling over adjacent values/pointers,
|
||||
and segfaulting later.
|
||||
|
||||
* Applied patch 1/3 from Piet Delport; from his email:
|
||||
|
||||
psycopg2-PyObject_HEAD.diff adds missing underscores to several
|
||||
"PyObject_HEAD" declarations. As far as i can tell from gdb, the
|
||||
"PyObject HEAD" versions end up accidentally meaning almost exactly
|
||||
the same, but get aligned differently on AMD64, resulting in wrong
|
||||
size calculation and memory corruption later.
|
||||
|
||||
2006-09-11 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* lib/extras.py: ported syntax error fix from 2.0 (#123).
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
# See the LICENSE file for details.
|
||||
|
||||
|
||||
ALLOWED_PSYCOPG_VERSIONS = ('2.0.1', '2.0.2', '2.0.3', '2.0.4', '2.0.5')
|
||||
ALLOWED_PSYCOPG_VERSIONS = ('2.0.1', '2.0.2', '2.0.3', '2.0.4', '2.0.5',
|
||||
'2.0.6')
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
@ -220,7 +221,10 @@ for icon in ('table', 'view', 'stable', 'what', 'field', 'text', 'bin',
|
|||
# convert an ISO timestamp string from postgres to a Zope DateTime object
|
||||
def _cast_DateTime(iso, curs):
|
||||
if iso:
|
||||
return DateTime(re.split("GMT\+?|GMT-?", iso)[0])
|
||||
if iso in ['-infinity', 'infinity']:
|
||||
return iso
|
||||
else:
|
||||
return DateTime(re.split("GMT\+?|GMT-?|\+|-", iso)[0])
|
||||
|
||||
# this will split us into [date, time, GMT/AM/PM(if there)]
|
||||
# dt = str.split(' ')
|
||||
|
@ -235,6 +239,9 @@ def _cast_DateTime(iso, curs):
|
|||
# convert an ISO date string from postgres to a Zope DateTime object
|
||||
def _cast_Date(iso, curs):
|
||||
if iso:
|
||||
if iso in ['-infinity', 'infinity']:
|
||||
return iso
|
||||
else:
|
||||
return DateTime(iso)
|
||||
|
||||
# Convert a time string from postgres to a Zope DateTime object.
|
||||
|
@ -242,6 +249,9 @@ def _cast_Date(iso, curs):
|
|||
# that it has the same DST settings.
|
||||
def _cast_Time(iso, curs):
|
||||
if iso:
|
||||
if iso in ['-infinity', 'infinity']:
|
||||
return iso
|
||||
else:
|
||||
return DateTime(time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time.time())[:3]+
|
||||
time.strptime(iso[:8], "%H:%M:%S")[3:]))
|
||||
|
|
7
debian/README.zpsycopgda2
vendored
Normal file
7
debian/README.zpsycopgda2
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
ZPsycopgDA (in the Debian zope-psycopgda package) is a Zope Database
|
||||
Adapter based on the psycopg Python/PostgreSQL driver. You'll find
|
||||
more information and documentation in the pythonX.Y-psycopg package,
|
||||
where X.Y is the version of your installed Python.
|
||||
|
||||
Details for ZPsycopgDA for Zope are found in the documentation of
|
||||
the python2.3-psycopg package.
|
587
debian/changelog
vendored
587
debian/changelog
vendored
|
@ -1,12 +1,585 @@
|
|||
psycopg2 (1.99.12.1-1) experimental; urgency=low
|
||||
psycopg2 (2.0.5.1-1) unstable; urgency=low
|
||||
|
||||
* Adapted from patches sent by W. Borgert.
|
||||
* Renamed source package to psycopg2.
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 4 Mar 2005 13:11:43 +0100
|
||||
-- Fabio Tranchitella <kobold@debian.org> Tue, 19 Sep 2006 08:22:36 +0200
|
||||
|
||||
psycopg2 (1.99.11-0.1) unstable; urgency=low
|
||||
psycopg2 (2.0.4-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* debian/control:
|
||||
+ removed dependency on python-egenix-mxdatetime.
|
||||
+ added ${shlibs:Depends} for the python-psycopg2 package.
|
||||
(Closes: #381462)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Wed, 9 Aug 2006 10:28:30 +0200
|
||||
|
||||
psycopg2 (2.0.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream major release, new source package. (Closes: #377956)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Sun, 16 Jul 2006 21:43:41 +0200
|
||||
|
||||
psycopg (1.1.21-8) unstable; urgency=low
|
||||
|
||||
* debian/zope-psycopgda.dzproduct: added 2.9 to the list of supported
|
||||
zope versions. (Closes: #376538)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 14 Jul 2006 10:19:54 +0200
|
||||
|
||||
psycopg (1.1.21-7) unstable; urgency=low
|
||||
|
||||
* Moved dh_installzope within an arch-indep target. (Closes: #373842)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 16 Jun 2006 09:37:23 +0200
|
||||
|
||||
psycopg (1.1.21-6) unstable; urgency=low
|
||||
|
||||
* Python policy transition. (Closes: #373482)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Thu, 15 Jun 2006 19:09:36 +0200
|
||||
|
||||
psycopg (1.1.21-5) unstable; urgency=high
|
||||
|
||||
* ypemod.c, new_psyco_bufferobject():
|
||||
- Escape quotes psycopg.Binary() results as '', not as \', since the
|
||||
latter does not work any more with some client encodings with the latest
|
||||
PostgreSQL (in some multi-byte encodings you can exploit \' escaping to
|
||||
inject SQL code, see CVE-2006-2314). (Closes: #369230)
|
||||
Thanks to Martin Pitt and Ubuntu security team for the patch.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Tue, 30 May 2006 22:15:06 +0200
|
||||
|
||||
psycopg (1.1.21-4) unstable; urgency=low
|
||||
|
||||
* debian/rules: remove *.o in the clean target. (Closes: #352835)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Thu, 16 Feb 2006 12:06:53 +0000
|
||||
|
||||
psycopg (1.1.21-3) unstable; urgency=low
|
||||
|
||||
* debian/control: removed build-dependency on postgresql-server-dev-8.0,
|
||||
as suggested by Martin Pitt. (Closes: #339640)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 18 Nov 2005 08:44:26 +0000
|
||||
|
||||
psycopg (1.1.21-2) unstable; urgency=low
|
||||
|
||||
* debian/control: zope-psycopgda should depend on the same version of the
|
||||
psycopg python module. (Closes: #336765)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Wed, 2 Nov 2005 12:07:33 +0000
|
||||
|
||||
psycopg (1.1.21-1) unstable; urgency=low
|
||||
|
||||
* New maintainer; Thanks Federico for your work, and be sure that I'll
|
||||
take care of this package.
|
||||
* New upstream release (Closes: #321592, #320618, #333638)
|
||||
* debian/python2.4-psycopg.dirs: added. (Closes: #319509, #329115)
|
||||
* debian/control: dropped support for python2.1 and
|
||||
python2.2. (Closes: #333639)
|
||||
* debian/control: Standards-Version bumped to 3.6.2, no changes required.
|
||||
* debian/rules: make use of dh_installzope from zope-debhelper to build the
|
||||
zope-psycopgda package.
|
||||
(Closes: #158669, #323599, #268975, #292247, #327415)
|
||||
* debian/control: added build-depends on postgresql-server-dev-8.0.
|
||||
(Closes: #333638)
|
||||
* Re-packaged upstream tarball replacing some broken images.
|
||||
(Closes: #292008, #305392)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 28 Oct 2005 11:24:37 +0000
|
||||
|
||||
psycopg (1.1.19-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Applied patch from Martin Krafft to build Zope 2.7 packages.
|
||||
* Modified to use the new PostgreSQL packages.
|
||||
* Added python 2.4 package (Closes: #301403).
|
||||
* Upstream applied various Ubuntu patches (Closes: #301947, #300893).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Sat, 16 Jul 2005 20:47:08 +0200
|
||||
|
||||
psycopg (1.1.18-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* 1.1.16 fixed rowcount bug (closes: #266299).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 5 Jan 2005 21:05:15 +0100
|
||||
|
||||
psycopg (1.1.17-1) unstable; urgency=high
|
||||
|
||||
* Urgency is still high because 1.1.16 was never uploaded.
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Thu, 19 Nov 2004 01:14:30 +0200
|
||||
|
||||
psycopg (1.1.16-1) unstable; urgency=high
|
||||
|
||||
* New upstream release.
|
||||
* Tagged with urgency=high because fix a grave bug (rowcount) introduced
|
||||
in 1.1.15.
|
||||
* Upstream fix: does not segfault when using COPY TO/COPY FROM in
|
||||
.execute() (closes: #279222).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Sat, 30 Oct 2004 02:35:30 +0200
|
||||
|
||||
psycopg (1.1.15-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Definitely fixed (ah ah) time interval problems (closes: #259213).
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Thu, 29 Jul 2004 23:43:59 +0200
|
||||
|
||||
psycopg (1.1.14-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Don't put two copies of changelog in every package anymore
|
||||
(closes: #256662).
|
||||
* Updated test script works as expected (closes: #231391).
|
||||
* Changes from NMU incorporated in 1.1.12:
|
||||
- zpsycopgda depends on python2.2-psycopg (closes: #227420, #227147).
|
||||
- compiled with postgresql in unstable (close: #220527).
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Fri, 9 Jul 2004 23:01:40 +0200
|
||||
|
||||
psycopg (1.1.13-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 21 May 2004 10:33:54 +0200
|
||||
|
||||
psycopg (1.1.12-1) unstable; urgency=low
|
||||
|
||||
* New upstream release (the "martin you won't have this package"
|
||||
release.)
|
||||
* Integrated changes from NMU releases.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Sun, 16 May 2004 10:14:47 +0200
|
||||
|
||||
psycopg (1.1.10-1.2) unstable; urgency=low
|
||||
|
||||
* Non-maintainer upload. Thinking about taking this package over...
|
||||
* Changed dependency on pyscopgda Python module to Python version 2.2.
|
||||
(closes: #227147, #227420)
|
||||
* Added Lintian overrides for image-in-/usr/lib warnings -- Zope needs
|
||||
these images...
|
||||
|
||||
-- martin f. krafft <madduck@debian.org> Thu, 15 Apr 2004 23:30:40 +0200
|
||||
|
||||
psycopg (1.1.10-1.1) unstable; urgency=low
|
||||
|
||||
* Non-maintainer upload.
|
||||
* No changes - this upload is simply a rebuild against the current unstable
|
||||
instead of experimental postgresql-dev.
|
||||
(closes: #219927, #220141, #220173, #220527)
|
||||
|
||||
-- Peter Hawkins <peterh@debian.org> Sun, 28 Dec 2003 10:57:30 +1100
|
||||
|
||||
psycopg (1.1.10-1) unstable; urgency=low
|
||||
|
||||
* Added download location to debian/copyright file (Closes: #215880).
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Sat, 8 Nov 2003 23:32:40 +0100
|
||||
|
||||
psycopg (1.1.9-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Bug was agains an old 1.0.x version of psycopg (Closes: #208702).
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Wed, 10 Sep 2003 13:04:42 +0200
|
||||
|
||||
psycopg (1.1.8-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Integrated NMU from Matthias Klose (closes: #205746).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 1 Aug 2003 11:50:57 +0200
|
||||
|
||||
psycopg (1.1.5.1-1.1) unstable; urgency=low
|
||||
|
||||
* NMU
|
||||
* Update for python2.3 as the default python version (closes: #205746).
|
||||
|
||||
-- Matthias Klose <doko@debian.org> Fri, 22 Aug 2003 00:02:25 +0200
|
||||
|
||||
psycopg (1.1.7-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Sat, 26 Jul 2003 15:03:39 +0200
|
||||
|
||||
psycopg (1.1.6-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Upstream applied patch from BTS (Closes: #200161).
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Sun, 13 Jul 2003 23:36:04 +0200
|
||||
|
||||
psycopg (1.1.5.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Mon, 23 Jun 2003 00:37:33 +0200
|
||||
|
||||
psycopg (1.1.5-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Sun, 22 Jun 2003 21:30:01 +0200
|
||||
|
||||
psycopg (1.1.4-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 7 May 2003 15:21:31 +0200
|
||||
|
||||
psycopg (1.1.3-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Changed section in debian/control (-> python).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 2 Apr 2003 10:33:36 +0200
|
||||
|
||||
psycopg (1.1.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Started to track the 1.1.x branch.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 25 Feb 2003 01:06:08 +0100
|
||||
|
||||
psycopg (1.0.15.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 14 Feb 2003 16:09:50 +0100
|
||||
|
||||
psycopg (1.0.15-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 12 Feb 2003 23:49:51 +0100
|
||||
|
||||
psycopg (1.0.14-1) unstable; urgency=low
|
||||
|
||||
* Applied patch from John Goerzen to fix memory leak in executemany()
|
||||
and callproc() (Closes: #169284).
|
||||
* New upstream release (Closes: #170297).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 25 Nov 2002 16:50:37 +0100
|
||||
|
||||
psycopg (1.0.13-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Python 2.3 package added (Closes: #160831)
|
||||
* IntegrityError raised when needed (upstream, Closes: #165791)
|
||||
* Packages are lintian clean again.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 25 Oct 2002 11:54:19 +0200
|
||||
|
||||
psycopg (1.0.12-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Fixed wrong url in RELEASE-1.0. (Closes: #153840)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 13 Sep 2002 13:16:36 +0200
|
||||
|
||||
psycopg (1.0.11.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 26 Aug 2002 10:41:54 +0200
|
||||
|
||||
psycopg (1.0.11-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* The dummy python-psycopg package now depends on the new default debian
|
||||
python (2.2) and on python2.2-psycopg.
|
||||
* Removed support for python 1.5 (support for 2.3 has to wait for egenix
|
||||
packages.)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 23 Aug 2002 11:25:01 +0200
|
||||
|
||||
psycopg (1.0.10-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@initd.org> Mon, 22 Jul 2002 02:04:59 +0200
|
||||
|
||||
psycopg (1.0.9-1) unstable; urgency=low
|
||||
|
||||
* Resolved section override (main->interpreters).
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Thu, 20 Jun 2002 14:00:42 +0200
|
||||
|
||||
psycopg (1.0.8-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 23 Apr 2002 22:42:22 +0200
|
||||
|
||||
psycopg (1.0.7.1-2) unstable; urgency=low
|
||||
|
||||
* Moved to main.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 19 Apr 2002 10:06:58 +0200
|
||||
|
||||
psycopg (1.0.7.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Fixed a bug in ./configure; closes: #141774.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 8 Apr 2002 18:54:24 +0200
|
||||
|
||||
psycopg (1.0.7-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 29 Mar 2002 14:24:45 +0100
|
||||
|
||||
psycopg (1.0.6-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Builds with new libpq libraries and header layout.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Thu, 7 Mar 2002 11:59:40 +0100
|
||||
|
||||
psycopg (1.0.5-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 4 Mar 2002 14:43:13 +0100
|
||||
|
||||
psycopg (1.0.4-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 20 Feb 2002 20:37:16 +0100
|
||||
|
||||
psycopg (1.0.3-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 8 Feb 2002 15:17:44 +0100
|
||||
|
||||
psycopg (1.0.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Added package for python2.2 (Closes: #132650).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 8 Feb 2002 00:45:07 +0100
|
||||
|
||||
psycopg (1.0.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Sun, 20 Jan 2002 18:27:22 +0100
|
||||
|
||||
psycopg (1.0-4) unstable; urgency=low
|
||||
|
||||
* Added build depend on plain python, to really close the %£$! #121229
|
||||
bug this time (Closes: #121229).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 28 Nov 2001 10:50:06 +0100
|
||||
|
||||
psycopg (1.0-3) unstable; urgency=low
|
||||
|
||||
* Added explicit build depends on python 1.5 & 2.1 (Closes: #121229).
|
||||
* Fixed bad dependency on python1.5-egenix-mxdatetime.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 26 Nov 2001 17:18:41 +0100
|
||||
|
||||
psycopg (1.0-2) unstable; urgency=low
|
||||
|
||||
* Fixed dependencies as per python policy.
|
||||
* Added default, unversioned psycopg package (python-psycopg).
|
||||
* Added non-US/main and rebuilt after REJECT.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 16 Nov 2001 01:14:54 +0100
|
||||
|
||||
psycopg (1.0-1) unstable; urgency=low
|
||||
|
||||
* New upstream release. 1.0!
|
||||
* Now we build versioned packages for python 1.5 and 2.1.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 13 Nov 2001 19:24:39 +0100
|
||||
|
||||
psycopg (0.99.7-1) unstable; urgency=low
|
||||
|
||||
* New upstream release fixing some little bugs.
|
||||
* This version requires the mx DateTime packages that are not yet in
|
||||
debian... waiting for them I'll distribute both psycopg and unofficial
|
||||
packages on the initd psycopg page.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 18 Sep 2001 23:28:51 +0200
|
||||
|
||||
psycopg (0.99.6-2) unstable; urgency=low
|
||||
|
||||
* Added suggested build-depends (Closes: #112112).
|
||||
* Applied patch by Michael Weber to configure.in, to look for a compiler
|
||||
(Closes: #112024).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Thu, 13 Sep 2001 10:49:37 +0200
|
||||
|
||||
psycopg (0.99.6-1) unstable; urgency=low
|
||||
|
||||
* Added Build-depends line (Closes: #89798).
|
||||
* Now zope-psycopgda requires python-psycopg, zope on debian still runs
|
||||
with python 1.x only (Closes: #108890).
|
||||
* Moved package to non-US (psycopg depends on postgresql that is in
|
||||
non-US, sic).
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 3 Sep 2001 13:02:11 +0200
|
||||
|
||||
psycopg (0.99.5-1) unstable; urgency=low
|
||||
|
||||
* New upstream release with bound variables quoting (Closes: #102843).
|
||||
* The build process set the correct path to DateTime module
|
||||
(Closes: #102838).
|
||||
* Removes .pyc files in prerm (Closes: #104382)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Thu, 12 Jul 2001 12:56:38 +0200
|
||||
|
||||
psycopg (0.99.4-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 2 Jul 2001 15:33:29 +0200
|
||||
|
||||
psycopg (0.99.3-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 20 Jun 2001 12:55:47 +0200
|
||||
|
||||
psycopg (0.99.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 5 Jun 2001 15:37:50 +0200
|
||||
|
||||
psycopg (0.99.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 5 Jun 2001 12:46:18 +0200
|
||||
|
||||
psycopg (0.5.5-1) unstable; urgency=low
|
||||
|
||||
* New upstream release (ok, *we* are the upstream authors, but after
|
||||
putting the -1 in the version i am supposed to say "new upstream
|
||||
version" when the non-debian versions changes, right? ouch...)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 1 Jun 2001 17:18:52 +0200
|
||||
|
||||
psycopg (0.5.4-1) unstable; urgency=low
|
||||
|
||||
* Another bugfixing release.
|
||||
* Added debian revision to be able to release multiple versions with the
|
||||
same upstream version.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 18 May 2001 19:32:59 +0200
|
||||
|
||||
psycopg (0.5.3) unstable; urgency=low
|
||||
|
||||
* Some bugs fixed, new release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 4 May 2001 16:19:09 +0200
|
||||
|
||||
psycopg (0.5.2) unstable; urgency=low
|
||||
|
||||
* New bugfixing release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 27 Apr 2001 09:52:16 +0200
|
||||
|
||||
psycopg (0.5.1) unstable; urgency=low
|
||||
|
||||
* New bugfixing release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 3 Apr 2001 11:13:26 +0200
|
||||
|
||||
psycopg (0.5.0) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 30 Mar 2001 12:54:42 +0200
|
||||
|
||||
psycopg (0.4.7) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
* Lots of small bug fixes (see detailed ChangeLog.)
|
||||
* Includes beginning of DBAPI-2.0 testsuite.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 16 Mar 2001 18:29:03 +0100
|
||||
|
||||
psycopg (0.4.6) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
* Fixed a little bug in debian/rules (does not create an examples
|
||||
directory inside examples.)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 14 Mar 2001 01:00:26 +0100
|
||||
|
||||
psycopg (0.4.5) unstable; urgency=low
|
||||
|
||||
* New upstream (mmm... but one of the upstream authors it is
|
||||
*me*... mmm...) release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 12 Mar 2001 11:41:42 +0100
|
||||
|
||||
psycopg (0.4.4) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
* Fixed Sections in debian/control.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 9 Mar 2001 10:11:02 +0100
|
||||
|
||||
psycopg (0.4.3) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
* Fixed typo in connectionAdd.dtml (Closes: #88817)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Wed, 7 Mar 2001 15:54:35 +0100
|
||||
|
||||
psycopg (0.4.2) unstable; urgency=low
|
||||
|
||||
* New release (fixes bugs in ZPsycopgDA.)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 5 Mar 2001 13:33:39 +0100
|
||||
|
||||
psycopg (0.4.1) unstable; urgency=low
|
||||
|
||||
* New release.
|
||||
* we now create packages for both versions of python in debian
|
||||
(1.5 and 2.0, packages python-* and python2-*)
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 2 Mar 2001 12:10:52 +0100
|
||||
|
||||
psycopg (0.4) unstable; urgency=low
|
||||
|
||||
* News release.
|
||||
* Now debian/rules build the Zope Database Adapter zope-psycopgda too.
|
||||
* Source name changed from python-psycopg to psycopg.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Tue, 27 Feb 2001 15:11:04 +0100
|
||||
|
||||
python-psycopg (0.3) unstable; urgency=low
|
||||
|
||||
* New release. Tons of bugs fixed and new features, see ChangeLog for
|
||||
details.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 26 Feb 2001 21:22:23 +0100
|
||||
|
||||
python-psycopg (0.2) unstable; urgency=low
|
||||
|
||||
* New release. Fixed lots of bugs and memory leaks.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Fri, 16 Feb 2001 11:04:17 +0100
|
||||
|
||||
python-psycopg (0.1) unstable; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Federico Di Gregorio <fog@debian.org> Mon, 12 Feb 2001 14:46:53 +0100
|
||||
|
||||
* Experimental package.
|
||||
|
||||
-- W. Borgert <debacle@debian.org> Sun, 09 Jan 2005 10:14:09 +0000
|
||||
|
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
5
|
66
debian/control
vendored
66
debian/control
vendored
|
@ -1,51 +1,35 @@
|
|||
Source: psycopg2
|
||||
Section: python
|
||||
Priority: optional
|
||||
Build-depends: postgresql-dev, debhelper (>> 3), python2.3-dev, cdbs
|
||||
Maintainer: Federico Di Gregorio <fog@debian.org>
|
||||
Standards-Version: 3.6.1.1
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev, python-central (>= 0.5.0), python (>= 2.3.5-7), python-egenix-mx-base-dev, autoconf, libpq-dev
|
||||
Build-Depends-Indep: zope-debhelper (>= 0.3.2.7)
|
||||
Maintainer: Fabio Tranchitella <kobold@debian.org>
|
||||
Standards-Version: 3.7.2
|
||||
XS-Python-Version: all
|
||||
|
||||
Package: python-psycopg2
|
||||
Architecture: any
|
||||
Section: python
|
||||
Depends: python (>= 2.3), python (<< 2.4), python2.3-psycopg2
|
||||
Description: Python module for PostgreSQL [dummy package]
|
||||
psycopg is a PostgreSQL database adapter for the Python programming
|
||||
language. It was written from scratch with the aim of being very small
|
||||
and fast, and stable as a rock. The main advantages of psycopg are that
|
||||
it supports the full Python DBAPI-2.0 and being thread safe at level 2.
|
||||
Depends: ${python:Depends}, ${shlibs:Depends}
|
||||
Provides: ${python:Provides}
|
||||
XB-Python-Version: ${python:Versions}
|
||||
Description: Python module for PostgreSQL
|
||||
psycopg is a PostgreSQL database adapter for the Python programming language
|
||||
(just like pygresql and popy.) This is version 2, a complete rewrite of the
|
||||
original code to provide new-style classes for connection and cursor objects
|
||||
and other sweet candies. Like the original, psycopg 2 was written with the
|
||||
aim of being very small and fast, and stable as a rock.
|
||||
.
|
||||
psycopg 2 is the next generation psycopg, implementing a much better
|
||||
type system and even more DBAPI extensions:
|
||||
.
|
||||
* support for Python datetime and Decimal types;
|
||||
* complete implementation of adapt() from PEP 246 to convert Python
|
||||
types to PostgreSQL ones;
|
||||
* COPY FROM/COPY TO support;
|
||||
* inehritable connection and cursor objects and support for connection
|
||||
and cursor factories;
|
||||
* automatic encoding conversion and support for unicode queries.
|
||||
.
|
||||
This dummy package just depends on the right, default version of Python
|
||||
and psycopg 2.
|
||||
psycopg 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.
|
||||
psycopg 2 also provides full asycronous operations for the really brave
|
||||
programmer.
|
||||
|
||||
Package: python2.3-psycopg2
|
||||
Architecture: any
|
||||
Package: zope-psycopgda2
|
||||
Architecture: all
|
||||
Section: python
|
||||
Depends: ${shlibs:Depends}, python2.3
|
||||
Description: Python 2.3 module for PostgreSQL
|
||||
psycopg is a PostgreSQL database adapter for the Python programming
|
||||
language. It was written from scratch with the aim of being very small
|
||||
and fast, and stable as a rock. The main advantages of psycopg are that
|
||||
it supports the full Python DBAPI-2.0 and being thread safe at level 2.
|
||||
.
|
||||
psycopg 2 is the next generation psycopg, implementing a much better
|
||||
type system and even more DBAPI extensions:
|
||||
.
|
||||
* support for Python datetime and Decimal types;
|
||||
* complete implementation of adapt() from PEP 246 to convert Python
|
||||
types to PostgreSQL ones;
|
||||
* COPY FROM/COPY TO support;
|
||||
* inehritable connection and cursor objects and support for connection
|
||||
and cursor factories;
|
||||
* automatic encoding conversion and support for unicode queries.
|
||||
Depends: ${zope:Depends}, python-psycopg2 (>= ${Source-Version})
|
||||
Description: Zope database adapter based on python-psycopg
|
||||
The package contains the PostgreSQL database adapter for Zope 2.7, 2.8 and
|
||||
2.9 based on the psycopg2 Python module.
|
||||
|
|
100
debian/copyright
vendored
100
debian/copyright
vendored
|
@ -1,10 +1,102 @@
|
|||
psycopg 2 can be downloaded from:
|
||||
This package was debianized by Fabio Tranchitella <kobold@debian.org> on
|
||||
Sun, 16 Jul 2006 21:10:01 +0200.
|
||||
|
||||
http://initd.org/pub/software/psycopg/ALPHA/
|
||||
psycopg2 can be downloaded from its homepage:
|
||||
|
||||
Copyright (c) 2001-2005 Federico Di Gregorio <fog@debian.org>
|
||||
http://initd.org/projects/psycopg
|
||||
|
||||
This program is distributed under the GNU GPL.
|
||||
The tarball has been re-packed to get rid of the upstream debian/ directory:
|
||||
no other changes have been made to the tarball.
|
||||
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright (C) 2001-2006 Federico Di Gregorio <fog@debian.org>
|
||||
Copyright (C) 2001 Michele Comitini <mcm@initd.org>
|
||||
|
||||
For the files doc/copy_from.py and doc/copy_to.py:
|
||||
Copyright (C) 2001-2005 Federico Di Gregorio <fog@debian.org>
|
||||
Copyright (C) 2002 Tom Jenkins <tjenkins@devis.com>
|
||||
|
||||
For the file tests/dbapi20.py:
|
||||
Copyright (C) 2003 Ian Bicking <ianb@colorstudy.com>
|
||||
|
||||
For the file scripts/ext2html.py:
|
||||
Copyright (C) 2003 Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
|
||||
|
||||
License for psycopg2 and ZPsycopgDA:
|
||||
|
||||
psycopg is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General
|
||||
Public License can be found in '/usr/share/common-licenses/GPL'.
|
||||
|
||||
As a special exception, specific permission is granted for the GPLed
|
||||
code in this distribition to be linked to OpenSSL and PostgreSQL libpq
|
||||
without invoking GPL clause 2(b).
|
||||
|
||||
Note that the GPL was chosen to avoid proprietary adapters based on
|
||||
psycopg code. Using psycopg in a proprietary product (even bundling
|
||||
psycopg with the proprietary product) is fine as long as:
|
||||
|
||||
1. psycopg is called from Python only using only the provided API
|
||||
(i.e., no linking with C code and no C modules based on it); and
|
||||
|
||||
2. all the other points of the GPL are respected (you offer a copy
|
||||
of psycopg's source code, and so on.)
|
||||
|
||||
|
||||
License for the files tests/dbapi20.py and scripts/ext2html.py:
|
||||
|
||||
These modules have been placed in the public domain.
|
||||
|
||||
|
||||
Alternative licenses for ZPsycopgDA:
|
||||
|
||||
If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e.,
|
||||
every file inside the ZPsycopgDA directory) user the ZPL license as
|
||||
published on the Zope web site, http://www.zope.org/Resources/ZPL.
|
||||
|
||||
|
||||
Alternative licenses for psycopg/adapter*.{j,c} and
|
||||
psycopg/microprotocol*.{h.c}:
|
||||
|
||||
Also, the following BSD-like license applies (at your option) to the
|
||||
files following the pattern psycopg/adapter*.{h,c} and
|
||||
psycopg/microprotocol*.{h,c}:
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
psycopg is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
Proprietary licenses:
|
||||
|
||||
A non-exclusive license is available for companies that want to include
|
||||
psycopg in their proprietary products without respecting the spirit of the
|
||||
GPL. The price of the license is one day of development done by the author,
|
||||
at the consulting fee he applies to his usual customers at the day of the
|
||||
request.
|
||||
|
||||
Please contact the upstream author (Federico Di Gregorio <fog@debian.org>)
|
||||
for more information about this license.
|
||||
|
||||
|
|
1
debian/pycompat
vendored
Normal file
1
debian/pycompat
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
2
|
78
debian/rules
vendored
78
debian/rules
vendored
|
@ -1,4 +1,78 @@
|
|||
#!/usr/bin/make -f
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# GNU copyright 1997 to 1999 by Joey Hess.
|
||||
|
||||
include /usr/share/cdbs/1/rules/debhelper.mk
|
||||
include /usr/share/cdbs/1/class/python-distutils.mk
|
||||
PYVERS=$(shell pyversions -r debian/control)
|
||||
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
rm -f configure
|
||||
touch configure-stamp
|
||||
|
||||
build: configure build-stamp
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
for python in $(PYVERS); do \
|
||||
$$python setup.py build ; \
|
||||
done
|
||||
touch build-stamp
|
||||
|
||||
clean: configure
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -fr *-stamp build
|
||||
for python in $(PYVERS); do \
|
||||
$$python setup.py clean ; \
|
||||
done
|
||||
dh_clean
|
||||
|
||||
install-arch: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
# psycopg2
|
||||
for python in $(PYVERS); \
|
||||
do $$python setup.py install --root=$(CURDIR)/debian/python-psycopg2 --no-compile; \
|
||||
done
|
||||
|
||||
install-indep: build
|
||||
# Zope package
|
||||
dh_installzope -p zope-psycopgda2 ZPsycopgDA
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install-indep
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdocs -i AUTHORS debian/README.zpsycopgda2
|
||||
dh_installchangelogs -i
|
||||
dh_link -i
|
||||
dh_compress -i
|
||||
dh_fixperms -i
|
||||
dh_installdeb -i
|
||||
dh_gencontrol -i
|
||||
dh_md5sums -i
|
||||
dh_builddeb -i
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: build install-arch
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdocs -a README AUTHORS doc tests
|
||||
dh_installchangelogs -a ChangeLog
|
||||
dh_link -a
|
||||
dh_strip -a
|
||||
dh_compress -a
|
||||
dh_fixperms -a
|
||||
dh_makeshlibs -a
|
||||
dh_pycentral -a
|
||||
dh_python -a
|
||||
dh_installdeb -a
|
||||
dh_shlibdeps -a
|
||||
dh_gencontrol -a
|
||||
dh_md5sums -a
|
||||
dh_builddeb -a
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
|
|
4
debian/zope-psycopgda2.dzproduct
vendored
Normal file
4
debian/zope-psycopgda2.dzproduct
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: ZPsycopgDA
|
||||
Directory: ZPsycopgDA:2
|
||||
Package: zope-psycopgda2
|
||||
ZopeVersions: 2.9 2.8 2.7
|
324
lib/errorcodes.py
Normal file
324
lib/errorcodes.py
Normal file
|
@ -0,0 +1,324 @@
|
|||
"""Error codes for PostgresSQL
|
||||
|
||||
This module contains symbolic names for all PostgreSQL error codes.
|
||||
"""
|
||||
# psycopg2/errorcodes.py - PostgreSQL error codes
|
||||
#
|
||||
# Copyright (C) 2006 Johan Dahlin <jdahlin@async.com.br>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# Based on:
|
||||
#
|
||||
# http://www.postgresql.org/docs/8.1/static/errcodes-appendix.html
|
||||
#
|
||||
|
||||
# Error classes
|
||||
CLASS_SUCCESSFUL_COMPLETION = '00'
|
||||
CLASS_WARNING = '01'
|
||||
CLASS_NO_DATA = '02'
|
||||
CLASS_SQL_STATEMENT_NOT_YET_COMPLETE = '03'
|
||||
CLASS_CONNECTION_EXCEPTION = '08'
|
||||
CLASS_TRIGGERED_ACTION_EXCEPTION = '09'
|
||||
CLASS_FEATURE_NOT_SUPPORTED = '0A'
|
||||
CLASS_INVALID_TRANSACTION_INITIATION = '0B'
|
||||
CLASS_LOCATOR_EXCEPTION = '0F'
|
||||
CLASS_INVALID_GRANTOR = '0L'
|
||||
CLASS_INVALID_ROLE_SPECIFICATION = '0P'
|
||||
CLASS_CARDINALITY_VIOLATION = '21'
|
||||
CLASS_DATA_EXCEPTION = '22'
|
||||
CLASS_INTEGRITY_CONSTRAINT_VIOLATION = '23'
|
||||
CLASS_INVALID_CURSOR_STATE = '24'
|
||||
CLASS_INVALID_TRANSACTION_STATE = '25'
|
||||
CLASS_INVALID_SQL_STATEMENT_NAME = '26'
|
||||
CLASS_TRIGGERED_DATA_CHANGE_VIOLATION = '27'
|
||||
CLASS_INVALID_AUTHORIZATION_SPECIFICATION = '28'
|
||||
CLASS_DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST = '2B'
|
||||
CLASS_INVALID_TRANSACTION_TERMINATION = '2D'
|
||||
CLASS_SQL_ROUTINE_EXCEPTION = '2F'
|
||||
CLASS_INVALID_CURSOR_NAME = '34'
|
||||
CLASS_EXTERNAL_ROUTINE_EXCEPTION = '38'
|
||||
CLASS_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION = '39'
|
||||
CLASS_SAVEPOINT_EXCEPTION = '3B'
|
||||
CLASS_INVALID_CATALOG_NAME = '3D'
|
||||
CLASS_INVALID_SCHEMA_NAME = '3F'
|
||||
CLASS_TRANSACTION_ROLLBACK = '40'
|
||||
CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION = '42'
|
||||
CLASS_WITH_CHECK_OPTION_VIOLATION = '44'
|
||||
CLASS_INSUFFICIENT_RESOURCES = '53'
|
||||
CLASS_PROGRAM_LIMIT_EXCEEDED = '54'
|
||||
CLASS_OBJECT_NOT_IN_PREREQUISITE_STATE = '55'
|
||||
CLASS_OPERATOR_INTERVENTION = '57'
|
||||
CLASS_SYSTEM_ERROR = '58'
|
||||
CLASS_CONFIGURATION_FILE_ERROR = 'F0'
|
||||
CLASS_PL_PGSQL_ERROR = 'P0'
|
||||
CLASS_INTERNAL_ERROR = 'XX'
|
||||
|
||||
# Class 00 - Successful Completion
|
||||
SUCCESSFUL_COMPLETION = '00'
|
||||
|
||||
# Class 01 - Warning
|
||||
WARNING = '01000'
|
||||
DYNAMIC_RESULT_SETS_RETURNED = '0100C'
|
||||
IMPLICIT_ZERO_BIT_PADDING = '01008'
|
||||
NULL_VALUE_ELIMINATED_IN_SET_FUNCTION = '01003'
|
||||
PRIVILEGE_NOT_GRANTED = '01007'
|
||||
PRIVILEGE_NOT_REVOKED = '01006'
|
||||
STRING_DATA_RIGHT_TRUNCATION = '01004'
|
||||
DEPRECATED_FEATURE = '01P01'
|
||||
|
||||
# Class 02 - No Data (this is also a warning class per the SQL standard)
|
||||
NO_DATA = '02000'
|
||||
NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED = '02001'
|
||||
|
||||
# Class 03 - SQL Statement Not Yet Complete
|
||||
SQL_STATEMENT_NOT_YET_COMPLETE = '03000'
|
||||
|
||||
# Class 08 - Connection Exception
|
||||
CONNECTION_EXCEPTION = '08000'
|
||||
CONNECTION_DOES_NOT_EXIST = '08003'
|
||||
CONNECTION_FAILURE = '08006'
|
||||
SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION = '08001'
|
||||
SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION = '08004'
|
||||
TRANSACTION_RESOLUTION_UNKNOWN = '08007'
|
||||
PROTOCOL_VIOLATION = '08P01'
|
||||
|
||||
# Class 09 - Triggered Action Exception
|
||||
TRIGGERED_ACTION_EXCEPTION = '09000'
|
||||
|
||||
# Class 0A - Feature Not Supported
|
||||
FEATURE_NOT_SUPPORTED = '0A000'
|
||||
|
||||
# Class 0B - Invalid Transaction Initiation
|
||||
INVALID_TRANSACTION_INITIATION = '0B000'
|
||||
|
||||
# Class 0F - Locator Exception
|
||||
LOCATOR_EXCEPTION = '0F000'
|
||||
INVALID_LOCATOR_SPECIFICATION = '0F001'
|
||||
|
||||
# Class 0L - Invalid Grantor
|
||||
INVALID_GRANTOR = '0L000'
|
||||
INVALID_GRANT_OPERATION = '0LP01'
|
||||
|
||||
# Class 0P - Invalid Role Specification
|
||||
INVALID_ROLE_SPECIFICATION = '0P000'
|
||||
|
||||
# Class 21 - Cardinality Violation
|
||||
CARDINALITY_VIOLATION = '21000'
|
||||
|
||||
# Class 22 - Data Exception
|
||||
DATA_EXCEPTION = '22000'
|
||||
ARRAY_SUBSCRIPT_ERROR = '2202E'
|
||||
CHARACTER_NOT_IN_REPERTOIRE = '22021'
|
||||
DATETIME_FIELD_OVERFLOW = '22008'
|
||||
DIVISION_BY_ZERO = '22012'
|
||||
ERROR_IN_ASSIGNMENT = '22005'
|
||||
ESCAPE_CHARACTER_CONFLICT = '2200B'
|
||||
INDICATOR_OVERFLOW = '22022'
|
||||
INTERVAL_FIELD_OVERFLOW = '22015'
|
||||
INVALID_ARGUMENT_FOR_LOGARITHM = '2201E'
|
||||
INVALID_ARGUMENT_FOR_POWER_FUNCTION = '2201F'
|
||||
INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION = '2201G'
|
||||
INVALID_CHARACTER_VALUE_FOR_CAST = '22018'
|
||||
INVALID_DATETIME_FORMAT = '22007'
|
||||
INVALID_ESCAPE_CHARACTER = '22019'
|
||||
INVALID_ESCAPE_OCTET = '2200D'
|
||||
INVALID_ESCAPE_SEQUENCE = '22025'
|
||||
NONSTANDARD_USE_OF_ESCAPE_CHARACTER = '22P06'
|
||||
INVALID_INDICATOR_PARAMETER_VALUE = '22010'
|
||||
INVALID_LIMIT_VALUE = '22020'
|
||||
INVALID_PARAMETER_VALUE = '22023'
|
||||
INVALID_REGULAR_EXPRESSION = '2201B'
|
||||
INVALID_TIME_ZONE_DISPLACEMENT_VALUE = '22009'
|
||||
INVALID_USE_OF_ESCAPE_CHARACTER = '2200C'
|
||||
MOST_SPECIFIC_TYPE_MISMATCH = '2200G'
|
||||
NULL_VALUE_NOT_ALLOWED = '22004'
|
||||
NULL_VALUE_NO_INDICATOR_PARAMETER = '22002'
|
||||
NUMERIC_VALUE_OUT_OF_RANGE = '22003'
|
||||
STRING_DATA_LENGTH_MISMATCH = '22026'
|
||||
STRING_DATA_RIGHT_TRUNCATION = '22001'
|
||||
SUBSTRING_ERROR = '22011'
|
||||
TRIM_ERROR = '22027'
|
||||
UNTERMINATED_C_STRING = '22024'
|
||||
ZERO_LENGTH_CHARACTER_STRING = '2200F'
|
||||
FLOATING_POINT_EXCEPTION = '22P01'
|
||||
INVALID_TEXT_REPRESENTATION = '22P02'
|
||||
INVALID_BINARY_REPRESENTATION = '22P03'
|
||||
BAD_COPY_FILE_FORMAT = '22P04'
|
||||
UNTRANSLATABLE_CHARACTER = '22P05'
|
||||
|
||||
# Class 23 - Integrity Constraint Violation
|
||||
INTEGRITY_CONSTRAINT_VIOLATION = '23000'
|
||||
RESTRICT_VIOLATION = '23001'
|
||||
NOT_NULL_VIOLATION = '23502'
|
||||
FOREIGN_KEY_VIOLATION = '23503'
|
||||
UNIQUE_VIOLATION = '23505'
|
||||
CHECK_VIOLATION = '23514'
|
||||
|
||||
# Class 24 - Invalid Cursor State
|
||||
INVALID_CURSOR_STATE = '24000'
|
||||
|
||||
# Class 25 - Invalid Transaction State
|
||||
INVALID_TRANSACTION_STATE = '25000'
|
||||
ACTIVE_SQL_TRANSACTION = '25001'
|
||||
BRANCH_TRANSACTION_ALREADY_ACTIVE = '25002'
|
||||
HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL = '25008'
|
||||
INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION = '25003'
|
||||
INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION = '25004'
|
||||
NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION = '25005'
|
||||
READ_ONLY_SQL_TRANSACTION = '25006'
|
||||
SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED = '25007'
|
||||
NO_ACTIVE_SQL_TRANSACTION = '25P01'
|
||||
IN_FAILED_SQL_TRANSACTION = '25P02'
|
||||
|
||||
# Class 26 - Invalid SQL Statement Name
|
||||
INVALID_SQL_STATEMENT_NAME = '26000'
|
||||
|
||||
# Class 27 - Triggered Data Change Violation
|
||||
TRIGGERED_DATA_CHANGE_VIOLATION = '27000'
|
||||
|
||||
# Class 28 - Invalid Authorization Specification
|
||||
INVALID_AUTHORIZATION_SPECIFICATION = '28000'
|
||||
|
||||
# Class 2B - Dependent Privilege Descriptors Still Exist
|
||||
DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST = '2B000'
|
||||
DEPENDENT_OBJECTS_STILL_EXIST = '2BP01'
|
||||
|
||||
# Class 2D - Invalid Transaction Termination
|
||||
INVALID_TRANSACTION_TERMINATION = '2D000'
|
||||
|
||||
# Class 2F - SQL Routine Exception
|
||||
SQL_ROUTINE_EXCEPTION = '2F000'
|
||||
FUNCTION_EXECUTED_NO_RETURN_STATEMENT = '2F005'
|
||||
MODIFYING_SQL_DATA_NOT_PERMITTED = '2F002'
|
||||
PROHIBITED_SQL_STATEMENT_ATTEMPTED = '2F003'
|
||||
READING_SQL_DATA_NOT_PERMITTED = '2F004'
|
||||
|
||||
# Class 34 - Invalid Cursor Name
|
||||
INVALID_CURSOR_NAME = '34000'
|
||||
|
||||
# Class 38 - External Routine Exception
|
||||
EXTERNAL_ROUTINE_EXCEPTION = '38000'
|
||||
CONTAINING_SQL_NOT_PERMITTED = '38001'
|
||||
MODIFYING_SQL_DATA_NOT_PERMITTED = '38002'
|
||||
PROHIBITED_SQL_STATEMENT_ATTEMPTED = '38003'
|
||||
READING_SQL_DATA_NOT_PERMITTED = '38004'
|
||||
|
||||
# Class 39 - External Routine Invocation Exception
|
||||
EXTERNAL_ROUTINE_INVOCATION_EXCEPTION = '39000'
|
||||
INVALID_SQLSTATE_RETURNED = '39001'
|
||||
NULL_VALUE_NOT_ALLOWED = '39004'
|
||||
TRIGGER_PROTOCOL_VIOLATED = '39P01'
|
||||
SRF_PROTOCOL_VIOLATED = '39P02'
|
||||
|
||||
# Class 3B - Savepoint Exception
|
||||
SAVEPOINT_EXCEPTION = '3B000'
|
||||
INVALID_SAVEPOINT_SPECIFICATION = '3B001'
|
||||
|
||||
# Class 3D - Invalid Catalog Name
|
||||
INVALID_CATALOG_NAME = '3D000'
|
||||
|
||||
# Class 3F - Invalid Schema Name
|
||||
INVALID_SCHEMA_NAME = '3F000'
|
||||
|
||||
# Class 40 - Transaction Rollback
|
||||
TRANSACTION_ROLLBACK = '40000'
|
||||
TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION = '40002'
|
||||
SERIALIZATION_FAILURE = '40001'
|
||||
STATEMENT_COMPLETION_UNKNOWN = '40003'
|
||||
DEADLOCK_DETECTED = '40P01'
|
||||
|
||||
# Class 42 - Syntax Error or Access Rule Violation
|
||||
SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION = '42000'
|
||||
SYNTAX_ERROR = '42601'
|
||||
INSUFFICIENT_PRIVILEGE = '42501'
|
||||
CANNOT_COERCE = '42846'
|
||||
GROUPING_ERROR = '42803'
|
||||
INVALID_FOREIGN_KEY = '42830'
|
||||
INVALID_NAME = '42602'
|
||||
NAME_TOO_LONG = '42622'
|
||||
RESERVED_NAME = '42939'
|
||||
DATATYPE_MISMATCH = '42804'
|
||||
INDETERMINATE_DATATYPE = '42P18'
|
||||
WRONG_OBJECT_TYPE = '42809'
|
||||
UNDEFINED_COLUMN = '42703'
|
||||
UNDEFINED_FUNCTION = '42883'
|
||||
UNDEFINED_TABLE = '42P01'
|
||||
UNDEFINED_PARAMETER = '42P02'
|
||||
UNDEFINED_OBJECT = '42704'
|
||||
DUPLICATE_COLUMN = '42701'
|
||||
DUPLICATE_CURSOR = '42P03'
|
||||
DUPLICATE_DATABASE = '42P04'
|
||||
DUPLICATE_FUNCTION = '42723'
|
||||
DUPLICATE_PREPARED_STATEMENT = '42P05'
|
||||
DUPLICATE_SCHEMA = '42P06'
|
||||
DUPLICATE_TABLE = '42P07'
|
||||
DUPLICATE_ALIAS = '42712'
|
||||
DUPLICATE_OBJECT = '42710'
|
||||
AMBIGUOUS_COLUMN = '42702'
|
||||
AMBIGUOUS_FUNCTION = '42725'
|
||||
AMBIGUOUS_PARAMETER = '42P08'
|
||||
AMBIGUOUS_ALIAS = '42P09'
|
||||
INVALID_COLUMN_REFERENCE = '42P10'
|
||||
INVALID_COLUMN_DEFINITION = '42611'
|
||||
INVALID_CURSOR_DEFINITION = '42P11'
|
||||
INVALID_DATABASE_DEFINITION = '42P12'
|
||||
INVALID_FUNCTION_DEFINITION = '42P13'
|
||||
INVALID_PREPARED_STATEMENT_DEFINITION = '42P14'
|
||||
INVALID_SCHEMA_DEFINITION = '42P15'
|
||||
INVALID_TABLE_DEFINITION = '42P16'
|
||||
INVALID_OBJECT_DEFINITION = '42P17'
|
||||
|
||||
# Class 44 - WITH CHECK OPTION Violation
|
||||
WITH_CHECK_OPTION_VIOLATION = '44000'
|
||||
|
||||
# Class 53 - Insufficient Resources
|
||||
INSUFFICIENT_RESOURCES = '53000'
|
||||
DISK_FULL = '53100'
|
||||
OUT_OF_MEMORY = '53200'
|
||||
TOO_MANY_CONNECTIONS = '53300'
|
||||
|
||||
# Class 54 - Program Limit Exceeded
|
||||
PROGRAM_LIMIT_EXCEEDED = '54000'
|
||||
STATEMENT_TOO_COMPLEX = '54001'
|
||||
TOO_MANY_COLUMNS = '54011'
|
||||
TOO_MANY_ARGUMENTS = '54023'
|
||||
|
||||
# Class 55 - Object Not In Prerequisite State
|
||||
OBJECT_NOT_IN_PREREQUISITE_STATE = '55000'
|
||||
OBJECT_IN_USE = '55006'
|
||||
CANT_CHANGE_RUNTIME_PARAM = '55P02'
|
||||
LOCK_NOT_AVAILABLE = '55P03'
|
||||
|
||||
# Class 57 - Operator Intervention
|
||||
OPERATOR_INTERVENTION = '57000'
|
||||
QUERY_CANCELED = '57014'
|
||||
ADMIN_SHUTDOWN = '57P01'
|
||||
CRASH_SHUTDOWN = '57P02'
|
||||
CANNOT_CONNECT_NOW = '57P03'
|
||||
|
||||
# Class 58 - System Error (errors external to PostgreSQL itself)
|
||||
IO_ERROR = '58030'
|
||||
UNDEFINED_FILE = '58P01'
|
||||
DUPLICATE_FILE = '58P02'
|
||||
|
||||
# Class F0 - Configuration File Error
|
||||
CONFIG_FILE_ERROR = 'F0000'
|
||||
LOCK_FILE_EXISTS = 'F0001'
|
||||
|
||||
# Class P0 - PL/pgSQL Error
|
||||
PLPGSQL_ERROR = 'P0000'
|
||||
RAISE_EXCEPTION = 'P0001'
|
||||
|
||||
# Class XX - Internal Error
|
||||
INTERNAL_ERROR = 'XX000'
|
||||
DATA_CORRUPTED = 'XX001'
|
||||
INDEX_CORRUPTED = 'XX002'
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject asisType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
/* this is the real object we wrap */
|
||||
PyObject *wrapped;
|
||||
|
|
|
@ -134,7 +134,7 @@ binary_quote(binaryObject *self)
|
|||
{
|
||||
char *to;
|
||||
const char *buffer;
|
||||
int buffer_len;
|
||||
Py_ssize_t buffer_len;
|
||||
size_t len = 0;
|
||||
|
||||
/* if we got a plain string or a buffer we escape it and save the buffer */
|
||||
|
|
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
extern PyTypeObject binaryType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
PyObject *buffer;
|
||||
|
|
|
@ -280,22 +280,23 @@ psyco_Time(PyObject *self, PyObject *args)
|
|||
PyObject *res = NULL;
|
||||
PyObject *tzinfo = NULL;
|
||||
int hours, minutes=0;
|
||||
double micro, seconds=0.0;
|
||||
double micro, second=0.0;
|
||||
|
||||
PyObject* obj = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iid|O", &hours, &minutes, &seconds,
|
||||
if (!PyArg_ParseTuple(args, "iid|O", &hours, &minutes, &second,
|
||||
&tzinfo))
|
||||
return NULL;
|
||||
|
||||
micro = (seconds - floor(seconds)) * 1000000.0;
|
||||
micro = (second - floor(second)) * 1000000.0;
|
||||
second = floor(second);
|
||||
|
||||
if (tzinfo == NULL)
|
||||
obj = PyObject_CallFunction(pyTimeTypeP, "iiii",
|
||||
hours, minutes, (int)round(seconds), (int)round(micro));
|
||||
hours, minutes, (int)second, (int)round(micro));
|
||||
else
|
||||
obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
|
||||
hours, minutes, (int)round(seconds), (int)round(micro), tzinfo);
|
||||
hours, minutes, (int)second, (int)round(micro), tzinfo);
|
||||
|
||||
if (obj) {
|
||||
res = PyObject_CallFunction((PyObject *)&pydatetimeType,
|
||||
|
@ -322,14 +323,15 @@ psyco_Timestamp(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
|
||||
micro = (second - floor(second)) * 1000000.0;
|
||||
second = floor(second);
|
||||
|
||||
if (tzinfo == NULL)
|
||||
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
|
||||
year, month, day, hour, minute, (int)round(second),
|
||||
year, month, day, hour, minute, (int)second,
|
||||
(int)round(micro));
|
||||
else
|
||||
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
|
||||
year, month, day, hour, minute, (int)round(second),
|
||||
year, month, day, hour, minute, (int)second,
|
||||
(int)round(micro), tzinfo);
|
||||
|
||||
if (obj) {
|
||||
|
@ -375,8 +377,10 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
|
||||
t = (time_t)round(ticks);
|
||||
ticks -= (double)t;
|
||||
if (localtime_r(&t, &tm)) {
|
||||
args = Py_BuildValue("iid", tm.tm_hour, tm.tm_min, (double)tm.tm_sec);
|
||||
args = Py_BuildValue("iid", tm.tm_hour, tm.tm_min,
|
||||
(double)tm.tm_sec + ticks);
|
||||
if (args) {
|
||||
res = psyco_Time(self, args);
|
||||
Py_DECREF(args);
|
||||
|
@ -397,10 +401,12 @@ psyco_TimestampFromTicks(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
|
||||
t = (time_t)round(ticks);
|
||||
ticks -= (double)t;
|
||||
if (localtime_r(&t, &tm)) {
|
||||
args = Py_BuildValue("iiiiidO",
|
||||
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, (double)tm.tm_sec,
|
||||
tm.tm_hour, tm.tm_min,
|
||||
(double)tm.tm_sec + ticks,
|
||||
pyPsycopgTzLOCAL);
|
||||
if (args) {
|
||||
res = psyco_Timestamp(self, args);
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject pydatetimeType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
int type;
|
||||
|
|
|
@ -40,7 +40,7 @@ list_quote(listObject *self)
|
|||
/* adapt the list by calling adapt() recursively and then wrapping
|
||||
everything into "ARRAY[]" */
|
||||
PyObject *tmp = NULL, *str = NULL, *joined = NULL, *res = NULL;
|
||||
int i, len;
|
||||
Py_ssize_t i, len;
|
||||
|
||||
len = PyList_GET_SIZE(self->wrapped);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject listType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
PyObject *connection;
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject mxdatetimeType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
int type;
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject pbooleanType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
/* this is the real object we wrap */
|
||||
PyObject *wrapped;
|
||||
|
|
|
@ -92,7 +92,7 @@ qstring_quote(qstringObject *self)
|
|||
{
|
||||
PyObject *str;
|
||||
char *s, *buffer;
|
||||
int len;
|
||||
Py_ssize_t len;
|
||||
|
||||
/* if the wrapped object is an unicode object we can encode it to match
|
||||
self->encoding but if the encoding is not specified we don't know what
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
extern PyTypeObject qstringType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
PyObject *buffer;
|
||||
|
|
|
@ -38,7 +38,7 @@ extern "C" {
|
|||
extern PyTypeObject connectionType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
pthread_mutex_t lock; /* the global connection lock */
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ extern "C" {
|
|||
extern PyTypeObject cursorType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
connectionObject *conn; /* connection owning the cursor */
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
|||
{
|
||||
PyObject *key, *value, *n, *item;
|
||||
char *d, *c;
|
||||
int index = 0, force = 0;
|
||||
Py_ssize_t index = 0;
|
||||
int force = 0;
|
||||
|
||||
/* from now on we'll use n and replace its value in *new only at the end,
|
||||
just before returning. we also init *new to NULL to exit with an error
|
||||
|
@ -872,7 +873,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
{
|
||||
char *procname = NULL, *sql = NULL;
|
||||
long int async = 0;
|
||||
int i, nparameters = 0, sl = 0;
|
||||
Py_ssize_t i, nparameters = 0, sl = 0;
|
||||
PyObject *parameters = NULL;
|
||||
PyObject *operation = NULL;
|
||||
PyObject *res = NULL;
|
||||
|
@ -1090,7 +1091,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
PyObject* collistiter = PyObject_GetIter(columns);
|
||||
PyObject* col;
|
||||
int collistlen = 2;
|
||||
int colitemlen;
|
||||
Py_ssize_t colitemlen;
|
||||
char* colname;
|
||||
if (collistiter == NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
extern PyTypeObject isqlquoteType;
|
||||
|
||||
typedef struct {
|
||||
PyObject HEAD;
|
||||
PyObject_HEAD;
|
||||
|
||||
PyObject *wrapped;
|
||||
|
||||
|
|
|
@ -590,7 +590,8 @@ _pq_copy_in_v3(cursorObject *curs)
|
|||
uses the new PQputCopyData() and can detect errors and set the correct
|
||||
exception */
|
||||
PyObject *o;
|
||||
int length = 0, error = 0;
|
||||
Py_ssize_t length = 0;
|
||||
int error = 0;
|
||||
|
||||
while (1) {
|
||||
o = PyObject_CallMethod(curs->copyfile, "read", "i", curs->copysize);
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Python 2.5 ssize_t compatibility */
|
||||
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
|
||||
typedef int Py_ssize_t;
|
||||
#define PY_SSIZE_T_MAX INT_MAX
|
||||
#define PY_SSIZE_T_MIN INT_MIN
|
||||
#endif
|
||||
|
||||
/* DBAPI compliance parameters */
|
||||
#define APILEVEL "2.0"
|
||||
#define THREADSAFETY 2
|
||||
|
|
|
@ -267,7 +267,7 @@ int
|
|||
typecast_add(PyObject *obj, int binary)
|
||||
{
|
||||
PyObject *val;
|
||||
int len, i;
|
||||
Py_ssize_t len, i;
|
||||
|
||||
typecastObject *type = (typecastObject *)obj;
|
||||
|
||||
|
@ -302,7 +302,8 @@ typecast_cmp(PyObject *obj1, PyObject* obj2)
|
|||
typecastObject *self = (typecastObject*)obj1;
|
||||
typecastObject *other = NULL;
|
||||
PyObject *number = NULL;
|
||||
int i, j, res = -1;
|
||||
Py_ssize_t i, j;
|
||||
int res = -1;
|
||||
|
||||
if (PyObject_TypeCheck(obj2, &typecastType)) {
|
||||
other = (typecastObject*)obj2;
|
||||
|
@ -505,7 +506,7 @@ typecast_from_c(typecastObject_initlist *type, PyObject *dict)
|
|||
{
|
||||
PyObject *tuple, *base = NULL;
|
||||
typecastObject *obj;
|
||||
int i, len = 0;
|
||||
Py_ssize_t i, len = 0;
|
||||
|
||||
/* before doing anything else we look for the base */
|
||||
if (type->base) {
|
||||
|
@ -538,7 +539,7 @@ typecast_from_c(typecastObject_initlist *type, PyObject *dict)
|
|||
}
|
||||
|
||||
PyObject *
|
||||
typecast_cast(PyObject *obj, char *str, int len, PyObject *curs)
|
||||
typecast_cast(PyObject *obj, char *str, Py_ssize_t len, PyObject *curs)
|
||||
{
|
||||
PyObject *old, *res = NULL;
|
||||
typecastObject *self = (typecastObject *)obj;
|
||||
|
|
|
@ -80,6 +80,6 @@ extern PyObject *typecast_from_python(
|
|||
|
||||
/* the function used to dispatch typecasting calls */
|
||||
extern PyObject *typecast_cast(
|
||||
PyObject *self, char *str, int len, PyObject *curs);
|
||||
PyObject *self, char *str, Py_ssize_t len, PyObject *curs);
|
||||
|
||||
#endif /* !defined(PSYCOPG_TYPECAST_H) */
|
||||
|
|
2
psycopg2da/DEPENDENCIES.cfg
Normal file
2
psycopg2da/DEPENDENCIES.cfg
Normal file
|
@ -0,0 +1,2 @@
|
|||
psycopg2
|
||||
zope.app
|
24
psycopg2da/PACKAGE.cfg
Normal file
24
psycopg2da/PACKAGE.cfg
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Load the license from an external source, so we don't have to keep a
|
||||
# copy of it sitting around:
|
||||
<load>
|
||||
LICENSE.txt http://svn.zope.org/*checkout*/Zope3/trunk/ZopePublicLicense.txt?rev=25177
|
||||
</load>
|
||||
|
||||
# Add a few things to the distribution root.
|
||||
<distribution>
|
||||
README.txt
|
||||
</distribution>
|
||||
|
||||
# Specify what is included in the component.
|
||||
<collection>
|
||||
|
||||
# Documentation files of the package:
|
||||
*.txt
|
||||
|
||||
# Python modules from the package:
|
||||
*.py
|
||||
|
||||
# Configuration files of the package:
|
||||
*.zcml
|
||||
|
||||
</collection>
|
9
psycopg2da/PUBLICATION.cfg
Normal file
9
psycopg2da/PUBLICATION.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: psycopg2da
|
||||
Summary: Psycopg2 Database Adapter for Zope 3
|
||||
Author: Fabio Tranchitella
|
||||
Author-email: kobold@debian.org
|
||||
License: ZPL 2.1
|
||||
Description:
|
||||
This package allows Zope 3 to connect to any PostGreSQL database via
|
||||
the common Zope 3 RDB connection facilities.
|
79
psycopg2da/README.txt
Normal file
79
psycopg2da/README.txt
Normal file
|
@ -0,0 +1,79 @@
|
|||
==========
|
||||
psycopg2da
|
||||
==========
|
||||
|
||||
This file outlines the basics of using Zope3 with PostgreSQL via PsycopgDA.
|
||||
|
||||
Installing PsycopgDA
|
||||
--------------------
|
||||
|
||||
1. Check out the psycopg2da package into a directory in your
|
||||
PYTHONPATH. INSTANCE_HOME/lib/python or Zope3/src is usually the
|
||||
most convenient place:
|
||||
|
||||
|
||||
svn co svn://svn.zope.org/repos/main/psycopg2da/trunk psycopg2da
|
||||
|
||||
|
||||
2. Copy `psycopg2-configure.zcml` to the `package-includes` directory
|
||||
of your Zope instance.
|
||||
|
||||
|
||||
Creating Database Connections
|
||||
------------------------------
|
||||
|
||||
It is time to add some connections. A connection in Zope 3 is
|
||||
registered as a utility.
|
||||
|
||||
3. Open a web browser on your Zope root folder (http://localhost:8080/
|
||||
if you use the default settings in zope.conf.in).
|
||||
|
||||
4. Click on the 'Manage Site' action on the right side of the
|
||||
screen. You should see a screen which reads 'Common Site Management
|
||||
Tasks'
|
||||
|
||||
5. Around the middle of that page, you should see a link named 'Add
|
||||
Utility'. Click on it.
|
||||
|
||||
6. Select 'Psycopg DA' and type in a name at the bottom of the page.
|
||||
|
||||
7. Enter the database connection string. It looks like this:
|
||||
|
||||
dbi://username:password@host:port/databasename
|
||||
|
||||
8. Click on the 'Add' button.
|
||||
|
||||
9. You should be on a page which reads 'Add Database Connection
|
||||
Registration'. There you can configure the permission needed to use
|
||||
the database connection, the name of the registration and the
|
||||
registration status. You can use any name for 'Register As' field,
|
||||
as long as it doesn't clash with an existing one. Choose a
|
||||
permission. Choose between 'Registered' and 'Active' for the
|
||||
'Registration Status'. Only one component of a kind can be 'Active'
|
||||
at a time, so be careful.
|
||||
|
||||
10. You should be redirected to the 'Edit' screen of the connection
|
||||
utility.
|
||||
|
||||
11. If you want to, you can go to the Test page and execute arbitrary
|
||||
SQL queries to see whether the connection is working as expected.
|
||||
|
||||
|
||||
Using SQL Scripts
|
||||
-----------------
|
||||
|
||||
You can create SQL Scripts in the content space. For example:
|
||||
|
||||
12. Go to Zope root.
|
||||
|
||||
13. Add an SQL script (you can use the Common Tasks box on the left,
|
||||
or the Add action on the right).
|
||||
|
||||
14. Click on the name of your new SQL script.
|
||||
|
||||
15. Choose a connection name (the one you entered in step 29) from the
|
||||
drop-down.
|
||||
|
||||
16. Enter your query and click on the 'Save Changes' button.
|
||||
|
||||
17. You can test the script in the -- surprise! -- Test page.
|
0
psycopg2da/__init__.py
Normal file
0
psycopg2da/__init__.py
Normal file
425
psycopg2da/adapter.py
Normal file
425
psycopg2da/adapter.py
Normal file
|
@ -0,0 +1,425 @@
|
|||
# psycopg2da
|
||||
# Copyright (C) 2006 Fabio Tranchitella <fabio@tranchitella.it>
|
||||
#
|
||||
# Based on psycopgda:
|
||||
#
|
||||
# Copyright (c) 2002-2006 Zope Corporation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# If you prefer you can use this package using the ZPL license as
|
||||
# published on the Zope web site, http://www.zope.org/Resources/ZPL.
|
||||
#
|
||||
"""PostgreSQL Database Adapter for Zope 3"""
|
||||
|
||||
from zope.interface import implements
|
||||
from zope.rdb import ZopeDatabaseAdapter, parseDSN, ZopeConnection, ZopeCursor
|
||||
from zope.rdb.interfaces import DatabaseException, IZopeConnection
|
||||
from zope.publisher.interfaces import Retry
|
||||
|
||||
from datetime import date, time, datetime, timedelta
|
||||
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
import re
|
||||
import sys
|
||||
|
||||
# OIDs from psycopg/pgtypes.h
|
||||
DATE_OID = 1082
|
||||
TIME_OID = 1083
|
||||
TIMETZ_OID = 1266
|
||||
TIMESTAMP_OID = 1114
|
||||
TIMESTAMPTZ_OID = 1184
|
||||
INTERVAL_OID = 1186
|
||||
CHAR_OID = 18
|
||||
TEXT_OID = 25
|
||||
BPCHAR_OID = 1042
|
||||
VARCHAR_OID = 1043
|
||||
|
||||
# date/time parsing functions
|
||||
_dateFmt = re.compile(r"^(\d\d\d\d)-?([01]\d)-?([0-3]\d)$")
|
||||
|
||||
def parse_date(s):
|
||||
"""Parses ISO-8601 compliant dates and returns a tuple (year, month,
|
||||
day).
|
||||
|
||||
The following formats are accepted:
|
||||
YYYY-MM-DD (extended format)
|
||||
YYYYMMDD (basic format)
|
||||
"""
|
||||
m = _dateFmt.match(s)
|
||||
if m is None:
|
||||
raise ValueError, 'invalid date string: %s' % s
|
||||
year, month, day = m.groups()
|
||||
return int(year), int(month), int(day)
|
||||
|
||||
|
||||
_timeFmt = re.compile(
|
||||
r"^([0-2]\d)(?::?([0-5]\d)(?::?([0-5]\d)(?:[.,](\d+))?)?)?$")
|
||||
|
||||
def parse_time(s):
|
||||
"""Parses ISO-8601 compliant times and returns a tuple (hour, minute,
|
||||
second).
|
||||
|
||||
The following formats are accepted:
|
||||
HH:MM:SS.ssss or HHMMSS.ssss
|
||||
HH:MM:SS,ssss or HHMMSS,ssss
|
||||
HH:MM:SS or HHMMSS
|
||||
HH:MM or HHMM
|
||||
HH
|
||||
"""
|
||||
m = _timeFmt.match(s)
|
||||
if m is None:
|
||||
raise ValueError, 'invalid time string: %s' % s
|
||||
hr, mn, sc, msc = m.groups(0)
|
||||
if msc != 0:
|
||||
sc = float("%s.%s" % (sc, msc))
|
||||
else:
|
||||
sc = int(sc)
|
||||
return int(hr), int(mn), sc
|
||||
|
||||
|
||||
_tzFmt = re.compile(r"^([+-])([0-2]\d)(?::?([0-5]\d))?$")
|
||||
|
||||
def parse_tz(s):
|
||||
"""Parses ISO-8601 timezones and returns the offset east of UTC in
|
||||
minutes.
|
||||
|
||||
The following formats are accepted:
|
||||
+/-HH:MM
|
||||
+/-HHMM
|
||||
+/-HH
|
||||
Z (equivalent to +0000)
|
||||
"""
|
||||
if s == 'Z':
|
||||
return 0
|
||||
m = _tzFmt.match(s)
|
||||
if m is None:
|
||||
raise ValueError, 'invalid time zone: %s' % s
|
||||
d, hoff, moff = m.groups(0)
|
||||
if d == "-":
|
||||
return - int(hoff) * 60 - int(moff)
|
||||
return int(hoff) * 60 + int(moff)
|
||||
|
||||
|
||||
_tzPos = re.compile(r"[Z+-]")
|
||||
|
||||
def parse_timetz(s):
|
||||
"""Parses ISO-8601 compliant times that may include timezone information
|
||||
and returns a tuple (hour, minute, second, tzoffset).
|
||||
|
||||
tzoffset is the offset east of UTC in minutes. It will be None if s does
|
||||
not include time zone information.
|
||||
|
||||
Formats accepted are those listed in the descriptions of parse_time() and
|
||||
parse_tz(). Time zone should immediatelly follow time without intervening
|
||||
spaces.
|
||||
"""
|
||||
m = _tzPos.search(s)
|
||||
if m is None:
|
||||
return parse_time(s) + (None,)
|
||||
pos = m.start()
|
||||
return parse_time(s[:pos]) + (parse_tz(s[pos:]),)
|
||||
|
||||
|
||||
_datetimeFmt = re.compile(r"[T ]")
|
||||
|
||||
def _split_datetime(s):
|
||||
"""Split date and time parts of ISO-8601 compliant timestamp and
|
||||
return a tuple (date, time).
|
||||
|
||||
' ' or 'T' used to separate date and time parts.
|
||||
"""
|
||||
m = _datetimeFmt.search(s)
|
||||
if m is None:
|
||||
raise ValueError, 'time part of datetime missing: %s' % s
|
||||
pos = m.start()
|
||||
return s[:pos], s[pos + 1:]
|
||||
|
||||
|
||||
def parse_datetime(s):
|
||||
"""Parses ISO-8601 compliant timestamp and returns a tuple (year, month,
|
||||
day, hour, minute, second).
|
||||
|
||||
Formats accepted are those listed in the descriptions of parse_date() and
|
||||
parse_time() with ' ' or 'T' used to separate date and time parts.
|
||||
"""
|
||||
dt, tm = _split_datetime(s)
|
||||
return parse_date(dt) + parse_time(tm)
|
||||
|
||||
|
||||
def parse_datetimetz(s):
|
||||
"""Parses ISO-8601 compliant timestamp that may include timezone
|
||||
information and returns a tuple (year, month, day, hour, minute, second,
|
||||
tzoffset).
|
||||
|
||||
tzoffset is the offset east of UTC in minutes. It will be None if s does
|
||||
not include time zone information.
|
||||
|
||||
Formats accepted are those listed in the descriptions of parse_date() and
|
||||
parse_timetz() with ' ' or 'T' used to separate date and time parts.
|
||||
"""
|
||||
dt, tm = _split_datetime(s)
|
||||
return parse_date(dt) + parse_timetz(tm)
|
||||
|
||||
|
||||
def parse_interval(s):
|
||||
"""Parses PostgreSQL interval notation and returns a tuple (years, months,
|
||||
days, hours, minutes, seconds).
|
||||
|
||||
Values accepted:
|
||||
interval ::= date
|
||||
| time
|
||||
| date time
|
||||
date ::= date_comp
|
||||
| date date_comp
|
||||
date_comp ::= 1 'day'
|
||||
| number 'days'
|
||||
| 1 'month'
|
||||
| 1 'mon'
|
||||
| number 'months'
|
||||
| number 'mons'
|
||||
| 1 'year'
|
||||
| number 'years'
|
||||
time ::= number ':' number
|
||||
| number ':' number ':' number
|
||||
| number ':' number ':' number '.' fraction
|
||||
"""
|
||||
years = months = days = 0
|
||||
hours = minutes = seconds = 0
|
||||
elements = s.split()
|
||||
# Tests with 7.4.6 on Ubuntu 5.4 interval output returns 'mon' and 'mons'
|
||||
# and not 'month' or 'months' as expected. I've fixed this and left
|
||||
# the original matches there too in case this is dependant on
|
||||
# OS or PostgreSQL release.
|
||||
for i in range(0, len(elements) - 1, 2):
|
||||
count, unit = elements[i:i+2]
|
||||
if unit == 'day' and count == '1':
|
||||
days += 1
|
||||
elif unit == 'days':
|
||||
days += int(count)
|
||||
elif unit == 'month' and count == '1':
|
||||
months += 1
|
||||
elif unit == 'mon' and count == '1':
|
||||
months += 1
|
||||
elif unit == 'months':
|
||||
months += int(count)
|
||||
elif unit == 'mons':
|
||||
months += int(count)
|
||||
elif unit == 'year' and count == '1':
|
||||
years += 1
|
||||
elif unit == 'years':
|
||||
years += int(count)
|
||||
else:
|
||||
raise ValueError, 'unknown time interval %s %s' % (count, unit)
|
||||
if len(elements) % 2 == 1:
|
||||
hours, minutes, seconds = parse_time(elements[-1])
|
||||
return (years, months, days, hours, minutes, seconds)
|
||||
|
||||
|
||||
# Type conversions
|
||||
def _conv_date(s, cursor):
|
||||
if s:
|
||||
return date(*parse_date(s))
|
||||
|
||||
def _conv_time(s, cursor):
|
||||
if s:
|
||||
hr, mn, sc = parse_time(s)
|
||||
sc, micro = divmod(sc, 1.0)
|
||||
micro = round(micro * 1000000)
|
||||
return time(hr, mn, int(sc), int(micro))
|
||||
|
||||
def _conv_timetz(s, cursor):
|
||||
if s:
|
||||
from zope.datetime import tzinfo
|
||||
hr, mn, sc, tz = parse_timetz(s)
|
||||
sc, micro = divmod(sc, 1.0)
|
||||
micro = round(micro * 1000000)
|
||||
if tz: tz = tzinfo(tz)
|
||||
return time(hr, mn, int(sc), int(micro), tz)
|
||||
|
||||
def _conv_timestamp(s, cursor):
|
||||
if s:
|
||||
y, m, d, hr, mn, sc = parse_datetime(s)
|
||||
sc, micro = divmod(sc, 1.0)
|
||||
micro = round(micro * 1000000)
|
||||
return datetime(y, m, d, hr, mn, int(sc), int(micro))
|
||||
|
||||
def _conv_timestamptz(s, cursor):
|
||||
if s:
|
||||
from zope.datetime import tzinfo
|
||||
y, m, d, hr, mn, sc, tz = parse_datetimetz(s)
|
||||
sc, micro = divmod(sc, 1.0)
|
||||
micro = round(micro * 1000000)
|
||||
if tz: tz = tzinfo(tz)
|
||||
return datetime(y, m, d, hr, mn, int(sc), int(micro), tz)
|
||||
|
||||
def _conv_interval(s, cursor):
|
||||
if s:
|
||||
y, m, d, hr, mn, sc = parse_interval(s)
|
||||
if (y, m) != (0, 0):
|
||||
# XXX: Currently there's no way to represent years and months as
|
||||
# timedeltas
|
||||
return s
|
||||
else:
|
||||
return timedelta(days=d, hours=hr, minutes=mn, seconds=sc)
|
||||
|
||||
def _get_string_conv(encoding):
|
||||
def _conv_string(s, cursor):
|
||||
if s is not None:
|
||||
s = s.decode(encoding)
|
||||
return s
|
||||
return _conv_string
|
||||
|
||||
# User-defined types
|
||||
DATE = psycopg2.extensions.new_type((DATE_OID,), "ZDATE", _conv_date)
|
||||
TIME = psycopg2.extensions.new_type((TIME_OID,), "ZTIME", _conv_time)
|
||||
TIMETZ = psycopg2.extensions.new_type((TIMETZ_OID,), "ZTIMETZ", _conv_timetz)
|
||||
TIMESTAMP = psycopg2.extensions.new_type((TIMESTAMP_OID,), "ZTIMESTAMP", _conv_timestamp)
|
||||
TIMESTAMPTZ = psycopg2.extensions.new_type((TIMESTAMPTZ_OID,), "ZTIMESTAMPTZ", _conv_timestamptz)
|
||||
INTERVAL = psycopg2.extensions.new_type((INTERVAL_OID,), "ZINTERVAL", _conv_interval)
|
||||
|
||||
def registerTypes(encoding):
|
||||
"""Register type conversions for psycopg"""
|
||||
psycopg2.extensions.register_type(DATE)
|
||||
psycopg2.extensions.register_type(TIME)
|
||||
psycopg2.extensions.register_type(TIMETZ)
|
||||
psycopg2.extensions.register_type(TIMESTAMP)
|
||||
psycopg2.extensions.register_type(TIMESTAMPTZ)
|
||||
psycopg2.extensions.register_type(INTERVAL)
|
||||
STRING = psycopg2.extensions.new_type((CHAR_OID, TEXT_OID, BPCHAR_OID, VARCHAR_OID), "ZSTRING", _get_string_conv(encoding))
|
||||
psycopg2.extensions.register_type(STRING)
|
||||
|
||||
|
||||
dsn2option_mapping = {'host': 'host',
|
||||
'port': 'port',
|
||||
'dbname': 'dbname',
|
||||
'username': 'user',
|
||||
'password': 'password'}
|
||||
|
||||
class Psycopg2Adapter(ZopeDatabaseAdapter):
|
||||
"""A psycopg2 adapter for Zope3.
|
||||
|
||||
The following type conversions are performed:
|
||||
|
||||
DATE -> datetime.date
|
||||
TIME -> datetime.time
|
||||
TIMETZ -> datetime.time
|
||||
TIMESTAMP -> datetime.datetime
|
||||
TIMESTAMPTZ -> datetime.datetime
|
||||
|
||||
XXX: INTERVAL cannot be represented exactly as datetime.timedelta since
|
||||
it might be something like '1 month', which is a variable number of days.
|
||||
"""
|
||||
|
||||
def connect(self):
|
||||
if not self.isConnected():
|
||||
try:
|
||||
self._v_connection = Psycopg2Connection(
|
||||
self._connection_factory(), self
|
||||
)
|
||||
except psycopg2.Error, error:
|
||||
raise DatabaseException, str(error)
|
||||
|
||||
def registerTypes(self):
|
||||
registerTypes(self.getEncoding())
|
||||
|
||||
def _connection_factory(self):
|
||||
"""Create a psycopg2 DBI connection based on the DSN"""
|
||||
self.registerTypes()
|
||||
conn_info = parseDSN(self.dsn)
|
||||
conn_list = []
|
||||
for dsnname, optname in dsn2option_mapping.iteritems():
|
||||
if conn_info[dsnname]:
|
||||
conn_list.append('%s=%s' % (optname, conn_info[dsnname]))
|
||||
conn_str = ' '.join(conn_list)
|
||||
connection = psycopg2.connect(conn_str)
|
||||
connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE)
|
||||
return connection
|
||||
|
||||
def disconnect(self):
|
||||
if self.isConnected():
|
||||
try:
|
||||
self._v_connection.close()
|
||||
except psycopg2.InterfaceError:
|
||||
pass
|
||||
self._v_connection = None
|
||||
|
||||
|
||||
def _handle_psycopg_exception(error):
|
||||
"""Called from a exception handler for psycopg2.Error.
|
||||
|
||||
If we have a serialization exception or a deadlock, we should retry the
|
||||
transaction by raising a Retry exception. Otherwise, we reraise.
|
||||
"""
|
||||
if not error.args:
|
||||
raise
|
||||
msg = error.args[0]
|
||||
# These messages are from PostgreSQL 8.0. They may change between
|
||||
# PostgreSQL releases - if so, the different messages should be added
|
||||
# rather than the existing ones changed so this logic works with
|
||||
# different versions.
|
||||
if msg.startswith(
|
||||
'ERROR: could not serialize access due to concurrent update'
|
||||
):
|
||||
raise Retry(sys.exc_info())
|
||||
if msg.startswith('ERROR: deadlock detected'):
|
||||
raise Retry(sys.exc_info())
|
||||
raise
|
||||
|
||||
|
||||
class IPsycopg2ZopeConnection(IZopeConnection):
|
||||
"""A marker interface stating that this connection uses PostgreSQL."""
|
||||
|
||||
|
||||
class Psycopg2Connection(ZopeConnection):
|
||||
|
||||
implements(IPsycopg2ZopeConnection)
|
||||
|
||||
def cursor(self):
|
||||
"""See IZopeConnection"""
|
||||
return Psycopg2Cursor(self.conn.cursor(), self)
|
||||
|
||||
def commit(self):
|
||||
try:
|
||||
ZopeConnection.commit(self)
|
||||
except psycopg2.Error, error:
|
||||
_handle_psycopg_exception(error)
|
||||
|
||||
|
||||
class Psycopg2Cursor(ZopeCursor):
|
||||
|
||||
def execute(self, operation, parameters=None):
|
||||
"""See IZopeCursor"""
|
||||
try:
|
||||
return ZopeCursor.execute(self, operation, parameters)
|
||||
except psycopg2.Error, error:
|
||||
_handle_psycopg_exception(error)
|
||||
|
||||
def executemany(operation, seq_of_parameters=None):
|
||||
"""See IZopeCursor"""
|
||||
raise RuntimeError, 'Oos'
|
||||
try:
|
||||
return ZopeCursor.execute(self, operation, seq_of_parameters)
|
||||
except psycopg2.Error, error:
|
||||
_handle_psycopg_exception(error)
|
51
psycopg2da/configure.zcml
Normal file
51
psycopg2da/configure.zcml
Normal file
|
@ -0,0 +1,51 @@
|
|||
<configure
|
||||
xmlns="http://namespaces.zope.org/zope"
|
||||
xmlns:browser="http://namespaces.zope.org/browser"
|
||||
i18n_domain="psycopg2da">
|
||||
|
||||
<class class=".adapter.Psycopg2Adapter">
|
||||
<factory id="zope.da.Psycopg2DA" />
|
||||
<require
|
||||
permission="zope.rdb.Use"
|
||||
interface="zope.rdb.interfaces.IZopeDatabaseAdapter"
|
||||
/>
|
||||
<require
|
||||
permission="zope.ManageServices"
|
||||
interface="zope.rdb.interfaces.IZopeDatabaseAdapterManagement"
|
||||
/>
|
||||
</class>
|
||||
|
||||
<class class=".adapter.Psycopg2Connection">
|
||||
<require
|
||||
permission="zope.rdb.Use"
|
||||
interface="zope.rdb.interfaces.IZopeConnection"
|
||||
/>
|
||||
</class>
|
||||
|
||||
<class class=".adapter.Psycopg2Cursor">
|
||||
<require
|
||||
permission="zope.rdb.Use"
|
||||
interface="zope.rdb.interfaces.IZopeCursor"
|
||||
/>
|
||||
</class>
|
||||
|
||||
<browser:addform
|
||||
name="AddPsycopg2DA"
|
||||
schema="zope.rdb.interfaces.IManageableZopeDatabaseAdapter"
|
||||
label="Add Psycopg2 (PostGreSQL) Database Adapter"
|
||||
content_factory=".adapter.Psycopg2Adapter"
|
||||
arguments="dsn"
|
||||
fields="dsn"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<!-- Menu entry for "add utility" menu -->
|
||||
<browser:addMenuItem
|
||||
class=".adapter.Psycopg2Adapter"
|
||||
title="Psycopg2 DA"
|
||||
description="A PostgreSQL Database Adapter using the Psycopg2 driver"
|
||||
permission="zope.ManageApplication"
|
||||
view="AddPsycopg2DA"
|
||||
/>
|
||||
|
||||
</configure>
|
1
psycopg2da/psycopgda-configure.zcml
Normal file
1
psycopg2da/psycopgda-configure.zcml
Normal file
|
@ -0,0 +1 @@
|
|||
<include package="psycopg2da" />
|
389
psycopg2da/tests.py
Normal file
389
psycopg2da/tests.py
Normal file
|
@ -0,0 +1,389 @@
|
|||
# psycopg2da
|
||||
# Copyright (C) 2006 Fabio Tranchitella <fabio@tranchitella.it>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
"""Unit tests for Psycopg2DA."""
|
||||
|
||||
from unittest import TestCase, TestSuite, main, makeSuite
|
||||
from datetime import tzinfo, timedelta
|
||||
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
|
||||
|
||||
class Stub(object):
|
||||
|
||||
def __init__(self, **kw):
|
||||
self.__dict__.update(kw)
|
||||
|
||||
class TZStub(tzinfo):
|
||||
|
||||
def __init__(self, h, m):
|
||||
self.offset = h * 60 + m
|
||||
|
||||
def utcoffset(self, dt):
|
||||
return timedelta(minutes=self.offset)
|
||||
|
||||
def dst(self, dt):
|
||||
return 0
|
||||
|
||||
def tzname(self, dt):
|
||||
return ''
|
||||
|
||||
def __repr__(self):
|
||||
return 'tzinfo(%d)' % self.offset
|
||||
|
||||
def __reduce__(self):
|
||||
return type(self), (), self.__dict__
|
||||
|
||||
class ConnectionStub(object):
|
||||
|
||||
def set_isolation_level(self, level):
|
||||
pass
|
||||
|
||||
class Psycopg2Stub(object):
|
||||
|
||||
__shared_state = {} # 'Borg' design pattern
|
||||
|
||||
DATE = psycopg2.extensions.DATE
|
||||
TIME = psycopg2.extensions.TIME
|
||||
DATETIME = psycopg2.DATETIME
|
||||
INTERVAL = psycopg2.extensions.INTERVAL
|
||||
ISOLATION_LEVEL_SERIALIZABLE = psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE
|
||||
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
self.types = {}
|
||||
|
||||
def connect(self, connection_string):
|
||||
self.last_connection_string = connection_string
|
||||
return ConnectionStub()
|
||||
|
||||
def new_type(self, values, name, converter):
|
||||
return Stub(name=name, values=values)
|
||||
|
||||
def register_type(self, type):
|
||||
for typeid in type.values:
|
||||
self.types[typeid] = type
|
||||
|
||||
def getExtensions(self):
|
||||
return self
|
||||
extensions = property(getExtensions)
|
||||
|
||||
|
||||
class TestPsycopg2TypeConversion(TestCase):
|
||||
|
||||
def test_conv_date(self):
|
||||
from psycopg2da.adapter import _conv_date
|
||||
from datetime import date
|
||||
def c(s):
|
||||
return _conv_date(s, None)
|
||||
self.assertEquals(c(''), None)
|
||||
self.assertEquals(c('2001-03-02'), date(2001, 3, 2))
|
||||
|
||||
def test_conv_time(self):
|
||||
from psycopg2da.adapter import _conv_time
|
||||
from datetime import time
|
||||
def c(s):
|
||||
return _conv_time(s, None)
|
||||
self.assertEquals(c(''), None)
|
||||
self.assertEquals(c('23:17:57'), time(23, 17, 57))
|
||||
self.assertEquals(c('23:17:57.037'), time(23, 17, 57, 37000))
|
||||
|
||||
def test_conv_timetz(self):
|
||||
from psycopg2da.adapter import _conv_timetz
|
||||
from datetime import time
|
||||
def c(s):
|
||||
return _conv_timetz(s, None)
|
||||
self.assertEquals(c(''), None)
|
||||
self.assertEquals(c('12:44:01+01:00'), time(12, 44, 01, 0, TZStub(1,0)))
|
||||
self.assertEquals(c('12:44:01.037-00:30'), time(12, 44, 01, 37000, TZStub(0,-30)))
|
||||
|
||||
def test_conv_timestamp(self):
|
||||
from psycopg2da.adapter import _conv_timestamp
|
||||
from datetime import datetime
|
||||
def c(s):
|
||||
return _conv_timestamp(s, None)
|
||||
self.assertEquals(c(''), None)
|
||||
self.assertEquals(c('2001-03-02 12:44:01'),
|
||||
datetime(2001, 3, 2, 12, 44, 01))
|
||||
self.assertEquals(c('2001-03-02 12:44:01.037'),
|
||||
datetime(2001, 3, 2, 12, 44, 01, 37000))
|
||||
self.assertEquals(c('2001-03-02 12:44:01.000001'),
|
||||
datetime(2001, 3, 2, 12, 44, 01, 1))
|
||||
|
||||
def test_conv_timestamptz(self):
|
||||
from psycopg2da.adapter import _conv_timestamptz
|
||||
from datetime import datetime
|
||||
def c(s):
|
||||
return _conv_timestamptz(s, None)
|
||||
self.assertEquals(c(''), None)
|
||||
|
||||
self.assertEquals(c('2001-03-02 12:44:01+01:00'),
|
||||
datetime(2001, 3, 2, 12, 44, 01, 0, TZStub(1,0)))
|
||||
self.assertEquals(c('2001-03-02 12:44:01.037-00:30'),
|
||||
datetime(2001, 3, 2, 12, 44, 01, 37000, TZStub(0,-30)))
|
||||
self.assertEquals(c('2001-03-02 12:44:01.000001+12:00'),
|
||||
datetime(2001, 3, 2, 12, 44, 01, 1, TZStub(12,0)))
|
||||
self.assertEquals(c('2001-06-25 12:14:00-07'),
|
||||
datetime(2001, 6, 25, 12, 14, 00, 0, TZStub(-7,0)))
|
||||
|
||||
def test_conv_interval(self):
|
||||
from psycopg2da.adapter import _conv_interval
|
||||
from datetime import timedelta
|
||||
def c(s):
|
||||
return _conv_interval(s, None)
|
||||
|
||||
self.assertEquals(c(''), None)
|
||||
self.assertEquals(c('01:00'), timedelta(hours=1))
|
||||
self.assertEquals(c('00:15'), timedelta(minutes=15))
|
||||
self.assertEquals(c('00:00:47'), timedelta(seconds=47))
|
||||
self.assertEquals(c('00:00:00.037'), timedelta(microseconds=37000))
|
||||
self.assertEquals(c('00:00:00.111111'), timedelta(microseconds=111111))
|
||||
self.assertEquals(c('1 day'), timedelta(days=1))
|
||||
self.assertEquals(c('2 days'), timedelta(days=2))
|
||||
self.assertEquals(c('374 days'), timedelta(days=374))
|
||||
self.assertEquals(c('2 days 03:20:15.123456'),
|
||||
timedelta(days=2, hours=3, minutes=20,
|
||||
seconds=15, microseconds=123456))
|
||||
# XXX There's a problem with years and months. Currently timedelta
|
||||
# cannot represent them accurately
|
||||
self.assertEquals(c('1 month'), '1 month')
|
||||
self.assertEquals(c('2 months'), '2 months')
|
||||
self.assertEquals(c('1 mon'), '1 mon')
|
||||
self.assertEquals(c('2 mons'), '2 mons')
|
||||
self.assertEquals(c('1 year'), '1 year')
|
||||
self.assertEquals(c('3 years'), '3 years')
|
||||
# Later we might be able to use
|
||||
## self.assertEquals(c('1 month'), timedelta(months=1))
|
||||
## self.assertEquals(c('2 months'), timedelta(months=2))
|
||||
## self.assertEquals(c('1 year'), timedelta(years=1))
|
||||
## self.assertEquals(c('3 years'), timedelta(years=3))
|
||||
|
||||
self.assertRaises(ValueError, c, '2 day')
|
||||
self.assertRaises(ValueError, c, '2days')
|
||||
self.assertRaises(ValueError, c, '123')
|
||||
|
||||
def test_conv_string(self):
|
||||
from psycopg2da.adapter import _get_string_conv
|
||||
_conv_string = _get_string_conv("utf-8")
|
||||
def c(s):
|
||||
return _conv_string(s, None)
|
||||
self.assertEquals(c(None), None)
|
||||
self.assertEquals(c(''), u'')
|
||||
self.assertEquals(c('c'), u'c')
|
||||
self.assertEquals(c('\xc3\x82\xc2\xa2'), u'\xc2\xa2')
|
||||
self.assertEquals(c('c\xc3\x82\xc2\xa2'), u'c\xc2\xa2')
|
||||
|
||||
class TestPsycopg2Adapter(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
import psycopg2da.adapter as adapter
|
||||
self.real_psycopg2 = adapter.psycopg2
|
||||
adapter.psycopg2 = self.psycopg2_stub = Psycopg2Stub()
|
||||
|
||||
def tearDown(self):
|
||||
import psycopg2da.adapter as adapter
|
||||
adapter.psycopg2 = self.real_psycopg2
|
||||
|
||||
def test_connection_factory(self):
|
||||
from psycopg2da.adapter import Psycopg2Adapter
|
||||
a = Psycopg2Adapter('dbi://username:password@hostname:port/dbname;junk=ignored')
|
||||
c = a._connection_factory()
|
||||
args = self.psycopg2_stub.last_connection_string.split()
|
||||
args.sort()
|
||||
self.assertEquals(args, ['dbname=dbname', 'host=hostname',
|
||||
'password=password', 'port=port',
|
||||
'user=username'])
|
||||
|
||||
def test_registerTypes(self):
|
||||
import psycopg2da.adapter as adapter
|
||||
from psycopg2da.adapter import Psycopg2Adapter
|
||||
a = Psycopg2Adapter('dbi://')
|
||||
a.registerTypes()
|
||||
for typename in ('DATE', 'TIME', 'TIMETZ', 'TIMESTAMP',
|
||||
'TIMESTAMPTZ', 'INTERVAL'):
|
||||
typeid = getattr(adapter, '%s_OID' % typename)
|
||||
result = self.psycopg2_stub.types.get(typeid, None)
|
||||
if not result:
|
||||
# comparing None with psycopg2.type object segfaults
|
||||
self.fail("did not register %s (%d): got None, not Z%s"
|
||||
% (typename, typeid, typename))
|
||||
else:
|
||||
result_name = getattr(result, 'name', 'None')
|
||||
self.assertEquals(result, getattr(adapter, typename),
|
||||
"did not register %s (%d): got %s, not Z%s"
|
||||
% (typename, typeid, result_name, typename))
|
||||
|
||||
|
||||
class TestISODateTime(TestCase):
|
||||
|
||||
# Test if date/time parsing functions accept a sensible subset of ISO-8601
|
||||
# compliant date/time strings.
|
||||
#
|
||||
# Resources:
|
||||
# http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
||||
# http://www.mcs.vuw.ac.nz/technical/software/SGML/doc/iso8601/ISO8601.html
|
||||
# http://www.w3.org/TR/NOTE-datetime
|
||||
# http://www.ietf.org/rfc/rfc3339.txt
|
||||
|
||||
basic_dates = (('20020304', (2002, 03, 04)),
|
||||
('20000229', (2000, 02, 29)))
|
||||
|
||||
extended_dates = (('2002-03-04', (2002, 03, 04)),
|
||||
('2000-02-29', (2000, 02, 29)))
|
||||
|
||||
basic_times = (('12', (12, 0, 0)),
|
||||
('1234', (12, 34, 0)),
|
||||
('123417', (12, 34, 17)),
|
||||
('123417.5', (12, 34, 17.5)),
|
||||
('123417,5', (12, 34, 17.5)))
|
||||
|
||||
extended_times = (('12', (12, 0, 0)),
|
||||
('12:34', (12, 34, 0)),
|
||||
('12:34:17', (12, 34, 17)),
|
||||
('12:34:17.5', (12, 34, 17.5)),
|
||||
('12:34:17,5', (12, 34, 17.5)))
|
||||
|
||||
basic_tzs = (('Z', 0),
|
||||
('+02', 2*60),
|
||||
('+1130', 11*60+30),
|
||||
('-05', -5*60),
|
||||
('-0030', -30))
|
||||
|
||||
extended_tzs = (('Z', 0),
|
||||
('+02', 2*60),
|
||||
('+11:30', 11*60+30),
|
||||
('-05', -5*60),
|
||||
('-00:30', -30))
|
||||
|
||||
time_separators = (' ', 'T')
|
||||
|
||||
bad_dates = ('', 'foo', 'XXXXXXXX', 'XXXX-XX-XX', '2001-2-29',
|
||||
'1990/13/14')
|
||||
|
||||
bad_times = ('', 'foo', 'XXXXXX', '12:34,5', '12:34:56,')
|
||||
|
||||
bad_timetzs = ('12+12 34', '15:45 +1234', '18:00-12:34:56', '18:00+123', '18:00Q')
|
||||
|
||||
bad_datetimes = ('', 'foo', '2002-03-0412:33')
|
||||
|
||||
bad_datetimetzs = ('', 'foo', '2002-03-04T12:33 +1200')
|
||||
|
||||
exception_type = ValueError
|
||||
|
||||
# We need the following funcions:
|
||||
# parse_date -> (year, month, day)
|
||||
# parse_time -> (hour, minute, second)
|
||||
# parse_timetz -> (hour, minute, second, tzoffset)
|
||||
# parse_datetime -> (year, month, day, hour, minute, second)
|
||||
# parse_datetimetz -> (year, month, day, hour, minute, second, tzoffset)
|
||||
# second can be a float, all other values are ints
|
||||
# tzoffset is offset in minutes east of UTC
|
||||
|
||||
def setUp(self):
|
||||
from psycopg2da.adapter import parse_date, parse_time, \
|
||||
parse_timetz, parse_datetime, parse_datetimetz
|
||||
self.parse_date = parse_date
|
||||
self.parse_time = parse_time
|
||||
self.parse_timetz = parse_timetz
|
||||
self.parse_datetime = parse_datetime
|
||||
self.parse_datetimetz = parse_datetimetz
|
||||
|
||||
def test_basic_date(self):
|
||||
for s, d in self.basic_dates:
|
||||
self.assertEqual(self.parse_date(s), d)
|
||||
|
||||
def test_extended_date(self):
|
||||
for s, d in self.extended_dates:
|
||||
self.assertEqual(self.parse_date(s), d)
|
||||
|
||||
def test_bad_date(self):
|
||||
for s in self.bad_dates:
|
||||
self.assertRaises(self.exception_type, self.parse_date, s)
|
||||
|
||||
def test_basic_time(self):
|
||||
for s, t in self.basic_times:
|
||||
self.assertEqual(self.parse_time(s), t)
|
||||
|
||||
def test_extended_time(self):
|
||||
for s, t in self.extended_times:
|
||||
self.assertEqual(self.parse_time(s), t)
|
||||
|
||||
def test_bad_time(self):
|
||||
for s in self.bad_times:
|
||||
self.assertRaises(self.exception_type, self.parse_time, s)
|
||||
|
||||
def test_basic_timetz(self):
|
||||
for s, t in self.basic_times:
|
||||
for tz, off in self.basic_tzs:
|
||||
self.assertEqual(self.parse_timetz(s+tz), t + (off,))
|
||||
|
||||
def test_extended_timetz(self):
|
||||
for s, t in self.extended_times:
|
||||
for tz, off in self.extended_tzs:
|
||||
self.assertEqual(self.parse_timetz(s+tz), t + (off,))
|
||||
|
||||
def test_bad_timetzs(self):
|
||||
for s in self.bad_timetzs:
|
||||
self.assertRaises(self.exception_type, self.parse_timetz, s)
|
||||
|
||||
def test_basic_datetime(self):
|
||||
for ds, d in self.basic_dates:
|
||||
for ts, t in self.basic_times:
|
||||
for sep in self.time_separators:
|
||||
self.assertEqual(self.parse_datetime(ds+sep+ts), d + t)
|
||||
|
||||
def test_extended_datetime(self):
|
||||
for ds, d in self.extended_dates:
|
||||
for ts, t in self.extended_times:
|
||||
for sep in self.time_separators:
|
||||
self.assertEqual(self.parse_datetime(ds+sep+ts), d + t)
|
||||
|
||||
def test_bad_datetimes(self):
|
||||
for s in self.bad_datetimes:
|
||||
self.assertRaises(self.exception_type, self.parse_datetime, s)
|
||||
|
||||
def test_basic_datetimetz(self):
|
||||
for ds, d in self.basic_dates:
|
||||
for ts, t in self.basic_times:
|
||||
for tz, off in self.basic_tzs:
|
||||
for sep in self.time_separators:
|
||||
self.assertEqual(self.parse_datetimetz(ds+sep+ts+tz),
|
||||
d + t + (off,))
|
||||
|
||||
def test_extended_datetimetz(self):
|
||||
for ds, d in self.extended_dates:
|
||||
for ts, t in self.extended_times:
|
||||
for tz, off in self.extended_tzs:
|
||||
for sep in self.time_separators:
|
||||
self.assertEqual(self.parse_datetimetz(ds+sep+ts+tz),
|
||||
d + t + (off,))
|
||||
|
||||
def test_bad_datetimetzs(self):
|
||||
for s in self.bad_datetimetzs:
|
||||
self.assertRaises(self.exception_type, self.parse_datetimetz, s)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return TestSuite((
|
||||
makeSuite(TestPsycopg2TypeConversion),
|
||||
makeSuite(TestPsycopg2Adapter),
|
||||
makeSuite(TestISODateTime),
|
||||
))
|
||||
|
||||
if __name__=='__main__':
|
||||
main(defaultTest='test_suite')
|
Loading…
Reference in New Issue
Block a user