Compare commits
No commits in common. "master" and "2_4_6" have entirely different histories.
4
.github/FUNDING.yml
vendored
|
@ -1,4 +0,0 @@
|
|||
github:
|
||||
- dvarrazzo
|
||||
custom:
|
||||
- "https://www.paypal.me/dvarrazzo"
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
name: Problem installing psycopg2
|
||||
about: Report a case in which psycopg2 failed to install on your platform
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**This is a bug tracker**
|
||||
If you have a question, such has "how do you do X with Python/PostgreSQL/psycopg2" please [write to the mailing list](https://lists.postgresql.org/manage/) or [open a question](https://github.com/psycopg/psycopg2/discussions) instead.
|
||||
|
||||
**Before opening this ticket, please confirm that:**
|
||||
- [ ] I am running the latest version of pip, i.e. typing ``pip --version`` you get [this version](https://pypi.org/project/pip/).
|
||||
- [ ] I have read the [installation documentation](https://www.psycopg.org/docs/install.html) and the [frequently asked questions](https://www.psycopg.org/docs/faq.html)
|
||||
- [ ] If install failed, I typed `pg_config` on the command line and I obtained an output instead of an error.
|
||||
|
||||
**Please complete the following information:**
|
||||
- OS:
|
||||
- Psycopg version:
|
||||
- Python version:
|
||||
- PostgreSQL version:
|
||||
- pip version
|
27
.github/ISSUE_TEMPLATE/problem-using-psycopg2.md
vendored
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
name: Problem using psycopg2
|
||||
about: Report a case in which psycopg2 is not working as expected
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**This is a bug tracker**
|
||||
If you have a question, such has "how do you do X with Python/PostgreSQL/psycopg2" please [write to the mailing list](https://lists.postgresql.org/manage/) or [open a question](https://github.com/psycopg/psycopg2/discussions) instead.
|
||||
|
||||
**Please complete the following information:**
|
||||
- OS:
|
||||
- Psycopg version:
|
||||
- Python version:
|
||||
- PostgreSQL version:
|
||||
- pip version
|
||||
|
||||
**Describe the bug**
|
||||
Please let us know:
|
||||
|
||||
1: what you did
|
||||
2: what you expected to happen
|
||||
3: what happened instead
|
||||
|
||||
If possible, provide a script reproducing the issue.
|
6
.github/dependabot.yml
vendored
|
@ -1,6 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
18
.github/workflows/docs.yml
vendored
|
@ -1,18 +0,0 @@
|
|||
name: Build documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
# This should match the DOC_BRANCH value in the psycopg-website Makefile
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger docs build
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
repository: psycopg/psycopg-website
|
||||
event-type: psycopg2-commit
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
266
.github/workflows/packages.yml
vendored
|
@ -1,266 +0,0 @@
|
|||
---
|
||||
name: Build packages
|
||||
on:
|
||||
- workflow_dispatch
|
||||
|
||||
env:
|
||||
PIP_BREAK_SYSTEM_PACKAGES: "1"
|
||||
LIBPQ_VERSION: "16.0"
|
||||
OPENSSL_VERSION: "1.1.1w"
|
||||
|
||||
jobs:
|
||||
sdist: # {{{
|
||||
if: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- package_name: psycopg2
|
||||
- package_name: psycopg2-binary
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repos
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build sdist
|
||||
run: ./scripts/build/build_sdist.sh
|
||||
env:
|
||||
PACKAGE_NAME: ${{ matrix.package_name }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdist-${{ matrix.package_name }}
|
||||
path: |
|
||||
dist/*.tar.gz
|
||||
|
||||
env:
|
||||
PSYCOPG2_TESTDB: postgres
|
||||
PSYCOPG2_TESTDB_HOST: 172.17.0.1
|
||||
PSYCOPG2_TESTDB_USER: postgres
|
||||
PSYCOPG2_TESTDB_PASSWORD: password
|
||||
PSYCOPG2_TEST_FAST: 1
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_PASSWORD: password
|
||||
ports:
|
||||
- 5432:5432
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
# }}}
|
||||
|
||||
linux: # {{{
|
||||
if: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [manylinux, musllinux]
|
||||
arch: [x86_64, i686, aarch64, ppc64le]
|
||||
pyver: [cp38, cp39, cp310, cp311, cp312, cp313]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repos
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU for multi-arch build
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Cache libpq build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/libpq.build
|
||||
key: libpq-${{ env.LIBPQ_VERSION }}-${{ matrix.platform }}-${{ matrix.arch }}
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.23.2
|
||||
env:
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
|
||||
CIBW_MANYLINUX_I686_IMAGE: manylinux2014
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014
|
||||
CIBW_MANYLINUX_PPC64LE_IMAGE: manylinux2014
|
||||
CIBW_BUILD: ${{matrix.pyver}}-${{matrix.platform}}_${{matrix.arch}}
|
||||
CIBW_ARCHS_LINUX: auto aarch64 ppc64le
|
||||
CIBW_BEFORE_ALL_LINUX: ./scripts/build/wheel_linux_before_all.sh
|
||||
CIBW_REPAIR_WHEEL_COMMAND: >-
|
||||
./scripts/build/strip_wheel.sh {wheel}
|
||||
&& auditwheel repair -w {dest_dir} {wheel}
|
||||
CIBW_TEST_COMMAND: >-
|
||||
export PYTHONPATH={project} &&
|
||||
python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')"
|
||||
CIBW_ENVIRONMENT_PASS_LINUX: LIBPQ_VERSION OPENSSL_VERSION
|
||||
CIBW_ENVIRONMENT: >-
|
||||
PACKAGE_NAME=psycopg2-binary
|
||||
LIBPQ_BUILD_PREFIX=/host/tmp/libpq.build
|
||||
PATH="$LIBPQ_BUILD_PREFIX/bin:$PATH"
|
||||
LD_LIBRARY_PATH="$LIBPQ_BUILD_PREFIX/lib:$LIBPQ_BUILD_PREFIX/lib64"
|
||||
PSYCOPG2_TESTDB=postgres
|
||||
PSYCOPG2_TESTDB_HOST=172.17.0.1
|
||||
PSYCOPG2_TESTDB_USER=postgres
|
||||
PSYCOPG2_TESTDB_PASSWORD=password
|
||||
PSYCOPG2_TEST_FAST=1
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-${{matrix.pyver}}-${{matrix.platform}}_${{matrix.arch}}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_PASSWORD: password
|
||||
ports:
|
||||
- 5432:5432
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
# }}}
|
||||
|
||||
macos: # {{{
|
||||
runs-on: macos-latest
|
||||
if: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# These archs require an Apple M1 runner: [arm64, universal2]
|
||||
arch: [x86_64, arm64]
|
||||
pyver: [cp39, cp310, cp311, cp312, cp313]
|
||||
|
||||
steps:
|
||||
- name: Checkout repos
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache libpq build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/libpq.build
|
||||
key: libpq-${{ env.LIBPQ_VERSION }}-macos-${{ matrix.arch }}
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.23.2
|
||||
env:
|
||||
CIBW_BUILD: ${{matrix.pyver}}-macosx_${{matrix.arch}}
|
||||
CIBW_ARCHS_MACOS: ${{matrix.arch}}
|
||||
MACOSX_ARCHITECTURE: ${{matrix.arch}}
|
||||
CIBW_BEFORE_ALL_MACOS: ./scripts/build/wheel_macos_before_all.sh
|
||||
CIBW_TEST_COMMAND: >-
|
||||
export PYTHONPATH={project} &&
|
||||
python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')"
|
||||
CIBW_ENVIRONMENT: >-
|
||||
PG_VERSION=16
|
||||
PACKAGE_NAME=psycopg2-binary
|
||||
PSYCOPG2_TESTDB=postgres
|
||||
PATH="/tmp/libpq.build/bin:$PATH"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-${{matrix.pyver}}-macos-${{matrix.arch}}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
# }}}
|
||||
|
||||
windows: # {{{
|
||||
runs-on: windows-latest
|
||||
if: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [win_amd64]
|
||||
pyver: [cp38, cp39, cp310, cp311, cp312, cp313]
|
||||
package_name: [psycopg2, psycopg2-binary]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
# there are some other libpq in PATH
|
||||
- name: Drop spurious libpq in the path
|
||||
run: rm -rf c:/tools/php C:/Strawberry/c/bin
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Start PostgreSQL service for test
|
||||
run: |
|
||||
$PgSvc = Get-Service "postgresql*"
|
||||
Set-Service $PgSvc.Name -StartupType manual
|
||||
$PgSvc.Start()
|
||||
shell: powershell
|
||||
|
||||
- name: Export GitHub Actions cache environment variables
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const path = require('path')
|
||||
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||
core.addPath(path.join(process.env.VCPKG_INSTALLATION_ROOT, 'installed/x64-windows-release/lib'));
|
||||
core.addPath(path.join(process.env.VCPKG_INSTALLATION_ROOT, 'installed/x64-windows-release/bin'));
|
||||
|
||||
- name: Create the binary package source tree
|
||||
run: >-
|
||||
sed -i 's/^setup(name="psycopg2"/setup(name="${{matrix.package_name}}"/'
|
||||
setup.py
|
||||
if: ${{ matrix.package_name != 'psycopg2' }}
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.23.2
|
||||
env:
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" # cache vcpkg
|
||||
CIBW_BUILD: ${{matrix.pyver}}-${{matrix.arch}}
|
||||
CIBW_ARCHS_WINDOWS: AMD64 x86
|
||||
CIBW_BEFORE_BUILD_WINDOWS: '.\scripts\build\wheel_win32_before_build.bat'
|
||||
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >-
|
||||
delvewheel repair -w {dest_dir}
|
||||
--no-mangle "libiconv-2.dll;libwinpthread-1.dll" {wheel}
|
||||
CIBW_TEST_COMMAND: >-
|
||||
set PYTHONPATH={project} &&
|
||||
python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')"
|
||||
# Note: no fast test because we don't run Windows tests
|
||||
CIBW_ENVIRONMENT_WINDOWS: >-
|
||||
PSYCOPG2_TESTDB=postgres
|
||||
PSYCOPG2_TESTDB_USER=postgres
|
||||
PSYCOPG2_TESTDB_HOST=localhost
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-${{ matrix.package_name }}-${{matrix.pyver}}-${{matrix.arch}}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
# }}}
|
||||
|
||||
merge: # {{{
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- sdist
|
||||
- linux
|
||||
- macos
|
||||
- windows
|
||||
steps:
|
||||
- name: Merge Artifacts
|
||||
uses: actions/upload-artifact/merge@v4
|
||||
with:
|
||||
name: psycopg2-artifacts
|
||||
delete-merged: true
|
||||
|
||||
# }}}
|
79
.github/workflows/tests.yml
vendored
|
@ -1,79 +0,0 @@
|
|||
name: Tests
|
||||
|
||||
env:
|
||||
PIP_BREAK_SYSTEM_PACKAGES: "1"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
if: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {python: "3.8", postgres: "12"}
|
||||
- {python: "3.9", postgres: "13"}
|
||||
- {python: "3.10", postgres: "14"}
|
||||
- {python: "3.11", postgres: "15"}
|
||||
- {python: "3.12", postgres: "16"}
|
||||
- {python: "3.13", postgres: "17"}
|
||||
|
||||
# Opposite extremes of the supported Py/PG range, other architecture
|
||||
- {python: "3.8", postgres: "17", architecture: "x86"}
|
||||
- {python: "3.9", postgres: "16", architecture: "x86"}
|
||||
- {python: "3.10", postgres: "15", architecture: "x86"}
|
||||
- {python: "3.11", postgres: "14", architecture: "x86"}
|
||||
- {python: "3.12", postgres: "13", architecture: "x86"}
|
||||
- {python: "3.13", postgres: "12", architecture: "x86"}
|
||||
|
||||
env:
|
||||
PSYCOPG2_TESTDB: postgres
|
||||
PSYCOPG2_TESTDB_HOST: 127.0.0.1
|
||||
PSYCOPG2_TESTDB_USER: postgres
|
||||
PSYCOPG2_TESTDB_PASSWORD: password
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:${{ matrix.postgres }}
|
||||
env:
|
||||
POSTGRES_PASSWORD: password
|
||||
ports:
|
||||
- 5432:5432
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Can enable to test an unreleased libpq version.
|
||||
- name: install libpq 16
|
||||
if: false
|
||||
run: |
|
||||
set -x
|
||||
rel=$(lsb_release -c -s)
|
||||
echo "deb http://apt.postgresql.org/pub/repos/apt ${rel}-pgdg main 16" \
|
||||
| sudo tee -a /etc/apt/sources.list.d/pgdg.list
|
||||
sudo apt-get -qq update
|
||||
pqver=$(apt-cache show libpq5 | grep ^Version: | head -1 \
|
||||
| awk '{print $2}')
|
||||
sudo apt-get -qq -y install "libpq-dev=${pqver}" "libpq5=${pqver}"
|
||||
|
||||
- name: Install tox
|
||||
run: pip install "tox < 4"
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Run tests
|
||||
env:
|
||||
MATRIX_PYTHON: ${{ matrix.python }}
|
||||
run: tox -e ${MATRIX_PYTHON%-dev}
|
||||
timeout-minutes: 5
|
14
.gitignore
vendored
|
@ -4,15 +4,9 @@ MANIFEST
|
|||
*.pidb
|
||||
*.pyc
|
||||
*.sw[po]
|
||||
*.egg-info/
|
||||
dist/*
|
||||
/build
|
||||
build/*
|
||||
doc/src/_build/*
|
||||
doc/html/*
|
||||
doc/psycopg2.txt
|
||||
env
|
||||
env?
|
||||
.idea
|
||||
.tox
|
||||
.vscode/
|
||||
/rel
|
||||
/wheels
|
||||
/packages
|
||||
/wheelhouse
|
||||
|
|
105
INSTALL
|
@ -1,4 +1,103 @@
|
|||
Installation instructions are included in the docs.
|
||||
Compiling and installing psycopg
|
||||
********************************
|
||||
|
||||
** Important note: if you plan to use psycopg2 in a multithreaded application,
|
||||
make sure that your libpq has been compiled with the --with-thread-safety
|
||||
option. psycopg2 will work correctly even with a non-thread-safe libpq but
|
||||
libpq will leak memory.
|
||||
|
||||
psycopg2 uses distutils for its build process, so most of the process is
|
||||
executed by the setup.py script. Before building psycopg look at
|
||||
setup.cfg file and change any settings to follow your system (or taste);
|
||||
then:
|
||||
|
||||
python setup.py build
|
||||
|
||||
to build in the local directory; and:
|
||||
|
||||
python setup.py install
|
||||
|
||||
to install system-wide.
|
||||
|
||||
|
||||
Common errors and build problems
|
||||
================================
|
||||
|
||||
One of the most common errors is trying to build psycopg without the right
|
||||
development headers for PostgreSQL, Python or both. If you get errors, look
|
||||
for the following messages and then take the appropriate action:
|
||||
|
||||
libpq-fe.h: No such file or directory
|
||||
PostgreSQL headers are not properly installed on your system or are
|
||||
installed in a non default path. First make sure they are installed, then
|
||||
check setup.cfg and make sure pg_config points to a valid pg_config
|
||||
executable. If you don't have a working pg_config try to play with the
|
||||
include_dirs variable (and note that a working pg_config is better.)
|
||||
|
||||
|
||||
Running the test suite
|
||||
======================
|
||||
|
||||
The included Makefile allows to run all the tests included in the
|
||||
distribution. Just use:
|
||||
|
||||
make
|
||||
make check
|
||||
|
||||
The tests are run against a database called psycopg2_test on unix socket
|
||||
and standard port. You can configure a different database to run the test
|
||||
by setting the environment variables:
|
||||
|
||||
- PSYCOPG2_TESTDB
|
||||
- PSYCOPG2_TESTDB_HOST
|
||||
- PSYCOPG2_TESTDB_PORT
|
||||
- PSYCOPG2_TESTDB_USER
|
||||
|
||||
The database should be created before running the tests.
|
||||
|
||||
The standard Python unittest is used to run the tests. But if unittest2 is
|
||||
found it will be used instead, with the result of having more informations
|
||||
about skipped tests.
|
||||
|
||||
|
||||
Building the documentation
|
||||
==========================
|
||||
|
||||
In order to build the documentation included in the distribution, use
|
||||
|
||||
make env
|
||||
make docs
|
||||
|
||||
The first command will install all the dependencies (Sphinx, Docutils) in
|
||||
an 'env' directory in the project tree. The second command will build both
|
||||
the html format (in the 'doc/html' directory) and in plain text
|
||||
(doc/psycopg2.txt)
|
||||
|
||||
|
||||
Using setuptools and EasyInstall
|
||||
================================
|
||||
|
||||
If setuptools are installed on your system you can easily create an egg for
|
||||
psycopg and install it. Download the source distribution (if you're reading
|
||||
this file you probably already have) and then edit setup.cfg to your taste
|
||||
and build from the source distribution top-level directory using:
|
||||
|
||||
easy_install .
|
||||
|
||||
|
||||
Compiling under Windows with mingw32
|
||||
====================================
|
||||
|
||||
You can compile psycopg under Windows platform with mingw32
|
||||
(http://www.mingw.org/) compiler. MinGW is also shipped with IDEs such as
|
||||
Dev-C++ (http://www.bloodshed.net/devcpp.html) and Code::Blocks
|
||||
(http://www.codeblocks.org). gcc binaries should be in your PATH.
|
||||
|
||||
You need a PostgreSQL with include and libary files installed. At least v8.0
|
||||
is required.
|
||||
|
||||
First you need to create a libpython2X.a as described in
|
||||
http://starship.python.net/crew/kernr/mingw32/Notes.html. Then run:
|
||||
|
||||
python setup.py build_ext --compiler=mingw32 install
|
||||
|
||||
Please check the 'doc/src/install.rst' file or online at
|
||||
<https://www.psycopg.org/docs/install.html>.
|
||||
|
|
15
LICENSE
|
@ -1,5 +1,5 @@
|
|||
psycopg2 and the LGPL
|
||||
---------------------
|
||||
=====================
|
||||
|
||||
psycopg2 is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published
|
||||
|
@ -25,14 +25,19 @@ statement from all source files in the program, then also delete it here.
|
|||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with psycopg2 (see the doc/ directory.)
|
||||
If not, see <https://www.gnu.org/licenses/>.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Alternative licenses
|
||||
--------------------
|
||||
====================
|
||||
|
||||
The following BSD-like license applies (at your option) to the files following
|
||||
the pattern ``psycopg/adapter*.{h,c}`` and ``psycopg/microprotocol*.{h,c}``:
|
||||
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.
|
||||
|
||||
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
|
||||
|
|
15
MANIFEST.in
|
@ -1,9 +1,16 @@
|
|||
recursive-include psycopg *.c *.h *.manifest
|
||||
recursive-include lib *.py
|
||||
recursive-include tests *.py
|
||||
include doc/README.rst doc/SUCCESS doc/COPYING.LESSER doc/pep-0249.txt
|
||||
include doc/Makefile doc/requirements.txt
|
||||
recursive-include ZPsycopgDA *.py *.gif *.dtml
|
||||
recursive-include psycopg2da *
|
||||
recursive-include examples *.py somehackers.jpg whereareyou.jpg
|
||||
recursive-include debian *
|
||||
recursive-include doc README HACKING SUCCESS COPYING* ChangeLog-1.x pep-0249.txt
|
||||
recursive-include doc *.txt *.html *.css *.js Makefile
|
||||
recursive-include doc/src *.rst *.py *.css Makefile
|
||||
recursive-include doc/html *
|
||||
prune doc/src/_build
|
||||
recursive-include scripts *.py *.sh
|
||||
include AUTHORS README.rst INSTALL LICENSE NEWS
|
||||
include MANIFEST.in setup.py setup.cfg Makefile
|
||||
include scripts/maketypes.sh scripts/buildtypes.py
|
||||
include AUTHORS README INSTALL LICENSE NEWS ChangeLog
|
||||
include PKG-INFO MANIFEST.in MANIFEST setup.py setup.cfg Makefile
|
||||
|
|
52
Makefile
|
@ -6,11 +6,12 @@
|
|||
#
|
||||
# Build the documentation::
|
||||
#
|
||||
# make env (once)
|
||||
# make env
|
||||
# make docs
|
||||
#
|
||||
# Create a source package::
|
||||
#
|
||||
# make env # required to build the documentation
|
||||
# make sdist
|
||||
#
|
||||
# Run the test::
|
||||
|
@ -20,6 +21,9 @@
|
|||
PYTHON := python$(PYTHON_VERSION)
|
||||
PYTHON_VERSION ?= $(shell $(PYTHON) -c 'import sys; print ("%d.%d" % sys.version_info[:2])')
|
||||
BUILD_DIR = $(shell pwd)/build/lib.$(PYTHON_VERSION)
|
||||
ENV_DIR = $(shell pwd)/env/py-$(PYTHON_VERSION)
|
||||
ENV_BIN = $(ENV_DIR)/bin
|
||||
ENV_LIB = $(ENV_DIR)/lib
|
||||
|
||||
SOURCE_C := $(wildcard psycopg/*.c psycopg/*.h)
|
||||
SOURCE_PY := $(wildcard lib/*.py)
|
||||
|
@ -29,7 +33,8 @@ SOURCE := $(SOURCE_C) $(SOURCE_PY) $(SOURCE_TESTS) $(SOURCE_DOC)
|
|||
|
||||
PACKAGE := $(BUILD_DIR)/psycopg2
|
||||
PLATLIB := $(PACKAGE)/_psycopg.so
|
||||
PURELIB := $(patsubst lib/%,$(PACKAGE)/%,$(SOURCE_PY))
|
||||
PURELIB := $(patsubst lib/%,$(PACKAGE)/%,$(SOURCE_PY)) \
|
||||
$(patsubst tests/%,$(PACKAGE)/tests/%,$(SOURCE_TESTS))
|
||||
|
||||
BUILD_OPT := --build-lib=$(BUILD_DIR)
|
||||
BUILD_EXT_OPT := --build-lib=$(BUILD_DIR)
|
||||
|
@ -42,7 +47,10 @@ endif
|
|||
VERSION := $(shell grep PSYCOPG_VERSION setup.py | head -1 | sed -e "s/.*'\(.*\)'/\1/")
|
||||
SDIST := dist/psycopg2-$(VERSION).tar.gz
|
||||
|
||||
.PHONY: check clean
|
||||
EASY_INSTALL = PYTHONPATH=$(ENV_LIB) $(ENV_BIN)/easy_install-$(PYTHON_VERSION) -d $(ENV_LIB) -s $(ENV_BIN)
|
||||
EZ_SETUP = $(ENV_BIN)/ez_setup.py
|
||||
|
||||
.PHONY: env check clean
|
||||
|
||||
default: package
|
||||
|
||||
|
@ -50,20 +58,36 @@ all: package sdist
|
|||
|
||||
package: $(PLATLIB) $(PURELIB)
|
||||
|
||||
docs: docs-html
|
||||
docs: docs-html docs-txt
|
||||
|
||||
docs-html: doc/html/genindex.html
|
||||
|
||||
docs-txt: doc/psycopg2.txt
|
||||
|
||||
# for PyPI documentation
|
||||
docs-zip: doc/docs.zip
|
||||
|
||||
sdist: $(SDIST)
|
||||
|
||||
env:
|
||||
$(MAKE) -C doc $@
|
||||
# The environment is currently required to build the documentation.
|
||||
# It is not clean by 'make clean'
|
||||
|
||||
env: easy_install
|
||||
mkdir -p $(ENV_BIN)
|
||||
mkdir -p $(ENV_LIB)
|
||||
$(EASY_INSTALL) docutils
|
||||
$(EASY_INSTALL) sphinx
|
||||
|
||||
easy_install: ez_setup
|
||||
PYTHONPATH=$(ENV_LIB) $(PYTHON) $(EZ_SETUP) -d $(ENV_LIB) -s $(ENV_BIN) setuptools
|
||||
|
||||
ez_setup:
|
||||
mkdir -p $(ENV_BIN)
|
||||
mkdir -p $(ENV_LIB)
|
||||
wget -O $(EZ_SETUP) http://peak.telecommunity.com/dist/ez_setup.py
|
||||
|
||||
check:
|
||||
PYTHONPATH=$(BUILD_DIR) $(PYTHON) -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose
|
||||
PYTHONPATH=$(BUILD_DIR):$(PYTHONPATH) $(PYTHON) -c "from psycopg2 import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose
|
||||
|
||||
testdb:
|
||||
@echo "* Creating $(TESTDB)"
|
||||
|
@ -89,16 +113,24 @@ $(PACKAGE)/tests/%.py: tests/%.py
|
|||
$(PYTHON) setup.py build_py $(BUILD_OPT)
|
||||
touch $@
|
||||
|
||||
$(SDIST): $(SOURCE)
|
||||
$(SDIST): docs MANIFEST $(SOURCE)
|
||||
$(PYTHON) setup.py sdist $(SDIST_OPT)
|
||||
|
||||
MANIFEST: MANIFEST.in $(SOURCE)
|
||||
# Run twice as MANIFEST.in includes MANIFEST
|
||||
$(PYTHON) setup.py sdist --manifest-only
|
||||
$(PYTHON) setup.py sdist --manifest-only
|
||||
|
||||
# docs depend on the build as it partly use introspection.
|
||||
doc/html/genindex.html: $(PLATLIB) $(PURELIB) $(SOURCE_DOC)
|
||||
$(MAKE) -C doc html
|
||||
PYTHONPATH=$(ENV_LIB):$(BUILD_DIR) $(MAKE) SPHINXBUILD=$(ENV_BIN)/sphinx-build -C doc html
|
||||
|
||||
doc/psycopg2.txt: $(PLATLIB) $(PURELIB) $(SOURCE_DOC)
|
||||
PYTHONPATH=$(ENV_LIB):$(BUILD_DIR) $(MAKE) SPHINXBUILD=$(ENV_BIN)/sphinx-build -C doc text
|
||||
|
||||
doc/docs.zip: doc/html/genindex.html
|
||||
(cd doc/html && zip -r ../docs.zip *)
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
rm -rf build MANIFEST
|
||||
$(MAKE) -C doc clean
|
||||
|
|
38
README
Normal file
|
@ -0,0 +1,38 @@
|
|||
psycopg2 - Python-PostgreSQL Database Adapter
|
||||
********************************************
|
||||
|
||||
psycopg2 is a PostgreSQL database adapter for the Python programming
|
||||
language. psycopg2 was written with the aim of being very small and fast,
|
||||
and stable as a rock.
|
||||
|
||||
psycopg2 is different from the other database adapter because it was
|
||||
designed for heavily multi-threaded applications that create and destroy
|
||||
lots of cursors and make a conspicuous number of concurrent INSERTs or
|
||||
UPDATEs. psycopg2 also provides full asynchronous operations and support
|
||||
for coroutine libraries.
|
||||
|
||||
psycopg2 can compile and run on Linux, FreeBSD, Solaris, MacOS X and
|
||||
Windows architecture. It supports Python versions from 2.4 onwards and
|
||||
PostgreSQL versions from 7.4 onwards.
|
||||
|
||||
psycopg2 is free software ("free as in freedom" but I like beer too.)
|
||||
It is licensed under the GNU Lesser General Public License, version 3 or
|
||||
later plus an exception to allow OpenSSL (libpq) linking; see LICENSE for
|
||||
more details.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Start by reading the INSTALL file. More information about psycopg2 extensions
|
||||
to the DBAPI-2.0 is available in the files located in the doc/ direcory.
|
||||
Example code can be found in the examples/ directory. If you make any changes
|
||||
to the code make sure to run the unit tests localed in tests/.
|
||||
|
||||
Online documentation can be found at: http://initd.org/psycopg/
|
||||
|
||||
If you stumble upon any bugs, please tell us at: http://psycopg.lighthouseapp.com/
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
For a list of contributors to the project, see the AUTHORS file.
|
80
README.rst
|
@ -1,80 +0,0 @@
|
|||
psycopg2 - Python-PostgreSQL Database Adapter
|
||||
=============================================
|
||||
|
||||
Psycopg is the most popular PostgreSQL database adapter for the Python
|
||||
programming language. Its main features are the complete implementation of
|
||||
the Python DB API 2.0 specification and the thread safety (several threads can
|
||||
share the same connection). It was designed for heavily multi-threaded
|
||||
applications that create and destroy lots of cursors and make a large number
|
||||
of concurrent "INSERT"s or "UPDATE"s.
|
||||
|
||||
Psycopg 2 is mostly implemented in C as a libpq wrapper, resulting in being
|
||||
both efficient and secure. It features client-side and server-side cursors,
|
||||
asynchronous communication and notifications, "COPY TO/COPY FROM" support.
|
||||
Many Python types are supported out-of-the-box and adapted to matching
|
||||
PostgreSQL data types; adaptation can be extended and customized thanks to a
|
||||
flexible objects adaptation system.
|
||||
|
||||
Psycopg 2 is both Unicode and Python 3 friendly.
|
||||
|
||||
.. Note::
|
||||
|
||||
The psycopg2 package is still widely used and actively maintained, but it
|
||||
is not expected to receive new features.
|
||||
|
||||
`Psycopg 3`__ is the evolution of psycopg2 and is where `new features are
|
||||
being developed`__: if you are starting a new project you should probably
|
||||
start from 3!
|
||||
|
||||
.. __: https://pypi.org/project/psycopg/
|
||||
.. __: https://www.psycopg.org/psycopg3/docs/index.html
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Documentation is included in the ``doc`` directory and is `available online`__.
|
||||
|
||||
.. __: https://www.psycopg.org/docs/
|
||||
|
||||
For any other resource (source code repository, bug tracker, mailing list)
|
||||
please check the `project homepage`__.
|
||||
|
||||
.. __: https://psycopg.org/
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Building Psycopg requires a few prerequisites (a C compiler, some development
|
||||
packages): please check the install_ and the faq_ documents in the ``doc`` dir
|
||||
or online for the details.
|
||||
|
||||
If prerequisites are met, you can install psycopg like any other Python
|
||||
package, using ``pip`` to download it from PyPI_::
|
||||
|
||||
$ pip install psycopg2
|
||||
|
||||
or using ``setup.py`` if you have downloaded the source package locally::
|
||||
|
||||
$ python setup.py build
|
||||
$ sudo python setup.py install
|
||||
|
||||
You can also obtain a stand-alone package, not requiring a compiler or
|
||||
external libraries, by installing the `psycopg2-binary`_ package from PyPI::
|
||||
|
||||
$ pip install psycopg2-binary
|
||||
|
||||
The binary package is a practical choice for development and testing but in
|
||||
production it is advised to use the package built from sources.
|
||||
|
||||
.. _PyPI: https://pypi.org/project/psycopg2/
|
||||
.. _psycopg2-binary: https://pypi.org/project/psycopg2-binary/
|
||||
.. _install: https://www.psycopg.org/docs/install.html#install-from-source
|
||||
.. _faq: https://www.psycopg.org/docs/faq.html#faq-compile
|
||||
|
||||
:Build status: |gh-actions|
|
||||
|
||||
.. |gh-actions| image:: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml/badge.svg
|
||||
:target: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml
|
||||
:alt: Build status
|
360
ZPsycopgDA/DA.py
Normal file
|
@ -0,0 +1,360 @@
|
|||
# ZPsycopgDA/DA.py - ZPsycopgDA Zope product: Database Connection
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
# Import modules needed by _psycopg to allow tools like py2exe to do
|
||||
# their work without bothering about the module dependencies.
|
||||
|
||||
|
||||
ALLOWED_PSYCOPG_VERSIONS = ('2.4', '2.4.1', '2.4.4', '2.4.5', '2.4.6')
|
||||
|
||||
import sys
|
||||
import time
|
||||
import db
|
||||
import re
|
||||
|
||||
import Acquisition
|
||||
import Shared.DC.ZRDB.Connection
|
||||
|
||||
from db import DB
|
||||
from Globals import HTMLFile
|
||||
from ExtensionClass import Base
|
||||
from App.Dialogs import MessageDialog
|
||||
from DateTime import DateTime
|
||||
|
||||
# ImageFile is deprecated in Zope >= 2.9
|
||||
try:
|
||||
from App.ImageFile import ImageFile
|
||||
except ImportError:
|
||||
# Zope < 2.9. If PIL's installed with a .pth file, we're probably
|
||||
# hosed.
|
||||
from ImageFile import ImageFile
|
||||
|
||||
# import psycopg and functions/singletons needed for date/time conversions
|
||||
|
||||
import psycopg2
|
||||
from psycopg2 import NUMBER, STRING, ROWID, DATETIME
|
||||
from psycopg2.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN, DATE
|
||||
from psycopg2.extensions import TIME, INTERVAL
|
||||
from psycopg2.extensions import new_type, register_type
|
||||
|
||||
|
||||
# add a new connection to a folder
|
||||
|
||||
manage_addZPsycopgConnectionForm = HTMLFile('dtml/add',globals())
|
||||
|
||||
def manage_addZPsycopgConnection(self, id, title, connection_string,
|
||||
zdatetime=None, tilevel=2,
|
||||
encoding='', check=None, REQUEST=None):
|
||||
"""Add a DB connection to a folder."""
|
||||
self._setObject(id, Connection(id, title, connection_string,
|
||||
zdatetime, check, tilevel, encoding))
|
||||
if REQUEST is not None: return self.manage_main(self, REQUEST)
|
||||
|
||||
|
||||
# the connection object
|
||||
|
||||
class Connection(Shared.DC.ZRDB.Connection.Connection):
|
||||
"""ZPsycopg Connection."""
|
||||
_isAnSQLConnection = 1
|
||||
|
||||
id = 'Psycopg2_database_connection'
|
||||
database_type = 'Psycopg2'
|
||||
meta_type = title = 'Z Psycopg 2 Database Connection'
|
||||
icon = 'misc_/conn'
|
||||
|
||||
def __init__(self, id, title, connection_string,
|
||||
zdatetime, check=None, tilevel=2, encoding='UTF-8'):
|
||||
self.zdatetime = zdatetime
|
||||
self.id = str(id)
|
||||
self.edit(title, connection_string, zdatetime,
|
||||
check=check, tilevel=tilevel, encoding=encoding)
|
||||
|
||||
def factory(self):
|
||||
return DB
|
||||
|
||||
## connection parameters editing ##
|
||||
|
||||
def edit(self, title, connection_string,
|
||||
zdatetime, check=None, tilevel=2, encoding='UTF-8'):
|
||||
self.title = title
|
||||
self.connection_string = connection_string
|
||||
self.zdatetime = zdatetime
|
||||
self.tilevel = tilevel
|
||||
self.encoding = encoding
|
||||
|
||||
if check: self.connect(self.connection_string)
|
||||
|
||||
manage_properties = HTMLFile('dtml/edit', globals())
|
||||
|
||||
def manage_edit(self, title, connection_string,
|
||||
zdatetime=None, check=None, tilevel=2, encoding='UTF-8',
|
||||
REQUEST=None):
|
||||
"""Edit the DB connection."""
|
||||
self.edit(title, connection_string, zdatetime,
|
||||
check=check, tilevel=tilevel, encoding=encoding)
|
||||
if REQUEST is not None:
|
||||
msg = "Connection edited."
|
||||
return self.manage_main(self,REQUEST,manage_tabs_message=msg)
|
||||
|
||||
def connect(self, s):
|
||||
try:
|
||||
self._v_database_connection.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
# check psycopg version and raise exception if does not match
|
||||
if psycopg2.__version__.split(' ')[0] not in ALLOWED_PSYCOPG_VERSIONS:
|
||||
raise ImportError("psycopg version mismatch (imported %s)" %
|
||||
psycopg2.__version__)
|
||||
|
||||
self._v_connected = ''
|
||||
dbf = self.factory()
|
||||
|
||||
# TODO: let the psycopg exception propagate, or not?
|
||||
self._v_database_connection = dbf(
|
||||
self.connection_string, self.tilevel, self.get_type_casts(), self.encoding)
|
||||
self._v_database_connection.open()
|
||||
self._v_connected = DateTime()
|
||||
|
||||
return self
|
||||
|
||||
def get_type_casts(self):
|
||||
# note that in both cases order *is* important
|
||||
if self.zdatetime:
|
||||
return ZDATETIME, ZDATE, ZTIME
|
||||
else:
|
||||
return DATETIME, DATE, TIME
|
||||
|
||||
## browsing and table/column management ##
|
||||
|
||||
manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options
|
||||
# + (
|
||||
# {'label': 'Browse', 'action':'manage_browse'},)
|
||||
|
||||
#manage_tables = HTMLFile('dtml/tables', globals())
|
||||
#manage_browse = HTMLFile('dtml/browse', globals())
|
||||
|
||||
info = None
|
||||
|
||||
def table_info(self):
|
||||
return self._v_database_connection.table_info()
|
||||
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name == 'tableNamed':
|
||||
if not hasattr(self, '_v_tables'): self.tpValues()
|
||||
return self._v_tables.__of__(self)
|
||||
raise KeyError, name
|
||||
|
||||
def tpValues(self):
|
||||
res = []
|
||||
conn = self._v_database_connection
|
||||
for d in conn.tables(rdb=0):
|
||||
try:
|
||||
name = d['TABLE_NAME']
|
||||
b = TableBrowser()
|
||||
b.__name__ = name
|
||||
b._d = d
|
||||
b._c = c
|
||||
try:
|
||||
b.icon = table_icons[d['TABLE_TYPE']]
|
||||
except:
|
||||
pass
|
||||
r.append(b)
|
||||
except:
|
||||
pass
|
||||
return res
|
||||
|
||||
|
||||
## database connection registration data ##
|
||||
|
||||
classes = (Connection,)
|
||||
|
||||
meta_types = ({'name':'Z Psycopg 2 Database Connection',
|
||||
'action':'manage_addZPsycopgConnectionForm'},)
|
||||
|
||||
folder_methods = {
|
||||
'manage_addZPsycopgConnection': manage_addZPsycopgConnection,
|
||||
'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm}
|
||||
|
||||
__ac_permissions__ = (
|
||||
('Add Z Psycopg Database Connections',
|
||||
('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),)
|
||||
|
||||
# add icons
|
||||
|
||||
misc_={'conn': ImageFile('icons/DBAdapterFolder_icon.gif', globals())}
|
||||
|
||||
for icon in ('table', 'view', 'stable', 'what', 'field', 'text', 'bin',
|
||||
'int', 'float', 'date', 'time', 'datetime'):
|
||||
misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())
|
||||
|
||||
|
||||
## zope-specific psycopg typecasters ##
|
||||
|
||||
# convert an ISO timestamp string from postgres to a Zope DateTime object
|
||||
def _cast_DateTime(iso, curs):
|
||||
if iso:
|
||||
if iso in ['-infinity', 'infinity']:
|
||||
return iso
|
||||
else:
|
||||
return DateTime(iso)
|
||||
|
||||
# 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.
|
||||
# NOTE: we set the day as today before feeding to DateTime so
|
||||
# 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:]))
|
||||
|
||||
# NOTE: we don't cast intervals anymore because they are passed
|
||||
# untouched to Zope.
|
||||
def _cast_Interval(iso, curs):
|
||||
return iso
|
||||
|
||||
ZDATETIME = new_type((1184, 1114), "ZDATETIME", _cast_DateTime)
|
||||
ZINTERVAL = new_type((1186,), "ZINTERVAL", _cast_Interval)
|
||||
ZDATE = new_type((1082,), "ZDATE", _cast_Date)
|
||||
ZTIME = new_type((1083,), "ZTIME", _cast_Time)
|
||||
|
||||
|
||||
## table browsing helpers ##
|
||||
|
||||
class TableBrowserCollection(Acquisition.Implicit):
|
||||
pass
|
||||
|
||||
class Browser(Base):
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self._d[name]
|
||||
except KeyError:
|
||||
raise AttributeError, name
|
||||
|
||||
class values:
|
||||
def len(self):
|
||||
return 1
|
||||
|
||||
def __getitem__(self, i):
|
||||
try:
|
||||
return self._d[i]
|
||||
except AttributeError:
|
||||
pass
|
||||
self._d = self._f()
|
||||
return self._d[i]
|
||||
|
||||
class TableBrowser(Browser, Acquisition.Implicit):
|
||||
icon = 'what'
|
||||
Description = check = ''
|
||||
info = HTMLFile('table_info', globals())
|
||||
menu = HTMLFile('table_menu', globals())
|
||||
|
||||
def tpValues(self):
|
||||
v = values()
|
||||
v._f = self.tpValues_
|
||||
return v
|
||||
|
||||
def tpValues_(self):
|
||||
r=[]
|
||||
tname=self.__name__
|
||||
for d in self._c.columns(tname):
|
||||
b=ColumnBrowser()
|
||||
b._d=d
|
||||
try: b.icon=field_icons[d['Type']]
|
||||
except: pass
|
||||
b.TABLE_NAME=tname
|
||||
r.append(b)
|
||||
return r
|
||||
|
||||
def tpId(self): return self._d['TABLE_NAME']
|
||||
def tpURL(self): return "Table/%s" % self._d['TABLE_NAME']
|
||||
def Name(self): return self._d['TABLE_NAME']
|
||||
def Type(self): return self._d['TABLE_TYPE']
|
||||
|
||||
manage_designInput=HTMLFile('designInput',globals())
|
||||
def manage_buildInput(self, id, source, default, REQUEST=None):
|
||||
"Create a database method for an input form"
|
||||
args=[]
|
||||
values=[]
|
||||
names=[]
|
||||
columns=self._columns
|
||||
for i in range(len(source)):
|
||||
s=source[i]
|
||||
if s=='Null': continue
|
||||
c=columns[i]
|
||||
d=default[i]
|
||||
t=c['Type']
|
||||
n=c['Name']
|
||||
names.append(n)
|
||||
if s=='Argument':
|
||||
values.append("<dtml-sqlvar %s type=%s>'" %
|
||||
(n, vartype(t)))
|
||||
a='%s%s' % (n, boboType(t))
|
||||
if d: a="%s=%s" % (a,d)
|
||||
args.append(a)
|
||||
elif s=='Property':
|
||||
values.append("<dtml-sqlvar %s type=%s>'" %
|
||||
(n, vartype(t)))
|
||||
else:
|
||||
if isStringType(t):
|
||||
if find(d,"\'") >= 0: d=join(split(d,"\'"),"''")
|
||||
values.append("'%s'" % d)
|
||||
elif d:
|
||||
values.append(str(d))
|
||||
else:
|
||||
raise ValueError, (
|
||||
'no default was given for <em>%s</em>' % n)
|
||||
|
||||
class ColumnBrowser(Browser):
|
||||
icon='field'
|
||||
|
||||
def check(self):
|
||||
return ('\t<input type=checkbox name="%s.%s">' %
|
||||
(self.TABLE_NAME, self._d['Name']))
|
||||
def tpId(self): return self._d['Name']
|
||||
def tpURL(self): return "Column/%s" % self._d['Name']
|
||||
def Description(self):
|
||||
d=self._d
|
||||
if d['Scale']:
|
||||
return " %(Type)s(%(Precision)s,%(Scale)s) %(Nullable)s" % d
|
||||
else:
|
||||
return " %(Type)s(%(Precision)s) %(Nullable)s" % d
|
||||
|
||||
table_icons={
|
||||
'TABLE': 'table',
|
||||
'VIEW':'view',
|
||||
'SYSTEM_TABLE': 'stable',
|
||||
}
|
||||
|
||||
field_icons={
|
||||
NUMBER.name: 'i',
|
||||
STRING.name: 'text',
|
||||
DATETIME.name: 'date',
|
||||
INTEGER.name: 'int',
|
||||
FLOAT.name: 'float',
|
||||
BOOLEAN.name: 'bin',
|
||||
ROWID.name: 'int'
|
||||
}
|
29
ZPsycopgDA/__init__.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# ZPsycopgDA/__init__.py - ZPsycopgDA Zope product
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
# Import modules needed by _psycopg to allow tools like py2exe to do
|
||||
# their work without bothering about the module dependencies.
|
||||
|
||||
__doc__ = "ZPsycopg Database Adapter Registration."
|
||||
__version__ = '2.0'
|
||||
|
||||
import DA
|
||||
|
||||
def initialize(context):
|
||||
context.registerClass(
|
||||
DA.Connection,
|
||||
permission = 'Add Z Psycopg 2 Database Connections',
|
||||
constructors = (DA.manage_addZPsycopgConnectionForm,
|
||||
DA.manage_addZPsycopgConnection),
|
||||
icon = 'icons/DBAdapterFolder_icon.gif')
|
209
ZPsycopgDA/db.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
# ZPsycopgDA/db.py - query execution
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
# Import modules needed by _psycopg to allow tools like py2exe to do
|
||||
# their work without bothering about the module dependencies.
|
||||
|
||||
from Shared.DC.ZRDB.TM import TM
|
||||
from Shared.DC.ZRDB import dbi_db
|
||||
|
||||
from ZODB.POSException import ConflictError
|
||||
|
||||
import site
|
||||
import pool
|
||||
|
||||
import psycopg2
|
||||
from psycopg2.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN, DATE, TIME
|
||||
from psycopg2.extensions import TransactionRollbackError, register_type
|
||||
from psycopg2 import NUMBER, STRING, ROWID, DATETIME
|
||||
|
||||
|
||||
# the DB object, managing all the real query work
|
||||
|
||||
class DB(TM, dbi_db.DB):
|
||||
|
||||
_p_oid = _p_changed = _registered = None
|
||||
|
||||
def __init__(self, dsn, tilevel, typecasts, enc='utf-8'):
|
||||
self.dsn = dsn
|
||||
self.tilevel = tilevel
|
||||
self.typecasts = typecasts
|
||||
if enc is None or enc == "":
|
||||
self.encoding = "utf-8"
|
||||
else:
|
||||
self.encoding = enc
|
||||
self.failures = 0
|
||||
self.calls = 0
|
||||
self.make_mappings()
|
||||
|
||||
def getconn(self, init=True):
|
||||
# if init is False we are trying to get hold on an already existing
|
||||
# connection, so we avoid to (re)initialize it risking errors.
|
||||
conn = pool.getconn(self.dsn)
|
||||
if init:
|
||||
# use set_session where available as in these versions
|
||||
# set_isolation_level generates an extra query.
|
||||
if psycopg2.__version__ >= '2.4.2':
|
||||
conn.set_session(isolation_level=int(self.tilevel))
|
||||
else:
|
||||
conn.set_isolation_level(int(self.tilevel))
|
||||
conn.set_client_encoding(self.encoding)
|
||||
for tc in self.typecasts:
|
||||
register_type(tc, conn)
|
||||
return conn
|
||||
|
||||
def putconn(self, close=False):
|
||||
try:
|
||||
conn = pool.getconn(self.dsn, False)
|
||||
except AttributeError:
|
||||
pass
|
||||
pool.putconn(self.dsn, conn, close)
|
||||
|
||||
def getcursor(self):
|
||||
conn = self.getconn(False)
|
||||
return conn.cursor()
|
||||
|
||||
def _finish(self, *ignored):
|
||||
try:
|
||||
conn = self.getconn(False)
|
||||
conn.commit()
|
||||
self.putconn()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _abort(self, *ignored):
|
||||
try:
|
||||
conn = self.getconn(False)
|
||||
conn.rollback()
|
||||
self.putconn()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def open(self):
|
||||
# this will create a new pool for our DSN if not already existing,
|
||||
# then get and immediately release a connection
|
||||
self.getconn()
|
||||
self.putconn()
|
||||
|
||||
def close(self):
|
||||
# FIXME: if this connection is closed we flush all the pool associated
|
||||
# with the current DSN; does this makes sense?
|
||||
pool.flushpool(self.dsn)
|
||||
|
||||
def sortKey(self):
|
||||
return 1
|
||||
|
||||
def make_mappings(self):
|
||||
"""Generate the mappings used later by self.convert_description()."""
|
||||
self.type_mappings = {}
|
||||
for t, s in [(INTEGER,'i'), (LONGINTEGER, 'i'), (NUMBER, 'n'),
|
||||
(BOOLEAN,'n'), (ROWID, 'i'),
|
||||
(DATETIME, 'd'), (DATE, 'd'), (TIME, 'd')]:
|
||||
for v in t.values:
|
||||
self.type_mappings[v] = (t, s)
|
||||
|
||||
def convert_description(self, desc, use_psycopg_types=False):
|
||||
"""Convert DBAPI-2.0 description field to Zope format."""
|
||||
items = []
|
||||
for name, typ, width, ds, p, scale, null_ok in desc:
|
||||
m = self.type_mappings.get(typ, (STRING, 's'))
|
||||
items.append({
|
||||
'name': name,
|
||||
'type': use_psycopg_types and m[0] or m[1],
|
||||
'width': width,
|
||||
'precision': p,
|
||||
'scale': scale,
|
||||
'null': null_ok,
|
||||
})
|
||||
return items
|
||||
|
||||
## tables and rows ##
|
||||
|
||||
def tables(self, rdb=0, _care=('TABLE', 'VIEW')):
|
||||
self._register()
|
||||
c = self.getcursor()
|
||||
c.execute(
|
||||
"SELECT t.tablename AS NAME, 'TABLE' AS TYPE "
|
||||
" FROM pg_tables t WHERE tableowner <> 'postgres' "
|
||||
"UNION SELECT v.viewname AS NAME, 'VIEW' AS TYPE "
|
||||
" FROM pg_views v WHERE viewowner <> 'postgres' "
|
||||
"UNION SELECT t.tablename AS NAME, 'SYSTEM_TABLE\' AS TYPE "
|
||||
" FROM pg_tables t WHERE tableowner = 'postgres' "
|
||||
"UNION SELECT v.viewname AS NAME, 'SYSTEM_TABLE' AS TYPE "
|
||||
"FROM pg_views v WHERE viewowner = 'postgres'")
|
||||
res = []
|
||||
for name, typ in c.fetchall():
|
||||
if typ in _care:
|
||||
res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ})
|
||||
self.putconn()
|
||||
return res
|
||||
|
||||
def columns(self, table_name):
|
||||
self._register()
|
||||
c = self.getcursor()
|
||||
try:
|
||||
r = c.execute('SELECT * FROM "%s" WHERE 1=0' % table_name)
|
||||
except:
|
||||
return ()
|
||||
self.putconn()
|
||||
return self.convert_description(c.description, True)
|
||||
|
||||
## query execution ##
|
||||
|
||||
def query(self, query_string, max_rows=None, query_data=None):
|
||||
self._register()
|
||||
self.calls = self.calls+1
|
||||
|
||||
desc = ()
|
||||
res = []
|
||||
nselects = 0
|
||||
|
||||
c = self.getcursor()
|
||||
|
||||
try:
|
||||
for qs in [x for x in query_string.split('\0') if x]:
|
||||
try:
|
||||
if query_data:
|
||||
c.execute(qs, query_data)
|
||||
else:
|
||||
c.execute(qs)
|
||||
except TransactionRollbackError:
|
||||
# Ha, here we have to look like we are the ZODB raising conflict errrors, raising ZPublisher.Publish.Retry just doesn't work
|
||||
#logging.debug("Serialization Error, retrying transaction", exc_info=True)
|
||||
raise ConflictError("TransactionRollbackError from psycopg2")
|
||||
except psycopg2.OperationalError:
|
||||
#logging.exception("Operational error on connection, closing it.")
|
||||
try:
|
||||
# Only close our connection
|
||||
self.putconn(True)
|
||||
except:
|
||||
#logging.debug("Something went wrong when we tried to close the pool", exc_info=True)
|
||||
pass
|
||||
if c.description is not None:
|
||||
nselects += 1
|
||||
if c.description != desc and nselects > 1:
|
||||
raise psycopg2.ProgrammingError(
|
||||
'multiple selects in single query not allowed')
|
||||
if max_rows:
|
||||
res = c.fetchmany(max_rows)
|
||||
else:
|
||||
res = c.fetchall()
|
||||
desc = c.description
|
||||
self.failures = 0
|
||||
|
||||
except StandardError, err:
|
||||
self._abort()
|
||||
raise err
|
||||
|
||||
return self.convert_description(desc), res
|
108
ZPsycopgDA/dtml/add.dtml
Normal file
|
@ -0,0 +1,108 @@
|
|||
<dtml-var manage_page_header>
|
||||
|
||||
<dtml-var "manage_form_title(this(), _,
|
||||
form_title='Add Z Psycopg 2 Database Connection',
|
||||
help_product='ZPsycopgDA',
|
||||
help_topic='ZPsycopgDA-Method-Add.stx'
|
||||
)">
|
||||
|
||||
<p class="form-help">
|
||||
A Zope Psycopg 2 Database Connection is used to connect and execute
|
||||
queries on a PostgreSQL database.
|
||||
</p>
|
||||
|
||||
<p class="form-help">
|
||||
In the form below <em>Connection String</em> (also called the Data Source Name
|
||||
or DSN for short) is a string... (TODO: finish docs)
|
||||
</p>
|
||||
|
||||
<form action="manage_addZPsycopgConnection" method="POST">
|
||||
<table cellspacing="0" cellpadding="2" border="0">
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Id
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="id" size="40"
|
||||
value="Psycopg2_database_connection" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-optional">
|
||||
Title
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="title" size="40"
|
||||
value="Z Psycopg 2 Database Connection"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Connection string
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="connection_string" size="40" value="" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Connect immediately
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="checkbox" name="check" value="YES" checked="YES" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Use Zope's internal DateTime
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="checkbox" name="zdatetime" value="YES" checked="YES" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Transaction isolation level
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<select name="tilevel:int">
|
||||
<option value="4">Read uncommitted</option>
|
||||
<option value="1">Read committed</option>
|
||||
<option value="2" selected="YES">Repeatable read</option>
|
||||
<option value="3">Serializable</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Encoding
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="encoding" size="40" value="" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top" colspan="2">
|
||||
<div class="form-element">
|
||||
<input class="form-element" type="submit" name="submit" value=" Add " />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<dtml-var manage_page_footer>
|
11
ZPsycopgDA/dtml/browse.dtml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head><title><dtml-var title_or_id >tables</title></head>
|
||||
<body bgcolor="#FFFFFF" link="#000099" vlink="#555555" alink="#77003B">
|
||||
<dtml-var manage_tabs>
|
||||
<dtml-tree header="info">
|
||||
<IMG SRC="<dtml-var SCRIPT_NAME >/misc_/ZPsycopgDA/<dtml-var icon>"
|
||||
ALT="<dtml-var Type>" BORDER="0">
|
||||
<dtml-var Name><dtml-var Description>
|
||||
</dtml-tree>
|
||||
</body>
|
||||
</html>
|
84
ZPsycopgDA/dtml/edit.dtml
Normal file
|
@ -0,0 +1,84 @@
|
|||
<dtml-var manage_page_header>
|
||||
<dtml-var manage_tabs>
|
||||
|
||||
<form action="manage_edit" method="POST">
|
||||
<table cellspacing="0" cellpadding="2" border="0">
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-optional">
|
||||
Title
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="title" size="40"
|
||||
value="&dtml-title;"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Connection string
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="connection_string" size="40"
|
||||
value="&dtml-connection_string;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Use Zope's internal DateTime
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="checkbox" name="zdatetime" value="YES"
|
||||
<dtml-if expr="zdatetime">checked="YES"</dtml-if> />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Transaction isolation level
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<select name="tilevel:int">
|
||||
<option value="4"
|
||||
<dtml-if expr="tilevel==4">selected="YES"</dtml-if>>
|
||||
Read uncommitted</option>
|
||||
<option value="1"
|
||||
<dtml-if expr="tilevel==1">selected="YES"</dtml-if>>
|
||||
Read committed</option>
|
||||
<option value="2"
|
||||
<dtml-if expr="tilevel==2">selected="YES"</dtml-if>>
|
||||
Repeatable read</option>
|
||||
<option value="3"
|
||||
<dtml-if expr="tilevel==3">selected="YES"</dtml-if>>
|
||||
Serializable</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<div class="form-label">
|
||||
Encoding
|
||||
</div>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<input type="text" name="encoding" size="40"
|
||||
value="&dtml-encoding;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" valign="top" colspan="2">
|
||||
<div class="form-element">
|
||||
<input class="form-element" type="submit" name="submit"
|
||||
value=" Save Changes " />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<dtml-var manage_page_footer>
|
7
ZPsycopgDA/dtml/table_info.dtml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<dtml-var standard_html_header>
|
||||
|
||||
<dtml-var TABLE_TYPE><dtml-if TABLE_OWNER>
|
||||
owned by <dtml-var TABLE_OWNER></dtml-if>
|
||||
<dtml-if REMARKS><br><dtml-var REMARKS></dtml-if>
|
||||
|
||||
<dtml-var standard_html_footer>
|
BIN
ZPsycopgDA/icons/DBAdapterFolder_icon.gif
Executable file
After Width: | Height: | Size: 897 B |
BIN
ZPsycopgDA/icons/bin.gif
Normal file
After Width: | Height: | Size: 924 B |
BIN
ZPsycopgDA/icons/date.gif
Normal file
After Width: | Height: | Size: 930 B |
BIN
ZPsycopgDA/icons/datetime.gif
Normal file
After Width: | Height: | Size: 925 B |
BIN
ZPsycopgDA/icons/field.gif
Normal file
After Width: | Height: | Size: 915 B |
BIN
ZPsycopgDA/icons/float.gif
Normal file
After Width: | Height: | Size: 929 B |
BIN
ZPsycopgDA/icons/int.gif
Normal file
After Width: | Height: | Size: 918 B |
BIN
ZPsycopgDA/icons/stable.gif
Normal file
After Width: | Height: | Size: 884 B |
BIN
ZPsycopgDA/icons/table.gif
Normal file
After Width: | Height: | Size: 878 B |
BIN
ZPsycopgDA/icons/text.gif
Normal file
After Width: | Height: | Size: 918 B |
BIN
ZPsycopgDA/icons/time.gif
Normal file
After Width: | Height: | Size: 926 B |
BIN
ZPsycopgDA/icons/view.gif
Normal file
After Width: | Height: | Size: 893 B |
BIN
ZPsycopgDA/icons/what.gif
Normal file
After Width: | Height: | Size: 894 B |
193
ZPsycopgDA/pool.py
Normal file
|
@ -0,0 +1,193 @@
|
|||
# ZPsycopgDA/pool.py - ZPsycopgDA Zope product: connection pooling
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
# Import modules needed by _psycopg to allow tools like py2exe to do
|
||||
# their work without bothering about the module dependencies.
|
||||
|
||||
# All the connections are held in a pool of pools, directly accessible by the
|
||||
# ZPsycopgDA code in db.py.
|
||||
|
||||
import threading
|
||||
import psycopg2
|
||||
from psycopg2.pool import PoolError
|
||||
|
||||
|
||||
class AbstractConnectionPool(object):
|
||||
"""Generic key-based pooling code."""
|
||||
|
||||
def __init__(self, minconn, maxconn, *args, **kwargs):
|
||||
"""Initialize the connection pool.
|
||||
|
||||
New 'minconn' connections are created immediately calling 'connfunc'
|
||||
with given parameters. The connection pool will support a maximum of
|
||||
about 'maxconn' connections.
|
||||
"""
|
||||
self.minconn = minconn
|
||||
self.maxconn = maxconn
|
||||
self.closed = False
|
||||
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
|
||||
self._pool = []
|
||||
self._used = {}
|
||||
self._rused = {} # id(conn) -> key map
|
||||
self._keys = 0
|
||||
|
||||
for i in range(self.minconn):
|
||||
self._connect()
|
||||
|
||||
def _connect(self, key=None):
|
||||
"""Create a new connection and assign it to 'key' if not None."""
|
||||
conn = psycopg2.connect(*self._args, **self._kwargs)
|
||||
if key is not None:
|
||||
self._used[key] = conn
|
||||
self._rused[id(conn)] = key
|
||||
else:
|
||||
self._pool.append(conn)
|
||||
return conn
|
||||
|
||||
def _getkey(self):
|
||||
"""Return a new unique key."""
|
||||
self._keys += 1
|
||||
return self._keys
|
||||
|
||||
def _getconn(self, key=None):
|
||||
"""Get a free connection and assign it to 'key' if not None."""
|
||||
if self.closed: raise PoolError("connection pool is closed")
|
||||
if key is None: key = self._getkey()
|
||||
|
||||
if key in self._used:
|
||||
return self._used[key]
|
||||
|
||||
if self._pool:
|
||||
self._used[key] = conn = self._pool.pop()
|
||||
self._rused[id(conn)] = key
|
||||
return conn
|
||||
else:
|
||||
if len(self._used) == self.maxconn:
|
||||
raise PoolError("connection pool exausted")
|
||||
return self._connect(key)
|
||||
|
||||
def _putconn(self, conn, key=None, close=False):
|
||||
"""Put away a connection."""
|
||||
if self.closed: raise PoolError("connection pool is closed")
|
||||
if key is None: key = self._rused[id(conn)]
|
||||
|
||||
if not key:
|
||||
raise PoolError("trying to put unkeyed connection")
|
||||
|
||||
if len(self._pool) < self.minconn and not close:
|
||||
self._pool.append(conn)
|
||||
else:
|
||||
conn.close()
|
||||
|
||||
# here we check for the presence of key because it can happen that a
|
||||
# thread tries to put back a connection after a call to close
|
||||
if not self.closed or key in self._used:
|
||||
del self._used[key]
|
||||
del self._rused[id(conn)]
|
||||
|
||||
def _closeall(self):
|
||||
"""Close all connections.
|
||||
|
||||
Note that this can lead to some code fail badly when trying to use
|
||||
an already closed connection. If you call .closeall() make sure
|
||||
your code can deal with it.
|
||||
"""
|
||||
if self.closed: raise PoolError("connection pool is closed")
|
||||
for conn in self._pool + list(self._used.values()):
|
||||
try:
|
||||
conn.close()
|
||||
except:
|
||||
pass
|
||||
self.closed = True
|
||||
|
||||
|
||||
class PersistentConnectionPool(AbstractConnectionPool):
|
||||
"""A pool that assigns persistent connections to different threads.
|
||||
|
||||
Note that this connection pool generates by itself the required keys
|
||||
using the current thread id. This means that until a thread puts away
|
||||
a connection it will always get the same connection object by successive
|
||||
`!getconn()` calls. This also means that a thread can't use more than one
|
||||
single connection from the pool.
|
||||
"""
|
||||
|
||||
def __init__(self, minconn, maxconn, *args, **kwargs):
|
||||
"""Initialize the threading lock."""
|
||||
import threading
|
||||
AbstractConnectionPool.__init__(
|
||||
self, minconn, maxconn, *args, **kwargs)
|
||||
self._lock = threading.Lock()
|
||||
|
||||
# we we'll need the thread module, to determine thread ids, so we
|
||||
# import it here and copy it in an instance variable
|
||||
import thread
|
||||
self.__thread = thread
|
||||
|
||||
def getconn(self):
|
||||
"""Generate thread id and return a connection."""
|
||||
key = self.__thread.get_ident()
|
||||
self._lock.acquire()
|
||||
try:
|
||||
return self._getconn(key)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def putconn(self, conn=None, close=False):
|
||||
"""Put away an unused connection."""
|
||||
key = self.__thread.get_ident()
|
||||
self._lock.acquire()
|
||||
try:
|
||||
if not conn: conn = self._used[key]
|
||||
self._putconn(conn, key, close)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def closeall(self):
|
||||
"""Close all connections (even the one currently in use.)"""
|
||||
self._lock.acquire()
|
||||
try:
|
||||
self._closeall()
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
|
||||
_connections_pool = {}
|
||||
_connections_lock = threading.Lock()
|
||||
|
||||
def getpool(dsn, create=True):
|
||||
_connections_lock.acquire()
|
||||
try:
|
||||
if not _connections_pool.has_key(dsn) and create:
|
||||
_connections_pool[dsn] = \
|
||||
PersistentConnectionPool(4, 200, dsn)
|
||||
finally:
|
||||
_connections_lock.release()
|
||||
return _connections_pool[dsn]
|
||||
|
||||
def flushpool(dsn):
|
||||
_connections_lock.acquire()
|
||||
try:
|
||||
_connections_pool[dsn].closeall()
|
||||
del _connections_pool[dsn]
|
||||
finally:
|
||||
_connections_lock.release()
|
||||
|
||||
def getconn(dsn, create=True):
|
||||
return getpool(dsn, create=create).getconn()
|
||||
|
||||
def putconn(dsn, conn, close=False):
|
||||
getpool(dsn).putconn(conn, close=close)
|
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.
|
676
debian/changelog
vendored
Normal file
|
@ -0,0 +1,676 @@
|
|||
psycopg2 (2.0.7-2) unstable; urgency=medium
|
||||
|
||||
* ZPsycopgDA/DA.py: updated the patch. (Closes: #478860)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Thu, 01 May 2008 17:43:54 +0200
|
||||
|
||||
psycopg2 (2.0.7-1) unstable; urgency=low
|
||||
|
||||
* New upstream release. (Closes: #476101)
|
||||
* debian/control: bumped Standard-Versions to 3.7.3.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Tue, 15 Apr 2008 10:05:51 +0200
|
||||
|
||||
psycopg2 (2.0.6-4) unstable; urgency=low
|
||||
|
||||
[ Sandro Tosi ]
|
||||
* debian/control
|
||||
- uniforming Vcs-Browser field
|
||||
|
||||
[ Fabio Tranchitella ]
|
||||
* Provides a encoding parameter when adding a ZPsycopgDA instance using the
|
||||
ZMI. (Closes: #475123)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Wed, 09 Apr 2008 19:51:10 +0200
|
||||
|
||||
psycopg2 (2.0.6-3) unstable; urgency=low
|
||||
|
||||
[ Piotr Ożarowski ]
|
||||
* XS-Vcs-Svn field renamed to Vcs-Svn
|
||||
* Vcs-Browser field added
|
||||
|
||||
[ Fabio Tranchitella ]
|
||||
* Mention DB-API 2.0 compatibility in the long description.
|
||||
(Closes: #430763)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Thu, 08 Nov 2007 15:07:05 +0100
|
||||
|
||||
psycopg2 (2.0.6-2) unstable; urgency=low
|
||||
|
||||
* Build a python-psycopg-dbg package
|
||||
|
||||
-- Scott Kitterman <scott@kitterman.com> Tue, 03 Jul 2007 16:55:48 -0400
|
||||
|
||||
psycopg2 (2.0.6-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* psycopg2da: removed, merged upstream.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Sat, 09 Jun 2007 22:38:23 +0200
|
||||
|
||||
psycopg2 (2.0.5.1-7) UNRELEASED; urgency=low
|
||||
|
||||
* debian/watch: added.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 9 Feb 2007 12:35:55 +0100
|
||||
|
||||
psycopg2 (2.0.5.1-6) unstable; urgency=high
|
||||
|
||||
* debian/zope-psycopgda2.dzproduct: requires Zope 2.9 or higher: previous
|
||||
versions use python2.3 which is not supported anymore in psycopg.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Mon, 15 Jan 2007 11:39:15 +0100
|
||||
|
||||
psycopg2 (2.0.5.1-5) unstable; urgency=medium
|
||||
|
||||
* Do not run dh_pycentral on zope-psycopgda2. (Closes: #400846)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Wed, 29 Nov 2006 09:04:09 +0100
|
||||
|
||||
psycopg2 (2.0.5.1-4) unstable; urgency=medium
|
||||
|
||||
* Fixed a bug in psycopg2da.
|
||||
* debian/control: bumped build-dependency on zope-debhelper.
|
||||
* Added XS-Vcs-Svn field
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 24 Nov 2006 13:50:11 +0100
|
||||
|
||||
psycopg2 (2.0.5.1-3) unstable; urgency=low
|
||||
|
||||
* psycopgda: imported upstream psycopg2da database adapter from SVN, which
|
||||
builds a new binary package, python-psycopg2da.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Fri, 10 Nov 2006 08:56:05 +0100
|
||||
|
||||
psycopg2 (2.0.5.1-2) unstable; urgency=low
|
||||
|
||||
* debian/control: added again a dependency on python-egenix-mxdatetime.
|
||||
(Closes: #389636)
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Tue, 3 Oct 2006 10:25:22 +0200
|
||||
|
||||
psycopg2 (2.0.5.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Fabio Tranchitella <kobold@debian.org> Tue, 19 Sep 2006 08:22:36 +0200
|
||||
|
||||
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
|
||||
|
||||
|
1
debian/compat
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
5
|
64
debian/control
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
Source: psycopg2
|
||||
Section: python
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev, python-all-dbg, 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.4)
|
||||
Maintainer: Fabio Tranchitella <kobold@debian.org>
|
||||
Standards-Version: 3.7.3
|
||||
XS-Python-Version: all
|
||||
Vcs-Svn: svn://svn.debian.org/python-modules/packages/psycopg2/trunk/
|
||||
Vcs-Browser: http://svn.debian.org/wsvn/python-modules/packages/psycopg2/trunk/?op=log
|
||||
|
||||
Package: python-psycopg2
|
||||
Architecture: any
|
||||
Section: python
|
||||
Depends: ${python:Depends}, ${shlibs:Depends}, python-egenix-mxdatetime
|
||||
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 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.
|
||||
.
|
||||
The main advantages of psycopg2 are that it supports the full Python DBAPI-2.0
|
||||
and being thread safe at level 2. It also includes some extensions to the
|
||||
standard DBAPI-2.0 to allow for better thread performance.
|
||||
|
||||
Package: python-psycopg2-dbg
|
||||
Priority: extra
|
||||
Architecture: any
|
||||
Section: python
|
||||
Depends: python-psycopg2 (= ${binary:Version}), python-dbg, python-egenix-mxdatetime-dbg, ${shlibs:Depends}
|
||||
Description: Python module for PostgreSQL (debug extension)
|
||||
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.
|
||||
.
|
||||
This package contains the extensions built for the Python debug interpreter.
|
||||
|
||||
Package: zope-psycopgda2
|
||||
Architecture: all
|
||||
Section: python
|
||||
Depends: ${zope:Depends}, python-psycopg2 (>= ${source:Version})
|
||||
Description: Zope database adapter based on python-psycopg2
|
||||
The package contains the PostgreSQL database adapter for Zope 2.7, 2.8 and
|
||||
2.9 based on the psycopg2 Python module.
|
||||
|
||||
Package: python-psycopg2da
|
||||
Architecture: all
|
||||
Section: python
|
||||
Depends: ${zope:Depends}, python-psycopg2 (>= ${source:Version})
|
||||
XB-Python-Version: ${zope:PythonVersion}
|
||||
Description: Zope database adapter based on python-psycopg2 -- zope3 version
|
||||
The package contains the PostgreSQL database adapter for Zope 3 based on
|
||||
the psycopg2 Python module.
|
112
debian/copyright
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
This package was debianized by Fabio Tranchitella <kobold@debian.org> on
|
||||
Sun, 16 Jul 2006 21:10:01 +0200.
|
||||
|
||||
psycopg2 can be downloaded from its homepage:
|
||||
|
||||
http://initd.org/projects/psycopg
|
||||
|
||||
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 psycopg2da:
|
||||
Copyright (C) 2006 Fabio Tranchitella <kobold@debian.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, ZPsycopgDA and psycopg2da:
|
||||
|
||||
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 psycopg2da:
|
||||
|
||||
If you prefer you can use the Zope3 Database Adapter psycopg2da (i.e.,
|
||||
every file inside the psycopg2da 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
|
@ -0,0 +1 @@
|
|||
2
|
3
debian/python-psycopg2da.dzproduct
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Name: psycopg2da
|
||||
ZopeVersions: 3
|
||||
Global: yes
|
93
debian/rules
vendored
Executable file
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/make -f
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# GNU copyright 1997 to 1999 by Joey Hess.
|
||||
|
||||
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
|
||||
for python in $(PYVERS); do \
|
||||
$$python-dbg 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
|
||||
for python in $(PYVERS); do \
|
||||
$$python-dbg setup.py install \
|
||||
--root=$(CURDIR)/debian/python-psycopg2-dbg --no-compile; \
|
||||
done
|
||||
find debian/python-*-dbg ! -type d ! -name '*.so' | xargs rm -f
|
||||
find debian/python-*-dbg -depth -empty -exec rmdir {} \;
|
||||
|
||||
install-indep: build
|
||||
# Zope package
|
||||
dh_installzope -p zope-psycopgda2 ZPsycopgDA
|
||||
# Zope3 package
|
||||
dh_installzope -p python-psycopg2da psycopg2da
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install-indep
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdocs -i AUTHORS
|
||||
dh_installchangelogs -i
|
||||
dh_link -i
|
||||
dh_compress -i
|
||||
dh_fixperms -i
|
||||
dh_pycentral -p python-psycopg2da
|
||||
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 -ppython-psycopg2 --dbg-package=python-psycopg2-dbg
|
||||
rm -rf debian/python-psycopg2-dbg/usr/share/doc/python-psycopg2-dbg
|
||||
ln -s python-psycopg2 debian/python-psycopg2-dbg/usr/share/doc/python-psycopg2-dbg
|
||||
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
|
2
debian/watch
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
version=3
|
||||
http://www.initd.org/pub/software/psycopg/psycopg2-([0-9][0-9\.\-]*).tar.gz debian uupdate
|
4
debian/zope-psycopgda2.dzproduct
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: ZPsycopgDA
|
||||
Directory: ZPsycopgDA:2
|
||||
Package: zope-psycopgda2
|
||||
ZopeVersions: >= 2.9
|
8
doc/.gitignore
vendored
|
@ -1,8 +0,0 @@
|
|||
env
|
||||
src/_build/*
|
||||
html/*
|
||||
psycopg2.txt
|
||||
src/sqlstate_errors.rst
|
||||
|
||||
# Added by psycopg-website to customize published docs
|
||||
src/_templates/layout.html
|
676
doc/COPYING
Normal file
|
@ -0,0 +1,676 @@
|
|||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
1744
doc/ChangeLog-1.x
Normal file
43
doc/HACKING
Normal file
|
@ -0,0 +1,43 @@
|
|||
General information
|
||||
*******************
|
||||
|
||||
Some help to people wanting to hack on psycopg. First of all, note that
|
||||
*every* function in the psycopg module source code is prefixed by one of the
|
||||
following words:
|
||||
|
||||
psyco is used for function directly callable from python (i.e., functions
|
||||
in the psycopg module itself.) the only notable exception is the
|
||||
source code for the module itself, that uses "psyco" even for C-only
|
||||
functions.
|
||||
|
||||
conn is used for functions related to connection objects.
|
||||
|
||||
curs is used for functions related to cursor objects.
|
||||
|
||||
typecast is used for typecasters and utility function related to
|
||||
typecaster creation and registration.
|
||||
|
||||
Pythonic definition of types and functions available from python are defined
|
||||
in *_type.c files. Internal functions, callable only from C are located in
|
||||
*_int.c files and extensions to the DBAPI can be found in the *_ext.c files.
|
||||
|
||||
|
||||
Patches
|
||||
*******
|
||||
|
||||
If you submit a patch, please send a diff generated with the "-u" switch.
|
||||
Also note that I don't like that much cosmetic changes (like renaming
|
||||
already existing variables) and I will rewrap the patch to 78 columns
|
||||
anyway, so it is much better if you do that beforehand.
|
||||
|
||||
|
||||
The type system
|
||||
***************
|
||||
|
||||
Simple types, like integers and strings, are converted to python base types
|
||||
(the conversion functions are in typecast_base.c). Complex types are
|
||||
converted to ad-hoc types, defined in the typeobj_*.{c,h} files. The
|
||||
conversion function are in the other typecast_*.c files. typecast.c defines
|
||||
the basic utility functions (available through the psycopg module) used when
|
||||
defining new typecasters from C and python.
|
||||
|
40
doc/Makefile
|
@ -1,39 +1,23 @@
|
|||
.PHONY: env help clean html package doctest
|
||||
.PHONY: help clean html text doctest
|
||||
|
||||
docs: html
|
||||
docs: html text
|
||||
|
||||
check: doctest
|
||||
|
||||
# The environment is currently required to build the documentation.
|
||||
# It is not clean by 'make clean'
|
||||
help:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
PYTHON := python$(PYTHON_VERSION)
|
||||
PYTHON_VERSION ?= $(shell $(PYTHON) -c 'import sys; print("%d.%d" % sys.version_info[:2])')
|
||||
BUILD_DIR = $(shell pwd)/../build/lib.$(PYTHON_VERSION)
|
||||
|
||||
SPHINXBUILD ?= $$(pwd)/env/bin/sphinx-build
|
||||
SPHOPTS = SPHINXBUILD=$(SPHINXBUILD)
|
||||
|
||||
html: package src/sqlstate_errors.rst
|
||||
$(MAKE) $(SPHOPTS) -C src $@
|
||||
html:
|
||||
cd src && $(MAKE) $@
|
||||
cp -r src/_build/html .
|
||||
|
||||
src/sqlstate_errors.rst: ../psycopg/sqlstate_errors.h $(BUILD_DIR)
|
||||
./env/bin/python src/tools/make_sqlstate_docs.py $< > $@
|
||||
|
||||
$(BUILD_DIR):
|
||||
$(MAKE) PYTHON=$(PYTHON) -C .. package
|
||||
text:
|
||||
cd src && $(MAKE) $@
|
||||
cd src && tools/stitch_text.py index.rst _build/text > ../psycopg2.txt
|
||||
|
||||
doctest:
|
||||
$(MAKE) PYTHON=$(PYTHON) -C .. package
|
||||
$(MAKE) $(SPHOPTS) -C src $@
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
clean:
|
||||
$(MAKE) $(SPHOPTS) -C src $@
|
||||
rm -rf html src/sqlstate_errors.rst
|
||||
|
||||
env: requirements.txt
|
||||
$(PYTHON) -m venv env
|
||||
./env/bin/pip install -r requirements.txt
|
||||
echo "$$(pwd)/../build/lib.$(PYTHON_VERSION)" \
|
||||
> env/lib/python$(PYTHON_VERSION)/site-packages/psycopg.pth
|
||||
cd src && $(MAKE) $@
|
||||
rm -rf html psycopg2.txt
|
||||
|
|
42
doc/README
Normal file
|
@ -0,0 +1,42 @@
|
|||
How to build psycopg documentation
|
||||
----------------------------------
|
||||
|
||||
- Install Sphinx, maybe in a virtualenv. Tested with Sphinx 0.6.4::
|
||||
|
||||
~$ virtualenv pd
|
||||
New python executable in pd/bin/python
|
||||
Installing setuptools............done.
|
||||
~$ cd pd
|
||||
~/pd$ source bin/activate
|
||||
(pd)~/pd$
|
||||
|
||||
- Install Sphinx in the env::
|
||||
|
||||
(pd)~/pd$ easy_install sphinx
|
||||
Searching for sphinx
|
||||
Reading http://pypi.python.org/simple/sphinx/
|
||||
Reading http://sphinx.pocoo.org/
|
||||
Best match: Sphinx 0.6.4
|
||||
...
|
||||
Finished processing dependencies for sphinx
|
||||
|
||||
- Build psycopg2 and ensure the package can be imported (it will be used for
|
||||
reading the version number, autodocs etc.)::
|
||||
|
||||
(pd)~/pd/psycopg2$ python setup.py build
|
||||
(pd)~/pd/psycopg2$ python setup.py install
|
||||
running install
|
||||
...
|
||||
creating ~/pd/lib/python2.6/site-packages/psycopg2
|
||||
...
|
||||
|
||||
- Move to the ``doc`` dir and run ``make`` from there::
|
||||
|
||||
(pd)~/pd/psycopg2$ cd doc/
|
||||
(pd)~/pd/psycopg2/doc$ make
|
||||
Running Sphinx v0.6.4
|
||||
...
|
||||
|
||||
You should have the rendered documentation in ``./html`` and the text file
|
||||
``psycopg2.txt`` now.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
How to build psycopg documentation
|
||||
----------------------------------
|
||||
|
||||
Building the documentation usually requires building the library too for
|
||||
introspection, so you will need the same prerequisites_. The only extra
|
||||
prerequisite is virtualenv_: the packages needed to build the docs will be
|
||||
installed when building the env.
|
||||
|
||||
.. _prerequisites: https://www.psycopg.org/docs/install.html#install-from-source
|
||||
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
|
||||
|
||||
Build the env once with::
|
||||
|
||||
make env
|
||||
|
||||
Then you can build the documentation with::
|
||||
|
||||
make
|
||||
|
||||
You should find the rendered documentation in the ``html`` directory.
|
|
@ -23,7 +23,7 @@ Date: 23 Oct 2001 09:53:11 +0600
|
|||
|
||||
We use psycopg and psycopg zope adapter since fisrt public
|
||||
release (it seems version 0.4). Now it works on 3 our sites and in intranet
|
||||
applications. We had few problems, but all problems were quickly
|
||||
applications. We had few problems, but all problems were quckly
|
||||
solved. The strong side of psycopg is that it's code is well organized
|
||||
and easy to understand. When I found a problem with non-ISO datestyle in first
|
||||
version of psycopg, it took for me 15 or 20 minutes to learn code and
|
||||
|
|
|
@ -255,7 +255,7 @@ Cursor Objects
|
|||
display_size, internal_size, precision, scale,
|
||||
null_ok). The first two items (name and type_code) are
|
||||
mandatory, the other five are optional and must be set to
|
||||
None if meaningful values are not provided.
|
||||
None if meaningfull values are not provided.
|
||||
|
||||
This attribute will be None for operations that
|
||||
do not return rows or if the cursor has not had an
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
How to make a psycopg2 release
|
||||
==============================
|
||||
|
||||
- Edit ``setup.py`` and set a stable version release. Use PEP 440 to choose
|
||||
version numbers, e.g.
|
||||
|
||||
- ``2.7``: a new major release, new features
|
||||
- ``2.7.1``: a bugfix release
|
||||
- ``2.7.1.1``: a release to fix packaging problems
|
||||
- ``2.7.2.dev0``: version held during development, non-public test packages...
|
||||
- ``2.8b1``: a beta for public tests
|
||||
|
||||
In the rest of this document we assume you have exported the version number
|
||||
into an environment variable, e.g.::
|
||||
|
||||
$ export VERSION=2.8.4
|
||||
|
||||
- Push psycopg2 to master or to the maint branch. Make sure tests on `GitHub
|
||||
Actions`__.
|
||||
|
||||
.. __: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml
|
||||
|
||||
- Create a signed tag with the content of the relevant NEWS bit and push it.
|
||||
E.g.::
|
||||
|
||||
# Tag name will be 2_8_4
|
||||
$ git tag -a -s ${VERSION//\./_}
|
||||
|
||||
Psycopg 2.8.4 released
|
||||
|
||||
What's new in psycopg 2.8.4
|
||||
---------------------------
|
||||
|
||||
New features:
|
||||
|
||||
- Fixed bug blah (:ticket:`#42`).
|
||||
...
|
||||
|
||||
- Create the packages:
|
||||
|
||||
- On GitHub Actions run manually a `package build workflow`__.
|
||||
|
||||
.. __: https://github.com/psycopg/psycopg2/actions/workflows/packages.yml
|
||||
|
||||
- When the workflows have finished download the packages from the job
|
||||
artifacts.
|
||||
|
||||
- Only for stable packages: upload the signed packages on PyPI::
|
||||
|
||||
$ twine upload -s wheelhouse/psycopg2-${VERSION}/*
|
||||
|
||||
- Create a release and release notes in the psycopg website, announce to
|
||||
psycopg and pgsql-announce mailing lists.
|
||||
|
||||
- Edit ``setup.py`` changing the version again (e.g. go to ``2.8.5.dev0``).
|
||||
|
||||
|
||||
Releasing test packages
|
||||
-----------------------
|
||||
|
||||
Test packages may be uploaded on the `PyPI testing site`__ using::
|
||||
|
||||
$ twine upload -s -r testpypi wheelhouse/psycopg2-${VERSION}/*
|
||||
|
||||
assuming `proper configuration`__ of ``~/.pypirc``.
|
||||
|
||||
.. __: https://test.pypi.org/project/psycopg2/
|
||||
.. __: https://wiki.python.org/moin/TestPyPI
|
|
@ -1,2 +0,0 @@
|
|||
Sphinx
|
||||
sphinx-better-theme
|
|
@ -1,50 +0,0 @@
|
|||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.10
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile requirements.in
|
||||
#
|
||||
alabaster==0.7.13
|
||||
# via sphinx
|
||||
babel==2.12.1
|
||||
# via sphinx
|
||||
certifi>=2023.7.22
|
||||
# via requests
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
docutils==0.19
|
||||
# via sphinx
|
||||
idna==3.4
|
||||
# via requests
|
||||
imagesize==1.4.1
|
||||
# via sphinx
|
||||
jinja2==3.1.2
|
||||
# via sphinx
|
||||
markupsafe==2.1.2
|
||||
# via jinja2
|
||||
packaging==23.1
|
||||
# via sphinx
|
||||
pygments==2.15.0
|
||||
# via sphinx
|
||||
requests==2.31.0
|
||||
# via sphinx
|
||||
snowballstemmer==2.2.0
|
||||
# via sphinx
|
||||
sphinx==6.1.3
|
||||
# via -r requirements.in
|
||||
sphinx-better-theme==0.1.5
|
||||
# via -r requirements.in
|
||||
sphinxcontrib-applehelp==1.0.4
|
||||
# via sphinx
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
# via sphinx
|
||||
sphinxcontrib-htmlhelp==2.0.1
|
||||
# via sphinx
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
# via sphinx
|
||||
sphinxcontrib-qthelp==1.0.3
|
||||
# via sphinx
|
||||
sphinxcontrib-serializinghtml==1.1.5
|
||||
# via sphinx
|
||||
urllib3==1.26.17
|
||||
# via requests
|
|
@ -1,3 +1,5 @@
|
|||
@import url("default.css");
|
||||
|
||||
blockquote {
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -12,18 +14,11 @@ div.dbapi-extension {
|
|||
border: 1px solid #aaf;
|
||||
}
|
||||
|
||||
code.sql,
|
||||
tt.sql {
|
||||
font-size: 1em;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a > code.sql,
|
||||
a > tt.sql {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a > code.sql:hover,
|
||||
a > tt.sql:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
@ -31,106 +26,3 @@ a > tt.sql:hover {
|
|||
dl.faq dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.data-types div.line-block {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
/* better theme customisation */
|
||||
|
||||
body {
|
||||
background-color: #216464;
|
||||
}
|
||||
|
||||
header, .related, .document, footer {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 150%;
|
||||
margin-bottom: 0;
|
||||
padding: 0.5rem 10px 0.5rem 10px;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.body h1, .body h2, .body h3 {
|
||||
color: #074848;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 160%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
footer#pagefooter {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 85%;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
#rellinks, #breadcrumbs {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.sphinxsidebar {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.bodywrapper {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
div.body h1, div.body h2, div.body h3 {
|
||||
background-color: #f2f2f2;
|
||||
border-bottom: 1px solid #d0d0d0;
|
||||
}
|
||||
|
||||
div.body p.rubric {
|
||||
border-bottom: 1px solid #d0d0d0;
|
||||
}
|
||||
|
||||
body .sphinxsidebar .search {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
html pre {
|
||||
background-color: #efc;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: #0b6868;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #ede;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
{# Add a title over the search box #}
|
||||
|
||||
{%- if pagename != "search" %}
|
||||
<h3>Quick search</h3>
|
||||
{%- include "!searchbox.html" %}
|
||||
{%- endif %}
|
|
@ -12,7 +12,7 @@ More advanced topics
|
|||
conn.commit()
|
||||
|
||||
def wait(conn):
|
||||
while True:
|
||||
while 1:
|
||||
state = conn.poll()
|
||||
if state == psycopg2.extensions.POLL_OK:
|
||||
break
|
||||
|
@ -27,7 +27,6 @@ More advanced topics
|
|||
wait(aconn)
|
||||
acurs = aconn.cursor()
|
||||
|
||||
|
||||
.. index::
|
||||
double: Subclassing; Cursor
|
||||
double: Subclassing; Connection
|
||||
|
@ -46,16 +45,6 @@ but other uses are possible. `cursor` is much more interesting, because
|
|||
it is the class where query building, execution and result type-casting into
|
||||
Python variables happens.
|
||||
|
||||
The `~psycopg2.extras` module contains several examples of :ref:`connection
|
||||
and cursor subclasses <cursor-subclasses>`.
|
||||
|
||||
.. note::
|
||||
|
||||
If you only need a customized cursor class, since Psycopg 2.5 you can use
|
||||
the `~connection.cursor_factory` parameter of a regular connection instead
|
||||
of creating a new `!connection` subclass.
|
||||
|
||||
|
||||
.. index::
|
||||
single: Example; Cursor subclass
|
||||
|
||||
|
@ -145,9 +134,7 @@ geometric type:
|
|||
... self.y = y
|
||||
|
||||
>>> def adapt_point(point):
|
||||
... x = adapt(point.x).getquoted()
|
||||
... y = adapt(point.y).getquoted()
|
||||
... return AsIs("'(%s, %s)'" % (x, y))
|
||||
... return AsIs("'(%s, %s)'" % (adapt(point.x), adapt(point.y)))
|
||||
|
||||
>>> register_adapter(Point, adapt_point)
|
||||
|
||||
|
@ -156,7 +143,7 @@ geometric type:
|
|||
|
||||
|
||||
.. |point| replace:: :sql:`point`
|
||||
.. _point: https://www.postgresql.org/docs/current/static/datatype-geometric.html#DATATYPE-GEOMETRIC
|
||||
.. _point: http://www.postgresql.org/docs/current/static/datatype-geometric.html#DATATYPE-GEOMETRIC
|
||||
|
||||
The above function call results in the SQL command::
|
||||
|
||||
|
@ -226,7 +213,7 @@ read:
|
|||
|
||||
>>> cur.execute("SELECT '(10.2,20.3)'::point")
|
||||
>>> point = cur.fetchone()[0]
|
||||
>>> print(type(point), point.x, point.y)
|
||||
>>> print type(point), point.x, point.y
|
||||
<class 'Point'> 10.2 20.3
|
||||
|
||||
A typecaster created by `!new_type()` can be also used with
|
||||
|
@ -259,9 +246,9 @@ documentation), you should keep the connection in `~connection.autocommit`
|
|||
mode if you wish to receive or send notifications in a timely manner.
|
||||
|
||||
.. |LISTEN| replace:: :sql:`LISTEN`
|
||||
.. _LISTEN: https://www.postgresql.org/docs/current/static/sql-listen.html
|
||||
.. _LISTEN: http://www.postgresql.org/docs/current/static/sql-listen.html
|
||||
.. |NOTIFY| replace:: :sql:`NOTIFY`
|
||||
.. _NOTIFY: https://www.postgresql.org/docs/current/static/sql-notify.html
|
||||
.. _NOTIFY: http://www.postgresql.org/docs/current/static/sql-notify.html
|
||||
|
||||
Notifications are received after every query execution. If the user is
|
||||
interested in receiving notifications but not in performing any query, the
|
||||
|
@ -270,7 +257,7 @@ wasting resources.
|
|||
|
||||
A simple application could poll the connection from time to time to check if
|
||||
something new has arrived. A better strategy is to use some I/O completion
|
||||
function such as :py:func:`~select.select` to sleep until awakened by the kernel when there is
|
||||
function such as :py:func:`~select.select` to sleep until awaken from the kernel when there is
|
||||
some data to read on the connection, thereby using no CPU unless there is
|
||||
something to read::
|
||||
|
||||
|
@ -284,20 +271,18 @@ something to read::
|
|||
curs = conn.cursor()
|
||||
curs.execute("LISTEN test;")
|
||||
|
||||
print("Waiting for notifications on channel 'test'")
|
||||
while True:
|
||||
print "Waiting for notifications on channel 'test'"
|
||||
while 1:
|
||||
if select.select([conn],[],[],5) == ([],[],[]):
|
||||
print("Timeout")
|
||||
print "Timeout"
|
||||
else:
|
||||
conn.poll()
|
||||
while conn.notifies:
|
||||
notify = conn.notifies.pop(0)
|
||||
print("Got NOTIFY:", notify.pid, notify.channel, notify.payload)
|
||||
notify = conn.notifies.pop()
|
||||
print "Got NOTIFY:", notify.pid, notify.channel, notify.payload
|
||||
|
||||
Running the script and executing a command such as :sql:`NOTIFY test, 'hello'`
|
||||
in a separate :program:`psql` shell, the output may look similar to:
|
||||
|
||||
.. code-block:: none
|
||||
in a separate :program:`psql` shell, the output may look similar to::
|
||||
|
||||
Waiting for notifications on channel 'test'
|
||||
Timeout
|
||||
|
@ -314,10 +299,6 @@ received from a previous version server will have the
|
|||
Added `~psycopg2.extensions.Notify` object and handling notification
|
||||
payload.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
The `~connection.notifies` attribute is writable: it is possible to
|
||||
replace it with any object exposing an `!append()` method. An useful
|
||||
example would be to use a `~collections.deque` object.
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -328,7 +309,7 @@ received from a previous version server will have the
|
|||
Asynchronous support
|
||||
--------------------
|
||||
|
||||
.. versionadded:: 2.2
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
Psycopg can issue asynchronous queries to a PostgreSQL database. An asynchronous
|
||||
communication style is established passing the parameter *async*\=1 to the
|
||||
|
@ -347,7 +328,7 @@ together with the Python :py:func:`~select.select` function in order to carry on
|
|||
asynchronous operations with Psycopg::
|
||||
|
||||
def wait(conn):
|
||||
while True:
|
||||
while 1:
|
||||
state = conn.poll()
|
||||
if state == psycopg2.extensions.POLL_OK:
|
||||
break
|
||||
|
@ -375,7 +356,7 @@ completely non-blocking connection attempt: see the libpq documentation for
|
|||
|PQconnectStart|_.
|
||||
|
||||
.. |PQconnectStart| replace:: `!PQconnectStart()`
|
||||
.. _PQconnectStart: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS
|
||||
.. _PQconnectStart: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS
|
||||
|
||||
The same loop should be also used to perform nonblocking queries: after
|
||||
sending a query via `~cursor.execute()` or `~cursor.callproc()`, call
|
||||
|
@ -422,13 +403,13 @@ this will be probably implemented in a future release.
|
|||
|
||||
.. _green-support:
|
||||
|
||||
Support for coroutine libraries
|
||||
-------------------------------
|
||||
Support to coroutine libraries
|
||||
------------------------------
|
||||
|
||||
.. versionadded:: 2.2
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
Psycopg can be used together with coroutine_\-based libraries and participate
|
||||
in cooperative multithreading.
|
||||
Psycopg can be used together with coroutine_\-based libraries, and participate
|
||||
to cooperative multithreading.
|
||||
|
||||
Coroutine-based libraries (such as Eventlet_ or gevent_) can usually patch the
|
||||
Python standard library in order to enable a coroutine switch in the presence of
|
||||
|
@ -468,7 +449,7 @@ example callback (using `!select()` to block) is provided as
|
|||
`psycopg2.extras.wait_select()`: it boils down to something similar to::
|
||||
|
||||
def wait_select(conn):
|
||||
while True:
|
||||
while 1:
|
||||
state = conn.poll()
|
||||
if state == extensions.POLL_OK:
|
||||
break
|
||||
|
@ -484,14 +465,14 @@ psycopg2 scope, as the callback can be tied to the libraries' implementation
|
|||
details. You can check the `psycogreen`_ project for further informations and
|
||||
resources about the topic.
|
||||
|
||||
.. _coroutine: https://en.wikipedia.org/wiki/Coroutine
|
||||
.. _greenlet: https://pypi.org/project/greenlet/
|
||||
.. _green threads: https://en.wikipedia.org/wiki/Green_threads
|
||||
.. _Eventlet: https://eventlet.net/
|
||||
.. _coroutine: http://en.wikipedia.org/wiki/Coroutine
|
||||
.. _greenlet: http://pypi.python.org/pypi/greenlet
|
||||
.. _green threads: http://en.wikipedia.org/wiki/Green_threads
|
||||
.. _Eventlet: http://eventlet.net/
|
||||
.. _gevent: http://www.gevent.org/
|
||||
.. _SQLAlchemy: https://www.sqlalchemy.org/
|
||||
.. _psycogreen: https://github.com/psycopg/psycogreen/
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-async.html
|
||||
.. _SQLAlchemy: http://www.sqlalchemy.org/
|
||||
.. _psycogreen: http://bitbucket.org/dvarrazzo/psycogreen/
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-async.html
|
||||
|
||||
.. warning::
|
||||
|
||||
|
@ -511,89 +492,3 @@ resources about the topic.
|
|||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
|
||||
|
||||
.. index::
|
||||
single: Replication
|
||||
|
||||
.. _replication-support:
|
||||
|
||||
Replication protocol support
|
||||
----------------------------
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
Modern PostgreSQL servers (version 9.0 and above) support replication. The
|
||||
replication protocol is built on top of the client-server protocol and can be
|
||||
operated using ``libpq``, as such it can be also operated by ``psycopg2``.
|
||||
The replication protocol can be operated on both synchronous and
|
||||
:ref:`asynchronous <async-support>` connections.
|
||||
|
||||
Server version 9.4 adds a new feature called *Logical Replication*.
|
||||
|
||||
.. seealso::
|
||||
|
||||
- PostgreSQL `Streaming Replication Protocol`__
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/protocol-replication.html
|
||||
|
||||
|
||||
Logical replication Quick-Start
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You must be using PostgreSQL server version 9.4 or above to run this quick
|
||||
start.
|
||||
|
||||
Make sure that replication connections are permitted for user ``postgres`` in
|
||||
``pg_hba.conf`` and reload the server configuration. You also need to set
|
||||
``wal_level=logical`` and ``max_wal_senders``, ``max_replication_slots`` to
|
||||
value greater than zero in ``postgresql.conf`` (these changes require a server
|
||||
restart). Create a database ``psycopg2_test``.
|
||||
|
||||
Then run the following code to quickly try the replication support out. This
|
||||
is not production code -- it's only intended as a simple demo of logical
|
||||
replication::
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
|
||||
conn = psycopg2.connect('dbname=psycopg2_test user=postgres',
|
||||
connection_factory=psycopg2.extras.LogicalReplicationConnection)
|
||||
cur = conn.cursor()
|
||||
try:
|
||||
# test_decoding produces textual output
|
||||
cur.start_replication(slot_name='pytest', decode=True)
|
||||
except psycopg2.ProgrammingError:
|
||||
cur.create_replication_slot('pytest', output_plugin='test_decoding')
|
||||
cur.start_replication(slot_name='pytest', decode=True)
|
||||
|
||||
class DemoConsumer(object):
|
||||
def __call__(self, msg):
|
||||
print(msg.payload)
|
||||
msg.cursor.send_feedback(flush_lsn=msg.data_start)
|
||||
|
||||
democonsumer = DemoConsumer()
|
||||
|
||||
print("Starting streaming, press Control-C to end...", file=sys.stderr)
|
||||
try:
|
||||
cur.consume_stream(democonsumer)
|
||||
except KeyboardInterrupt:
|
||||
cur.close()
|
||||
conn.close()
|
||||
print("The slot 'pytest' still exists. Drop it with "
|
||||
"SELECT pg_drop_replication_slot('pytest'); if no longer needed.",
|
||||
file=sys.stderr)
|
||||
print("WARNING: Transaction logs will accumulate in pg_xlog "
|
||||
"until the slot is dropped.", file=sys.stderr)
|
||||
|
||||
|
||||
You can now make changes to the ``psycopg2_test`` database using a normal
|
||||
psycopg2 session, ``psql``, etc. and see the logical decoding stream printed
|
||||
by this demo client.
|
||||
|
||||
This will continue running until terminated with ``Control-C``.
|
||||
|
||||
For the details see :ref:`replication-objects`.
|
||||
|
|
136
doc/src/conf.py
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Psycopg documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Feb 7 13:48:41 2010.
|
||||
|
@ -10,9 +11,7 @@
|
|||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import os
|
||||
import sys
|
||||
from better import better_theme_path
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
|
@ -23,16 +22,11 @@ sys.path.append(os.path.abspath('tools/lib'))
|
|||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.intersphinx',
|
||||
]
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.doctest', 'sphinx.ext.intersphinx' ]
|
||||
|
||||
# Specific extensions for Psycopg documentation.
|
||||
extensions += ['dbapi_extension', 'sql_role', 'ticket_role']
|
||||
extensions += [ 'dbapi_extension', 'sql_role' ]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
@ -41,16 +35,14 @@ templates_path = ['_templates']
|
|||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8'
|
||||
#source_encoding = 'utf-8'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Psycopg'
|
||||
copyright = (
|
||||
'2001-2021, Federico Di Gregorio, Daniele Varrazzo, The Psycopg Team'
|
||||
)
|
||||
project = u'Psycopg'
|
||||
copyright = u'2001-2011, Federico Di Gregorio. Documentation by Daniele Varrazzo'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
@ -62,32 +54,29 @@ version = '2.0'
|
|||
# The full version, including alpha/beta/rc tags.
|
||||
try:
|
||||
import psycopg2
|
||||
except ImportError:
|
||||
print("WARNING: couldn't import psycopg to read version.")
|
||||
release = version
|
||||
else:
|
||||
release = psycopg2.__version__.split()[0]
|
||||
version = '.'.join(release.split('.')[:2])
|
||||
except ImportError:
|
||||
print "WARNING: couldn't import psycopg to read version."
|
||||
release = version
|
||||
|
||||
intersphinx_mapping = {'py': ('https://docs.python.org/3', None)}
|
||||
|
||||
# Pattern to generate links to the bug tracker
|
||||
ticket_url = 'https://github.com/psycopg/psycopg2/issues/%s'
|
||||
ticket_remap_until = 25
|
||||
ticket_remap_offset = 230
|
||||
intersphinx_mapping = {
|
||||
'py': ('http://docs.python.org/', None),
|
||||
'py3': ('http://docs.python.org/3.2', None),
|
||||
}
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
# language = None
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
# today_fmt = '%B %d, %Y'
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of documents that shouldn't be included in the build.
|
||||
# unused_docs = []
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directory, that shouldn't be searched
|
||||
# for source files.
|
||||
|
@ -97,25 +86,21 @@ exclude_trees = ['_build', 'html']
|
|||
default_role = 'obj'
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
# add_function_parentheses = True
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
# add_module_names = True
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
# show_authors = False
|
||||
|
||||
# Using 'python' instead of the default gives warnings if parsing an example
|
||||
# fails, instead of defaulting to none
|
||||
highlight_language = 'python'
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# Include TODO items in the documentation
|
||||
todo_include_todos = False
|
||||
|
@ -123,10 +108,12 @@ todo_include_todos = False
|
|||
rst_epilog = """
|
||||
.. |DBAPI| replace:: DB API 2.0
|
||||
|
||||
.. _DBAPI: https://www.python.org/dev/peps/pep-0249/
|
||||
.. _DBAPI: http://www.python.org/dev/peps/pep-0249/
|
||||
|
||||
.. _transaction isolation level:
|
||||
https://www.postgresql.org/docs/current/static/transaction-iso.html
|
||||
http://www.postgresql.org/docs/current/static/transaction-iso.html
|
||||
|
||||
.. _mx.DateTime: http://www.egenix.com/products/python/mxBase/mxDateTime/
|
||||
|
||||
.. |MVCC| replace:: :abbr:`MVCC (Multiversion concurrency control)`
|
||||
"""
|
||||
|
@ -135,41 +122,35 @@ rst_epilog = """
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'better'
|
||||
html_theme = 'default'
|
||||
|
||||
# The stylesheet to use with HTML output: this will include the original one
|
||||
# adding a few classes.
|
||||
# html_style = 'psycopg.css'
|
||||
|
||||
# Hide the sphinx footer
|
||||
html_show_sphinx = False
|
||||
html_style = 'psycopg.css'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
html_theme_options = {
|
||||
'linktotheme': False,
|
||||
'cssfiles': ['_static/psycopg.css'],
|
||||
}
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = [better_theme_path]
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
# html_title = None
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
html_short_title = 'Home'
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
# html_logo = None
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
# html_favicon = None
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
|
@ -178,41 +159,38 @@ html_static_path = ['_static']
|
|||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
# html_use_smartypants = True
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
# no need for the prev/next topic link using better theme: they are on top
|
||||
html_sidebars = {
|
||||
'**': ['localtoc.html', 'searchbox.html'],
|
||||
}
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
# html_additional_pages = {}
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
# html_use_modindex = True
|
||||
#html_use_modindex = True
|
||||
|
||||
# If false, no index is generated.
|
||||
# html_use_index = True
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
# html_split_index = False
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
# html_show_sourcelink = True
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
# html_use_opensearch = ''
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = ''
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'psycopgdoc'
|
||||
|
@ -221,41 +199,35 @@ htmlhelp_basename = 'psycopgdoc'
|
|||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
# latex_paper_size = 'letter'
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
# latex_font_size = '10pt'
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
(
|
||||
'index',
|
||||
'psycopg.tex',
|
||||
'Psycopg Documentation',
|
||||
'Federico Di Gregorio',
|
||||
'manual',
|
||||
)
|
||||
('index', 'psycopg.tex', u'Psycopg Documentation',
|
||||
u'Federico Di Gregorio', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
# latex_logo = None
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
# latex_use_parts = False
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
# latex_preamble = ''
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_use_modindex = True
|
||||
#latex_use_modindex = True
|
||||
|
||||
toc_object_entries = False
|
||||
|
||||
doctest_global_setup = """
|
||||
|
||||
|
|
|
@ -21,39 +21,16 @@ The ``connection`` class
|
|||
Connections are thread safe and can be shared among many threads. See
|
||||
:ref:`thread-safety` for details.
|
||||
|
||||
Connections can be used as context managers. Note that a context wraps a
|
||||
transaction: if the context exits with success the transaction is
|
||||
committed, if it exits with an exception the transaction is rolled back.
|
||||
Note that the connection is not closed by the context and it can be used
|
||||
for several contexts.
|
||||
|
||||
.. code:: python
|
||||
|
||||
conn = psycopg2.connect(DSN)
|
||||
|
||||
with conn:
|
||||
with conn.cursor() as curs:
|
||||
curs.execute(SQL1)
|
||||
|
||||
with conn:
|
||||
with conn.cursor() as curs:
|
||||
curs.execute(SQL2)
|
||||
|
||||
# leaving contexts doesn't close the connection
|
||||
conn.close()
|
||||
|
||||
|
||||
.. method:: cursor(name=None, cursor_factory=None, scrollable=None, withhold=False)
|
||||
.. method:: cursor([name] [, cursor_factory] [, withhold])
|
||||
|
||||
Return a new `cursor` object using the connection.
|
||||
|
||||
If *name* is specified, the returned cursor will be a :ref:`server
|
||||
side cursor <server-side-cursors>` (also known as *named cursor*).
|
||||
Otherwise it will be a regular *client side* cursor. By default a
|
||||
named cursor is declared without :sql:`SCROLL` option and
|
||||
:sql:`WITHOUT HOLD`: set the argument or property `~cursor.scrollable`
|
||||
to `!True`/`!False` and or `~cursor.withhold` to `!True` to change the
|
||||
declaration.
|
||||
Otherwise it will be a regular *client side* cursor. By default a
|
||||
:sql:`WITHOUT HOLD` cursor is created; to create a :sql:`WITH HOLD`
|
||||
cursor, pass a `!True` value as the *withhold* parameter. See
|
||||
:ref:`server-side-cursors`.
|
||||
|
||||
The name can be a string not valid as a PostgreSQL identifier: for
|
||||
example it may start with a digit and contain non-alphanumeric
|
||||
|
@ -63,18 +40,20 @@ The ``connection`` class
|
|||
previously only valid PostgreSQL identifiers were accepted as
|
||||
cursor name.
|
||||
|
||||
The *cursor_factory* argument can be used to create non-standard
|
||||
cursors. The class returned must be a subclass of
|
||||
`psycopg2.extensions.cursor`. See :ref:`subclassing-cursor` for
|
||||
details. A default factory for the connection can also be specified
|
||||
using the `~connection.cursor_factory` attribute.
|
||||
.. warning::
|
||||
It is unsafe to expose the *name* to an untrusted source, for
|
||||
instance you shouldn't allow *name* to be read from a HTML form.
|
||||
Consider it as part of the query, not as a query parameter.
|
||||
|
||||
.. versionchanged:: 2.4.3 added the *withhold* argument.
|
||||
.. versionchanged:: 2.5 added the *scrollable* argument.
|
||||
The *cursor_factory* argument can be used to create non-standard
|
||||
cursors. The class returned should be a subclass of
|
||||
`psycopg2.extensions.cursor`. See :ref:`subclassing-cursor` for
|
||||
details.
|
||||
|
||||
.. extension::
|
||||
|
||||
All the function arguments are Psycopg extensions to the |DBAPI|.
|
||||
The `name` and `cursor_factory` parameters are Psycopg
|
||||
extensions to the |DBAPI|.
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -92,10 +71,6 @@ The ``connection`` class
|
|||
automatically open, commands have immediate effect. See
|
||||
:ref:`transactions-control` for details.
|
||||
|
||||
.. versionchanged:: 2.5 if the connection is used in a ``with``
|
||||
statement, the method is automatically called if no exception is
|
||||
raised in the ``with`` block.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Rollback
|
||||
|
@ -106,10 +81,6 @@ The ``connection`` class
|
|||
connection without committing the changes first will cause an implicit
|
||||
rollback to be performed.
|
||||
|
||||
.. versionchanged:: 2.5 if the connection is used in a ``with``
|
||||
statement, the method is automatically called if an exception is
|
||||
raised in the ``with`` block.
|
||||
|
||||
|
||||
.. method:: close()
|
||||
|
||||
|
@ -139,7 +110,7 @@ The ``connection`` class
|
|||
with a `~connection.commit()`/`~connection.rollback()` before
|
||||
closing.
|
||||
|
||||
.. _PgBouncer: http://www.pgbouncer.org/
|
||||
.. _PgBouncer: http://pgbouncer.projects.postgresql.org/
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -220,7 +191,7 @@ The ``connection`` class
|
|||
.. seealso:: the |PREPARE TRANSACTION|_ PostgreSQL command.
|
||||
|
||||
.. |PREPARE TRANSACTION| replace:: :sql:`PREPARE TRANSACTION`
|
||||
.. _PREPARE TRANSACTION: https://www.postgresql.org/docs/current/static/sql-prepare-transaction.html
|
||||
.. _PREPARE TRANSACTION: http://www.postgresql.org/docs/current/static/sql-prepare-transaction.html
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -246,7 +217,7 @@ The ``connection`` class
|
|||
.. seealso:: the |COMMIT PREPARED|_ PostgreSQL command.
|
||||
|
||||
.. |COMMIT PREPARED| replace:: :sql:`COMMIT PREPARED`
|
||||
.. _COMMIT PREPARED: https://www.postgresql.org/docs/current/static/sql-commit-prepared.html
|
||||
.. _COMMIT PREPARED: http://www.postgresql.org/docs/current/static/sql-commit-prepared.html
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -268,7 +239,7 @@ The ``connection`` class
|
|||
.. seealso:: the |ROLLBACK PREPARED|_ PostgreSQL command.
|
||||
|
||||
.. |ROLLBACK PREPARED| replace:: :sql:`ROLLBACK PREPARED`
|
||||
.. _ROLLBACK PREPARED: https://www.postgresql.org/docs/current/static/sql-rollback-prepared.html
|
||||
.. _ROLLBACK PREPARED: http://www.postgresql.org/docs/current/static/sql-rollback-prepared.html
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -289,7 +260,7 @@ The ``connection`` class
|
|||
transactions initiated by a program using such driver should be
|
||||
unpacked correctly.
|
||||
|
||||
.. __: https://jdbc.postgresql.org/
|
||||
.. __: http://jdbc.postgresql.org/
|
||||
|
||||
Xids returned by `!tpc_recover()` also have extra attributes
|
||||
`~psycopg2.extensions.Xid.prepared`, `~psycopg2.extensions.Xid.owner`,
|
||||
|
@ -299,7 +270,7 @@ The ``connection`` class
|
|||
.. seealso:: the |pg_prepared_xacts|_ system view.
|
||||
|
||||
.. |pg_prepared_xacts| replace:: `pg_prepared_xacts`
|
||||
.. _pg_prepared_xacts: https://www.postgresql.org/docs/current/static/view-pg-prepared-xacts.html
|
||||
.. _pg_prepared_xacts: http://www.postgresql.org/docs/current/static/view-pg-prepared-xacts.html
|
||||
|
||||
|
||||
|
||||
|
@ -312,8 +283,8 @@ The ``connection`` class
|
|||
|
||||
.. attribute:: closed
|
||||
|
||||
Read-only integer attribute: 0 if the connection is open, nonzero if
|
||||
it is closed or broken.
|
||||
Read-only attribute reporting whether the database connection is open
|
||||
(0) or closed (1).
|
||||
|
||||
|
||||
.. method:: cancel
|
||||
|
@ -331,7 +302,7 @@ The ``connection`` class
|
|||
|PQcancel|_.
|
||||
|
||||
.. |PQcancel| replace:: `!PQcancel()`
|
||||
.. _PQcancel: https://www.postgresql.org/docs/current/static/libpq-cancel.html#LIBPQ-PQCANCEL
|
||||
.. _PQcancel: http://www.postgresql.org/docs/current/static/libpq-cancel.html#LIBPQ-PQCANCEL
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
@ -347,10 +318,10 @@ The ``connection`` class
|
|||
available for recover.
|
||||
|
||||
.. |RESET| replace:: :sql:`RESET`
|
||||
.. _RESET: https://www.postgresql.org/docs/current/static/sql-reset.html
|
||||
.. _RESET: http://www.postgresql.org/docs/current/static/sql-reset.html
|
||||
|
||||
.. |SET SESSION AUTHORIZATION| replace:: :sql:`SET SESSION AUTHORIZATION`
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-set-session-authorization.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/sql-set-session-authorization.html
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
@ -360,28 +331,25 @@ The ``connection`` class
|
|||
Read-only string containing the connection string used by the
|
||||
connection.
|
||||
|
||||
If a password was specified in the connection string it will be
|
||||
obscured.
|
||||
|
||||
|
||||
|
||||
.. rubric:: Transaction control methods and attributes.
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Autocommit
|
||||
pair: Transaction; Isolation level
|
||||
|
||||
.. method:: set_session(isolation_level=None, readonly=None, deferrable=None, autocommit=None)
|
||||
.. method:: set_session([isolation_level,] [readonly,] [deferrable,] [autocommit])
|
||||
|
||||
Set one or more parameters for the next transactions or statements in
|
||||
the current session.
|
||||
the current session. See |SET TRANSACTION|_ for further details.
|
||||
|
||||
.. |SET TRANSACTION| replace:: :sql:`SET TRANSACTION`
|
||||
.. _SET TRANSACTION: http://www.postgresql.org/docs/current/static/sql-set-transaction.html
|
||||
|
||||
:param isolation_level: set the `isolation level`_ for the next
|
||||
transactions/statements. The value can be one of the literal
|
||||
values ``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE
|
||||
READ``, ``SERIALIZABLE`` or the equivalent :ref:`constant
|
||||
<isolation-level-constants>` defined in the `~psycopg2.extensions`
|
||||
module.
|
||||
transactions/statements. The value can be one of the
|
||||
:ref:`constants <isolation-level-constants>` defined in the
|
||||
`~psycopg2.extensions` module or one of the literal values
|
||||
``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE READ``,
|
||||
``SERIALIZABLE``.
|
||||
:param readonly: if `!True`, set the connection to read only;
|
||||
read/write if `!False`.
|
||||
:param deferrable: if `!True`, set the connection to deferrable;
|
||||
|
@ -390,59 +358,35 @@ The ``connection`` class
|
|||
PostgreSQL session setting but an alias for setting the
|
||||
`autocommit` attribute.
|
||||
|
||||
.. _isolation level:
|
||||
https://www.postgresql.org/docs/current/static/transaction-iso.html
|
||||
|
||||
Arguments set to `!None` (the default for all) will not be changed.
|
||||
The parameters *isolation_level*, *readonly* and *deferrable* also
|
||||
accept the string ``DEFAULT`` as a value: the effect is to reset the
|
||||
parameter to the server default. Defaults are defined by the server
|
||||
configuration: see values for |default_transaction_isolation|__,
|
||||
parameter to the server default.
|
||||
|
||||
.. _isolation level:
|
||||
http://www.postgresql.org/docs/current/static/transaction-iso.html
|
||||
|
||||
The function must be invoked with no transaction in progress. At every
|
||||
function invocation, only the specified parameters are changed.
|
||||
|
||||
The default for the values are defined by the server configuration:
|
||||
see values for |default_transaction_isolation|__,
|
||||
|default_transaction_read_only|__, |default_transaction_deferrable|__.
|
||||
|
||||
.. |default_transaction_isolation| replace:: :sql:`default_transaction_isolation`
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION
|
||||
.. __: http://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION
|
||||
.. |default_transaction_read_only| replace:: :sql:`default_transaction_read_only`
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY
|
||||
.. __: http://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY
|
||||
.. |default_transaction_deferrable| replace:: :sql:`default_transaction_deferrable`
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-DEFERRABLE
|
||||
.. __: http://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-DEFERRABLE
|
||||
|
||||
The function must be invoked with no transaction in progress.
|
||||
.. note::
|
||||
|
||||
.. seealso:: |SET TRANSACTION|_ for further details about the behaviour
|
||||
of the transaction parameters in the server.
|
||||
|
||||
.. |SET TRANSACTION| replace:: :sql:`SET TRANSACTION`
|
||||
.. _SET TRANSACTION: https://www.postgresql.org/docs/current/static/sql-set-transaction.html
|
||||
There is currently no builtin method to read the current value for
|
||||
the parameters: use :sql:`SHOW default_transaction_...` to read
|
||||
the values from the backend.
|
||||
|
||||
.. versionadded:: 2.4.2
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
Before this version, the function would have set
|
||||
:sql:`default_transaction_*` attribute in the current session;
|
||||
this implementation has the problem of not playing well with
|
||||
external connection pooling working at transaction level and not
|
||||
resetting the state of the session: changing the default
|
||||
transaction would pollute the connections in the pool and create
|
||||
problems to other applications using the same pool.
|
||||
|
||||
Starting from 2.7, if the connection is not autocommit, the
|
||||
transaction characteristics are issued together with :sql:`BEGIN`
|
||||
and will leave the :sql:`default_transaction_*` settings untouched.
|
||||
For example::
|
||||
|
||||
conn.set_session(readonly=True)
|
||||
|
||||
will not change :sql:`default_transaction_read_only`, but
|
||||
following transaction will start with a :sql:`BEGIN READ ONLY`.
|
||||
Conversely, using::
|
||||
|
||||
conn.set_session(readonly=True, autocommit=True)
|
||||
|
||||
will set :sql:`default_transaction_read_only` to :sql:`on` and
|
||||
rely on the server to apply the read only state to whatever
|
||||
transaction, implicit or explicit, is executed in the connection.
|
||||
|
||||
|
||||
.. attribute:: autocommit
|
||||
|
||||
|
@ -462,8 +406,8 @@ The ``connection`` class
|
|||
|
||||
By default, any query execution, including a simple :sql:`SELECT`
|
||||
will start a transaction: for long-running programs, if no further
|
||||
action is taken, the session will remain "idle in transaction", an
|
||||
undesirable condition for several reasons (locks are held by
|
||||
action is taken, the session will remain "idle in transaction", a
|
||||
condition non desiderable for several reasons (locks are held by
|
||||
the session, tables bloat...). For long lived scripts, either
|
||||
ensure to terminate a transaction as soon as possible or use an
|
||||
autocommit connection.
|
||||
|
@ -472,83 +416,31 @@ The ``connection`` class
|
|||
|
||||
|
||||
.. attribute:: isolation_level
|
||||
|
||||
Return or set the `transaction isolation level`_ for the current
|
||||
session. The value is one of the :ref:`isolation-level-constants`
|
||||
defined in the `psycopg2.extensions` module. On set it is also
|
||||
possible to use one of the literal values ``READ UNCOMMITTED``, ``READ
|
||||
COMMITTED``, ``REPEATABLE READ``, ``SERIALIZABLE``, ``DEFAULT``.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
|
||||
the property is writable.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
|
||||
the default value for `!isolation_level` is
|
||||
`~psycopg2.extensions.ISOLATION_LEVEL_DEFAULT`; previously the
|
||||
property would have queried the server and returned the real value
|
||||
applied. To know this value you can run a query such as :sql:`show
|
||||
transaction_isolation`. Usually the default value is `READ
|
||||
COMMITTED`, but this may be changed in the server configuration.
|
||||
|
||||
This value is now entirely separate from the `autocommit`
|
||||
property: in previous version, if `!autocommit` was set to `!True`
|
||||
this property would have returned
|
||||
`~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT`; it will now
|
||||
return the server isolation level.
|
||||
|
||||
|
||||
.. attribute:: readonly
|
||||
|
||||
Return or set the read-only status for the current session. Available
|
||||
values are `!True` (new transactions will be in read-only mode),
|
||||
`!False` (new transactions will be writable), `!None` (use the default
|
||||
configured for the server by :sql:`default_transaction_read_only`).
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. attribute:: deferrable
|
||||
|
||||
Return or set the `deferrable status`__ for the current session.
|
||||
Available values are `!True` (new transactions will be in deferrable
|
||||
mode), `!False` (new transactions will be in non deferrable mode),
|
||||
`!None` (use the default configured for the server by
|
||||
:sql:`default_transaction_deferrable`).
|
||||
|
||||
.. __: `SET TRANSACTION`_
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. method:: set_isolation_level(level)
|
||||
|
||||
.. note::
|
||||
|
||||
This is a legacy method mixing `~conn.isolation_level` and
|
||||
`~conn.autocommit`. Using the respective properties is a better
|
||||
option.
|
||||
From version 2.4.2, `set_session()` and `autocommit`, offer
|
||||
finer control on the transaction characteristics.
|
||||
|
||||
Set the `transaction isolation level`_ for the current session.
|
||||
Read or set the `transaction isolation level`_ for the current session.
|
||||
The level defines the different phenomena that can happen in the
|
||||
database between concurrent transactions.
|
||||
|
||||
The value set is an integer: symbolic constants are defined in
|
||||
The value set or read is an integer: symbolic constants are defined in
|
||||
the module `psycopg2.extensions`: see
|
||||
:ref:`isolation-level-constants` for the available values.
|
||||
|
||||
The default level is `~psycopg2.extensions.ISOLATION_LEVEL_DEFAULT`:
|
||||
at this level a transaction is automatically started the first time a
|
||||
database command is executed. If you want an *autocommit* mode,
|
||||
switch to `~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT` before
|
||||
The default level is :sql:`READ COMMITTED`: at this level a
|
||||
transaction is automatically started the first time a database command
|
||||
is executed. If you want an *autocommit* mode, switch to
|
||||
`~psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT` before
|
||||
executing any command::
|
||||
|
||||
>>> conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
|
||||
See also :ref:`transactions-control`.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Client; Encoding
|
||||
|
||||
|
@ -559,7 +451,7 @@ The ``connection`` class
|
|||
is the encoding defined by the database. It should be one of the
|
||||
`characters set supported by PostgreSQL`__
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/multibyte.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/multibyte.html
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -571,29 +463,21 @@ The ``connection`` class
|
|||
the session.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
:options: NORMALIZE_WHITESPACE
|
||||
|
||||
>>> cur.execute("CREATE TABLE foo (id serial PRIMARY KEY);")
|
||||
>>> pprint(conn.notices)
|
||||
['NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"\n',
|
||||
'NOTICE: CREATE TABLE will create implicit sequence "foo_id_seq" for serial column "foo.id"\n']
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
The `!notices` attribute is writable: the user may replace it
|
||||
with any Python object exposing an `!append()` method. If
|
||||
appending raises an exception the notice is silently
|
||||
dropped.
|
||||
|
||||
To avoid a leak in case excessive notices are generated, only the last
|
||||
50 messages are kept. This check is only in place if the `!notices`
|
||||
attribute is a list: if any other object is used it will be up to the
|
||||
user to guard from leakage.
|
||||
50 messages are kept.
|
||||
|
||||
You can configure what messages to receive using `PostgreSQL logging
|
||||
configuration parameters`__ such as ``log_statement``,
|
||||
``client_min_messages``, ``log_min_duration_statement`` etc.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-logging.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/runtime-config-logging.html
|
||||
|
||||
|
||||
.. attribute:: notifies
|
||||
|
@ -609,30 +493,93 @@ The ``connection`` class
|
|||
the payload was not accessible. To keep backward compatibility,
|
||||
`!Notify` objects can still be accessed as 2 items tuples.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
The `!notifies` attribute is writable: the user may replace it
|
||||
with any Python object exposing an `!append()` method. If
|
||||
appending raises an exception the notification is silently
|
||||
dropped.
|
||||
.. index::
|
||||
pair: Backend; PID
|
||||
|
||||
.. method:: get_backend_pid()
|
||||
|
||||
.. attribute:: cursor_factory
|
||||
Returns the process ID (PID) of the backend server process handling
|
||||
this connection.
|
||||
|
||||
The default cursor factory used by `~connection.cursor()` if the
|
||||
parameter is not specified.
|
||||
Note that the PID belongs to a process executing on the database
|
||||
server host, not the local host!
|
||||
|
||||
.. versionadded:: 2.5
|
||||
.. seealso:: libpq docs for `PQbackendPID()`__ for details.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQBACKENDPID
|
||||
|
||||
.. versionadded:: 2.0.8
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Connection; Info
|
||||
pair: Server; Parameters
|
||||
|
||||
.. attribute:: info
|
||||
.. method:: get_parameter_status(parameter)
|
||||
|
||||
A `~psycopg2.extensions.ConnectionInfo` object exposing information
|
||||
about the native libpq connection.
|
||||
Look up a current parameter setting of the server.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
Potential values for ``parameter`` are: ``server_version``,
|
||||
``server_encoding``, ``client_encoding``, ``is_superuser``,
|
||||
``session_authorization``, ``DateStyle``, ``TimeZone``,
|
||||
``integer_datetimes``, and ``standard_conforming_strings``.
|
||||
|
||||
If server did not report requested parameter, return `!None`.
|
||||
|
||||
.. seealso:: libpq docs for `PQparameterStatus()`__ for details.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Status
|
||||
|
||||
.. method:: get_transaction_status()
|
||||
|
||||
Return the current session transaction status as an integer. Symbolic
|
||||
constants for the values are defined in the module
|
||||
`psycopg2.extensions`: see :ref:`transaction-status-constants`
|
||||
for the available values.
|
||||
|
||||
.. seealso:: libpq docs for `PQtransactionStatus()`__ for details.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Protocol; Version
|
||||
|
||||
.. attribute:: protocol_version
|
||||
|
||||
A read-only integer representing frontend/backend protocol being used.
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. seealso:: libpq docs for `PQprotocolVersion()`__ for details.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPROTOCOLVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Version
|
||||
|
||||
.. attribute:: server_version
|
||||
|
||||
A read-only integer representing the backend version.
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
For example, version 8.1.5 will be returned as ``80105``.
|
||||
|
||||
.. seealso:: libpq docs for `PQserverVersion()`__ for details.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -645,8 +592,6 @@ The ``connection`` class
|
|||
`psycopg2.extensions`: see :ref:`connection-status-constants`
|
||||
for the available values.
|
||||
|
||||
The status is undefined for `closed` connections.
|
||||
|
||||
|
||||
.. method:: lobject([oid [, mode [, new_oid [, new_file [, lobject_factory]]]]])
|
||||
|
||||
|
@ -661,13 +606,13 @@ The ``connection`` class
|
|||
:param new_oid: Create a new object using the specified OID. The
|
||||
function raises `~psycopg2.OperationalError` if the OID is already
|
||||
in use. Default is 0, meaning assign a new one automatically.
|
||||
:param new_file: The name of a file to be imported in the database
|
||||
:param new_file: The name of a file to be imported in the the database
|
||||
(using the |lo_import|_ function)
|
||||
:param lobject_factory: Subclass of
|
||||
`~psycopg2.extensions.lobject` to be instantiated.
|
||||
|
||||
.. |lo_import| replace:: `!lo_import()`
|
||||
.. _lo_import: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-IMPORT
|
||||
.. _lo_import: http://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-IMPORT
|
||||
|
||||
Available values for *mode* are:
|
||||
|
||||
|
@ -692,21 +637,17 @@ The ``connection`` class
|
|||
support.
|
||||
|
||||
|
||||
.. rubric:: Methods related to asynchronous support
|
||||
.. rubric:: Methods related to asynchronous support.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
.. seealso:: :ref:`async-support` and :ref:`green-support`.
|
||||
|
||||
|
||||
.. attribute:: async
|
||||
async_
|
||||
|
||||
Read only attribute: 1 if the connection is asynchronous, 0 otherwise.
|
||||
|
||||
.. versionchanged:: 2.7 added the `!async_` alias for Python versions
|
||||
where `!async` is a keyword.
|
||||
|
||||
|
||||
.. method:: poll()
|
||||
|
||||
|
@ -716,7 +657,7 @@ The ``connection`` class
|
|||
|
||||
Return one of the constants defined in :ref:`poll-constants`. If it
|
||||
returns `~psycopg2.extensions.POLL_OK` then the connection has been
|
||||
established or the query results are available on the client.
|
||||
estabilished or the query results are available on the client.
|
||||
Otherwise wait until the file descriptor returned by `fileno()` is
|
||||
ready to read or to write, as explained in :ref:`async-support`.
|
||||
`poll()` should be also used by the function installed by
|
||||
|
@ -738,178 +679,6 @@ The ``connection`` class
|
|||
Return `!True` if the connection is executing an asynchronous operation.
|
||||
|
||||
|
||||
.. rubric:: Interoperation with other C API modules
|
||||
|
||||
.. attribute:: pgconn_ptr
|
||||
|
||||
Return the internal `!PGconn*` as integer. Useful to pass the libpq
|
||||
raw connection structure to C functions, e.g. via `ctypes`::
|
||||
|
||||
>>> import ctypes
|
||||
>>> import ctypes.util
|
||||
>>> libpq = ctypes.pydll.LoadLibrary(ctypes.util.find_library('pq'))
|
||||
>>> libpq.PQserverVersion.argtypes = [ctypes.c_void_p]
|
||||
>>> libpq.PQserverVersion.restype = ctypes.c_int
|
||||
>>> libpq.PQserverVersion(conn.pgconn_ptr)
|
||||
90611
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
.. method:: get_native_connection()
|
||||
|
||||
Return the internal `!PGconn*` wrapped in a PyCapsule object. This is
|
||||
only useful for passing the `libpq` raw connection associated to this
|
||||
connection object to other C-level modules that may have a use for it.
|
||||
|
||||
.. seealso:: Python C API `Capsules`__ docs.
|
||||
|
||||
.. __: https://docs.python.org/3.1/c-api/capsule.html
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
|
||||
.. rubric:: informative methods of the native connection
|
||||
|
||||
.. note::
|
||||
|
||||
These methods are better accessed using the `~connection.info`
|
||||
attributes and may be dropped in future versions.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Status
|
||||
|
||||
.. method:: get_transaction_status()
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.transaction_status`.
|
||||
|
||||
Return the current session transaction status as an integer. Symbolic
|
||||
constants for the values are defined in the module
|
||||
`psycopg2.extensions`: see :ref:`transaction-status-constants`
|
||||
for the available values.
|
||||
|
||||
.. seealso:: libpq docs for `PQtransactionStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Protocol; Version
|
||||
|
||||
.. attribute:: protocol_version
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.protocol_version`.
|
||||
|
||||
A read-only integer representing frontend/backend protocol being used.
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. seealso:: libpq docs for `PQprotocolVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPROTOCOLVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Version
|
||||
|
||||
.. attribute:: server_version
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.server_version`.
|
||||
|
||||
A read-only integer representing the backend version.
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
For example, version 8.1.5 will be returned as ``80105``.
|
||||
|
||||
.. seealso:: libpq docs for `PQserverVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Backend; PID
|
||||
|
||||
.. method:: get_backend_pid()
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.backend_pid`.
|
||||
|
||||
Returns the process ID (PID) of the backend server process *you
|
||||
connected to*. Note that if you use a connection pool service such as
|
||||
PgBouncer_ this value will not be updated if your connection is
|
||||
switched to a different backend.
|
||||
|
||||
Note that the PID belongs to a process executing on the database
|
||||
server host, not the local host!
|
||||
|
||||
.. seealso:: libpq docs for `PQbackendPID()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQBACKENDPID
|
||||
|
||||
.. versionadded:: 2.0.8
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Parameters
|
||||
|
||||
.. method:: get_parameter_status(parameter)
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.parameter_status()`.
|
||||
|
||||
Look up a current parameter setting of the server.
|
||||
|
||||
Potential values for ``parameter`` are: ``server_version``,
|
||||
``server_encoding``, ``client_encoding``, ``is_superuser``,
|
||||
``session_authorization``, ``DateStyle``, ``TimeZone``,
|
||||
``integer_datetimes``, and ``standard_conforming_strings``.
|
||||
|
||||
If server did not report requested parameter, return `!None`.
|
||||
|
||||
.. seealso:: libpq docs for `PQparameterStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Connection; Parameters
|
||||
|
||||
.. method:: get_dsn_parameters()
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.dsn_parameters`.
|
||||
|
||||
Get the effective dsn parameters for the connection as a dictionary.
|
||||
|
||||
The *password* parameter is removed from the result.
|
||||
|
||||
Example::
|
||||
|
||||
>>> conn.get_dsn_parameters()
|
||||
{'dbname': 'test', 'user': 'postgres', 'port': '5432', 'sslmode': 'prefer'}
|
||||
|
||||
Requires libpq >= 9.3.
|
||||
|
||||
.. seealso:: libpq docs for `PQconninfo()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNINFO
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. testcode::
|
||||
:hide:
|
||||
|
||||
|
|
|
@ -34,62 +34,49 @@ The ``cursor`` class
|
|||
many cursors from the same connection and should use each cursor from
|
||||
a single thread. See :ref:`thread-safety` for details.
|
||||
|
||||
Cursors can be used as context managers: leaving the context will close
|
||||
the cursor.
|
||||
|
||||
.. code:: python
|
||||
|
||||
with conn.cursor() as curs:
|
||||
curs.execute(SQL)
|
||||
|
||||
# the cursor is now closed
|
||||
|
||||
|
||||
.. attribute:: description
|
||||
|
||||
Read-only attribute describing the result of a query. It is a
|
||||
sequence of `~psycopg2.extensions.Column` instances, each one
|
||||
describing one result column in order. The attribute is `!None` for
|
||||
operations that do not return rows or if the cursor has not had an
|
||||
operation invoked via the |execute*|_ methods yet.
|
||||
This read-only attribute is a sequence of 7-item sequences.
|
||||
|
||||
For compatibility with the DB-API, every object can be unpacked as a
|
||||
7-items sequence: the attributes retuned this way are the following.
|
||||
For further details and other attributes available check the
|
||||
`~psycopg2.extensions.Column` documentation.
|
||||
Each of these sequences is a named tuple (a regular tuple if
|
||||
:func:`collections.namedtuple` is not available) containing information
|
||||
describing one result column:
|
||||
|
||||
0. `~psycopg2.extensions.Column.name`: the name of the column returned.
|
||||
0. `!name`: the name of the column returned.
|
||||
1. `!type_code`: the PostgreSQL OID of the column. You can use the
|
||||
|pg_type|_ system table to get more informations about the type.
|
||||
This is the value used by Psycopg to decide what Python type use
|
||||
to represent the value. See also
|
||||
:ref:`type-casting-from-sql-to-python`.
|
||||
2. `!display_size`: the actual length of the column in bytes.
|
||||
Obtaining this value is computationally intensive, so it is
|
||||
always `!None` unless the :envvar:`PSYCOPG_DISPLAY_SIZE` parameter
|
||||
is set at compile time. See also PQgetlength_.
|
||||
3. `!internal_size`: the size in bytes of the column associated to
|
||||
this column on the server. Set to a negative value for
|
||||
variable-size types See also PQfsize_.
|
||||
4. `!precision`: total number of significant digits in columns of
|
||||
type |NUMERIC|_. `!None` for other types.
|
||||
5. `!scale`: count of decimal digits in the fractional part in
|
||||
columns of type |NUMERIC|. `!None` for other types.
|
||||
6. `!null_ok`: always `!None` as not easy to retrieve from the libpq.
|
||||
|
||||
1. `~psycopg2.extensions.Column.type_code`: the PostgreSQL OID of the
|
||||
column.
|
||||
This attribute will be `!None` for operations that do not return rows
|
||||
or if the cursor has not had an operation invoked via the
|
||||
|execute*|_ methods yet.
|
||||
|
||||
2. `~psycopg2.extensions.Column.display_size`: the actual length of
|
||||
the column in bytes.
|
||||
|
||||
3. `~psycopg2.extensions.Column.internal_size`: the size in bytes of
|
||||
the column associated to this column on the server.
|
||||
|
||||
4. `~psycopg2.extensions.Column.precision`: total number of
|
||||
significant digits in columns of type |NUMERIC|. `!None`
|
||||
for other types.
|
||||
|
||||
5. `~psycopg2.extensions.Column.scale`: count of decimal digits in
|
||||
the fractional part in columns of type |NUMERIC|. `!None`
|
||||
for other types.
|
||||
|
||||
6. `~psycopg2.extensions.Column.null_ok`: always `!None` as not easy
|
||||
to retrieve from the libpq.
|
||||
.. |pg_type| replace:: :sql:`pg_type`
|
||||
.. _pg_type: http://www.postgresql.org/docs/current/static/catalog-pg-type.html
|
||||
.. _PQgetlength: http://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQGETLENGTH
|
||||
.. _PQfsize: http://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQFSIZE
|
||||
.. _NUMERIC: http://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL
|
||||
.. |NUMERIC| replace:: :sql:`NUMERIC`
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
if possible, columns descriptions are named tuple instead of
|
||||
regular tuples.
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
columns descriptions are instances of `!Column`, exposing extra
|
||||
attributes.
|
||||
|
||||
.. |NUMERIC| replace:: :sql:`NUMERIC`
|
||||
|
||||
.. method:: close()
|
||||
|
||||
Close the cursor now (rather than whenever `del` is executed).
|
||||
|
@ -97,11 +84,6 @@ The ``cursor`` class
|
|||
`~psycopg2.InterfaceError` will be raised if any operation is
|
||||
attempted with the cursor.
|
||||
|
||||
.. versionchanged:: 2.5 if the cursor is used in a ``with`` statement,
|
||||
the method is automatically called at the end of the ``with``
|
||||
block.
|
||||
|
||||
|
||||
.. attribute:: closed
|
||||
|
||||
Read-only boolean attribute: specifies if the cursor is closed
|
||||
|
@ -124,7 +106,7 @@ The ``cursor`` class
|
|||
.. attribute:: name
|
||||
|
||||
Read-only attribute containing the name of the cursor if it was
|
||||
created as named cursor by `connection.cursor()`, or `!None` if
|
||||
creates as named cursor by `connection.cursor()`, or `!None` if
|
||||
it is a client side cursor. See :ref:`server-side-cursors`.
|
||||
|
||||
.. extension::
|
||||
|
@ -132,44 +114,13 @@ The ``cursor`` class
|
|||
The `name` attribute is a Psycopg extension to the |DBAPI|.
|
||||
|
||||
|
||||
.. attribute:: scrollable
|
||||
|
||||
Read/write attribute: specifies if a named cursor is declared
|
||||
:sql:`SCROLL`, hence is capable to scroll backwards (using
|
||||
`~cursor.scroll()`). If `!True`, the cursor can be scrolled backwards,
|
||||
if `!False` it is never scrollable. If `!None` (default) the cursor
|
||||
scroll option is not specified, usually but not always meaning no
|
||||
backward scroll (see the |declare-notes|__).
|
||||
|
||||
.. |declare-notes| replace:: :sql:`DECLARE` notes
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-declare.html#SQL-DECLARE-NOTES
|
||||
|
||||
.. note::
|
||||
|
||||
set the value before calling `~cursor.execute()` or use the
|
||||
`connection.cursor()` *scrollable* parameter, otherwise the value
|
||||
will have no effect.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
.. extension::
|
||||
|
||||
The `scrollable` attribute is a Psycopg extension to the |DBAPI|.
|
||||
|
||||
|
||||
.. attribute:: withhold
|
||||
|
||||
Read/write attribute: specifies if a named cursor lifetime should
|
||||
extend outside of the current transaction, i.e., it is possible to
|
||||
fetch from the cursor even after a `connection.commit()` (but not after
|
||||
fetch from the cursor even after a `commection.commit()` (but not after
|
||||
a `connection.rollback()`). See :ref:`server-side-cursors`
|
||||
|
||||
.. note::
|
||||
|
||||
set the value before calling `~cursor.execute()` or use the
|
||||
`connection.cursor()` *withhold* parameter, otherwise the value
|
||||
will have no effect.
|
||||
|
||||
.. versionadded:: 2.4.3
|
||||
|
||||
.. extension::
|
||||
|
@ -184,9 +135,9 @@ The ``cursor`` class
|
|||
.. rubric:: Commands execution methods
|
||||
|
||||
|
||||
.. method:: execute(query, vars=None)
|
||||
.. method:: execute(operation [, parameters])
|
||||
|
||||
Execute a database operation (query or command).
|
||||
Prepare and execute a database operation (query or command).
|
||||
|
||||
Parameters may be provided as sequence or mapping and will be bound to
|
||||
variables in the operation. Variables are specified either with
|
||||
|
@ -197,10 +148,11 @@ The ``cursor`` class
|
|||
values can be retrieved using |fetch*|_ methods.
|
||||
|
||||
|
||||
.. method:: executemany(query, vars_list)
|
||||
.. method:: executemany(operation, seq_of_parameters)
|
||||
|
||||
Execute a database operation (query or command) against all parameter
|
||||
tuples or mappings found in the sequence *vars_list*.
|
||||
Prepare a database operation (query or command) and then execute it
|
||||
against all parameter tuples or mappings found in the sequence
|
||||
`seq_of_parameters`.
|
||||
|
||||
The function is mostly useful for commands that update the database:
|
||||
any result set returned by the query is discarded.
|
||||
|
@ -208,47 +160,18 @@ The ``cursor`` class
|
|||
Parameters are bounded to the query using the same rules described in
|
||||
the `~cursor.execute()` method.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> nums = ((1,), (5,), (10,))
|
||||
>>> cur.executemany("INSERT INTO test (num) VALUES (%s)", nums)
|
||||
|
||||
>>> tuples = ((123, "foo"), (42, "bar"), (23, "baz"))
|
||||
>>> cur.executemany("INSERT INTO test (num, data) VALUES (%s, %s)", tuples)
|
||||
|
||||
.. warning::
|
||||
In its current implementation this method is not faster than
|
||||
executing `~cursor.execute()` in a loop. For better performance
|
||||
you can use the functions described in :ref:`fast-exec`.
|
||||
|
||||
|
||||
.. method:: callproc(procname [, parameters])
|
||||
|
||||
Call a stored database procedure with the given name. The sequence of
|
||||
parameters must contain one entry for each argument that the procedure
|
||||
expects. Overloaded procedures are supported. Named parameters can be
|
||||
used by supplying the parameters as a dictionary.
|
||||
expects. The result of the call is returned as modified copy of the
|
||||
input sequence. Input parameters are left untouched, output and
|
||||
input/output parameters replaced with possibly new values.
|
||||
|
||||
This function is, at present, not DBAPI-compliant. The return value is
|
||||
supposed to consist of the sequence of parameters with modified output
|
||||
and input/output parameters. In future versions, the DBAPI-compliant
|
||||
return value may be implemented, but for now the function returns None.
|
||||
The procedure may also provide a result set as output. This must then
|
||||
be made available through the standard |fetch*|_ methods.
|
||||
|
||||
The procedure may provide a result set as output. This is then made
|
||||
available through the standard |fetch*|_ methods.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
added support for named arguments.
|
||||
|
||||
.. note::
|
||||
|
||||
`!callproc()` can only be used with PostgreSQL functions__, not
|
||||
with the procedures__ introduced in PostgreSQL 11, which require
|
||||
the :sql:`CALL` statement to run. Please use a normal
|
||||
`execute()` to run them.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/sql-createfunction.html
|
||||
.. __: https://www.postgresql.org/docs/current/sql-createprocedure.html
|
||||
|
||||
.. method:: mogrify(operation [, parameters])
|
||||
|
||||
|
@ -256,8 +179,6 @@ The ``cursor`` class
|
|||
exactly the one that would be sent to the database running the
|
||||
`~cursor.execute()` method or similar.
|
||||
|
||||
The returned string is always a bytes string.
|
||||
|
||||
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
|
||||
"INSERT INTO test (num, data) VALUES (42, E'bar')"
|
||||
|
||||
|
@ -292,7 +213,7 @@ The ``cursor`` class
|
|||
|
||||
>>> cur.execute("SELECT * FROM test;")
|
||||
>>> for record in cur:
|
||||
... print(record)
|
||||
... print record
|
||||
...
|
||||
(1, 100, "abc'def")
|
||||
(2, None, 'dada')
|
||||
|
@ -375,6 +296,9 @@ The ``cursor`` class
|
|||
`~psycopg2.ProgrammingError` is raised and the cursor position is
|
||||
not changed.
|
||||
|
||||
The method can be used both for client-side cursors and
|
||||
:ref:`server-side cursors <server-side-cursors>`.
|
||||
|
||||
.. note::
|
||||
|
||||
According to the |DBAPI|_, the exception raised for a cursor out
|
||||
|
@ -386,13 +310,6 @@ The ``cursor`` class
|
|||
except (ProgrammingError, IndexError), exc:
|
||||
deal_with_it(exc)
|
||||
|
||||
The method can be used both for client-side cursors and
|
||||
:ref:`server-side cursors <server-side-cursors>`. Server-side cursors
|
||||
can usually scroll backwards only if declared `~cursor.scrollable`.
|
||||
Moving out-of-bound in a server-side cursor doesn't result in an
|
||||
exception, if the backend doesn't raise any (Postgres doesn't tell us
|
||||
in a reliable way if we went out of bound).
|
||||
|
||||
|
||||
.. attribute:: arraysize
|
||||
|
||||
|
@ -461,17 +378,17 @@ The ``cursor`` class
|
|||
more flexibility.
|
||||
|
||||
.. |CREATE-TABLE| replace:: :sql:`CREATE TABLE`
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-createtable.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/sql-createtable.html
|
||||
|
||||
.. |INSERT-RETURNING| replace:: :sql:`INSERT ... RETURNING`
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-insert.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/sql-insert.html
|
||||
|
||||
|
||||
.. attribute:: query
|
||||
|
||||
Read-only attribute containing the body of the last query sent to the
|
||||
backend (including bound arguments) as bytes string. `!None` if no
|
||||
query has been executed yet:
|
||||
backend (including bound arguments). `!None` if no query has been
|
||||
executed yet:
|
||||
|
||||
>>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
|
||||
>>> cur.query
|
||||
|
@ -516,10 +433,8 @@ The ``cursor`` class
|
|||
|
||||
The time zone factory used to handle data types such as
|
||||
:sql:`TIMESTAMP WITH TIME ZONE`. It should be a `~datetime.tzinfo`
|
||||
object. Default is `datetime.timezone`.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
previosly the default factory was `psycopg2.tz.FixedOffsetTimezone`.
|
||||
object. A few implementations are available in the `psycopg2.tz`
|
||||
module.
|
||||
|
||||
|
||||
.. method:: nextset()
|
||||
|
@ -537,9 +452,6 @@ The ``cursor`` class
|
|||
|
||||
.. rubric:: COPY-related methods
|
||||
|
||||
Efficiently copy data from file-like objects to the database and back. See
|
||||
:ref:`copy` for an overview.
|
||||
|
||||
.. extension::
|
||||
|
||||
The :sql:`COPY` command is a PostgreSQL extension to the SQL standard.
|
||||
|
@ -548,7 +460,7 @@ The ``cursor`` class
|
|||
.. method:: copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None)
|
||||
|
||||
Read data *from* the file-like object *file* appending them to
|
||||
the table named *table*.
|
||||
the table named *table*. See :ref:`copy` for an overview.
|
||||
|
||||
:param file: file-like object to read data from. It must have both
|
||||
`!read()` and `!readline()` methods.
|
||||
|
@ -578,11 +490,6 @@ The ``cursor`` class
|
|||
are encoded in the connection `~connection.encoding` when sent to
|
||||
the backend.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
the table and fields names are now quoted. If you need to specify
|
||||
a schema-qualified table please use `copy_expert()`.
|
||||
|
||||
|
||||
.. method:: copy_to(file, table, sep='\\t', null='\\\\N', columns=None)
|
||||
|
||||
Write the content of the table named *table* *to* the file-like
|
||||
|
@ -612,10 +519,6 @@ The ``cursor`` class
|
|||
are decoded in the connection `~connection.encoding` when read
|
||||
from the backend.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
the table and fields names are now quoted. If you need to specify
|
||||
a schema-qualified table please use `copy_expert()`.
|
||||
|
||||
|
||||
.. method:: copy_expert(sql, file, size=8192)
|
||||
|
||||
|
@ -624,22 +527,10 @@ The ``cursor`` class
|
|||
|COPY|__ command documentation).
|
||||
|
||||
:param sql: the :sql:`COPY` statement to execute.
|
||||
:param file: a file-like object to read or write (according to *sql*).
|
||||
:param file: a file-like object; must be a readable file for
|
||||
:sql:`COPY FROM` or an writable file for :sql:`COPY TO`.
|
||||
:param size: size of the read buffer to be used in :sql:`COPY FROM`.
|
||||
|
||||
The *sql* statement should be in the form :samp:`COPY {table} TO
|
||||
STDOUT` to export :samp:`{table}` to the *file* object passed as
|
||||
argument or :samp:`COPY {table} FROM STDIN` to import the content of
|
||||
the *file* object into :samp:`{table}`. If you need to compose a
|
||||
:sql:`COPY` statement dynamically (because table, fields, or query
|
||||
parameters are in Python variables) you may use the objects provided
|
||||
by the `psycopg2.sql` module.
|
||||
|
||||
*file* must be a readable file-like object (as required by
|
||||
`~cursor.copy_from()`) for *sql* statement :sql:`COPY ... FROM STDIN`
|
||||
or a writable one (as required by `~cursor.copy_to()`) for :sql:`COPY
|
||||
... TO STDOUT`.
|
||||
|
||||
Example:
|
||||
|
||||
>>> cur.copy_expert("COPY test TO STDOUT WITH CSV HEADER", sys.stdout)
|
||||
|
@ -649,7 +540,7 @@ The ``cursor`` class
|
|||
...
|
||||
|
||||
.. |COPY| replace:: :sql:`COPY`
|
||||
.. __: https://www.postgresql.org/docs/current/static/sql-copy.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/sql-copy.html
|
||||
|
||||
.. versionadded:: 2.0.6
|
||||
|
||||
|
@ -658,24 +549,6 @@ The ``cursor`` class
|
|||
using Unicode data instead of bytes.
|
||||
|
||||
|
||||
.. rubric:: Interoperation with other C API modules
|
||||
|
||||
.. attribute:: pgresult_ptr
|
||||
|
||||
Return the cursor's internal `!PGresult*` as integer. Useful to pass
|
||||
the libpq raw result structure to C functions, e.g. via `ctypes`::
|
||||
|
||||
>>> import ctypes
|
||||
>>> libpq = ctypes.pydll.LoadLibrary(ctypes.util.find_library('pq'))
|
||||
>>> libpq.PQcmdStatus.argtypes = [ctypes.c_void_p]
|
||||
>>> libpq.PQcmdStatus.restype = ctypes.c_char_p
|
||||
|
||||
>>> curs.execute("select 'x'")
|
||||
>>> libpq.PQcmdStatus(curs.pgresult_ptr)
|
||||
b'SELECT 1'
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. testcode::
|
||||
:hide:
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ From PostgreSQL documentation:
|
|||
|
||||
.. seealso:: `PostgreSQL Error Codes table`__
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE
|
||||
.. __: http://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE
|
||||
|
||||
|
||||
An example of the available constants defined in the module:
|
||||
|
@ -49,8 +49,8 @@ An example of the available constants defined in the module:
|
|||
>>> errorcodes.UNDEFINED_TABLE
|
||||
'42P01'
|
||||
|
||||
Constants representing all the error values defined by PostgreSQL versions
|
||||
between 8.1 and 15 are included in the module.
|
||||
Constants representing all the error values documented by PostgreSQL versions
|
||||
between 8.1 and 9.1 are included in the module.
|
||||
|
||||
|
||||
.. autofunction:: lookup(code)
|
||||
|
@ -59,7 +59,7 @@ between 8.1 and 15 are included in the module.
|
|||
|
||||
>>> try:
|
||||
... cur.execute("SELECT ouch FROM aargh;")
|
||||
... except Exception as e:
|
||||
... except Exception, e:
|
||||
... pass
|
||||
...
|
||||
>>> errorcodes.lookup(e.pgcode[:2])
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
`psycopg2.errors` -- Exception classes mapping PostgreSQL errors
|
||||
================================================================
|
||||
|
||||
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
|
||||
.. index::
|
||||
single: Error; Class
|
||||
|
||||
.. module:: psycopg2.errors
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. versionchanged:: 2.8.4 added errors introduced in PostgreSQL 12
|
||||
|
||||
.. versionchanged:: 2.8.6 added errors introduced in PostgreSQL 13
|
||||
|
||||
.. versionchanged:: 2.9.2 added errors introduced in PostgreSQL 14
|
||||
|
||||
.. versionchanged:: 2.9.4 added errors introduced in PostgreSQL 15
|
||||
|
||||
.. versionchanged:: 2.9.10 added errors introduced in PostgreSQL 17
|
||||
|
||||
This module exposes the classes psycopg raises upon receiving an error from
|
||||
the database with a :sql:`SQLSTATE` value attached (available in the
|
||||
`~psycopg2.Error.pgcode` attribute). The content of the module is generated
|
||||
from the PostgreSQL source code and includes classes for every error defined
|
||||
by PostgreSQL in versions between 9.1 and 15.
|
||||
|
||||
Every class in the module is named after what referred as "condition name" `in
|
||||
the documentation`__, converted to CamelCase: e.g. the error 22012,
|
||||
``division_by_zero`` is exposed by this module as the class `!DivisionByZero`.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE
|
||||
|
||||
Every exception class is a subclass of one of the :ref:`standard DB-API
|
||||
exception <dbapi-exceptions>` and expose the `~psycopg2.Error` interface.
|
||||
Each class' superclass is what used to be raised by psycopg in versions before
|
||||
the introduction of this module, so everything should be compatible with
|
||||
previously written code catching one the DB-API class: if your code used to
|
||||
catch `!IntegrityError` to detect a duplicate entry, it will keep on working
|
||||
even if a more specialised subclass such as `UniqueViolation` is raised.
|
||||
|
||||
The new classes allow a more idiomatic way to check and process a specific
|
||||
error among the many the database may return. For instance, in order to check
|
||||
that a table is locked, the following code could have been used previously:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
|
||||
except psycopg2.OperationalError as e:
|
||||
if e.pgcode == psycopg2.errorcodes.LOCK_NOT_AVAILABLE:
|
||||
locked = True
|
||||
else:
|
||||
raise
|
||||
|
||||
While this method is still available, the specialised class allows for a more
|
||||
idiomatic error handler:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
|
||||
except psycopg2.errors.LockNotAvailable:
|
||||
locked = True
|
||||
|
||||
|
||||
.. autofunction:: lookup
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT")
|
||||
except psycopg2.errors.lookup("55P03"):
|
||||
locked = True
|
||||
|
||||
|
||||
SQLSTATE exception classes
|
||||
--------------------------
|
||||
|
||||
The following table contains the list of all the SQLSTATE classes exposed by
|
||||
the module.
|
||||
|
||||
Note that, for completeness, the module also exposes all the
|
||||
:ref:`DB-API-defined exceptions <dbapi-exceptions>` and :ref:`a few
|
||||
psycopg-specific ones <extension-exceptions>` exposed by the `!extensions`
|
||||
module, which are not listed here.
|
||||
|
||||
.. include:: sqlstate_errors.rst
|
|
@ -12,14 +12,8 @@
|
|||
The module contains a few objects and function extending the minimum set of
|
||||
functionalities defined by the |DBAPI|_.
|
||||
|
||||
Classes definitions
|
||||
-------------------
|
||||
|
||||
Instances of these classes are usually returned by factory functions or
|
||||
attributes. Their definitions are exposed here to allow subclassing,
|
||||
introspection etc.
|
||||
|
||||
.. class:: connection(dsn, async=False)
|
||||
.. class:: connection
|
||||
|
||||
Is the class usually returned by the `~psycopg2.connect()` function.
|
||||
It is exposed by the `extensions` module in order to allow
|
||||
|
@ -27,14 +21,13 @@ introspection etc.
|
|||
`!connect()` function using the `connection_factory` parameter.
|
||||
See also :ref:`subclassing-connection`.
|
||||
|
||||
Subclasses should have constructor signature :samp:`({dsn}, {async}=0)`.
|
||||
|
||||
For a complete description of the class, see `connection`.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
*async_* can be used as alias for *async*.
|
||||
.. class:: cursor
|
||||
|
||||
.. class:: cursor(conn, name=None)
|
||||
|
||||
It is the class usually returned by the `connection.cursor()`
|
||||
It is the class usually returnded by the `connection.cursor()`
|
||||
method. It is exposed by the `extensions` module in order to allow
|
||||
subclassing to extend its behaviour: the subclass should be passed to the
|
||||
`!cursor()` method using the `cursor_factory` parameter. See
|
||||
|
@ -42,7 +35,6 @@ introspection etc.
|
|||
|
||||
For a complete description of the class, see `cursor`.
|
||||
|
||||
|
||||
.. class:: lobject(conn [, oid [, mode [, new_oid [, new_file ]]]])
|
||||
|
||||
Wrapper for a PostgreSQL large object. See :ref:`large-objects` for an
|
||||
|
@ -57,13 +49,11 @@ introspection etc.
|
|||
|
||||
Database OID of the object.
|
||||
|
||||
|
||||
.. attribute:: mode
|
||||
|
||||
The mode the database was open. See `connection.lobject()` for a
|
||||
description of the available modes.
|
||||
|
||||
|
||||
.. method:: read(bytes=-1)
|
||||
|
||||
Read a chunk of data from the current file position. If -1 (default)
|
||||
|
@ -76,7 +66,6 @@ introspection etc.
|
|||
.. versionchanged:: 2.4
|
||||
added Unicode support.
|
||||
|
||||
|
||||
.. method:: write(str)
|
||||
|
||||
Write a string to the large object. Return the number of bytes
|
||||
|
@ -86,7 +75,6 @@ introspection etc.
|
|||
.. versionchanged:: 2.4
|
||||
added Unicode support.
|
||||
|
||||
|
||||
.. method:: export(file_name)
|
||||
|
||||
Export the large object content to the file system.
|
||||
|
@ -94,52 +82,35 @@ introspection etc.
|
|||
The method uses the efficient |lo_export|_ libpq function.
|
||||
|
||||
.. |lo_export| replace:: `!lo_export()`
|
||||
.. _lo_export: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-EXPORT
|
||||
|
||||
.. _lo_export: http://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-EXPORT
|
||||
|
||||
.. method:: seek(offset, whence=0)
|
||||
|
||||
Set the lobject current position.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
added support for *offset* > 2GB.
|
||||
|
||||
|
||||
.. method:: tell()
|
||||
|
||||
Return the lobject current position.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
added support for return value > 2GB.
|
||||
|
||||
|
||||
.. method:: truncate(len=0)
|
||||
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
Truncate the lobject to the given size.
|
||||
|
||||
The method will only be available if Psycopg has been built against
|
||||
libpq from PostgreSQL 8.3 or later and can only be used with
|
||||
PostgreSQL servers running these versions. It uses the |lo_truncate|_
|
||||
libpq function.
|
||||
The method will only be available if Psycopg has been built against libpq
|
||||
from PostgreSQL 8.3 or later and can only be used with PostgreSQL servers
|
||||
running these versions. It uses the |lo_truncate|_ libpq function.
|
||||
|
||||
.. |lo_truncate| replace:: `!lo_truncate()`
|
||||
.. _lo_truncate: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-TRUNCATE
|
||||
.. _lo_truncate: http://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-TRUNCATE
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
added support for *len* > 2GB.
|
||||
|
||||
.. warning::
|
||||
|
||||
If Psycopg is built with |lo_truncate| support or with the 64 bits API
|
||||
support (resp. from PostgreSQL versions 8.3 and 9.3) but at runtime an
|
||||
older version of the dynamic library is found, the ``psycopg2`` module
|
||||
will fail to import. See :ref:`the lo_truncate FAQ <faq-lo_truncate>`
|
||||
about the problem.
|
||||
.. warning::
|
||||
|
||||
If Psycopg is built with |lo_truncate| support (i.e. if the
|
||||
:program:`pg_config` used during setup is version >= 8.3), but at
|
||||
runtime an older libpq is found, Psycopg will fail to import. See
|
||||
:ref:`the lo_truncate FAQ <faq-lo_truncate>` about the problem.
|
||||
|
||||
.. method:: close()
|
||||
|
||||
|
@ -154,130 +125,6 @@ introspection etc.
|
|||
Close the object and remove it from the database.
|
||||
|
||||
|
||||
|
||||
.. autoclass:: ConnectionInfo(connection)
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. autoattribute:: dbname
|
||||
.. autoattribute:: user
|
||||
.. autoattribute:: password
|
||||
.. autoattribute:: host
|
||||
.. autoattribute:: port
|
||||
.. autoattribute:: options
|
||||
.. autoattribute:: dsn_parameters
|
||||
|
||||
Example::
|
||||
|
||||
>>> conn.info.dsn_parameters
|
||||
{'dbname': 'test', 'user': 'postgres', 'port': '5432', 'sslmode': 'prefer'}
|
||||
|
||||
Requires libpq >= 9.3.
|
||||
|
||||
.. autoattribute:: status
|
||||
.. autoattribute:: transaction_status
|
||||
.. automethod:: parameter_status(name)
|
||||
|
||||
.. autoattribute:: protocol_version
|
||||
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. autoattribute:: server_version
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
After PostgreSQL 10 the minor version was dropped, so the second group
|
||||
of digits is always ``00``. For example, version 9.3.5 will be
|
||||
returned as ``90305``, version 10.2 as ``100002``.
|
||||
|
||||
.. autoattribute:: error_message
|
||||
.. autoattribute:: socket
|
||||
.. autoattribute:: backend_pid
|
||||
.. autoattribute:: needs_password
|
||||
.. autoattribute:: used_password
|
||||
.. autoattribute:: ssl_in_use
|
||||
.. automethod:: ssl_attribute(name)
|
||||
.. autoattribute:: ssl_attribute_names
|
||||
|
||||
|
||||
.. class:: Column(\*args, \*\*kwargs)
|
||||
|
||||
Description of one result column, exposed as items of the
|
||||
`cursor.description` sequence.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
in previous version the `!description` attribute was a sequence of
|
||||
simple tuples or namedtuples.
|
||||
|
||||
.. attribute:: name
|
||||
|
||||
The name of the column returned.
|
||||
|
||||
.. attribute:: type_code
|
||||
|
||||
The PostgreSQL OID of the column. You can use the |pg_type|_ system
|
||||
table to get more informations about the type. This is the value used
|
||||
by Psycopg to decide what Python type use to represent the value. See
|
||||
also :ref:`type-casting-from-sql-to-python`.
|
||||
|
||||
.. attribute:: display_size
|
||||
|
||||
Supposed to be the actual length of the column in bytes. Obtaining
|
||||
this value is computationally intensive, so it is always `!None`.
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
It was previously possible to obtain this value using a compiler
|
||||
flag at builtin.
|
||||
|
||||
.. attribute:: internal_size
|
||||
|
||||
The size in bytes of the column associated to this column on the
|
||||
server. Set to a negative value for variable-size types See also
|
||||
PQfsize_.
|
||||
|
||||
.. attribute:: precision
|
||||
|
||||
Total number of significant digits in columns of type |NUMERIC|_.
|
||||
`!None` for other types.
|
||||
|
||||
.. attribute:: scale
|
||||
|
||||
Count of decimal digits in the fractional part in columns of type
|
||||
|NUMERIC|. `!None` for other types.
|
||||
|
||||
.. attribute:: null_ok
|
||||
|
||||
Always `!None` as not easy to retrieve from the libpq.
|
||||
|
||||
.. attribute:: table_oid
|
||||
|
||||
The oid of the table from which the column was fetched (matching
|
||||
:sql:`pg_class.oid`). `!None` if the column is not a simple reference
|
||||
to a table column. See also PQftable_.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. attribute:: table_column
|
||||
|
||||
The number of the column (within its table) making up the result
|
||||
(matching :sql:`pg_attribute.attnum`, so it will start from 1).
|
||||
`!None` if the column is not a simple reference to a table column. See
|
||||
also PQftablecol_.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. |pg_type| replace:: :sql:`pg_type`
|
||||
.. _pg_type: https://www.postgresql.org/docs/current/static/catalog-pg-type.html
|
||||
.. _PQgetlength: https://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQGETLENGTH
|
||||
.. _PQfsize: https://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQFSIZE
|
||||
.. _PQftable: https://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQFTABLE
|
||||
.. _PQftablecol: https://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQFTABLECOL
|
||||
.. _NUMERIC: https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL
|
||||
.. |NUMERIC| replace:: :sql:`NUMERIC`
|
||||
|
||||
.. autoclass:: Notify(pid, channel, payload='')
|
||||
:members: pid, channel, payload
|
||||
|
||||
|
@ -292,40 +139,13 @@ introspection etc.
|
|||
.. automethod:: from_string(s)
|
||||
|
||||
|
||||
.. autoclass:: Diagnostics(exception)
|
||||
.. autofunction:: set_wait_callback(f)
|
||||
|
||||
.. versionadded:: 2.5
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
The attributes currently available are:
|
||||
|
||||
.. attribute::
|
||||
column_name
|
||||
constraint_name
|
||||
context
|
||||
datatype_name
|
||||
internal_position
|
||||
internal_query
|
||||
message_detail
|
||||
message_hint
|
||||
message_primary
|
||||
schema_name
|
||||
severity
|
||||
severity_nonlocalized
|
||||
source_file
|
||||
source_function
|
||||
source_line
|
||||
sqlstate
|
||||
statement_position
|
||||
table_name
|
||||
|
||||
A string with the error field if available; `!None` if not available.
|
||||
The attribute value is available only if the error sent by the server:
|
||||
not all the fields are available for all the errors and for all the
|
||||
server versions.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
The `!severity_nonlocalized` attribute.
|
||||
.. autofunction:: get_wait_callback()
|
||||
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
|
||||
.. _sql-adaptation-objects:
|
||||
|
@ -340,7 +160,7 @@ deal with Python objects adaptation:
|
|||
|
||||
.. function:: adapt(obj)
|
||||
|
||||
Return the SQL representation of *obj* as an `ISQLQuote`. Raise a
|
||||
Return the SQL representation of *obj* as a string. Raise a
|
||||
`~psycopg2.ProgrammingError` if how to adapt the object is unknown.
|
||||
In order to allow new objects to be adapted, register a new adapter for it
|
||||
using the `register_adapter()` function.
|
||||
|
@ -354,7 +174,7 @@ deal with Python objects adaptation:
|
|||
Register a new adapter for the objects of class *class*.
|
||||
|
||||
*adapter* should be a function taking a single argument (the object
|
||||
to adapt) and returning an object conforming to the `ISQLQuote`
|
||||
to adapt) and returning an object conforming the `ISQLQuote`
|
||||
protocol (e.g. exposing a `!getquoted()` method). The `AsIs` is
|
||||
often useful for this task.
|
||||
|
||||
|
@ -413,9 +233,9 @@ deal with Python objects adaptation:
|
|||
|
||||
.. method:: getquoted()
|
||||
|
||||
Return the string enclosed in single quotes. Any single quote appearing
|
||||
in the string is escaped by doubling it according to SQL string
|
||||
constants syntax. Backslashes are escaped too.
|
||||
Return the string enclosed in single quotes. Any single quote
|
||||
appearing in the the string is escaped by doubling it according to SQL
|
||||
string constants syntax. Backslashes are escaped too.
|
||||
|
||||
>>> QuotedString(r"O'Reilly").getquoted()
|
||||
"'O''Reilly'"
|
||||
|
@ -453,6 +273,13 @@ deal with Python objects adaptation:
|
|||
|
||||
Specialized adapters for Python datetime objects.
|
||||
|
||||
.. class:: DateFromMx
|
||||
TimeFromMx
|
||||
TimestampFromMx
|
||||
IntervalFromMx
|
||||
|
||||
Specialized adapters for `mx.DateTime`_ objects.
|
||||
|
||||
.. data:: adapters
|
||||
|
||||
Dictionary of the currently registered object adapters. Use
|
||||
|
@ -496,8 +323,8 @@ details.
|
|||
`register_type()` to be used.
|
||||
|
||||
:param oids: tuple of OIDs of the PostgreSQL type to convert. It should
|
||||
probably contain the oid of the array type (e.g. the ``typarray``
|
||||
field in the ``pg_type`` table).
|
||||
probably be the oid of the array type (e.g. the ``typarray`` field in
|
||||
the ``pg_type`` table.
|
||||
:param name: the name of the new type adapter.
|
||||
:param base_caster: a Psycopg typecaster, e.g. created using the
|
||||
`new_type()` function. The caster should be able to parse a single
|
||||
|
@ -510,12 +337,11 @@ details.
|
|||
.. note::
|
||||
|
||||
The function can be used to create a generic array typecaster,
|
||||
returning a list of strings: just use `psycopg2.STRING` as base
|
||||
typecaster. For instance, if you want to receive an array of
|
||||
:sql:`macaddr` from the database, each address represented by string,
|
||||
you can use::
|
||||
returning a list of strings: just use the `~psycopg2.STRING` as base
|
||||
typecaster. For instance, if you want to receive from the database an
|
||||
array of :sql:`macaddr`, each address represented by string, you can
|
||||
use::
|
||||
|
||||
# select typarray from pg_type where typname = 'macaddr' -> 1040
|
||||
psycopg2.extensions.register_type(
|
||||
psycopg2.extensions.new_array_type(
|
||||
(1040,), 'MACADDR[]', psycopg2.STRING))
|
||||
|
@ -540,31 +366,24 @@ details.
|
|||
|
||||
.. data:: encodings
|
||||
|
||||
Mapping from `PostgreSQL encoding`__ to `Python encoding`__ names.
|
||||
Mapping from `PostgreSQL encoding`__ names to `Python codec`__ names.
|
||||
Used by Psycopg when adapting or casting unicode strings. See
|
||||
:ref:`unicode-handling`.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/multibyte.html
|
||||
.. __: https://docs.python.org/library/codecs.html#standard-encodings
|
||||
.. __: http://www.postgresql.org/docs/current/static/multibyte.html
|
||||
.. __: http://docs.python.org/library/codecs.html#standard-encodings
|
||||
|
||||
|
||||
|
||||
.. index::
|
||||
single: Exceptions; Additional
|
||||
|
||||
.. _extension-exceptions:
|
||||
|
||||
Additional exceptions
|
||||
---------------------
|
||||
|
||||
The module exports a few exceptions in addition to the :ref:`standard ones
|
||||
<dbapi-exceptions>` defined by the |DBAPI|_.
|
||||
|
||||
.. note::
|
||||
From psycopg 2.8 these error classes are also exposed by the
|
||||
`psycopg2.errors` module.
|
||||
|
||||
|
||||
.. exception:: QueryCanceledError
|
||||
|
||||
(subclasses `~psycopg2.OperationalError`)
|
||||
|
@ -579,143 +398,13 @@ The module exports a few exceptions in addition to the :ref:`standard ones
|
|||
|
||||
(subclasses `~psycopg2.OperationalError`)
|
||||
|
||||
Error causing transaction rollback (deadlocks, serialization failures,
|
||||
Error causing transaction rollback (deadlocks, serialisation failures,
|
||||
etc). It can be trapped specifically to detect a deadlock.
|
||||
|
||||
.. versionadded:: 2.0.7
|
||||
|
||||
|
||||
|
||||
.. _coroutines-functions:
|
||||
|
||||
Coroutines support functions
|
||||
----------------------------
|
||||
|
||||
These functions are used to set and retrieve the callback function for
|
||||
:ref:`cooperation with coroutine libraries <green-support>`.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
.. autofunction:: set_wait_callback(f)
|
||||
|
||||
.. autofunction:: get_wait_callback()
|
||||
|
||||
|
||||
|
||||
Other functions
|
||||
---------------
|
||||
|
||||
.. function:: libpq_version()
|
||||
|
||||
Return the version number of the ``libpq`` dynamic library loaded as an
|
||||
integer, in the same format of `~connection.server_version`.
|
||||
|
||||
Raise `~psycopg2.NotSupportedError` if the ``psycopg2`` module was
|
||||
compiled with a ``libpq`` version lesser than 9.1 (which can be detected
|
||||
by the `~psycopg2.__libpq_version__` constant).
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. seealso:: libpq docs for `PQlibVersion()`__.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-misc.html#LIBPQ-PQLIBVERSION
|
||||
|
||||
|
||||
.. function:: make_dsn(dsn=None, \*\*kwargs)
|
||||
|
||||
Create a valid connection string from arguments.
|
||||
|
||||
Put together the arguments in *kwargs* into a connection string. If *dsn*
|
||||
is specified too, merge the arguments coming from both the sources. If the
|
||||
same argument name is specified in both the sources, the *kwargs* value
|
||||
overrides the *dsn* value.
|
||||
|
||||
The input arguments are validated: the output should always be a valid
|
||||
connection string (as far as `parse_dsn()` is concerned). If not raise
|
||||
`~psycopg2.ProgrammingError`.
|
||||
|
||||
Example::
|
||||
|
||||
>>> from psycopg2.extensions import make_dsn
|
||||
>>> make_dsn('dbname=foo host=example.com', password="s3cr3t")
|
||||
'host=example.com password=s3cr3t dbname=foo'
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. function:: parse_dsn(dsn)
|
||||
|
||||
Parse connection string into a dictionary of keywords and values.
|
||||
|
||||
Parsing is delegated to the libpq: different versions of the client
|
||||
library may support different formats or parameters (for example,
|
||||
`connection URIs`__ are only supported from libpq 9.2). Raise
|
||||
`~psycopg2.ProgrammingError` if the *dsn* is not valid.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||
|
||||
Example::
|
||||
|
||||
>>> from psycopg2.extensions import parse_dsn
|
||||
>>> parse_dsn('dbname=test user=postgres password=secret')
|
||||
{'password': 'secret', 'user': 'postgres', 'dbname': 'test'}
|
||||
>>> parse_dsn("postgresql://someone@example.com/somedb?connect_timeout=10")
|
||||
{'host': 'example.com', 'user': 'someone', 'dbname': 'somedb', 'connect_timeout': '10'}
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. seealso:: libpq docs for `PQconninfoParse()`__.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNINFOPARSE
|
||||
|
||||
|
||||
.. function:: quote_ident(str, scope)
|
||||
|
||||
Return quoted identifier according to PostgreSQL quoting rules.
|
||||
|
||||
The *scope* must be a `connection` or a `cursor`, the underlying
|
||||
connection encoding is used for any necessary character conversion.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. seealso:: libpq docs for `PQescapeIdentifier()`__
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQESCAPEIDENTIFIER
|
||||
|
||||
|
||||
.. method:: encrypt_password(password, user, scope=None, algorithm=None)
|
||||
|
||||
Return the encrypted form of a PostgreSQL password.
|
||||
|
||||
:param password: the cleartext password to encrypt
|
||||
:param user: the name of the user to use the password for
|
||||
:param scope: the scope to encrypt the password into; if *algorithm* is
|
||||
``md5`` it can be `!None`
|
||||
:type scope: `connection` or `cursor`
|
||||
:param algorithm: the password encryption algorithm to use
|
||||
|
||||
The *algorithm* ``md5`` is always supported. Other algorithms are only
|
||||
supported if the client libpq version is at least 10 and may require a
|
||||
compatible server version: check the `PostgreSQL encryption
|
||||
documentation`__ to know the algorithms supported by your server.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/encryption-options.html
|
||||
|
||||
Using `!None` as *algorithm* will result in querying the server to know the
|
||||
current server password encryption setting, which is a blocking operation:
|
||||
query the server separately and specify a value for *algorithm* if you
|
||||
want to maintain a non-blocking behaviour.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. seealso:: PostgreSQL docs for the `password_encryption`__ setting, libpq `PQencryptPasswordConn()`__, `PQencryptPassword()`__ functions.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-connection.html#GUC-PASSWORD-ENCRYPTION
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORD
|
||||
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Isolation level; Constants
|
||||
|
||||
|
@ -725,16 +414,15 @@ Isolation level constants
|
|||
-------------------------
|
||||
|
||||
Psycopg2 `connection` objects hold informations about the PostgreSQL
|
||||
`transaction isolation level`_. By default Psycopg doesn't change the default
|
||||
configuration of the server (`ISOLATION_LEVEL_DEFAULT`); the default for
|
||||
PostgreSQL servers is typically :sql:`READ COMMITTED`, but this may be changed
|
||||
in the server configuration files. A different isolation level can be set
|
||||
through the `~connection.set_isolation_level()` or `~connection.set_session()`
|
||||
methods. The level can be set to one of the following constants:
|
||||
`transaction isolation level`_. The current transaction level can be read
|
||||
from the `~connection.isolation_level` attribute. The default isolation
|
||||
level is :sql:`READ COMMITTED`. A different isolation level con be set
|
||||
through the `~connection.set_isolation_level()` method. The level can be
|
||||
set to one of the following constants:
|
||||
|
||||
.. data:: ISOLATION_LEVEL_AUTOCOMMIT
|
||||
|
||||
No transaction is started when commands are executed and no
|
||||
No transaction is started when command are issued and no
|
||||
`~connection.commit()` or `~connection.rollback()` is required.
|
||||
Some PostgreSQL command such as :sql:`CREATE DATABASE` or :sql:`VACUUM`
|
||||
can't run into a transaction: to run such command use::
|
||||
|
@ -751,8 +439,8 @@ methods. The level can be set to one of the following constants:
|
|||
|
||||
.. data:: ISOLATION_LEVEL_READ_COMMITTED
|
||||
|
||||
This is usually the default PostgreSQL value, but a different default may
|
||||
be set in the database configuration.
|
||||
This is usually the the default PostgreSQL value, but a different default
|
||||
may be set in the database configuration.
|
||||
|
||||
A new transaction is started at the first `~cursor.execute()` command on a
|
||||
cursor and at each new `!execute()` after a `~connection.commit()` or a
|
||||
|
@ -765,7 +453,7 @@ methods. The level can be set to one of the following constants:
|
|||
.. seealso:: `Read Committed Isolation Level`__ in PostgreSQL
|
||||
documentation.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-READ-COMMITTED
|
||||
.. __: http://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-READ-COMMITTED
|
||||
|
||||
.. data:: ISOLATION_LEVEL_REPEATABLE_READ
|
||||
|
||||
|
@ -789,7 +477,7 @@ methods. The level can be set to one of the following constants:
|
|||
.. seealso:: `Repeatable Read Isolation Level`__ in PostgreSQL
|
||||
documentation.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-REPEATABLE-READ
|
||||
.. __: http://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-REPEATABLE-READ
|
||||
|
||||
.. data:: ISOLATION_LEVEL_SERIALIZABLE
|
||||
|
||||
|
@ -798,7 +486,7 @@ methods. The level can be set to one of the following constants:
|
|||
:sql:`SERIALIZABLE` isolation level. This is the strictest transactions
|
||||
isolation level, equivalent to having the transactions executed serially
|
||||
rather than concurrently. However applications using this level must be
|
||||
prepared to retry transactions due to serialization failures.
|
||||
prepared to retry reansactions due to serialization failures.
|
||||
|
||||
Starting from PostgreSQL 9.1, this mode monitors for conditions which
|
||||
could make execution of a concurrent set of serializable transactions
|
||||
|
@ -808,18 +496,8 @@ methods. The level can be set to one of the following constants:
|
|||
|
||||
.. seealso:: `Serializable Isolation Level`__ in PostgreSQL documentation.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-SERIALIZABLE
|
||||
.. __: http://www.postgresql.org/docs/current/static/transaction-iso.html#XACT-SERIALIZABLE
|
||||
|
||||
.. data:: ISOLATION_LEVEL_DEFAULT
|
||||
|
||||
A new transaction is started at the first `~cursor.execute()` command, but
|
||||
the isolation level is not explicitly selected by Psycopg: the server will
|
||||
use whatever level is defined in its configuration or by statements
|
||||
executed within the session outside Pyscopg control. If you want to know
|
||||
what the value is you can use a query such as :sql:`show
|
||||
transaction_isolation`.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -831,7 +509,7 @@ Transaction status constants
|
|||
----------------------------
|
||||
|
||||
These values represent the possible status of a transaction: the current value
|
||||
can be read using the `connection.info.transaction_status` property.
|
||||
can be read using the `connection.get_transaction_status()` method.
|
||||
|
||||
.. data:: TRANSACTION_STATUS_IDLE
|
||||
|
||||
|
@ -902,7 +580,7 @@ internal usage and Python code should not rely on them.
|
|||
Poll constants
|
||||
--------------
|
||||
|
||||
.. versionadded:: 2.2
|
||||
.. versionadded:: 2.2.0
|
||||
|
||||
These values can be returned by `connection.poll()` during asynchronous
|
||||
connection and communication. They match the values in the libpq enum
|
||||
|
@ -951,7 +629,6 @@ Python objects. All the typecasters are automatically registered, except
|
|||
from the database. See :ref:`unicode-handling` for details.
|
||||
|
||||
.. data:: BOOLEAN
|
||||
BYTES
|
||||
DATE
|
||||
DECIMAL
|
||||
FLOAT
|
||||
|
@ -968,7 +645,6 @@ from the database. See :ref:`unicode-handling` for details.
|
|||
|
||||
.. data:: BINARYARRAY
|
||||
BOOLEANARRAY
|
||||
BYTESARRAY
|
||||
DATEARRAY
|
||||
DATETIMEARRAY
|
||||
DECIMALARRAY
|
||||
|
@ -985,26 +661,31 @@ from the database. See :ref:`unicode-handling` for details.
|
|||
|
||||
.. data:: PYDATE
|
||||
PYDATETIME
|
||||
PYDATETIMETZ
|
||||
PYINTERVAL
|
||||
PYTIME
|
||||
PYDATEARRAY
|
||||
PYDATETIMEARRAY
|
||||
PYDATETIMETZARRAY
|
||||
PYINTERVALARRAY
|
||||
PYTIMEARRAY
|
||||
|
||||
Typecasters to convert time-related data types to Python `!datetime`
|
||||
objects.
|
||||
|
||||
.. versionchanged:: 2.2
|
||||
.. data:: MXDATE
|
||||
MXDATETIME
|
||||
MXINTERVAL
|
||||
MXTIME
|
||||
MXDATEARRAY
|
||||
MXDATETIMEARRAY
|
||||
MXINTERVALARRAY
|
||||
MXTIMEARRAY
|
||||
|
||||
Typecasters to convert time-related data types to `mx.DateTime`_ objects.
|
||||
Only available if Psycopg was compiled with `!mx` support.
|
||||
|
||||
.. versionchanged:: 2.2.0
|
||||
previously the `DECIMAL` typecaster and the specific time-related
|
||||
typecasters (`!PY*` and `!MX*`) were not exposed by the `extensions`
|
||||
module. In older versions they can be imported from the implementation
|
||||
module `!psycopg2._psycopg`.
|
||||
|
||||
.. versionadded:: 2.7.2
|
||||
the `!*DATETIMETZ*` objects.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
the `!BYTES` and `BYTESARRAY` objects.
|
||||
|
|
171
doc/src/faq.rst
|
@ -7,32 +7,6 @@ Here are a few gotchas you may encounter using `psycopg2`. Feel free to
|
|||
suggest new entries!
|
||||
|
||||
|
||||
Meta
|
||||
----
|
||||
|
||||
.. _faq-question:
|
||||
.. cssclass:: faq
|
||||
|
||||
How do I ask a question?
|
||||
- Have you first checked if your question is answered already in the
|
||||
documentation?
|
||||
|
||||
- If your question is about installing psycopg, have you checked the
|
||||
:ref:`install FAQ <faq-compile>` and the :ref:`install docs
|
||||
<installation>`?
|
||||
|
||||
- Have you googled for your error message?
|
||||
|
||||
- If you haven't found an answer yet, please write to the `Mailing List`_.
|
||||
|
||||
- If you haven't found a bug, DO NOT write to the bug tracker to ask
|
||||
questions. You will only get piro grumpy.
|
||||
|
||||
.. _mailing list: https://www.postgresql.org/list/psycopg/
|
||||
|
||||
|
||||
.. _faq-transactions:
|
||||
|
||||
Problems with transactions handling
|
||||
-----------------------------------
|
||||
|
||||
|
@ -64,7 +38,7 @@ I receive the error *current transaction is aborted, commands ignored until end
|
|||
PostgreSQL supports nested transactions using the |SAVEPOINT|_ command).
|
||||
|
||||
.. |SAVEPOINT| replace:: :sql:`SAVEPOINT`
|
||||
.. _SAVEPOINT: https://www.postgresql.org/docs/current/static/sql-savepoint.html
|
||||
.. _SAVEPOINT: http://www.postgresql.org/docs/current/static/sql-savepoint.html
|
||||
|
||||
|
||||
.. _faq-transaction-aborted-multiprocess:
|
||||
|
@ -77,8 +51,6 @@ Why do I get the error *current transaction is aborted, commands ignored until e
|
|||
informations.
|
||||
|
||||
|
||||
.. _faq-types:
|
||||
|
||||
Problems with type conversions
|
||||
------------------------------
|
||||
|
||||
|
@ -97,7 +69,7 @@ Why does `!cursor.execute()` raise the exception *can't adapt*?
|
|||
|
||||
I can't pass an integer or a float parameter to my query: it says *a number is required*, but *it is* a number!
|
||||
In your query string, you always have to use ``%s`` placeholders,
|
||||
even when passing a number. All Python objects are converted by Psycopg
|
||||
event when passing a number. All Python objects are converted by Psycopg
|
||||
in their SQL representation, so they get passed to the query as strings.
|
||||
See :ref:`query-parameters`. ::
|
||||
|
||||
|
@ -132,19 +104,6 @@ My database is Unicode, but I receive all the strings as UTF-8 `!str`. Can I rec
|
|||
See :ref:`unicode-handling` for the gory details.
|
||||
|
||||
|
||||
.. _faq-bytes:
|
||||
.. cssclass:: faq
|
||||
|
||||
My database is in mixed encoding. My program was working on Python 2 but Python 3 fails decoding the strings. How do I avoid decoding?
|
||||
From psycopg 2.8 you can use the following adapters to always return bytes
|
||||
from strings::
|
||||
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.BYTES)
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.BYTESARRAY)
|
||||
|
||||
See :ref:`unicode-handling` for an example.
|
||||
|
||||
|
||||
.. _faq-float:
|
||||
.. cssclass:: faq
|
||||
|
||||
|
@ -158,54 +117,10 @@ Psycopg converts :sql:`decimal`\/\ :sql:`numeric` database types into Python `!D
|
|||
psycopg2.extensions.register_type(DEC2FLOAT)
|
||||
|
||||
See :ref:`type-casting-from-sql-to-python` to read the relevant
|
||||
documentation. If you find `!psycopg2.extensions.DECIMAL` not available, use
|
||||
documentation. If you find `!psycopg2.extensions.DECIMAL` not avalable, use
|
||||
`!psycopg2._psycopg.DECIMAL` instead.
|
||||
|
||||
|
||||
.. _faq-json-adapt:
|
||||
.. cssclass:: faq
|
||||
|
||||
Psycopg automatically converts PostgreSQL :sql:`json` data into Python objects. How can I receive strings instead?
|
||||
The easiest way to avoid JSON parsing is to register a no-op function with
|
||||
`~psycopg2.extras.register_default_json()`::
|
||||
|
||||
psycopg2.extras.register_default_json(loads=lambda x: x)
|
||||
|
||||
See :ref:`adapt-json` for further details.
|
||||
|
||||
|
||||
.. _faq-jsonb-adapt:
|
||||
.. cssclass:: faq
|
||||
|
||||
Psycopg converts :sql:`json` values into Python objects but :sql:`jsonb` values are returned as strings. Can :sql:`jsonb` be converted automatically?
|
||||
Automatic conversion of :sql:`jsonb` values is supported from Psycopg
|
||||
release 2.5.4. For previous versions you can register the :sql:`json`
|
||||
typecaster on the :sql:`jsonb` oids (which are known and not supposed to
|
||||
change in future PostgreSQL versions)::
|
||||
|
||||
psycopg2.extras.register_json(oid=3802, array_oid=3807, globally=True)
|
||||
|
||||
See :ref:`adapt-json` for further details.
|
||||
|
||||
|
||||
.. _faq-identifier:
|
||||
.. cssclass:: faq
|
||||
|
||||
How can I pass field/table names to a query?
|
||||
The arguments in the `~cursor.execute()` methods can only represent data
|
||||
to pass to the query: they cannot represent a table or field name::
|
||||
|
||||
# This doesn't work
|
||||
cur.execute("insert into %s values (%s)", ["my_table", 42])
|
||||
|
||||
If you want to build a query dynamically you can use the objects exposed
|
||||
by the `psycopg2.sql` module::
|
||||
|
||||
cur.execute(
|
||||
sql.SQL("insert into %s values (%%s)") % [sql.Identifier("my_table")],
|
||||
[42])
|
||||
|
||||
|
||||
.. _faq-bytea-9.0:
|
||||
.. cssclass:: faq
|
||||
|
||||
|
@ -221,8 +136,8 @@ Transferring binary data from PostgreSQL 9.0 doesn't work.
|
|||
session before reading binary data;
|
||||
- upgrade the libpq library on the client to at least 9.0.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/datatype-binary.html
|
||||
.. __: https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-BYTEA-OUTPUT
|
||||
.. __: http://www.postgresql.org/docs/current/static/datatype-binary.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-BYTEA-OUTPUT
|
||||
|
||||
|
||||
.. _faq-array:
|
||||
|
@ -236,8 +151,6 @@ Arrays of *TYPE* are not casted to list.
|
|||
provided in the `~psycopg2.extensions.new_array_type()` documentation.
|
||||
|
||||
|
||||
.. _faq-best-practices:
|
||||
|
||||
Best practices
|
||||
--------------
|
||||
|
||||
|
@ -271,64 +184,22 @@ When should I save and re-use a connection as opposed to creating a new one as n
|
|||
|
||||
What are the advantages or disadvantages of using named cursors?
|
||||
The only disadvantages is that they use up resources on the server and
|
||||
that there is a little overhead because at least two queries (one to
|
||||
that there is a little overhead because a at least two queries (one to
|
||||
create the cursor and one to fetch the initial result set) are issued to
|
||||
the backend. The advantage is that data is fetched one chunk at a time:
|
||||
using small `~cursor.fetchmany()` values it is possible to use very
|
||||
little memory on the client and to skip or discard parts of the result set.
|
||||
|
||||
|
||||
.. _faq-interrupt-query:
|
||||
.. cssclass:: faq
|
||||
|
||||
How do I interrupt a long-running query in an interactive shell?
|
||||
Normally the interactive shell becomes unresponsive to :kbd:`Ctrl-C` when
|
||||
running a query. Using a connection in green mode allows Python to
|
||||
receive and handle the interrupt, although it may leave the connection
|
||||
broken, if the async callback doesn't handle the `!KeyboardInterrupt`
|
||||
correctly.
|
||||
|
||||
Starting from psycopg 2.6.2, the `~psycopg2.extras.wait_select` callback
|
||||
can handle a :kbd:`Ctrl-C` correctly. For previous versions, you can use
|
||||
`this implementation`__.
|
||||
|
||||
.. __: https://www.psycopg.org/articles/2014/07/20/cancelling-postgresql-statements-python/
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> psycopg2.extensions.set_wait_callback(psycopg2.extras.wait_select)
|
||||
>>> cnn = psycopg2.connect('')
|
||||
>>> cur = cnn.cursor()
|
||||
>>> cur.execute("select pg_sleep(10)")
|
||||
^C
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
QueryCanceledError: canceling statement due to user request
|
||||
|
||||
>>> cnn.rollback()
|
||||
>>> # You can use the connection and cursor again from here
|
||||
|
||||
|
||||
.. _faq-compile:
|
||||
|
||||
Problems compiling and installing psycopg2
|
||||
------------------------------------------
|
||||
|
||||
.. _faq-wheels:
|
||||
.. cssclass:: faq
|
||||
|
||||
Psycopg 2.8 fails to install, Psycopg 2.7 was working fine.
|
||||
With Psycopg 2.7 you were installing binary packages, but they have proven
|
||||
unreliable so now you have to install them explicitly using the
|
||||
``psycopg2-binary`` package. See :ref:`binary-packages` for all the
|
||||
details.
|
||||
Problems compiling and deploying psycopg2
|
||||
-----------------------------------------
|
||||
|
||||
.. _faq-python-h:
|
||||
.. cssclass:: faq
|
||||
|
||||
I can't compile `!psycopg2`: the compiler says *error: Python.h: No such file or directory*. What am I missing?
|
||||
You need to install a Python development package: it is usually called
|
||||
``python-dev`` or ``python3-dev`` according to your Python version.
|
||||
``python-dev``.
|
||||
|
||||
|
||||
.. _faq-libpq-fe-h:
|
||||
|
@ -343,28 +214,19 @@ I can't compile `!psycopg2`: the compiler says *error: libpq-fe.h: No such file
|
|||
.. cssclass:: faq
|
||||
|
||||
`!psycopg2` raises `!ImportError` with message *_psycopg.so: undefined symbol: lo_truncate* when imported.
|
||||
This means that Psycopg was compiled with |lo_truncate|_ support (*i.e.*
|
||||
the libpq used at compile time was version >= 8.3) but at runtime an older
|
||||
libpq dynamic library is found.
|
||||
|
||||
Fast-forward several years, if the message reports *undefined symbol:
|
||||
lo_truncate64* it means that Psycopg was built with large objects 64 bits
|
||||
API support (*i.e.* the libpq used at compile time was at least 9.3) but
|
||||
at runtime an older libpq dynamic library is found.
|
||||
|
||||
You can use:
|
||||
|
||||
.. code-block:: shell
|
||||
This means that Psycopg has been compiled with |lo_truncate|_ support,
|
||||
which means that the libpq used at compile time was version >= 8.3, but at
|
||||
runtime an older libpq library is found. You can use::
|
||||
|
||||
$ ldd /path/to/packages/psycopg2/_psycopg.so | grep libpq
|
||||
|
||||
to find what is the libpq dynamic library used at runtime.
|
||||
to find what is the version used at runtime.
|
||||
|
||||
You can avoid the problem by using the same version of the
|
||||
:program:`pg_config` at install time and the libpq at runtime.
|
||||
|
||||
.. |lo_truncate| replace:: `!lo_truncate()`
|
||||
.. _lo_truncate: https://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-TRUNCATE
|
||||
.. _lo_truncate: http://www.postgresql.org/docs/current/static/lo-interfaces.html#LO-TRUNCATE
|
||||
|
||||
|
||||
.. _faq-import-mod_wsgi:
|
||||
|
@ -378,5 +240,6 @@ Psycopg raises *ImportError: cannot import name tz* on import in mod_wsgi / ASP,
|
|||
use the WSGIPythonEggs__ directive.
|
||||
|
||||
.. _egg: http://peak.telecommunity.com/DevCenter/PythonEggs
|
||||
.. __: https://stackoverflow.com/questions/2192323/what-is-the-python-egg-cache-python-egg-cache
|
||||
.. __: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPythonEggs.html
|
||||
.. __: http://stackoverflow.com/questions/2192323/what-is-the-python-egg-cache-python-egg-cache
|
||||
.. __: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPythonEggs
|
||||
|
||||
|
|
|
@ -4,29 +4,37 @@ Psycopg -- PostgreSQL database adapter for Python
|
|||
|
||||
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
|
||||
Psycopg_ is the most popular PostgreSQL_ database adapter for the Python_
|
||||
programming language. Its main features are the complete implementation of
|
||||
the Python |DBAPI|_ specification and the thread safety (several threads can
|
||||
share the same connection). It was designed for heavily multi-threaded
|
||||
applications that create and destroy lots of cursors and make a large number
|
||||
of concurrent :sql:`INSERT`\s or :sql:`UPDATE`\s.
|
||||
Psycopg_ is a PostgreSQL_ database adapter for the Python_ programming
|
||||
language. Its main features are that it supports the full Python |DBAPI|_
|
||||
and it is thread safe (threads can share the connections). It was designed for
|
||||
heavily multi-threaded applications that create and destroy lots of cursors and
|
||||
make a large number of concurrent :sql:`INSERT`\ s or :sql:`UPDATE`\ s.
|
||||
The Psycopg distribution includes ZPsycopgDA, a Zope_ Database Adapter.
|
||||
|
||||
Psycopg 2 is mostly implemented in C as a libpq_ wrapper, resulting in being
|
||||
both efficient and secure. It features client-side and :ref:`server-side
|
||||
<server-side-cursors>` cursors, :ref:`asynchronous communication
|
||||
<async-support>` and :ref:`notifications <async-notify>`, :ref:`COPY <copy>`
|
||||
support. Many Python types are supported out-of-the-box and :ref:`adapted to
|
||||
matching PostgreSQL data types <python-types-adaptation>`; adaptation can be
|
||||
extended and customized thanks to a flexible :ref:`objects adaptation system
|
||||
<adapting-new-types>`.
|
||||
<async-support>` and :ref:`notifications <async-notify>`, |COPY-TO-FROM|__
|
||||
support, and a flexible :ref:`objects adaptation system
|
||||
<python-types-adaptation>`. Many basic Python types are supported
|
||||
out-of-the-box and mapped to matching PostgreSQL data types, such as strings
|
||||
(both bytes and Unicode), numbers (ints, longs, floats, decimals), booleans and
|
||||
datetime objects (both built-in and `mx.DateTime`_), several types of
|
||||
:ref:`binary objects <adapt-binary>`. Also available are mappings between lists
|
||||
and PostgreSQL arrays of any supported type, between :ref:`dictionaries and
|
||||
PostgreSQL hstores <adapt-hstore>`, and between :ref:`tuples/namedtuples and
|
||||
PostgreSQL composite types <adapt-composite>`.
|
||||
|
||||
Psycopg 2 is both Unicode and Python 3 friendly.
|
||||
|
||||
|
||||
.. _Psycopg: https://psycopg.org/
|
||||
.. _PostgreSQL: https://www.postgresql.org/
|
||||
.. _Python: https://www.python.org/
|
||||
.. _libpq: https://www.postgresql.org/docs/current/static/libpq.html
|
||||
.. _Psycopg: http://initd.org/psycopg/
|
||||
.. _PostgreSQL: http://www.postgresql.org/
|
||||
.. _Python: http://www.python.org/
|
||||
.. _Zope: http://www.zope.org/
|
||||
.. _libpq: http://www.postgresql.org/docs/current/static/libpq.html
|
||||
.. |COPY-TO-FROM| replace:: :sql:`COPY TO/COPY FROM`
|
||||
.. __: http://www.postgresql.org/docs/current/static/sql-copy.html
|
||||
|
||||
|
||||
.. rubric:: Contents
|
||||
|
@ -34,22 +42,17 @@ Psycopg 2 is both Unicode and Python 3 friendly.
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install
|
||||
usage
|
||||
module
|
||||
connection
|
||||
cursor
|
||||
advanced
|
||||
extensions
|
||||
extras
|
||||
errors
|
||||
sql
|
||||
tz
|
||||
pool
|
||||
extras
|
||||
errorcodes
|
||||
faq
|
||||
news
|
||||
license
|
||||
|
||||
|
||||
.. ifconfig:: builder != 'text'
|
||||
|
@ -57,7 +60,6 @@ Psycopg 2 is both Unicode and Python 3 friendly.
|
|||
.. rubric:: Indices and tables
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
|
||||
|
@ -68,3 +70,4 @@ Psycopg 2 is both Unicode and Python 3 friendly.
|
|||
**To Do items in the documentation**
|
||||
|
||||
.. todolist::
|
||||
|
||||
|
|
|
@ -1,364 +0,0 @@
|
|||
.. _installation:
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
|
||||
Psycopg is a PostgreSQL_ adapter for the Python_ programming language. It is a
|
||||
wrapper for the libpq_, the official PostgreSQL client library.
|
||||
|
||||
.. _PostgreSQL: https://www.postgresql.org/
|
||||
.. _Python: https://www.python.org/
|
||||
|
||||
|
||||
.. index::
|
||||
single: Install; from PyPI
|
||||
single: Install; wheel
|
||||
single: Wheel
|
||||
|
||||
.. _binary-packages:
|
||||
|
||||
Quick Install
|
||||
-------------
|
||||
|
||||
For most operating systems, the quickest way to install Psycopg is using the
|
||||
wheel_ package available on PyPI_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install psycopg2-binary
|
||||
|
||||
This will install a pre-compiled binary version of the module which does not
|
||||
require the build or runtime prerequisites described below. Make sure to use
|
||||
an up-to-date version of :program:`pip` (you can upgrade it using something
|
||||
like ``pip install -U pip``).
|
||||
|
||||
You may then import the ``psycopg2`` package, as usual:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import psycopg2
|
||||
|
||||
# Connect to your postgres DB
|
||||
conn = psycopg2.connect("dbname=test user=postgres")
|
||||
|
||||
# Open a cursor to perform database operations
|
||||
cur = conn.cursor()
|
||||
|
||||
# Execute a query
|
||||
cur.execute("SELECT * FROM my_data")
|
||||
|
||||
# Retrieve query results
|
||||
records = cur.fetchall()
|
||||
|
||||
.. _PyPI: https://pypi.org/project/psycopg2-binary/
|
||||
.. _wheel: https://pythonwheels.com/
|
||||
|
||||
|
||||
psycopg vs psycopg-binary
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``psycopg2-binary`` package is meant for beginners to start playing
|
||||
with Python and PostgreSQL without the need to meet the build
|
||||
requirements.
|
||||
|
||||
If you are the maintainer of a published package depending on `!psycopg2`
|
||||
you shouldn't use ``psycopg2-binary`` as a module dependency. **For
|
||||
production use you are advised to use the source distribution.**
|
||||
|
||||
The binary packages come with their own versions of a few C libraries,
|
||||
among which ``libpq`` and ``libssl``, which will be used regardless of other
|
||||
libraries available on the client: upgrading the system libraries will not
|
||||
upgrade the libraries used by `!psycopg2`. Please build `!psycopg2` from
|
||||
source if you want to maintain binary upgradeability.
|
||||
|
||||
.. warning::
|
||||
|
||||
The `!psycopg2` wheel package comes packaged, among the others, with its
|
||||
own ``libssl`` binary. This may create conflicts with other extension
|
||||
modules binding with ``libssl`` as well, for instance with the Python
|
||||
`ssl` module: in some cases, under concurrency, the interaction between
|
||||
the two libraries may result in a segfault. In case of doubts you are
|
||||
advised to use a package built from source.
|
||||
|
||||
|
||||
.. index::
|
||||
single: Install; disable wheel
|
||||
single: Wheel; disable
|
||||
|
||||
.. _disable-wheel:
|
||||
|
||||
Change in binary packages between Psycopg 2.7 and 2.8
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In version 2.7.x, :command:`pip install psycopg2` would have tried to install
|
||||
automatically the binary package of Psycopg. Because of concurrency problems
|
||||
binary packages have displayed, ``psycopg2-binary`` has become a separate
|
||||
package, and from 2.8 it has become the only way to install the binary
|
||||
package.
|
||||
|
||||
If you are using Psycopg 2.7 and you want to disable the use of wheel binary
|
||||
packages, relying on the system libraries available on your client, you
|
||||
can use the :command:`pip` |--no-binary option|__, e.g.:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install --no-binary :all: psycopg2
|
||||
|
||||
.. |--no-binary option| replace:: ``--no-binary`` option
|
||||
.. __: https://pip.pypa.io/en/stable/reference/pip_install/#install-no-binary
|
||||
|
||||
which can be specified in your :file:`requirements.txt` files too, e.g. use:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
psycopg2>=2.7,<2.8 --no-binary psycopg2
|
||||
|
||||
to use the last bugfix release of the `!psycopg2` 2.7 package, specifying to
|
||||
always compile it from source. Of course in this case you will have to meet
|
||||
the :ref:`build prerequisites <build-prerequisites>`.
|
||||
|
||||
|
||||
.. index::
|
||||
single: Prerequisites
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
The current `!psycopg2` implementation supports:
|
||||
|
||||
..
|
||||
NOTE: keep consistent with setup.py and the /features/ page.
|
||||
|
||||
- Python versions from 3.8 to 3.13
|
||||
- PostgreSQL server versions from 7.4 to 17
|
||||
- PostgreSQL client library version from 9.1
|
||||
|
||||
.. note::
|
||||
|
||||
Not all the psycopg2 versions support all the supported Python versions.
|
||||
|
||||
Please see the :ref:`release notes <news>` to verify when the support for
|
||||
a new Python version was added and when the support for an old Python
|
||||
version was removed.
|
||||
|
||||
|
||||
.. _build-prerequisites:
|
||||
|
||||
Build prerequisites
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The build prerequisites are to be met in order to install Psycopg from source
|
||||
code, from a source distribution package, GitHub_ or from PyPI.
|
||||
|
||||
.. _GitHub: https://github.com/psycopg/psycopg2
|
||||
|
||||
Psycopg is a C wrapper around the libpq_ PostgreSQL client library. To install
|
||||
it from sources you will need:
|
||||
|
||||
- A C compiler.
|
||||
|
||||
- The Python header files. They are usually installed in a package such as
|
||||
**python-dev** or **python3-dev**. A message such as *error: Python.h: No
|
||||
such file or directory* is an indication that the Python headers are
|
||||
missing.
|
||||
|
||||
- The libpq header files. They are usually installed in a package such as
|
||||
**libpq-dev**. If you get an *error: libpq-fe.h: No such file or directory*
|
||||
you are missing them.
|
||||
|
||||
- The :program:`pg_config` program: it is usually installed by the
|
||||
**libpq-dev** package but sometimes it is not in a :envvar:`PATH` directory.
|
||||
Having it in the :envvar:`PATH` greatly streamlines the installation, so try
|
||||
running ``pg_config --version``: if it returns an error or an unexpected
|
||||
version number then locate the directory containing the :program:`pg_config`
|
||||
shipped with the right libpq version (usually
|
||||
``/usr/lib/postgresql/X.Y/bin/``) and add it to the :envvar:`PATH`:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ export PATH=/usr/lib/postgresql/X.Y/bin/:$PATH
|
||||
|
||||
You only need :program:`pg_config` to compile `!psycopg2`, not for its
|
||||
regular usage.
|
||||
|
||||
Once everything is in place it's just a matter of running the standard:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install psycopg2
|
||||
|
||||
or, from the directory containing the source code:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ python setup.py build
|
||||
$ python setup.py install
|
||||
|
||||
|
||||
Runtime requirements
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Unless you compile `!psycopg2` as a static library, or you install it from a
|
||||
self-contained wheel package, it will need the libpq_ library at runtime
|
||||
(usually distributed in a ``libpq.so`` or ``libpq.dll`` file). `!psycopg2`
|
||||
relies on the host OS to find the library if the library is installed in a
|
||||
standard location there is usually no problem; if the library is in a
|
||||
non-standard location you will have to tell Psycopg how to find it,
|
||||
which is OS-dependent (for instance setting a suitable
|
||||
:envvar:`LD_LIBRARY_PATH` on Linux).
|
||||
|
||||
.. note::
|
||||
|
||||
The libpq header files used to compile `!psycopg2` should match the
|
||||
version of the library linked at runtime. If you get errors about missing
|
||||
or mismatching libraries when importing `!psycopg2` check (e.g. using
|
||||
:program:`ldd`) if the module ``psycopg2/_psycopg.so`` is linked to the
|
||||
right ``libpq.so``.
|
||||
|
||||
.. note::
|
||||
|
||||
Whatever version of libpq `!psycopg2` is compiled with, it will be
|
||||
possible to connect to PostgreSQL servers of any supported version: just
|
||||
install the most recent libpq version or the most practical, without
|
||||
trying to match it to the version of the PostgreSQL server you will have
|
||||
to connect to.
|
||||
|
||||
|
||||
.. index::
|
||||
single: setup.py
|
||||
single: setup.cfg
|
||||
|
||||
Non-standard builds
|
||||
-------------------
|
||||
|
||||
If you have less standard requirements such as:
|
||||
|
||||
- creating a :ref:`debug build <debug-build>`,
|
||||
- using :program:`pg_config` not in the :envvar:`PATH`,
|
||||
|
||||
then take a look at the ``setup.cfg`` file.
|
||||
|
||||
Some of the options available in ``setup.cfg`` are also available as command
|
||||
line arguments of the ``build_ext`` sub-command. For instance you can specify
|
||||
an alternate :program:`pg_config` location using:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ python setup.py build_ext --pg-config /path/to/pg_config build
|
||||
|
||||
Use ``python setup.py build_ext --help`` to get a list of the options
|
||||
supported.
|
||||
|
||||
|
||||
.. index::
|
||||
single: debug
|
||||
single: PSYCOPG_DEBUG
|
||||
|
||||
.. _debug-build:
|
||||
|
||||
Creating a debug build
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In case of problems, Psycopg can be configured to emit detailed debug
|
||||
messages, which can be very useful for diagnostics and to report a bug. In
|
||||
order to create a debug package:
|
||||
|
||||
- `Download`__ and unpack the Psycopg *source package* (the ``.tar.gz``
|
||||
package).
|
||||
|
||||
- Edit the ``setup.cfg`` file adding the ``PSYCOPG_DEBUG`` flag to the
|
||||
``define`` option.
|
||||
|
||||
- :ref:`Compile and install <build-prerequisites>` the package.
|
||||
|
||||
- Set the :envvar:`PSYCOPG_DEBUG` environment variable:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ export PSYCOPG_DEBUG=1
|
||||
|
||||
- Run your program (making sure that the `!psycopg2` package imported is the
|
||||
one you just compiled and not e.g. the system one): you will have a copious
|
||||
stream of informations printed on stderr.
|
||||
|
||||
.. __: https://pypi.org/project/psycopg2/#files
|
||||
|
||||
|
||||
Non-standard Python Implementation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The `psycopg2` package is the current mature implementation of the adapter: it
|
||||
is a C extension and as such it is only compatible with CPython_. If you want
|
||||
to use Psycopg on a different Python implementation (PyPy, Jython, IronPython)
|
||||
there is a couple of alternative:
|
||||
|
||||
- a `Ctypes port`__, but it is not as mature as the C implementation yet
|
||||
and it is not as feature-complete;
|
||||
|
||||
- a `CFFI port`__ which is currently more used and reported more efficient on
|
||||
PyPy, but please be careful of its version numbers because they are not
|
||||
aligned to the official psycopg2 ones and some features may differ.
|
||||
|
||||
.. _PostgreSQL: https://www.postgresql.org/
|
||||
.. _Python: https://www.python.org/
|
||||
.. _libpq: https://www.postgresql.org/docs/current/static/libpq.html
|
||||
.. _CPython: https://en.wikipedia.org/wiki/CPython
|
||||
.. _Ctypes: https://docs.python.org/library/ctypes.html
|
||||
.. __: https://github.com/mvantellingen/psycopg2-ctypes
|
||||
.. __: https://github.com/chtd/psycopg2cffi
|
||||
|
||||
|
||||
.. index::
|
||||
single: tests
|
||||
|
||||
.. _test-suite:
|
||||
|
||||
Running the test suite
|
||||
----------------------
|
||||
|
||||
Once `!psycopg2` is installed you can run the test suite to verify it is
|
||||
working correctly. From the source directory, you can run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose
|
||||
|
||||
The tests run against a database called ``psycopg2_test`` on UNIX socket and
|
||||
the standard port. You can configure a different database to run the test by
|
||||
setting the environment variables:
|
||||
|
||||
- :envvar:`PSYCOPG2_TESTDB`
|
||||
- :envvar:`PSYCOPG2_TESTDB_HOST`
|
||||
- :envvar:`PSYCOPG2_TESTDB_PORT`
|
||||
- :envvar:`PSYCOPG2_TESTDB_USER`
|
||||
|
||||
The database should already exist before running the tests.
|
||||
|
||||
|
||||
.. _other-problems:
|
||||
|
||||
If you still have problems
|
||||
--------------------------
|
||||
|
||||
Try the following. *In order:*
|
||||
|
||||
- Read again the :ref:`build-prerequisites`.
|
||||
|
||||
- Read the :ref:`FAQ <faq-compile>`.
|
||||
|
||||
- Google for `!psycopg2` *your error message*. Especially useful the week
|
||||
after the release of a new OS X version.
|
||||
|
||||
- Write to the `Mailing List`_.
|
||||
|
||||
- If you think that you have discovered a bug, test failure or missing feature
|
||||
please raise a ticket in the `bug tracker`_.
|
||||
|
||||
- Complain on your blog or on Twitter that `!psycopg2` is the worst package
|
||||
ever and about the quality time you have wasted figuring out the correct
|
||||
:envvar:`ARCHFLAGS`. Especially useful from the Starbucks near you.
|
||||
|
||||
.. _mailing list: https://www.postgresql.org/list/psycopg/
|
||||
.. _bug tracker: https://github.com/psycopg/psycopg2/issues
|
|
@ -1,7 +0,0 @@
|
|||
.. index::
|
||||
single: License
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
.. include:: ../../LICENSE
|
|
@ -16,85 +16,53 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
single: Port; Connection
|
||||
single: DSN (Database Source Name)
|
||||
|
||||
.. function::
|
||||
connect(dsn=None, connection_factory=None, cursor_factory=None, async=False, \*\*kwargs)
|
||||
.. function:: connect(dsn or params [, connection_factory] [, async=0])
|
||||
|
||||
Create a new database session and return a new `connection` object.
|
||||
|
||||
The connection parameters can be specified as a `libpq connection
|
||||
string`__ using the *dsn* parameter::
|
||||
The connection parameters can be specified either as a string::
|
||||
|
||||
conn = psycopg2.connect("dbname=test user=postgres password=secret")
|
||||
|
||||
or using a set of keyword arguments::
|
||||
|
||||
conn = psycopg2.connect(dbname="test", user="postgres", password="secret")
|
||||
|
||||
or using a mix of both: if the same parameter name is specified in both
|
||||
sources, the *kwargs* value will have precedence over the *dsn* value.
|
||||
Note that either the *dsn* or at least one connection-related keyword
|
||||
argument is required.
|
||||
conn = psycopg2.connect(database="test", user="postgres", password="secret")
|
||||
|
||||
The basic connection parameters are:
|
||||
|
||||
- `!dbname` -- the database name (`!database` is a deprecated alias)
|
||||
- `!dbname` -- the database name (only in dsn string)
|
||||
- `!database` -- the database name (only as keyword argument)
|
||||
- `!user` -- user name used to authenticate
|
||||
- `!password` -- password used to authenticate
|
||||
- `!host` -- database host address (defaults to UNIX socket if not provided)
|
||||
- `!port` -- connection port number (defaults to 5432 if not provided)
|
||||
|
||||
Any other connection parameter supported by the client library/server can
|
||||
be passed either in the connection string or as a keyword. The PostgreSQL
|
||||
documentation contains the complete list of the `supported parameters`__.
|
||||
be passed either in the connection string or as keyword. See the
|
||||
PostgreSQL documentation for a complete `list of supported parameters`__.
|
||||
Also note that the same parameters can be passed to the client library
|
||||
using `environment variables`__.
|
||||
|
||||
.. __:
|
||||
.. _connstring: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||
.. __:
|
||||
.. _connparams: https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS
|
||||
.. __:
|
||||
.. _connenvvars: https://www.postgresql.org/docs/current/static/libpq-envars.html
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PQCONNECTDBPARAMS
|
||||
.. __: http://www.postgresql.org/docs/current/static/libpq-envars.html
|
||||
|
||||
Using the *connection_factory* parameter a different class or
|
||||
connections factory can be specified. It should be a callable object
|
||||
taking a *dsn* string argument. See :ref:`subclassing-connection` for
|
||||
details. If a *cursor_factory* is specified, the connection's
|
||||
`~connection.cursor_factory` is set to it. If you only need customized
|
||||
cursors you can use this parameter instead of subclassing a connection.
|
||||
taking a *dsn* argument. See :ref:`subclassing-connection` for
|
||||
details.
|
||||
|
||||
Using *async*\=\ `!True` an asynchronous connection will be created: see
|
||||
:ref:`async-support` to know about advantages and limitations. *async_* is
|
||||
a valid alias for the Python version where ``async`` is a keyword.
|
||||
Using *async*\=1 an asynchronous connection will be created: see
|
||||
:ref:`async-support` to know about advantages and limitations.
|
||||
|
||||
.. versionchanged:: 2.4.3
|
||||
any keyword argument is passed to the connection. Previously only the
|
||||
basic parameters (plus `!sslmode`) were supported as keywords.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
added the *cursor_factory* parameter.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
both *dsn* and keyword arguments can be specified.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
added *async_* alias.
|
||||
|
||||
.. seealso::
|
||||
|
||||
- `~psycopg2.extensions.parse_dsn`
|
||||
- libpq `connection string syntax`__
|
||||
- libpq supported `connection parameters`__
|
||||
- libpq supported `environment variables`__
|
||||
|
||||
.. __: connstring_
|
||||
.. __: connparams_
|
||||
.. __: connenvvars_
|
||||
|
||||
.. extension::
|
||||
|
||||
The non-connection-related keyword parameters are Psycopg extensions
|
||||
to the |DBAPI|_.
|
||||
The parameters *connection_factory* and *async* are Psycopg extensions
|
||||
to the |DBAPI|.
|
||||
|
||||
|
||||
.. data:: apilevel
|
||||
|
||||
|
@ -113,14 +81,6 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
by the interface. For `psycopg2` is ``pyformat``. See also
|
||||
:ref:`query-parameters`.
|
||||
|
||||
.. data:: __libpq_version__
|
||||
|
||||
Integer constant reporting the version of the ``libpq`` library this
|
||||
``psycopg2`` module was compiled with (in the same format of
|
||||
`~psycopg2.extensions.ConnectionInfo.server_version`). If this value is
|
||||
greater or equal than ``90100`` then you may query the version of the
|
||||
actually loaded library using the `~psycopg2.extensions.libpq_version()`
|
||||
function.
|
||||
|
||||
|
||||
.. index::
|
||||
|
@ -137,15 +97,14 @@ available through the following exceptions:
|
|||
.. exception:: Warning
|
||||
|
||||
Exception raised for important warnings like data truncations while
|
||||
inserting, etc. It is a subclass of the Python `StandardError`
|
||||
(`Exception` on Python 3).
|
||||
inserting, etc. It is a subclass of the Python `~exceptions.StandardError`.
|
||||
|
||||
.. exception:: Error
|
||||
|
||||
Exception that is the base class of all other error exceptions. You can
|
||||
use this to catch all errors with one single `!except` statement. Warnings
|
||||
are not considered errors and thus not use this class as base. It
|
||||
is a subclass of the Python `StandardError` (`Exception` on Python 3).
|
||||
is a subclass of the Python `!StandardError`.
|
||||
|
||||
.. attribute:: pgerror
|
||||
|
||||
|
@ -163,41 +122,23 @@ available through the following exceptions:
|
|||
|
||||
>>> try:
|
||||
... cur.execute("SELECT * FROM barf")
|
||||
... except psycopg2.Error as e:
|
||||
... except Exception, e:
|
||||
... pass
|
||||
|
||||
>>> e.pgcode
|
||||
'42P01'
|
||||
>>> print(e.pgerror)
|
||||
>>> print e.pgerror
|
||||
ERROR: relation "barf" does not exist
|
||||
LINE 1: SELECT * FROM barf
|
||||
^
|
||||
|
||||
.. attribute:: cursor
|
||||
|
||||
The cursor the exception was raised from; `None` if not applicable.
|
||||
|
||||
.. attribute:: diag
|
||||
|
||||
A `~psycopg2.extensions.Diagnostics` object containing further
|
||||
information about the error. ::
|
||||
|
||||
>>> try:
|
||||
... cur.execute("SELECT * FROM barf")
|
||||
... except psycopg2.Error as e:
|
||||
... pass
|
||||
|
||||
>>> e.diag.severity
|
||||
'ERROR'
|
||||
>>> e.diag.message_primary
|
||||
'relation "barf" does not exist'
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
.. extension::
|
||||
|
||||
The `~Error.pgerror`, `~Error.pgcode`, `~Error.cursor`, and
|
||||
`~Error.diag` attributes are Psycopg extensions.
|
||||
The `~Error.pgerror`, `~Error.pgcode`, and `~Error.cursor` attributes
|
||||
are Psycopg extensions.
|
||||
|
||||
|
||||
.. exception:: InterfaceError
|
||||
|
@ -252,14 +193,13 @@ available through the following exceptions:
|
|||
|
||||
.. extension::
|
||||
|
||||
Psycopg actually raises a different exception for each :sql:`SQLSTATE`
|
||||
error returned by the database: the classes are available in the
|
||||
`psycopg2.errors` module. Every exception class is a subclass of one of
|
||||
the exception classes defined here though, so they don't need to be
|
||||
trapped specifically: trapping `!Error` or `!DatabaseError` is usually
|
||||
what needed to write a generic error handler; trapping a specific error
|
||||
such as `!NotNullViolation` can be useful to write specific exception
|
||||
handlers.
|
||||
Psycopg may raise a few other, more specialized, exceptions: currently
|
||||
`~psycopg2.extensions.QueryCanceledError` and
|
||||
`~psycopg2.extensions.TransactionRollbackError` are defined. These
|
||||
exceptions are not exposed by the main `!psycopg2` module but are
|
||||
made available by the `~psycopg2.extensions` module. All the
|
||||
additional exceptions are subclasses of standard |DBAPI| exceptions, so
|
||||
trapping them specifically is not required.
|
||||
|
||||
|
||||
This is the exception inheritance layout:
|
||||
|
@ -273,6 +213,8 @@ This is the exception inheritance layout:
|
|||
\|__ `DatabaseError`
|
||||
\|__ `DataError`
|
||||
\|__ `OperationalError`
|
||||
\| \|__ `psycopg2.extensions.QueryCanceledError`
|
||||
\| \|__ `psycopg2.extensions.TransactionRollbackError`
|
||||
\|__ `IntegrityError`
|
||||
\|__ `InternalError`
|
||||
\|__ `ProgrammingError`
|
||||
|
@ -352,12 +294,6 @@ The module exports the following constructors and singletons:
|
|||
This function constructs an object capable of holding a binary (long)
|
||||
string value.
|
||||
|
||||
.. note::
|
||||
|
||||
All the adapters returned by the module level factories (`!Binary`,
|
||||
`!Date`, `!Time`, `!Timestamp` and the `!*FromTicks` variants) expose the
|
||||
wrapped object (a regular Python object such as `!datetime`) in an
|
||||
`!adapted` attribute.
|
||||
|
||||
.. data:: STRING
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
.. index::
|
||||
single: Release notes
|
||||
single: News
|
||||
|
||||
.. _news:
|
||||
|
||||
Release notes
|
||||
=============
|
||||
|
||||
.. include:: ../../NEWS
|
|
@ -24,18 +24,13 @@ directly in the client application.
|
|||
|
||||
.. method:: getconn(key=None)
|
||||
|
||||
Get a free connection from the pool.
|
||||
|
||||
The *key* parameter is optional: if used, the connection will be
|
||||
associated to the key and calling `!getconn()` with the same key again
|
||||
will return the same connection.
|
||||
Get a free connection and assign it to *key* if not `!None`.
|
||||
|
||||
.. method:: putconn(conn, key=None, close=False)
|
||||
|
||||
Put away a connection.
|
||||
|
||||
If *close* is `!True`, discard the connection from the pool.
|
||||
*key* should be used consistently with `getconn()`.
|
||||
|
||||
.. method:: closeall
|
||||
|
||||
|
@ -58,3 +53,12 @@ be used.
|
|||
.. autoclass:: ThreadedConnectionPool
|
||||
|
||||
.. note:: This pool class can be safely used in multi-threaded applications.
|
||||
|
||||
|
||||
.. autoclass:: PersistentConnectionPool
|
||||
|
||||
.. note::
|
||||
|
||||
This pool class is mostly designed to interact with Zope and probably
|
||||
not useful in generic applications.
|
||||
|
||||
|
|
147
doc/src/sql.rst
|
@ -1,147 +0,0 @@
|
|||
`psycopg2.sql` -- SQL string composition
|
||||
========================================
|
||||
|
||||
.. sectionauthor:: Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
|
||||
.. module:: psycopg2.sql
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
The module contains objects and functions useful to generate SQL dynamically,
|
||||
in a convenient and safe way. SQL identifiers (e.g. names of tables and
|
||||
fields) cannot be passed to the `~cursor.execute()` method like query
|
||||
arguments::
|
||||
|
||||
# This will not work
|
||||
table_name = 'my_table'
|
||||
cur.execute("insert into %s values (%s, %s)", [table_name, 10, 20])
|
||||
|
||||
The SQL query should be composed before the arguments are merged, for
|
||||
instance::
|
||||
|
||||
# This works, but it is not optimal
|
||||
table_name = 'my_table'
|
||||
cur.execute(
|
||||
"insert into %s values (%%s, %%s)" % table_name,
|
||||
[10, 20])
|
||||
|
||||
This sort of works, but it is an accident waiting to happen: the table name
|
||||
may be an invalid SQL literal and need quoting; even more serious is the
|
||||
security problem in case the table name comes from an untrusted source. The
|
||||
name should be escaped using `~psycopg2.extensions.quote_ident()`::
|
||||
|
||||
# This works, but it is not optimal
|
||||
table_name = 'my_table'
|
||||
cur.execute(
|
||||
"insert into %s values (%%s, %%s)" % ext.quote_ident(table_name, cur),
|
||||
[10, 20])
|
||||
|
||||
This is now safe, but it somewhat ad-hoc. In case, for some reason, it is
|
||||
necessary to include a value in the query string (as opposite as in a value)
|
||||
the merging rule is still different (`~psycopg2.extensions.adapt()` should be
|
||||
used...). It is also still relatively dangerous: if `!quote_ident()` is
|
||||
forgotten somewhere, the program will usually work, but will eventually crash
|
||||
in the presence of a table or field name with containing characters to escape,
|
||||
or will present a potentially exploitable weakness.
|
||||
|
||||
The objects exposed by the `!psycopg2.sql` module allow generating SQL
|
||||
statements on the fly, separating clearly the variable parts of the statement
|
||||
from the query parameters::
|
||||
|
||||
from psycopg2 import sql
|
||||
|
||||
cur.execute(
|
||||
sql.SQL("insert into {} values (%s, %s)")
|
||||
.format(sql.Identifier('my_table')),
|
||||
[10, 20])
|
||||
|
||||
|
||||
Module usage
|
||||
------------
|
||||
|
||||
Usually you should express the template of your query as an `SQL` instance
|
||||
with `{}`\-style placeholders and use `~SQL.format()` to merge the variable
|
||||
parts into them, all of which must be `Composable` subclasses. You can still
|
||||
have `%s`\ -style placeholders in your query and pass values to
|
||||
`~cursor.execute()`: such value placeholders will be untouched by
|
||||
`!format()`::
|
||||
|
||||
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
|
||||
field=sql.Identifier('my_name'),
|
||||
table=sql.Identifier('some_table'),
|
||||
pkey=sql.Identifier('id'))
|
||||
|
||||
The resulting object is meant to be passed directly to cursor methods such as
|
||||
`~cursor.execute()`, `~cursor.executemany()`, `~cursor.copy_expert()`, but can
|
||||
also be used to compose a query as a Python string, using the
|
||||
`~Composable.as_string()` method::
|
||||
|
||||
cur.execute(query, (42,))
|
||||
|
||||
If part of your query is a variable sequence of arguments, such as a
|
||||
comma-separated list of field names, you can use the `SQL.join()` method to
|
||||
pass them to the query::
|
||||
|
||||
query = sql.SQL("select {fields} from {table}").format(
|
||||
fields=sql.SQL(',').join([
|
||||
sql.Identifier('field1'),
|
||||
sql.Identifier('field2'),
|
||||
sql.Identifier('field3'),
|
||||
]),
|
||||
table=sql.Identifier('some_table'))
|
||||
|
||||
|
||||
`!sql` objects
|
||||
--------------
|
||||
|
||||
The `!sql` objects are in the following inheritance hierarchy:
|
||||
|
||||
| `Composable`: the base class exposing the common interface
|
||||
| ``|__`` `SQL`: a literal snippet of an SQL query
|
||||
| ``|__`` `Identifier`: a PostgreSQL identifier or dot-separated sequence of identifiers
|
||||
| ``|__`` `Literal`: a value hardcoded into a query
|
||||
| ``|__`` `Placeholder`: a `%s`\ -style placeholder whose value will be added later e.g. by `~cursor.execute()`
|
||||
| ``|__`` `Composed`: a sequence of `!Composable` instances.
|
||||
|
||||
|
||||
.. autoclass:: Composable
|
||||
|
||||
.. automethod:: as_string
|
||||
|
||||
|
||||
.. autoclass:: SQL
|
||||
|
||||
.. autoattribute:: string
|
||||
|
||||
.. automethod:: format
|
||||
|
||||
.. automethod:: join
|
||||
|
||||
|
||||
.. autoclass:: Identifier
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
added support for multiple strings.
|
||||
|
||||
.. autoattribute:: strings
|
||||
|
||||
.. versionadded:: 2.8
|
||||
previous verions only had a `!string` attribute. The attribute
|
||||
still exists but is deprecate and will only work if the
|
||||
`!Identifier` wraps a single string.
|
||||
|
||||
.. autoclass:: Literal
|
||||
|
||||
.. autoattribute:: wrapped
|
||||
|
||||
|
||||
.. autoclass:: Placeholder
|
||||
|
||||
.. autoattribute:: name
|
||||
|
||||
|
||||
.. autoclass:: Composed
|
||||
|
||||
.. autoattribute:: seq
|
||||
|
||||
.. automethod:: join
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
extension
|
||||
~~~~~~~~~
|
||||
|
@ -11,7 +12,7 @@
|
|||
from docutils import nodes
|
||||
|
||||
from sphinx.locale import _
|
||||
from docutils.parsers.rst import Directive
|
||||
from sphinx.util.compat import Directive, make_admonition
|
||||
|
||||
class extension_node(nodes.Admonition, nodes.Element): pass
|
||||
|
||||
|
@ -28,11 +29,12 @@ class Extension(Directive):
|
|||
option_spec = {}
|
||||
|
||||
def run(self):
|
||||
node = extension_node('\n'.join(self.content))
|
||||
node += nodes.title(_('DB API extension'), _('DB API extension'))
|
||||
self.state.nested_parse(self.content, self.content_offset, node)
|
||||
node['classes'].append('dbapi-extension')
|
||||
return [node]
|
||||
nodes = make_admonition(extension_node,
|
||||
self.name, [_('DB API extension')], self.options,
|
||||
self.content, self.lineno, self.content_offset,
|
||||
self.block_text, self.state, self.state_machine)
|
||||
nodes[0]['classes'].append('dbapi-extension')
|
||||
return nodes
|
||||
|
||||
|
||||
def visit_extension_node(self, node):
|
||||
|
@ -48,3 +50,4 @@ def setup(app):
|
|||
text=(visit_extension_node, depart_extension_node))
|
||||
|
||||
app.add_directive('extension', Extension)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sql role
|
||||
~~~~~~~~
|
||||
|
@ -17,3 +18,4 @@ def sql_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||
|
||||
def setup(app):
|
||||
roles.register_local_role('sql', sql_role)
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
"""
|
||||
ticket role
|
||||
~~~~~~~~~~~
|
||||
|
||||
An interpreted text role to link docs to tickets issues.
|
||||
|
||||
:copyright: Copyright 2013 by Daniele Varrazzo.
|
||||
"""
|
||||
|
||||
import re
|
||||
from docutils import nodes, utils
|
||||
from docutils.parsers.rst import roles
|
||||
|
||||
def ticket_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
cfg = inliner.document.settings.env.app.config
|
||||
if cfg.ticket_url is None:
|
||||
msg = inliner.reporter.warning(
|
||||
"ticket not configured: please configure ticket_url in conf.py")
|
||||
prb = inliner.problematic(rawtext, rawtext, msg)
|
||||
return [prb], [msg]
|
||||
|
||||
rv = [nodes.Text(name + ' ')]
|
||||
tokens = re.findall(r'(#?\d+)|([^\d#]+)', text)
|
||||
for ticket, noise in tokens:
|
||||
if ticket:
|
||||
num = int(ticket.replace('#', ''))
|
||||
|
||||
# Push numbers of the oldel tickets ahead.
|
||||
# We moved the tickets from a different tracker to GitHub and the
|
||||
# latter already had a few ticket numbers taken (as merge
|
||||
# requests).
|
||||
remap_until = cfg.ticket_remap_until
|
||||
remap_offset = cfg.ticket_remap_offset
|
||||
if remap_until and remap_offset:
|
||||
if num <= remap_until:
|
||||
num += remap_offset
|
||||
|
||||
url = cfg.ticket_url % num
|
||||
roles.set_classes(options)
|
||||
node = nodes.reference(ticket, utils.unescape(ticket),
|
||||
refuri=url, **options)
|
||||
|
||||
rv.append(node)
|
||||
|
||||
else:
|
||||
assert noise
|
||||
rv.append(nodes.Text(noise))
|
||||
|
||||
return rv, []
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('ticket_url', None, 'env')
|
||||
app.add_config_value('ticket_remap_until', None, 'env')
|
||||
app.add_config_value('ticket_remap_offset', None, 'env')
|
||||
app.add_role('ticket', ticket_role)
|
||||
app.add_role('tickets', ticket_role)
|
|
@ -1,57 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""Create the docs table of the sqlstate errors.
|
||||
"""
|
||||
|
||||
|
||||
import re
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from psycopg2._psycopg import sqlstate_errors
|
||||
|
||||
|
||||
def main():
|
||||
sqlclasses = {}
|
||||
clsfile = sys.argv[1]
|
||||
with open(clsfile) as f:
|
||||
for l in f:
|
||||
m = re.match(r'/\* Class (..) - (.+) \*/', l)
|
||||
if m is not None:
|
||||
sqlclasses[m.group(1)] = m.group(2)
|
||||
|
||||
Line = namedtuple('Line', 'colstate colexc colbase sqlstate')
|
||||
|
||||
lines = [Line('SQLSTATE', 'Exception', 'Base exception', None)]
|
||||
for k in sorted(sqlstate_errors):
|
||||
exc = sqlstate_errors[k]
|
||||
lines.append(Line(
|
||||
f"``{k}``", f"`!{exc.__name__}`",
|
||||
f"`!{get_base_exception(exc).__name__}`", k))
|
||||
|
||||
widths = [max(len(l[c]) for l in lines) for c in range(3)]
|
||||
h = Line(*(['=' * w for w in widths] + [None]))
|
||||
lines.insert(0, h)
|
||||
lines.insert(2, h)
|
||||
lines.append(h)
|
||||
|
||||
h1 = '-' * (sum(widths) + len(widths) - 1)
|
||||
sqlclass = None
|
||||
for l in lines:
|
||||
cls = l.sqlstate[:2] if l.sqlstate else None
|
||||
if cls and cls != sqlclass:
|
||||
print(f"**Class {cls}**: {sqlclasses[cls]}")
|
||||
print(h1)
|
||||
sqlclass = cls
|
||||
|
||||
print("%-*s %-*s %-*s" % (
|
||||
widths[0], l.colstate, widths[1], l.colexc, widths[2], l.colbase))
|
||||
|
||||
|
||||
def get_base_exception(exc):
|
||||
for cls in exc.__mro__:
|
||||
if cls.__module__ == 'psycopg2':
|
||||
return cls
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
63
doc/src/tools/stitch_text.py
Executable file
|
@ -0,0 +1,63 @@
|
|||
#! /usr/bin/env python
|
||||
"""A script to stitch together the generated text files in the correct order.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
sys.stderr.write("usage: %s index.rst text-dir\n")
|
||||
return 2
|
||||
|
||||
_, index, txt_dir = sys.argv
|
||||
|
||||
for fb in iter_file_base(index):
|
||||
emit(fb, txt_dir)
|
||||
|
||||
return 0
|
||||
|
||||
def iter_file_base(fn):
|
||||
f = open(fn)
|
||||
if sys.version_info[0] >= 3:
|
||||
have_line = iter(f).__next__
|
||||
else:
|
||||
have_line = iter(f).next
|
||||
|
||||
while not have_line().startswith('.. toctree'):
|
||||
pass
|
||||
while have_line().strip().startswith(':'):
|
||||
pass
|
||||
|
||||
yield os.path.splitext(os.path.basename(fn))[0]
|
||||
|
||||
n = 0
|
||||
while True:
|
||||
line = have_line()
|
||||
if line.isspace():
|
||||
continue
|
||||
if line.startswith(".."):
|
||||
break
|
||||
n += 1
|
||||
yield line.strip()
|
||||
|
||||
f.close()
|
||||
|
||||
if n < 5:
|
||||
# maybe format changed?
|
||||
raise Exception("Not enough files found. Format change in index.rst?")
|
||||
|
||||
def emit(basename, txt_dir):
|
||||
f = open(os.path.join(txt_dir, basename + ".txt"))
|
||||
for line in f:
|
||||
line = line.replace("``", "'")
|
||||
sys.stdout.write(line)
|
||||
f.close()
|
||||
|
||||
# some space between sections
|
||||
sys.stdout.write("\n\n")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
@ -5,10 +5,6 @@
|
|||
|
||||
.. module:: psycopg2.tz
|
||||
|
||||
.. deprecated:: 2.9
|
||||
The module will be dropped in psycopg 2.10. Use `datetime.timezone`
|
||||
instead.
|
||||
|
||||
This module holds two different tzinfo implementations that can be used as the
|
||||
`tzinfo` argument to `~datetime.datetime` constructors, directly passed to
|
||||
Psycopg functions or used to set the `cursor.tzinfo_factory` attribute in
|
||||
|
@ -17,3 +13,4 @@ cursors.
|
|||
.. autoclass:: psycopg2.tz.FixedOffsetTimezone
|
||||
|
||||
.. autoclass:: psycopg2.tz.LocalTimezone
|
||||
|
||||
|
|
89
examples/binary.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# binary.py - working with binary data
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
try:
|
||||
curs.execute("CREATE TABLE test_binary (id int4, name text, img bytea)")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_binary")
|
||||
curs.execute("CREATE TABLE test_binary (id int4, name text, img bytea)")
|
||||
conn.commit()
|
||||
|
||||
# first we try two inserts, one with an explicit Binary call and the other
|
||||
# using a buffer on a file object.
|
||||
|
||||
data1 = {'id':1, 'name':'somehackers.jpg',
|
||||
'img':psycopg2.Binary(open('somehackers.jpg').read())}
|
||||
data2 = {'id':2, 'name':'whereareyou.jpg',
|
||||
'img':buffer(open('whereareyou.jpg').read())}
|
||||
|
||||
curs.execute("""INSERT INTO test_binary
|
||||
VALUES (%(id)s, %(name)s, %(img)s)""", data1)
|
||||
curs.execute("""INSERT INTO test_binary
|
||||
VALUES (%(id)s, %(name)s, %(img)s)""", data2)
|
||||
|
||||
# now we try to extract the images as simple text strings
|
||||
|
||||
print "Extracting the images as strings..."
|
||||
curs.execute("SELECT * FROM test_binary")
|
||||
|
||||
for row in curs.fetchall():
|
||||
name, ext = row[1].split('.')
|
||||
new_name = name + '_S.' + ext
|
||||
print " writing %s to %s ..." % (name+'.'+ext, new_name),
|
||||
open(new_name, 'wb').write(row[2])
|
||||
print "done"
|
||||
print " python type of image data is", type(row[2])
|
||||
|
||||
# extract exactly the same data but using a binary cursor
|
||||
|
||||
print "Extracting the images using a binary cursor:"
|
||||
|
||||
curs.execute("""DECLARE zot CURSOR FOR
|
||||
SELECT img, name FROM test_binary FOR READ ONLY""")
|
||||
curs.execute("""FETCH ALL FROM zot""")
|
||||
|
||||
for row in curs.fetchall():
|
||||
name, ext = row[1].split('.')
|
||||
new_name = name + '_B.' + ext
|
||||
print " writing %s to %s ..." % (name+'.'+ext, new_name),
|
||||
open(new_name, 'wb').write(row[0])
|
||||
print "done"
|
||||
print " python type of image data is", type(row[0])
|
||||
|
||||
# this rollback is required because we can't drop a table with a binary cusor
|
||||
# declared and still open
|
||||
conn.rollback()
|
||||
|
||||
curs.execute("DROP TABLE test_binary")
|
||||
conn.commit()
|
||||
|
||||
print "\nNow try to load the new images, to check it worked!"
|
177
examples/copy_from.py
Normal file
|
@ -0,0 +1,177 @@
|
|||
# copy_from.py -- example about copy_from
|
||||
#
|
||||
# Copyright (C) 2002 Tom Jenkins <tjenkins@devis.com>
|
||||
# Copyright (C) 2005 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# 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.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import os
|
||||
import StringIO
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
try:
|
||||
curs.execute("CREATE TABLE test_copy (fld1 text, fld2 text, fld3 int4)")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_copy")
|
||||
curs.execute("CREATE TABLE test_copy (fld1 text, fld2 text, fld3 int4)")
|
||||
conn.commit()
|
||||
|
||||
# copy_from with default arguments, from open file
|
||||
|
||||
io = open('copy_from.txt', 'wr')
|
||||
data = ['Tom\tJenkins\t37\n',
|
||||
'Madonna\t\\N\t45\n',
|
||||
'Federico\tDi Gregorio\t\\N\n']
|
||||
io.writelines(data)
|
||||
io.close()
|
||||
|
||||
io = open('copy_from.txt', 'r')
|
||||
curs.copy_from(io, 'test_copy')
|
||||
print "1) Copy %d records from file object " % len(data) + \
|
||||
"using defaults (sep: \\t and null = \\N)"
|
||||
io.close()
|
||||
|
||||
curs.execute("SELECT * FROM test_copy")
|
||||
rows = curs.fetchall()
|
||||
print " Select returned %d rows" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
||||
curs.execute("delete from test_copy")
|
||||
conn.commit()
|
||||
|
||||
# copy_from using custom separator, from open file
|
||||
|
||||
io = open('copy_from.txt', 'wr')
|
||||
data = ['Tom:Jenkins:37\n',
|
||||
'Madonna:\N:45\n',
|
||||
'Federico:Di Gregorio:\N\n']
|
||||
io.writelines(data)
|
||||
io.close()
|
||||
|
||||
io = open('copy_from.txt', 'r')
|
||||
curs.copy_from(io, 'test_copy', ':')
|
||||
print "2) Copy %d records from file object using sep = :" % len(data)
|
||||
io.close()
|
||||
|
||||
curs.execute("SELECT * FROM test_copy")
|
||||
rows = curs.fetchall()
|
||||
print " Select returned %d rows" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
||||
curs.execute("delete from test_copy")
|
||||
conn.commit()
|
||||
|
||||
# copy_from using custom null identifier, from open file
|
||||
|
||||
io = open('copy_from.txt', 'wr')
|
||||
data = ['Tom\tJenkins\t37\n',
|
||||
'Madonna\tNULL\t45\n',
|
||||
'Federico\tDi Gregorio\tNULL\n']
|
||||
io.writelines(data)
|
||||
io.close()
|
||||
|
||||
io = open('copy_from.txt', 'r')
|
||||
curs.copy_from(io, 'test_copy', null='NULL')
|
||||
print "3) Copy %d records from file object using null = NULL" % len(data)
|
||||
io.close()
|
||||
|
||||
curs.execute("SELECT * FROM test_copy")
|
||||
rows = curs.fetchall()
|
||||
print " Select using cursor returned %d rows" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
||||
curs.execute("delete from test_copy")
|
||||
conn.commit()
|
||||
|
||||
# copy_from using custom separator and null identifier
|
||||
|
||||
io = open('copy_from.txt', 'wr')
|
||||
data = ['Tom:Jenkins:37\n', 'Madonna:NULL:45\n', 'Federico:Di Gregorio:NULL\n']
|
||||
io.writelines(data)
|
||||
io.close()
|
||||
|
||||
io = open('copy_from.txt', 'r')
|
||||
curs.copy_from(io, 'test_copy', ':', 'NULL')
|
||||
print "4) Copy %d records from file object " % len(data) + \
|
||||
"using sep = : and null = NULL"
|
||||
io.close()
|
||||
|
||||
curs.execute("SELECT * FROM test_copy")
|
||||
rows = curs.fetchall()
|
||||
print " Select using cursor returned %d rows" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
||||
curs.execute("delete from test_copy")
|
||||
conn.commit()
|
||||
|
||||
# anything can be used as a file if it has .read() and .readline() methods
|
||||
|
||||
data = StringIO.StringIO()
|
||||
data.write('\n'.join(['Tom\tJenkins\t37',
|
||||
'Madonna\t\N\t45',
|
||||
'Federico\tDi Gregorio\t\N']))
|
||||
data.seek(0)
|
||||
|
||||
curs.copy_from(data, 'test_copy')
|
||||
print "5) Copy 3 records from StringIO object using defaults"
|
||||
|
||||
curs.execute("SELECT * FROM test_copy")
|
||||
rows = curs.fetchall()
|
||||
print " Select using cursor returned %d rows" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " %s %s\t%s" % (r[0], r[1], r[2])
|
||||
curs.execute("delete from test_copy")
|
||||
conn.commit()
|
||||
|
||||
# simple error test
|
||||
|
||||
print "6) About to raise an error"
|
||||
data = StringIO.StringIO()
|
||||
data.write('\n'.join(['Tom\tJenkins\t37',
|
||||
'Madonna\t\N\t45',
|
||||
'Federico\tDi Gregorio\taaa']))
|
||||
data.seek(0)
|
||||
|
||||
try:
|
||||
curs.copy_from(data, 'test_copy')
|
||||
except StandardError, err:
|
||||
conn.rollback()
|
||||
print " Caught error (as expected):\n", err
|
||||
|
||||
conn.rollback()
|
||||
|
||||
curs.execute("DROP TABLE test_copy")
|
||||
os.unlink('copy_from.txt')
|
||||
conn.commit()
|
||||
|
||||
|
||||
|
103
examples/copy_to.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
# copy_to.py -- example about copy_to
|
||||
#
|
||||
# Copyright (C) 2002 Tom Jenkins <tjenkins@devis.com>
|
||||
# Copyright (C) 2005 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# 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.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import os
|
||||
import StringIO
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
try:
|
||||
curs.execute("CREATE TABLE test_copy (fld1 text, fld2 text, fld3 int4)")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_copy")
|
||||
curs.execute("CREATE TABLE test_copy (fld1 text, fld2 text, fld3 int4)")
|
||||
conn.commit()
|
||||
|
||||
# demostrate copy_to functionality
|
||||
data = [('Tom', 'Jenkins', '37'),
|
||||
('Madonna', None, '45'),
|
||||
('Federico', 'Di Gregorio', None)]
|
||||
query = "INSERT INTO test_copy VALUES (%s, %s, %s)"
|
||||
curs.executemany(query, data)
|
||||
conn.commit()
|
||||
|
||||
# copy_to using defaults
|
||||
io = open('copy_to.txt', 'w')
|
||||
curs.copy_to(io, 'test_copy')
|
||||
print "1) Copy %d records into file object using defaults: " % len (data) + \
|
||||
"sep = \\t and null = \\N"
|
||||
io.close()
|
||||
|
||||
rows = open('copy_to.txt', 'r').readlines()
|
||||
print " File has %d rows:" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " ", r,
|
||||
|
||||
# copy_to using custom separator
|
||||
io = open('copy_to.txt', 'w')
|
||||
curs.copy_to(io, 'test_copy', ':')
|
||||
print "2) Copy %d records into file object using sep = :" % len(data)
|
||||
io.close()
|
||||
|
||||
rows = open('copy_to.txt', 'r').readlines()
|
||||
print " File has %d rows:" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " ", r,
|
||||
|
||||
# copy_to using custom null identifier
|
||||
io = open('copy_to.txt', 'w')
|
||||
curs.copy_to(io, 'test_copy', null='NULL')
|
||||
print "3) Copy %d records into file object using null = NULL" % len(data)
|
||||
io.close()
|
||||
|
||||
rows = open('copy_to.txt', 'r').readlines()
|
||||
print " File has %d rows:" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " ", r,
|
||||
|
||||
# copy_to using custom separator and null identifier
|
||||
io = open('copy_to.txt', 'w')
|
||||
curs.copy_to(io, 'test_copy', ':', 'NULL')
|
||||
print "4) Copy %d records into file object using sep = : and null ) NULL" % \
|
||||
len(data)
|
||||
io.close()
|
||||
|
||||
rows = open('copy_to.txt', 'r').readlines()
|
||||
print " File has %d rows:" % len(rows)
|
||||
|
||||
for r in rows:
|
||||
print " ", r,
|
||||
|
||||
curs.execute("DROP TABLE test_copy")
|
||||
os.unlink('copy_to.txt')
|
||||
conn.commit()
|
63
examples/cursor.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
# cursor.py - how to subclass the cursor type
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dsn:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
|
||||
class NoDataError(psycopg2.ProgrammingError):
|
||||
"""Exception that will be raised by our cursor."""
|
||||
pass
|
||||
|
||||
class Cursor(psycopg2.extensions.cursor):
|
||||
"""A custom cursor."""
|
||||
|
||||
def fetchone(self):
|
||||
"""Like fetchone but raise an exception if no data is available.
|
||||
|
||||
Note that to have .fetchmany() and .fetchall() to raise the same
|
||||
exception we'll have to override them too; even if internally psycopg
|
||||
uses the same function to fetch rows, the code path from Python is
|
||||
different.
|
||||
"""
|
||||
d = psycopg2.extensions.cursor.fetchone(self)
|
||||
if d is None:
|
||||
raise NoDataError("no more data")
|
||||
return d
|
||||
|
||||
curs = conn.cursor(cursor_factory=Cursor)
|
||||
curs.execute("SELECT 1 AS foo")
|
||||
print "Result of fetchone():", curs.fetchone()
|
||||
|
||||
# now let's raise the exception
|
||||
try:
|
||||
curs.fetchone()
|
||||
except NoDataError, err:
|
||||
print "Exception caught:", err
|
||||
|
||||
conn.rollback()
|
144
examples/dialtone.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
"""
|
||||
This example/recipe has been contributed by Valentino Volonghi (dialtone)
|
||||
|
||||
Mapping arbitrary objects to a PostgreSQL database with psycopg2
|
||||
|
||||
- Problem
|
||||
|
||||
You need to store arbitrary objects in a PostgreSQL database without being
|
||||
intrusive for your classes (don't want inheritance from an 'Item' or
|
||||
'Persistent' object).
|
||||
|
||||
- Solution
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import psycopg2
|
||||
from psycopg2.extensions import adapt, register_adapter
|
||||
|
||||
try:
|
||||
sorted()
|
||||
except:
|
||||
def sorted(seq):
|
||||
seq.sort()
|
||||
return seq
|
||||
|
||||
# Here is the adapter for every object that we may ever need to
|
||||
# insert in the database. It receives the original object and does
|
||||
# its job on that instance
|
||||
|
||||
class ObjectMapper(object):
|
||||
def __init__(self, orig, curs=None):
|
||||
self.orig = orig
|
||||
self.tmp = {}
|
||||
self.items, self.fields = self._gatherState()
|
||||
|
||||
def _gatherState(self):
|
||||
adaptee_name = self.orig.__class__.__name__
|
||||
fields = sorted([(field, getattr(self.orig, field))
|
||||
for field in persistent_fields[adaptee_name]])
|
||||
items = []
|
||||
for item, value in fields:
|
||||
items.append(item)
|
||||
return items, fields
|
||||
|
||||
def getTableName(self):
|
||||
return self.orig.__class__.__name__
|
||||
|
||||
def getMappedValues(self):
|
||||
tmp = []
|
||||
for i in self.items:
|
||||
tmp.append("%%(%s)s"%i)
|
||||
return ", ".join(tmp)
|
||||
|
||||
def getValuesDict(self):
|
||||
return dict(self.fields)
|
||||
|
||||
def getFields(self):
|
||||
return self.items
|
||||
|
||||
def generateInsert(self):
|
||||
qry = "INSERT INTO"
|
||||
qry += " " + self.getTableName() + " ("
|
||||
qry += ", ".join(self.getFields()) + ") VALUES ("
|
||||
qry += self.getMappedValues() + ")"
|
||||
return qry, self.getValuesDict()
|
||||
|
||||
# Here are the objects
|
||||
class Album(object):
|
||||
id = 0
|
||||
def __init__(self):
|
||||
self.creation_time = datetime.now()
|
||||
self.album_id = self.id
|
||||
Album.id = Album.id + 1
|
||||
self.binary_data = buffer('12312312312121')
|
||||
|
||||
class Order(object):
|
||||
id = 0
|
||||
def __init__(self):
|
||||
self.items = ['rice','chocolate']
|
||||
self.price = 34
|
||||
self.order_id = self.id
|
||||
Order.id = Order.id + 1
|
||||
|
||||
register_adapter(Album, ObjectMapper)
|
||||
register_adapter(Order, ObjectMapper)
|
||||
|
||||
# Describe what is needed to save on each object
|
||||
# This is actually just configuration, you can use xml with a parser if you
|
||||
# like to have plenty of wasted CPU cycles ;P.
|
||||
|
||||
persistent_fields = {'Album': ['album_id', 'creation_time', 'binary_data'],
|
||||
'Order': ['order_id', 'items', 'price']
|
||||
}
|
||||
|
||||
print adapt(Album()).generateInsert()
|
||||
print adapt(Album()).generateInsert()
|
||||
print adapt(Album()).generateInsert()
|
||||
print adapt(Order()).generateInsert()
|
||||
print adapt(Order()).generateInsert()
|
||||
print adapt(Order()).generateInsert()
|
||||
|
||||
"""
|
||||
- Discussion
|
||||
|
||||
Psycopg 2 has a great new feature: adaptation. The big thing about
|
||||
adaptation is that it enables the programmer to glue most of the
|
||||
code out there without many difficulties.
|
||||
|
||||
This recipe tries to focus attention on a way to generate SQL queries to
|
||||
insert completely new objects inside a database. As you can see objects do
|
||||
not know anything about the code that is handling them. We specify all the
|
||||
fields that we need for each object through the persistent_fields dict.
|
||||
|
||||
The most important lines of this recipe are:
|
||||
register_adapter(Album, ObjectMapper)
|
||||
register_adapter(Order, ObjectMapper)
|
||||
|
||||
In these lines we notify the system that when we call adapt with an Album instance
|
||||
as an argument we want it to istantiate ObjectMapper passing the Album instance
|
||||
as argument (self.orig in the ObjectMapper class).
|
||||
|
||||
The output is something like this (for each call to generateInsert):
|
||||
|
||||
('INSERT INTO Album (album_id, binary_data, creation_time) VALUES
|
||||
(%(album_id)s, %(binary_data)s, %(creation_time)s)',
|
||||
|
||||
{'binary_data': <read-only buffer for 0x402de070, ...>,
|
||||
'creation_time': datetime.datetime(2004, 9, 10, 20, 48, 29, 633728),
|
||||
'album_id': 1}
|
||||
)
|
||||
|
||||
This is a tuple of {SQL_QUERY, FILLING_DICT}, and all the quoting/converting
|
||||
stuff (from python's datetime to postgres s and from python's buffer to
|
||||
postgres' blob) is handled with the same adaptation process hunder the hood
|
||||
by psycopg2.
|
||||
|
||||
At last, just notice that ObjectMapper is working for both Album and Order
|
||||
instances without any glitches at all, and both classes could have easily been
|
||||
coming from closed source libraries or C coded ones (which are not easily
|
||||
modified), whereas a common pattern in todays ORMs or OODBs is to provide
|
||||
a basic 'Persistent' object that already knows how to store itself in the
|
||||
database.
|
||||
"""
|
65
examples/dict.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
# dict.py - using DictCUrsor/DictRow
|
||||
#
|
||||
# Copyright (C) 2005-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dsn:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
|
||||
curs = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
|
||||
curs.execute("SELECT 1 AS foo, 'cip' AS bar, date(now()) as zot")
|
||||
print "Cursor's row factory is", curs.row_factory
|
||||
|
||||
data = curs.fetchone()
|
||||
print "The type of the data row is", type(data)
|
||||
print "Some data accessed both as tuple and dict:"
|
||||
print " ", data['foo'], data['bar'], data['zot']
|
||||
print " ", data[0], data[1], data[2]
|
||||
|
||||
# execute another query and demostrate we can still access the row
|
||||
curs.execute("SELECT 2 AS foo")
|
||||
print "The type of the data row is", type(data)
|
||||
print "Some more data accessed both as tuple and dict:"
|
||||
print " ", data['foo'], data['bar'], data['zot']
|
||||
print " ", data[0], data[1], data[2]
|
||||
|
||||
curs = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||
curs.execute("SELECT 1 AS foo, 'cip' AS bar, date(now()) as zot")
|
||||
print "Cursor's row factory is", curs.row_factory
|
||||
|
||||
data = curs.fetchone()
|
||||
print "The type of the data row is", type(data)
|
||||
print "Some data accessed both as tuple and dict:"
|
||||
print " ", data['foo'], data['bar'], data['zot']
|
||||
print " ", "No access using indices: this is a specialized cursor."
|
||||
|
||||
# execute another query and demostrate we can still access the row
|
||||
curs.execute("SELECT 2 AS foo")
|
||||
print "The type of the data row is", type(data)
|
||||
print "Some more data accessed both as tuple and dict:"
|
||||
print " ", data['foo'], data['bar'], data['zot']
|
||||
print " ", "No access using indices: this is a specialized cursor."
|
99
examples/dt.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
# datetime.py - example of using date and time types
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
import mx.DateTime
|
||||
import datetime
|
||||
|
||||
from psycopg2.extensions import adapt
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
curs = conn.cursor()
|
||||
|
||||
try:
|
||||
curs.execute("""CREATE TABLE test_dt (
|
||||
k int4, d date, t time, dt timestamp, z interval)""")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_dt")
|
||||
curs.execute("""CREATE TABLE test_dt (
|
||||
k int4, d date, t time, dt timestamp, z interval)""")
|
||||
conn.commit()
|
||||
|
||||
# build and insert some data using mx.DateTime
|
||||
mx1 = (
|
||||
1,
|
||||
mx.DateTime.Date(2004, 10, 19),
|
||||
mx.DateTime.Time(0, 11, 17.015),
|
||||
mx.DateTime.Timestamp(2004, 10, 19, 0, 11, 17.5),
|
||||
mx.DateTime.DateTimeDelta(13, 15, 17, 59.9))
|
||||
|
||||
from psycopg2.extensions import adapt
|
||||
import psycopg2.extras
|
||||
print adapt(mx1)
|
||||
|
||||
print "Inserting mx.DateTime values..."
|
||||
curs.execute("INSERT INTO test_dt VALUES (%s, %s, %s, %s, %s)", mx1)
|
||||
|
||||
# build and insert some values using the datetime adapters
|
||||
dt1 = (
|
||||
2,
|
||||
datetime.date(2004, 10, 19),
|
||||
datetime.time(0, 11, 17, 15000),
|
||||
datetime.datetime(2004, 10, 19, 0, 11, 17, 500000),
|
||||
datetime.timedelta(13, 15*3600+17*60+59, 900000))
|
||||
|
||||
print "Inserting Python datetime values..."
|
||||
curs.execute("INSERT INTO test_dt VALUES (%s, %s, %s, %s, %s)", dt1)
|
||||
|
||||
# now extract the row from database and print them
|
||||
print "Extracting values inserted with mx.DateTime wrappers:"
|
||||
curs.execute("SELECT d, t, dt, z FROM test_dt WHERE k = 1")
|
||||
for n, x in zip(mx1[1:], curs.fetchone()):
|
||||
try:
|
||||
# this will work only if psycopg has been compiled with datetime
|
||||
# as the default typecaster for date/time values
|
||||
s = repr(n) + "\n -> " + str(adapt(n)) + \
|
||||
"\n -> " + repr(x) + "\n -> " + x.isoformat()
|
||||
except:
|
||||
s = repr(n) + "\n -> " + str(adapt(n)) + \
|
||||
"\n -> " + repr(x) + "\n -> " + str(x)
|
||||
print s
|
||||
print
|
||||
|
||||
print "Extracting values inserted with Python datetime wrappers:"
|
||||
curs.execute("SELECT d, t, dt, z FROM test_dt WHERE k = 2")
|
||||
for n, x in zip(dt1[1:], curs.fetchone()):
|
||||
try:
|
||||
# this will work only if psycopg has been compiled with datetime
|
||||
# as the default typecaster for date/time values
|
||||
s = repr(n) + "\n -> " + repr(x) + "\n -> " + x.isoformat()
|
||||
except:
|
||||
s = repr(n) + "\n -> " + repr(x) + "\n -> " + str(x)
|
||||
print s
|
||||
print
|
||||
|
||||
curs.execute("DROP TABLE test_dt")
|
||||
conn.commit()
|
105
examples/encoding.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
# encoding.py - show to change client enkoding (and test it works)
|
||||
# -*- encoding: utf8 -*-
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Initial encoding for this connection is", conn.encoding
|
||||
|
||||
print "\n** This example is supposed to be run in a UNICODE terminal! **\n"
|
||||
|
||||
print "Available encodings:"
|
||||
encs = psycopg2.extensions.encodings.items()
|
||||
encs.sort()
|
||||
for a, b in encs:
|
||||
print " ", a, "<->", b
|
||||
|
||||
print "Using STRING typecaster"
|
||||
print "Setting backend encoding to LATIN1 and executing queries:"
|
||||
conn.set_client_encoding('LATIN1')
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT %s::TEXT AS foo", ('àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", unicode(x, 'latin-1').encode('utf-8'), type(x)
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", unicode(x, 'latin-1').encode('utf-8'), type(x)
|
||||
|
||||
print "Setting backend encoding to UTF8 and executing queries:"
|
||||
conn.set_client_encoding('UNICODE')
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù'.encode('utf-8'),))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x, type(x)
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x, type(x)
|
||||
|
||||
print "Using UNICODE typecaster"
|
||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||
|
||||
print "Setting backend encoding to LATIN1 and executing queries:"
|
||||
conn.set_client_encoding('LATIN1')
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT %s::TEXT AS foo", ('àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
|
||||
print "Setting backend encoding to UTF8 and executing queries:"
|
||||
conn.set_client_encoding('UNICODE')
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù'.encode('utf-8'),))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
curs.execute("SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
|
||||
print "Executing full UNICODE queries"
|
||||
|
||||
print "Setting backend encoding to LATIN1 and executing queries:"
|
||||
conn.set_client_encoding('LATIN1')
|
||||
curs = conn.cursor()
|
||||
curs.execute(u"SELECT %s::TEXT AS foo", ('àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
curs.execute(u"SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
|
||||
print "Setting backend encoding to UTF8 and executing queries:"
|
||||
conn.set_client_encoding('UNICODE')
|
||||
curs = conn.cursor()
|
||||
curs.execute(u"SELECT %s::TEXT AS foo", (u'àèìòù'.encode('utf-8'),))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
||||
curs.execute(u"SELECT %s::TEXT AS foo", (u'àèìòù',))
|
||||
x = curs.fetchone()[0]
|
||||
print " ->", x.encode('utf-8'), ":", type(x)
|
80
examples/fetch.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# fetch.py -- example about declaring cursors
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
try:
|
||||
curs.execute("CREATE TABLE test_fetch (val int4)")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_fetch")
|
||||
curs.execute("CREATE TABLE test_fetch (val int4)")
|
||||
conn.commit()
|
||||
|
||||
# we use this function to format the output
|
||||
|
||||
def flatten(l):
|
||||
"""Flattens list of tuples l."""
|
||||
return map(lambda x: x[0], l)
|
||||
|
||||
# insert 20 rows in the table
|
||||
|
||||
for i in range(20):
|
||||
curs.execute("INSERT INTO test_fetch VALUES(%s)", (i,))
|
||||
conn.commit()
|
||||
|
||||
# does some nice tricks with the transaction and postgres cursors
|
||||
# (remember to always commit or rollback before a DECLARE)
|
||||
#
|
||||
# we don't need to DECLARE ourselves, psycopg now supports named
|
||||
# cursors (but we leave the code here, comments, as an example of
|
||||
# what psycopg is doing under the hood)
|
||||
#
|
||||
#curs.execute("DECLARE crs CURSOR FOR SELECT * FROM test_fetch")
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "First 10 rows:", flatten(curs.fetchall())
|
||||
#curs.execute("MOVE -5 FROM crs")
|
||||
#print "Moved back cursor by 5 rows (to row 5.)"
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "Another 10 rows:", flatten(curs.fetchall())
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "The remaining rows:", flatten(curs.fetchall())
|
||||
|
||||
ncurs = conn.cursor("crs")
|
||||
ncurs.execute("SELECT * FROM test_fetch")
|
||||
print "First 10 rows:", flatten(ncurs.fetchmany(10))
|
||||
ncurs.scroll(-5)
|
||||
print "Moved back cursor by 5 rows (to row 5.)"
|
||||
print "Another 10 rows:", flatten(ncurs.fetchmany(10))
|
||||
print "Another one:", list(ncurs.fetchone())
|
||||
print "The remaining rows:", flatten(ncurs.fetchall())
|
||||
conn.rollback()
|
||||
|
||||
curs.execute("DROP TABLE test_fetch")
|
||||
conn.commit()
|
59
examples/lastrowid.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
# lastrowid.py - example of using .lastrowid attribute
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys, psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
curs = conn.cursor()
|
||||
|
||||
try:
|
||||
curs.execute("CREATE TABLE test_oid (name text, surname text)")
|
||||
except:
|
||||
conn.rollback()
|
||||
curs.execute("DROP TABLE test_oid")
|
||||
curs.execute("CREATE TABLE test_oid (name text, surname text)")
|
||||
conn.commit()
|
||||
|
||||
data = ({'name':'Federico', 'surname':'Di Gregorio'},
|
||||
{'name':'Pierluigi', 'surname':'Di Nunzio'})
|
||||
|
||||
curs.execute("""INSERT INTO test_oid
|
||||
VALUES (%(name)s, %(surname)s)""", data[0])
|
||||
|
||||
foid = curs.lastrowid
|
||||
print "Oid for %(name)s %(surname)s" % data[0], "is", foid
|
||||
|
||||
curs.execute("""INSERT INTO test_oid
|
||||
VALUES (%(name)s, %(surname)s)""", data[1])
|
||||
moid = curs.lastrowid
|
||||
print "Oid for %(name)s %(surname)s" % data[1], "is", moid
|
||||
|
||||
curs.execute("SELECT * FROM test_oid WHERE oid = %s", (foid,))
|
||||
print "Oid", foid, "selected %s %s" % curs.fetchone()
|
||||
|
||||
curs.execute("SELECT * FROM test_oid WHERE oid = %s", (moid,))
|
||||
print "Oid", moid, "selected %s %s" % curs.fetchone()
|
||||
|
||||
curs.execute("DROP TABLE test_oid")
|
||||
conn.commit()
|
91
examples/lobject.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
# lobject.py - lobject example
|
||||
#
|
||||
# Copyright (C) 2001-2006 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# 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.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
# this will create a large object with a new random oid, we'll
|
||||
# use it to make some basic tests about read/write and seek.
|
||||
lobj = conn.lobject()
|
||||
loid = lobj.oid
|
||||
print "Created a new large object with oid", loid
|
||||
|
||||
print "Manually importing some binary data into the object:"
|
||||
data = open("somehackers.jpg").read()
|
||||
len = lobj.write(data)
|
||||
print " imported", len, "bytes of data"
|
||||
|
||||
conn.commit()
|
||||
|
||||
print "Trying to (re)open large object with oid", loid
|
||||
lobj = conn.lobject(loid)
|
||||
print "Manually exporting the data from the lobject:"
|
||||
data1 = lobj.read()
|
||||
len = lobj.tell()
|
||||
lobj.seek(0, 0)
|
||||
data2 = lobj.read()
|
||||
if data1 != data2:
|
||||
print "ERROR: read after seek returned different data"
|
||||
open("somehackers_lobject1.jpg", 'wb').write(data1)
|
||||
print " written", len, "bytes of data to somehackers_lobject1.jpg"
|
||||
|
||||
lobj.unlink()
|
||||
print "Large object with oid", loid, "removed"
|
||||
|
||||
conn.commit()
|
||||
|
||||
# now we try to use the import and export functions to do the same
|
||||
lobj = conn.lobject(0, 'n', 0, "somehackers.jpg")
|
||||
loid = lobj.oid
|
||||
print "Imported a new large object with oid", loid
|
||||
|
||||
conn.commit()
|
||||
|
||||
print "Trying to (re)open large object with oid", loid
|
||||
lobj = conn.lobject(loid, 'n')
|
||||
print "Using export() to export the data from the large object:"
|
||||
lobj.export("somehackers_lobject2.jpg")
|
||||
print " exported large object to somehackers_lobject2.jpg"
|
||||
|
||||
lobj.unlink()
|
||||
print "Large object with oid", loid, "removed"
|
||||
|
||||
conn.commit()
|
||||
|
||||
# this will create a very large object with a new random oid.
|
||||
lobj = conn.lobject()
|
||||
loid = lobj.oid
|
||||
print "Created a new large object with oid", loid
|
||||
|
||||
print "Manually importing a lot of data into the object:"
|
||||
data = "data" * 1000000
|
||||
len = lobj.write(data)
|
||||
print " imported", len, "bytes of data"
|
||||
|
||||
conn.rollback()
|
||||
|
||||
print "\nNow try to load the new images, to check it worked!"
|
47
examples/mogrify.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
# mogrify.py - test all possible simple type mogrifications
|
||||
# -*- encoding: latin1 -*-
|
||||
#
|
||||
# Copyright (C) 2004-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details..
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys, psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':'bar'})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':None})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':True})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':42})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':u'yatt<EFBFBD>!'})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':u'bar'})
|
||||
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':'bar'})
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':None})
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':True})
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':42})
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':u'yatt<EFBFBD>!'})
|
||||
print curs.mogrify("SELECT %(foo)s AS foo", {'foo':u'bar'})
|
||||
|
||||
conn.rollback()
|
126
examples/myfirstrecipe.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
"""
|
||||
Using a tuple as a bound variable in "SELECT ... IN (...)" clauses
|
||||
in PostgreSQL using psycopg2
|
||||
|
||||
Some time ago someone asked on the psycopg mailing list how to have a
|
||||
bound variable expand to the right SQL for an SELECT IN clause:
|
||||
|
||||
SELECT * FROM atable WHERE afield IN (value1, value2, value3)
|
||||
|
||||
with the values to be used in the IN clause to be passed to the cursor
|
||||
.execute() method in a tuple as a bound variable, i.e.:
|
||||
|
||||
in_values = ("value1", "value2", "value3")
|
||||
curs.execute("SELECT ... IN %s", (in_values,))
|
||||
|
||||
psycopg 1 does support typecasting from Python to PostgreSQL (and back)
|
||||
only for simple types and this problem has no elegant solution (short or
|
||||
writing a wrapper class returning the pre-quoted text in an __str__
|
||||
method.
|
||||
|
||||
But psycopg2 offers a simple and elegant solution by partially
|
||||
implementing the Object Adaptation from PEP 246. psycopg2 moves
|
||||
the type-casting logic into external adapters and a somehow
|
||||
broken adapt() function.
|
||||
|
||||
While the original adapt() takes 3 arguments, psycopg2's one only takes
|
||||
1: the bound variable to be adapted. The result is an object supporting
|
||||
a not-yet well defined protocol that we can call ISQLQuote:
|
||||
|
||||
class ISQLQuote:
|
||||
|
||||
def getquoted(self):
|
||||
"Returns a quoted string representing the bound variable."
|
||||
|
||||
def getbinary(self):
|
||||
"Returns a binary quoted string representing the bound variable."
|
||||
|
||||
def getbuffer(self):
|
||||
"Returns the wrapped object itself."
|
||||
|
||||
__str__ = getquoted
|
||||
|
||||
Then one of the functions (usually .getquoted()) is called by psycopg2 at
|
||||
the right time to obtain the right, sql-quoted representation for the
|
||||
corresponding bound variable.
|
||||
|
||||
The nice part is that the default, built-in adapters, derived from
|
||||
psycopg 1 tyecasting code can be overridden by the programmer, simply
|
||||
replacing them in the psycopg.extensions.adapters dictionary.
|
||||
|
||||
Then the solution to the original problem is now obvious: write an
|
||||
adapter that adapts tuple objects into the right SQL string, by calling
|
||||
recursively adapt() on each element.
|
||||
|
||||
psycopg2 development can be tracked on the psycopg mailing list:
|
||||
|
||||
http://lists.initd.org/mailman/listinfo/psycopg
|
||||
|
||||
"""
|
||||
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
from psycopg2.extensions import adapt as psycoadapt
|
||||
from psycopg2.extensions import register_adapter
|
||||
|
||||
class AsIs(object):
|
||||
"""An adapter that just return the object 'as is'.
|
||||
|
||||
psycopg 1.99.9 has some optimizations that make impossible to call
|
||||
adapt() without adding some basic adapters externally. This limitation
|
||||
will be lifted in a future release.
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
self.__obj = obj
|
||||
def getquoted(self):
|
||||
return self.__obj
|
||||
|
||||
class SQL_IN(object):
|
||||
"""Adapt a tuple to an SQL quotable object."""
|
||||
|
||||
def __init__(self, seq):
|
||||
self._seq = seq
|
||||
|
||||
def prepare(self, conn):
|
||||
pass
|
||||
|
||||
def getquoted(self):
|
||||
# this is the important line: note how every object in the
|
||||
# list is adapted and then how getquoted() is called on it
|
||||
|
||||
qobjs = [str(psycoadapt(o).getquoted()) for o in self._seq]
|
||||
|
||||
return '(' + ', '.join(qobjs) + ')'
|
||||
|
||||
__str__ = getquoted
|
||||
|
||||
|
||||
# add our new adapter class to psycopg list of adapters
|
||||
register_adapter(tuple, SQL_IN)
|
||||
register_adapter(float, AsIs)
|
||||
register_adapter(int, AsIs)
|
||||
|
||||
# usually we would call:
|
||||
#
|
||||
# conn = psycopg.connect("...")
|
||||
# curs = conn.cursor()
|
||||
# curs.execute("SELECT ...", (("this", "is", "the", "tuple"),))
|
||||
#
|
||||
# but we have no connection to a database right now, so we just check
|
||||
# the SQL_IN class by calling psycopg's adapt() directly:
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "Note how the string will be SQL-quoted, but the number will not:"
|
||||
print psycoadapt(("this is an 'sql quoted' str\\ing", 1, 2.0))
|
45
examples/notify.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# notify.py - example of getting notifies
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
import sys
|
||||
import select
|
||||
import psycopg2
|
||||
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("listen test")
|
||||
|
||||
print "Waiting for 'NOTIFY test'"
|
||||
while 1:
|
||||
if select.select([conn],[],[],5)==([],[],[]):
|
||||
print "Timeout"
|
||||
else:
|
||||
conn.poll()
|
||||
while conn.notifies:
|
||||
print "Got NOTIFY:", conn.notifies.pop()
|
54
examples/simple.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
# simple.py - very simple example of plain DBAPI-2.0 usage
|
||||
#
|
||||
# currently used as test-me-stress-me script for psycopg 2.0
|
||||
#
|
||||
# Copyright (C) 2001-2010 Federico Di Gregorio <fog@debian.org>
|
||||
#
|
||||
# psycopg2 is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# psycopg2 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 Lesser General Public
|
||||
# License for more details.
|
||||
|
||||
## put in DSN your DSN string
|
||||
|
||||
DSN = 'dbname=test'
|
||||
|
||||
## don't modify anything below this line (except for experimenting)
|
||||
|
||||
class SimpleQuoter(object):
|
||||
def sqlquote(x=None):
|
||||
return "'bar'"
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
DSN = sys.argv[1]
|
||||
|
||||
print "Opening connection using dns:", DSN
|
||||
conn = psycopg2.connect(DSN)
|
||||
print "Encoding for this connection is", conn.encoding
|
||||
|
||||
curs = conn.cursor()
|
||||
curs.execute("SELECT 1 AS foo")
|
||||
print curs.fetchone()
|
||||
curs.execute("SELECT 1 AS foo")
|
||||
print curs.fetchmany()
|
||||
curs.execute("SELECT 1 AS foo")
|
||||
print curs.fetchall()
|
||||
|
||||
conn.rollback()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
curs.execute("SELECT 1 AS foo", async=1)
|
||||
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':'bar'})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':None})
|
||||
curs.execute("SELECT %(foo)f AS foo", {'foo':42})
|
||||
curs.execute("SELECT %(foo)s AS foo", {'foo':SimpleQuoter()})
|