You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

py-postgresql

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

py-postgresql - pypi Package Compare versions

Comparing version
1.2.1
to
1.2.2
+6
MANIFEST.in
include AUTHORS
include LICENSE
recursive-include postgresql *.c
recursive-include postgresql *.sql
recursive-include postgresql *.txt
recursive-include postgresql/documentation/sphinx *.rst conf.py
Administration
==============
This chapter covers the administration of py-postgresql. This includes
installation and other aspects of working with py-postgresql such as
environment variables and configuration files.
Installation
------------
py-postgresql uses Python's distutils package to manage the build and
installation process of the package. The normal entry point for
this is the ``setup.py`` script contained in the root project directory.
After extracting the archive and changing the into the project's directory,
installation is normally as simple as::
$ python3 ./setup.py install
However, if you need to install for use with a particular version of python,
just use the path of the executable that should be used::
$ /usr/opt/bin/python3 ./setup.py install
Environment
-----------
These environment variables effect the operation of the package:
============== ===============================================================================
PGINSTALLATION The path to the ``pg_config`` executable of the installation to use by default.
============== ===============================================================================
.. _alock:
**************
Advisory Locks
**************
.. warning:: `postgresql.alock` is a new feature in v1.0.
`Explicit Locking in PostgreSQL <http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS>`_.
PostgreSQL's advisory locks offer a cooperative synchronization primitive.
These are used in cases where an application needs access to a resource, but
using table locks may cause interference with other operations that can be
safely performed alongside the application-level, exclusive operation.
Advisory locks can be used by directly executing the stored procedures in the
database or by using the :class:`postgresql.alock.ALock` subclasses, which
provides a context manager that uses those stored procedures.
Currently, only two subclasses exist. Each represents the lock mode
supported by PostgreSQL's advisory locks:
* :class:`postgresql.alock.ShareLock`
* :class:`postgresql.alock.ExclusiveLock`
Acquiring ALocks
================
An ALock instance represents a sequence of advisory locks. A single ALock can
acquire and release multiple advisory locks by creating the instance with
multiple lock identifiers::
>>> from postgresql import alock
>>> table1_oid = 192842
>>> table2_oid = 192849
>>> l = alock.ExclusiveLock(db, (table1_oid, 0), (table2_oid, 0))
>>> l.acquire()
>>> ...
>>> l.release()
:class:`postgresql.alock.ALock` is similar to :class:`threading.RLock`; in
order for an ALock to be released, it must be released the number of times it
has been acquired. ALocks are associated with and survived by their session.
Much like how RLocks are associated with the thread they are acquired in:
acquiring an ALock again will merely increment its count.
PostgreSQL allows advisory locks to be identified using a pair of `int4` or a
single `int8`. ALock instances represent a *sequence* of those identifiers::
>>> from postgresql import alock
>>> ids = [(0,0), 0, 1]
>>> with alock.ShareLock(db, *ids):
... ...
Both types of identifiers may be used within the same ALock, and, regardless of
their type, will be aquired in the order that they were given to the class'
constructor. In the above example, ``(0,0)`` is acquired first, then ``0``, and
lastly ``1``.
ALocks
======
`postgresql.alock.ALock` is abstract; it defines the interface and some common
functionality. The lock mode is selected by choosing the appropriate subclass.
There are two:
``postgresql.alock.ExclusiveLock(database, *identifiers)``
Instantiate an ALock object representing the `identifiers` for use with the
`database`. Exclusive locks will conflict with other exclusive locks and share
locks.
``postgresql.alock.ShareLock(database, *identifiers)``
Instantiate an ALock object representing the `identifiers` for use with the
`database`. Share locks can be acquired when a share lock with the same
identifier has been acquired by another backend. However, an exclusive lock
with the same identifier will conflict.
ALock Interface Points
----------------------
Methods and properties available on :class:`postgresql.alock.ALock` instances:
``alock.acquire(blocking = True)``
Acquire the advisory locks represented by the ``alock`` object. If blocking is
`True`, the default, the method will block until locks on *all* the
identifiers have been acquired.
If blocking is `False`, acquisition may not block, and success will be
indicated by the returned object: `True` if *all* lock identifiers were
acquired and `False` if any of the lock identifiers could not be acquired.
``alock.release()``
Release the advisory locks represented by the ``alock`` object. If the lock
has not been acquired, a `RuntimeError` will be raised.
``alock.locked()``
Returns a boolean describing whether the locks are held or not. This will
return `False` if the lock connection has been closed.
``alock.__enter__()``
Alias to ``acquire``; context manager protocol. Always blocking.
``alock.__exit__(typ, val, tb)``
Alias to ``release``; context manager protocol.
Commands
********
This chapter discusses the usage of the available console scripts.
postgresql.bin.pg_python
========================
The ``pg_python`` command provides a simple way to write Python scripts against a
single target database. It acts like the regular Python console command, but
takes standard PostgreSQL options as well to specify the client parameters
to make establish connection with. The Python environment is then augmented
with the following built-ins:
``db``
The PG-API connection object.
``xact``
``db.xact``, the transaction creator.
``settings``
``db.settings``
``prepare``
``db.prepare``, the statement creator.
``proc``
``db.proc``
``do``
``db.do``, execute a single DO statement.
``sqlexec``
``db.execute``, execute multiple SQL statements (``None`` is always returned)
pg_python Usage
---------------
Usage: postgresql.bin.pg_python [connection options] [script] ...
Options:
--unix=UNIX path to filesystem socket
--ssl-mode=SSLMODE SSL requirement for connectivity: require, prefer,
allow, disable
-s SETTINGS, --setting=SETTINGS
run-time parameters to set upon connecting
-I PQ_IRI, --iri=PQ_IRI
database locator string
[pq://user:password@host:port/database?setting=value]
-h HOST, --host=HOST database server host
-p PORT, --port=PORT database server port
-U USER, --username=USER
user name to connect as
-W, --password prompt for password
-d DATABASE, --database=DATABASE
database's name
--pq-trace=PQ_TRACE trace PQ protocol transmissions
-C PYTHON_CONTEXT, --context=PYTHON_CONTEXT
Python context code to run[file://,module:,<code>]
-m PYTHON_MAIN Python module to run as script(__main__)
-c PYTHON_MAIN Python expression to run(__main__)
--version show program's version number and exit
--help show this help message and exit
Interactive Console Backslash Commands
--------------------------------------
Inspired by ``psql``::
>>> \?
Backslash Commands:
\? Show this help message.
\E Edit a file or a temporary script.
\e Edit and Execute the file directly in the context.
\i Execute a Python script within the interpreter's context.
\set Configure environment variables. \set without arguments to show all
\x Execute the Python command within this process.
pg_python Examples
------------------
Module execution taking advantage of the new built-ins::
$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit "prepare('SELECT 1').first()"
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 1.35 msec per loop
$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit -s "ps=prepare('SELECT 1')" "ps.first()"
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 442 usec per loop
Simple interactive usage::
$ python3 -m postgresql.bin.pg_python -h localhost -W
Password for pg_python[pq://jwp@localhost:5432]:
>>> ps = prepare('select 1')
>>> ps.first()
1
>>> c = ps()
>>> c.read()
[(1,)]
>>> ps.close()
>>> import sys
>>> sys.exit(0)
postgresql.bin.pg_dotconf
=========================
pg_dotconf is used to modify a PostgreSQL cluster's configuration file.
It provides a means to apply settings specified from the command line and from a
file referenced using the ``-f`` option.
.. warning::
``include`` directives in configuration files are *completely* ignored. If
modification of an included file is desired, the command must be applied to
that specific file.
pg_dotconf Usage
----------------
Usage: postgresql.bin.pg_dotconf [--stdout] [-f filepath] postgresql.conf ([param=val]|[param])*
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-f SETTINGS, --file=SETTINGS
A file of settings to *apply* to the given
"postgresql.conf"
--stdout Redirect the product to standard output instead of
writing back to the "postgresql.conf" file
Examples
--------
Modifying a simple configuration file::
$ echo "setting = value" >pg.conf
# change 'setting'
$ python3 -m postgresql.bin.pg_dotconf pg.conf setting=newvalue
$ cat pg.conf
setting = 'newvalue'
# new settings are appended to the file
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting=value
$ cat pg.conf
setting = 'newvalue'
another_setting = 'value'
# comment a setting
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting
$ cat pg.conf
setting = 'newvalue'
#another_setting = 'value'
When a setting is given on the command line, it must been seen as one argument
to the command, so it's *very* important to avoid invocations like::
$ python3 -m postgresql.bin.pg_dotconf pg.conf setting = value
ERROR: invalid setting, '=' after 'setting'
HINT: Settings must take the form 'setting=value' or 'setting_name_to_comment'. Settings must also be received as a single argument.
Changes in v1.0
===============
1.0.4 in development
--------------------
* Alter how changes are represented in documentation to simplify merging.
1.0.3 released on 2011-09-24
----------------------------
* Use raise x from y to generalize exceptions. (Elvis Pranskevichus)
* Alter postgresql.string.quote_ident to always quote. (Elvis Pranskevichus)
* Add postgresql.string.quote_ident_if_necessary (Modification of Elvis Pranskevichus' patch)
* Many postgresql.string bug fixes (Elvis Pranskevichus)
* Correct ResourceWarnings improving Python 3.2 support. (jwp)
* Add test command to setup.py (Elvis Pranskevichus)
1.0.2 released on 2010-09-18
----------------------------
* Add support for DOMAINs in registered composites. (Elvis Pranskevichus)
* Properly raise StopIteration in Cursor.__next__. (Elvis Pranskevichus)
* Add Cluster Management documentation.
* Release savepoints after rolling them back.
* Fix Startup() usage for Python 3.2.
* Emit deprecation warning when 'gid' is given to xact().
* Compensate for Python3.2's ElementTree API changes.
1.0.1 released on 2010-04-24
----------------------------
* Fix unpacking of array NULLs. (Elvis Pranskevichus)
* Fix .first()'s handling of counts and commands.
Bad logic caused zero-counts to return the command tag.
* Don't interrupt and close a temporal connection if it's not open.
* Use the Driver's typio attribute for TypeIO overrides. (Elvis Pranskevichus)
1.0 released on 2010-03-27
--------------------------
* **DEPRECATION**: Removed 2PC support documentation.
* **DEPRECATION**: Removed pg_python and pg_dotconf 'scripts'.
They are still accessible by python3 -m postgresql.bin.pg_*
* Add support for binary hstore.
* Add support for user service files.
* Implement a Copy manager for direct connection-to-connection COPY operations.
* Added db.do() method for DO-statement support(convenience method).
* Set the default client_min_messages level to WARNING.
NOTICEs are often not desired by programmers, and py-postgresql's
high verbosity further irritates that case.
* Added postgresql.project module to provide project information.
Project name, author, version, etc.
* Increased default recvsize and chunksize for improved performance.
* 'D' messages are special cased as builtins.tuples instead of
protocol.element3.Tuple
* Alter Statement.chunks() to return chunks of builtins.tuple. Being
an interface intended for speed, types.Row() impedes its performance.
* Fix handling of infinity values with timestamptz, timestamp, and date.
[Bug reported by Axel Rau.]
* Correct representation of PostgreSQL ARRAYs by properly recording
lowerbounds and upperbounds. Internally, sub-ARRAYs have their own
element lists.
* Implement a NotificationManager for managing the NOTIFYs received
by a connection. The class can manage NOTIFYs from multiple
connections, whereas the db.wait() method is tailored for single targets.
* Implement an ALock class for managing advisory locks using the
threading.Lock APIs. [Feedback from Valentine Gogichashvili]
* Implement reference symbols. Allow libraries to define symbols that
are used to create queries that inherit the original symbol's type and
execution method. ``db.prepare(db.prepare(...).first())``
* Fix handling of unix domain sockets by pg.open and driver.connect.
[Reported by twitter.com/rintavarustus]
* Fix typo/dropped parts of a raise LoadError in .lib.
[Reported by Vlad Pranskevichus]
* Fix db.tracer and pg_python's --pq-trace=
* Fix count return from .first() method. Failed to provide an empty
tuple for the rformats of the bind statement.
[Reported by dou dou]
Changes in v1.1
===============
1.1.0
-----
* Remove two-phase commit interfaces per deprecation in v1.0.
For proper two phase commit use, a lock manager must be employed that
the implementation did nothing to accommodate for.
* Add support for unpacking anonymous records (Elvis)
* Support PostgreSQL 9.2 (Elvis)
* Python 3.3 Support (Elvis)
* Add column execution method. (jwp)
* Add one-shot statement interface. Connection.query.* (jwp)
* Modify the inet/cidr support by relying on the ipaddress module introduced in Python 3.3 (Google's ipaddr project)
The existing implementation relied on simple str() representation supported by the
socket module. Unfortunately, MS Windows' socket library does not appear to support the
necessary functionality, or Python's socket module does not expose it. ipaddress fixes
the problem.
.. note::
The `ipaddress` module is now required for local inet and cidr. While it is
of "preliminary" status, the ipaddr project has been around for some time and
well supported. ipaddress appears to be the safest way forward for native
network types.
Changes in v1.2
===============
1.2.2 released on 2020-09-22
----------------------------
* Correct broken Connection.proc.
* Correct IPv6 IRI host oversight.
* Document an ambiguity case of DB-API 2.0 connection creation and the workaround(unix vs host/port).
* (Pending, active in 1.3) DB-API 2.0 connect() failures caused an undesired exception chain; ClientCannotConnect is now raised.
* Minor maintenance on tests and support modules.
1.2.0 released on 2016-06-23
----------------------------
* PostgreSQL 9.3 compatibility fixes (Elvis)
* Python 3.5 compatibility fixes (Elvis)
* Add support for JSONB type (Elvis)
Client Parameters
*****************
.. warning:: **The interfaces dealing with optparse are subject to change in 1.0**.
There are various sources of parameters used by PostgreSQL client applications.
The `postgresql.clientparameters` module provides a means for collecting and
managing those parameters.
Connection creation interfaces in `postgresql.driver` are purposefully simple.
All parameters taken by those interfaces are keywords, and are taken
literally; if a parameter is not given, it will effectively be `None`.
libpq-based drivers tend differ as they inherit some default client parameters
from the environment. Doing this by default is undesirable as it can cause
trivial failures due to unexpected parameter inheritance. However, using these
parameters from the environment and other sources are simply expected in *some*
cases: `postgresql.open`, `postgresql.bin.pg_python`, and other high-level
utilities. The `postgresql.clientparameters` module provides a means to collect
them into one dictionary object for subsequent application to a connection
creation interface.
`postgresql.clientparameters` is primarily useful to script authors that want to
provide an interface consistent with PostgreSQL commands like ``psql``.
Collecting Parameters
=====================
The primary entry points in `postgresql.clientparameters` are
`postgresql.clientparameters.collect` and
`postgresql.clientparameters.resolve_password`.
For most purposes, ``collect`` will suffice. By default, it will prompt for the
password if instructed to(``-W``). Therefore, ``resolve_password`` need not be
used in most cases::
>>> import sys
>>> import postgresql.clientparameters as pg_param
>>> p = pg_param.DefaultParser()
>>> co, ca = p.parse_args(sys.argv[1:])
>>> params = pg_param.collect(parsed_options = co)
The `postgresql.clientparameters` module is executable, so you can see the
results of the above snippet by::
$ python -m postgresql.clientparameters -h localhost -U a_db_user -ssearch_path=public
{'host': 'localhost',
'password': None,
'port': 5432,
'settings': {'search_path': 'public'},
'user': 'a_db_user'}
`postgresql.clientparameters.collect`
--------------------------------------
Build a client parameter dictionary from the environment and parsed command
line options. The following is a list of keyword arguments that ``collect`` will
accept:
``parsed_options``
Options parsed by `postgresql.clientparameters.StandardParser` or
`postgresql.clientparameters.DefaultParser` instances.
``no_defaults``
When `True`, don't include defaults like ``pgpassfile`` and ``user``.
Defaults to `False`.
``environ``
Environment variables to extract client parameter variables from.
Defaults to `os.environ` and expects a `collections.Mapping` interface.
``environ_prefix``
Environment variable prefix to use. Defaults to "PG". This allows the
collection of non-standard environment variables whose keys are partially
consistent with the standard variants. e.g. "PG_SRC_USER", "PG_SRC_HOST",
etc.
``default_pg_sysconfdir``
The location of the pg_service.conf file. The ``PGSYSCONFDIR`` environment
variable will override this. When a default installation is present,
``PGINSTALLATION``, it should be set to this.
``pg_service_file``
Explicit location of the service file. This will override the "sysconfdir"
based path.
``prompt_title``
Descriptive title to use if a password prompt is needed. `None` to disable
password resolution entirely. Setting this to `None` will also disable
pgpassfile lookups, so it is necessary that further processing occurs when
this is `None`.
``parameters``
Base client parameters to use. These are set after the *defaults* are
collected. (The defaults that can be disabled by ``no_defaults``).
If ``prompt_title`` is not set to `None`, it will prompt for the password when
instructed to do by the ``prompt_password`` key in the parameters::
>>> import postgresql.clientparameters as pg_param
>>> p = pg_param.collect(prompt_title = 'my_prompt!', parameters = {'prompt_password':True})
Password for my_prompt![pq://jwp@localhost:5432]:
>>> p
{'host': 'localhost', 'user': 'jwp', 'password': 'secret', 'port': 5432}
If `None`, it will leave the necessary password resolution information in the
parameters dictionary for ``resolve_password``::
>>> p = pg_param.collect(prompt_title = None, parameters = {'prompt_password':True})
>>> p
{'pgpassfile': '/Users/jwp/.pgpass', 'prompt_password': True, 'host': 'localhost', 'user': 'jwp', 'port': 5432}
Of course, ``'prompt_password'`` is normally specified when ``parsed_options``
received a ``-W`` option from the command line::
>>> op = pg_param.DefaultParser()
>>> co, ca = op.parse_args(['-W'])
>>> p = pg_param.collect(parsed_options = co)
>>> p=pg_param.collect(parsed_options = co)
Password for [pq://jwp@localhost:5432]:
>>> p
{'host': 'localhost', 'user': 'jwp', 'password': 'secret', 'port': 5432}
>>>
`postgresql.clientparameters.resolve_password`
----------------------------------------------
Resolve the password for the given client parameters dictionary returned by
``collect``. By default, this function need not be used as ``collect`` will
resolve the password by default. `resolve_password` accepts the following
arguments:
``parameters``
First positional argument. Normalized client parameters dictionary to update
in-place with the resolved password. If the 'prompt_password' key is in
``parameters``, it will prompt regardless(normally comes from ``-W``).
``getpass``
Function to call to prompt for the password. Defaults to `getpass.getpass`.
``prompt_title``
Additional title to use if a prompt is requested. This can also be specified
in the ``parameters`` as the ``prompt_title`` key. This *augments* the IRI
display on the prompt. Defaults to an empty string, ``''``.
The resolution process is effected by the contents of the given ``parameters``.
Notable keywords:
``prompt_password``
If present in the given parameters, the user will be prompted for the using
the given ``getpass`` function. This disables the password file lookup
process.
``prompt_title``
This states a default prompt title to use. If the ``prompt_title`` keyword
argument is given to ``resolve_password``, this will not be used.
``pgpassfile``
The PostgreSQL password file to lookup the password in. If the ``password``
parameter is present, this will not be used.
When resolution occurs, the ``prompt_password``, ``prompt_title``, and
``pgpassfile`` keys are *removed* from the given parameters dictionary::
>>> p=pg_param.collect(prompt_title = None)
>>> p
{'pgpassfile': '/Users/jwp/.pgpass', 'host': 'localhost', 'user': 'jwp', 'port': 5432}
>>> pg_param.resolve_password(p)
>>> p
{'host': 'localhost', 'password': 'secret', 'user': 'jwp', 'port': 5432}
Defaults
========
The following is a list of default parameters provided by ``collect`` and the
sources of their values:
==================== ===================================================================
Key Value
==================== ===================================================================
``'user'`` `getpass.getuser()` or ``'postgres'``
``'host'`` `postgresql.clientparameters.default_host` (``'localhost'``)
``'port'`` `postgresql.clientparameters.default_port` (``5432``)
``'pgpassfile'`` ``"$HOME/.pgpassfile"`` or ``[PGDATA]`` + ``'pgpass.conf'`` (Win32)
``'sslcrtfile'`` ``[PGDATA]`` + ``'postgresql.crt'``
``'sslkeyfile'`` ``[PGDATA]`` + ``'postgresql.key'``
``'sslrootcrtfile'`` ``[PGDATA]`` + ``'root.crt'``
``'sslrootcrlfile'`` ``[PGDATA]`` + ``'root.crl'``
==================== ===================================================================
``[PGDATA]`` referenced in the above table is a directory whose path is platform
dependent. On most systems, it is ``"$HOME/.postgresql"``, but on Windows based
systems it is ``"%APPDATA%\postgresql"``
.. note::
[PGDATA] is *not* an environment variable.
.. _pg_envvars:
PostgreSQL Environment Variables
================================
The following is a list of environment variables that will be collected by the
`postgresql.clientparameter.collect` function using "PG" as the
``environ_prefix`` and the keyword that it will be mapped to:
===================== ======================================
Environment Variable Keyword
===================== ======================================
``PGUSER`` ``'user'``
``PGDATABASE`` ``'database'``
``PGHOST`` ``'host'``
``PGPORT`` ``'port'``
``PGPASSWORD`` ``'password'``
``PGSSLMODE`` ``'sslmode'``
``PGSSLKEY`` ``'sslkey'``
``PGCONNECT_TIMEOUT`` ``'connect_timeout'``
``PGREALM`` ``'kerberos4_realm'``
``PGKRBSRVNAME`` ``'kerberos5_service'``
``PGPASSFILE`` ``'pgpassfile'``
``PGTZ`` ``'settings' = {'timezone': }``
``PGDATESTYLE`` ``'settings' = {'datestyle': }``
``PGCLIENTENCODING`` ``'settings' = {'client_encoding': }``
``PGGEQO`` ``'settings' = {'geqo': }``
===================== ======================================
.. _pg_passfile:
PostgreSQL Password File
========================
The password file is a simple newline separated list of ``:`` separated fields. It
is located at ``$HOME/.pgpass`` for most systems and at
``%APPDATA%\postgresql\pgpass.conf`` for Windows based systems. However, the
``PGPASSFILE`` environment variable may be used to override that location.
The lines in the file must be in the following form::
hostname:port:database:username:password
A single asterisk, ``*``, may be used to indicate that any value will match the
field. However, this only effects fields other than ``password``.
See http://www.postgresql.org/docs/current/static/libpq-pgpass.html for more
details.
Client parameters produced by ``collect`` that have not been processed
by ``resolve_password`` will include a ``'pgpassfile'`` key. This is the value
that ``resolve_password`` will use to locate the pgpassfile to interrogate if a
password key is not present and it is not instructed to prompt for a password.
.. warning::
Connection creation interfaces will *not* resolve ``'pgpassfile'``, so it is
important that the parameters produced by ``collect()`` are properly processed
before an attempt is made to establish a connection.
.. _cluster_management:
******************
Cluster Management
******************
py-postgresql provides cluster management tools in order to give the user
fine-grained control over a PostgreSQL cluster and access to information about an
installation of PostgreSQL.
.. _installation:
Installations
=============
`postgresql.installation.Installation` objects are primarily used to
access PostgreSQL installation information. Normally, they are created using a
dictionary constructed from the output of the pg_config_ executable::
from postgresql.installation import Installation, pg_config_dictionary
pg_install = Installation(pg_config_dictionary('/usr/local/pgsql/bin/pg_config'))
The extraction of pg_config_ information is isolated from Installation
instantiation in order to allow Installations to be created from arbitrary
dictionaries. This can be useful in cases where the installation layout is
inconsistent with the standard PostgreSQL installation layout, or if a faux
Installation needs to be created for testing purposes.
Installation Interface Points
-----------------------------
``Installation(info)``
Instantiate an Installation using the given information. Normally, this
information is extracted from a pg_config_ executable using
`postgresql.installation.pg_config_dictionary`::
info = pg_config_dictionary('/usr/local/pgsql/bin/pg_config')
pg_install = Installation(info)
``Installation.version``
The installation's version string::
pg_install.version
'PostgreSQL 9.0devel'
``Installation.version_info``
A tuple containing the version's ``(major, minor, patch, state, level)``.
Where ``major``, ``minor``, ``patch``, and ``level`` are `int` objects, and
``state`` is a `str` object::
pg_install.version_info
(9, 0, 0, 'devel', 0)
``Installation.ssl``
A `bool` indicating whether or not the installation has SSL support.
``Installation.configure_options``
The options given to the ``configure`` script that built the installation. The
options are represented using a dictionary object whose keys are normalized
long option names, and whose values are the option's argument. If the option
takes no argument, `True` will be used as the value.
The normalization of the long option names consists of removing the preceding
dashes, lowering the string, and replacing any dashes with underscores. For
instance, ``--enable-debug`` will be ``enable_debug``::
pg_install.configure_options
{'enable_debug': True, 'with_libxml': True,
'enable_cassert': True, 'with_libedit_preferred': True,
'prefix': '/src/build/pg90', 'with_openssl': True,
'enable_integer_datetimes': True, 'enable_depend': True}
``Installation.paths``
The paths of the installation as a dictionary where the keys are the path
identifiers and the values are the absolute file system paths. For instance,
``'bindir'`` is associated with ``$PREFIX/bin``, ``'libdir'`` is associated
with ``$PREFIX/lib``, etc. The paths included in this dictionary are
listed on the class' attributes: `Installation.pg_directories` and
`Installation.pg_executables`.
The keys that point to installation directories are: ``bindir``, ``docdir``,
``includedir``, ``pkgincludedir``, ``includedir_server``, ``libdir``,
``pkglibdir``, ``localedir``, ``mandir``, ``sharedir``, and ``sysconfdir``.
The keys that point to installation executables are: ``pg_config``, ``psql``,
``initdb``, ``pg_resetxlog``, ``pg_controldata``, ``clusterdb``, ``pg_ctl``,
``pg_dump``, ``pg_dumpall``, ``postgres``, ``postmaster``, ``reindexdb``,
``vacuumdb``, ``ipcclean``, ``createdb``, ``ecpg``, ``createuser``,
``createlang``, ``droplang``, ``dropuser``, and ``pg_restore``.
.. note:: If the executable does not exist, the value will be `None` instead
of an absoluate path.
To get the path to the psql_ executable::
from postgresql.installation import Installation
pg_install = Installation('/usr/local/pgsql/bin/pg_config')
psql_path = pg_install.paths['psql']
Clusters
========
`postgresql.cluster.Cluster` is the class used to manage a PostgreSQL
cluster--a data directory created by initdb_. A Cluster represents a data
directory with respect to a given installation of PostgreSQL, so
creating a `postgresql.cluster.Cluster` object requires a
`postgresql.installation.Installation`, and a
file system path to the data directory.
In part, a `postgresql.cluster.Cluster` is the Python programmer's variant of
the pg_ctl_ command. However, it goes beyond the basic process control
functionality and extends into initialization and configuration as well.
A Cluster manages the server process using the `subprocess` module and
signals. The `subprocess.Popen` object, ``Cluster.daemon_process``, is
retained when the Cluster starts the server process itself. This gives
the Cluster access to the result code of server process when it exits, and the
ability to redirect stderr and stdout to a parameterized file object using
subprocess features.
Despite its use of `subprocess`, Clusters can control a server process
that was *not* started by the Cluster's ``start`` method.
Initializing Clusters
---------------------
`postgresql.cluster.Cluster` provides a method for initializing a
`Cluster`'s data directory, ``init``. This method provides a Python interface to
the PostgreSQL initdb_ command.
``init`` is a regular method and accepts a few keyword parameters. Normally,
parameters are directly mapped to initdb_ command options. However, ``password``
makes use of initdb's capability to read the superuser's password from a file.
To do this, a temporary file is allocated internally by the method::
from postgresql.installation import Installation, pg_config_dictionary
from postgresql.cluster import Cluster
pg_install = Installation(pg_config_dictionary('/usr/local/pgsql/bin/pg_config'))
pg_cluster = Cluster(pg_install, 'pg_data')
pg_cluster.init(user = 'pg', password = 'secret', encoding = 'utf-8')
The init method will block until the initdb command is complete. Once
initialized, the Cluster may be configured.
Configuring Clusters
--------------------
A Cluster's `configuration file`_ can be manipulated using the
`Cluster.settings` mapping. The mapping's methods will always access the
configuration file, so it may be desirable to cache repeat reads. Also, if
multiple settings are being applied, using the ``update()`` method may be
important to avoid writing the entire file multiple times::
pg_cluster.settings.update({'listen_addresses' : 'localhost', 'port' : '6543'})
Similarly, to avoid opening and reading the entire file multiple times,
`Cluster.settings.getset` should be used to retrieve multiple settings::
d = pg_cluster.settings.getset(set(('listen_addresses', 'port')))
d
{'listen_addresses' : 'localhost', 'port' : '6543'}
Values contained in ``settings`` are always Python strings::
assert pg_cluster.settings['max_connections'].__class__ is str
The ``postgresql.conf`` file is only one part of the server configuration.
Structured access and manipulation of the pg_hba_ file is not
supported. Clusters only provide the file path to the pg_hba_ file::
hba = open(pg_cluster.hba_file)
If the configuration of the Cluster is altered while the server process is
running, it may be necessary to signal the process that configuration changes
have been made. This signal can be sent using the ``Cluster.reload()`` method.
``Cluster.reload()`` will send a SIGHUP signal to the server process. However,
not all changes to configuration settings can go into effect after calling
``Cluster.reload()``. In those cases, the server process will need to be
shutdown and started again.
Controlling Clusters
--------------------
The server process of a Cluster object can be controlled with the ``start()``,
``stop()``, ``shutdown()``, ``kill()``, and ``restart()`` methods.
These methods start the server process, signal the server process, or, in the
case of restart, a combination of the two.
When a Cluster starts the server process, it's ran as a subprocess. Therefore,
if the current process exits, the server process will exit as well. ``start()``
does *not* automatically daemonize the server process.
.. note:: Under Microsoft Windows, above does not hold true. The server process
will continue running despite the exit of the parent process.
To terminate a server process, one of these three methods should be called:
``stop``, ``shutdown``, or ``kill``. ``stop`` is a graceful shutdown and will
*wait for all clients to disconnect* before shutting down. ``shutdown`` will
close any open connections and safely shutdown the server process.
``kill`` will immediately terminate the server process leading to recovery upon
starting the server process again.
.. note:: Using ``kill`` may cause shared memory to be leaked.
Normally, `Cluster.shutdown` is the appropriate way to terminate a server
process.
Cluster Interface Points
------------------------
Methods and properties available on `postgresql.cluster.Cluster` instances:
``Cluster(installation, data_directory)``
Create a `postgresql.cluster.Cluster` object for the specified
`postgresql.installation.Installation`, and ``data_directory``.
The ``data_directory`` must be an absoluate file system path. The directory
does *not* need to exist. The ``init()`` method may later be used to create
the cluster.
``Cluster.installation``
The Cluster's `postgresql.installation.Installation` instance.
``Cluster.data_directory``
The absolute path to the PostgreSQL data directory.
This directory may not exist.
``Cluster.init([encoding = None[, user = None[, password = None]]])``
Run the `initdb`_ executable of the configured installation to initialize the
cluster at the configured data directory, `Cluster.data_directory`.
``encoding`` is mapped to ``-E``, the default database encoding. By default,
the encoding is determined from the environment's locale.
``user`` is mapped to ``-U``, the database superuser name. By default, the
current user's name.
``password`` is ultimately mapped to ``--pwfile``. The argument given to the
long option is actually a path to the temporary file that holds the given
password.
Raises `postgresql.cluster.InitDBError` when initdb_ returns a non-zero result
code.
Raises `postgresql.cluster.ClusterInitializationError` when there is no
initdb_ in the Installation.
``Cluster.initialized()``
Whether or not the data directory exists, *and* if it looks like a PostgreSQL
data directory. Meaning, the directory must contain a ``postgresql.conf`` file
and a ``base`` directory.
``Cluster.drop()``
Shutdown the Cluster's server process and completely remove the
`Cluster.data_directory` from the file system.
``Cluster.pid()``
The server's process identifier as a Python `int`. `None` if there is no
server process running.
This is a method rather than a property as it may read the PID from a file
in cases where the server process was not started by the Cluster.
``Cluster.start([logfile = None[, settings = None]])``
Start the PostgreSQL server process for the Cluster if it is not
already running. This will execute postgres_ as a subprocess.
If ``logfile``, an opened and writable file object, is given, stderr and
stdout will be redirected to that file. By default, both stderr and stdout are
closed.
If ``settings`` is given, the mapping or sequence of pairs will be used as
long options to the subprocess. For each item, ``--{key}={value}`` will be
given as an argument to the subprocess.
``Cluster.running()``
Whether or not the cluster's server process is running. Returns `True` or
`False`. Even if `True` is returned, it does *not* mean that the server
process is ready to accept connections.
``Cluster.ready_for_connections()``
Whether or not the Cluster is ready to accept connections. Usually called
after `Cluster.start`.
Returns `True` when the Cluster can accept connections, `False` when it
cannot, and `None` if the Cluster's server process is not running at all.
``Cluster.wait_until_started([timeout = 10[, delay = 0.05]])``
Blocks the process until the cluster is identified as being ready for
connections. Usually called after ``Cluster.start()``.
Raises `postgresql.cluster.ClusterNotRunningError` if the server process is
not running at all.
Raises `postgresql.cluster.ClusterTimeoutError` if
`Cluster.ready_for_connections()` does not return `True` within the given
`timeout` period.
Raises `postgresql.cluster.ClusterStartupError` if the server process
terminates while polling for readiness.
``timeout`` and ``delay`` are both in seconds. Where ``timeout`` is the
maximum time to wait for the Cluster to be ready for connections, and
``delay`` is the time to sleep between calls to
`Cluster.ready_for_connections()`.
``Cluster.stop()``
Signal the cluster to shutdown when possible. The *server* will wait for all
clients to disconnect before shutting down.
``Cluster.shutdown()``
Signal the cluster to shutdown immediately. Any open client connections will
be closed.
``Cluster.kill()``
Signal the absolute destruction of the server process(SIGKILL).
*This will require recovery when the cluster is started again.*
*Shared memory may be leaked.*
``Cluster.wait_until_stopped([timeout = 10[, delay = 0.05]])``
Blocks the process until the cluster is identified as being shutdown. Usually
called after `Cluster.stop` or `Cluster.shutdown`.
Raises `postgresql.cluster.ClusterTimeoutError` if
`Cluster.ready_for_connections` does not return `None` within the given
`timeout` period.
``Cluster.reload()``
Signal the server that it should reload its configuration files(SIGHUP).
Usually called after manipulating `Cluster.settings` or modifying the
contents of `Cluster.hba_file`.
``Cluster.restart([logfile = None[, settings = None[, timeout = 10]]])``
Stop the server process, wait until it is stopped, start the server
process, and wait until it has started.
.. note:: This calls ``Cluster.stop()``, so it will wait until clients
disconnect before starting up again.
The ``logfile`` and ``settings`` parameters will be given to `Cluster.start`.
``timeout`` will be given to `Cluster.wait_until_stopped` and
`Cluster.wait_until_started`.
``Cluster.settings``
A `collections.Mapping` interface to the ``postgresql.conf`` file of the
cluster.
A notable extension to the mapping interface is the ``getset`` method. This
method will return a dictionary object containing the settings whose names
were contained in the `set` object given to the method.
This method should be used when multiple settings need to be retrieved from
the configuration file.
``Cluster.hba_file``
The path to the cluster's pg_hba_ file. This property respects the HBA file
location setting in ``postgresql.conf``. Usually, ``$PGDATA/pg_hba.conf``.
``Cluster.daemon_path``
The path to the executable to use to start the server process.
``Cluster.daemon_process``
The `subprocess.Popen` instance of the server process. `None` if the server
process was not started or was not started using the Cluster object.
.. _pg_hba: http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html
.. _pg_config: http://www.postgresql.org/docs/current/static/app-pgconfig.html
.. _initdb: http://www.postgresql.org/docs/current/static/app-initdb.html
.. _psql: http://www.postgresql.org/docs/current/static/app-psql.html
.. _postgres: http://www.postgresql.org/docs/current/static/app-postgres.html
.. _pg_ctl: http://www.postgresql.org/docs/current/static/app-pg-ctl.html
.. _configuration file: http://www.postgresql.org/docs/current/static/runtime-config.html
.. _pg_copyman:
***************
Copy Management
***************
The `postgresql.copyman` module provides a way to quickly move COPY data coming
from one connection to many connections. Alternatively, it can be sourced
by arbitrary iterators and target arbitrary callables.
Statement execution methods offer a way for running COPY operations
with iterators, but the cost of allocating objects for each row is too
significant for transferring gigabytes of COPY data from one connection to
another. The interfaces available on statement objects are primarily intended to
be used when transferring COPY data to and from arbitrary Python
objects.
Direct connection-to-connection COPY operations can be performed using the
high-level `postgresql.copyman.transfer` function::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> total_rows, total_bytes = copyman.transfer(send_stmt, receive_stmt)
However, if more control is needed, the `postgresql.copyman.CopyManager` class
should be used directly.
Copy Managers
=============
The `postgresql.copyman.CopyManager` class manages the Producer and the
Receivers involved in a COPY operation. Normally,
`postgresql.copyman.StatementProducer` and
`postgresql.copyman.StatementReceiver` instances. Naturally, a Producer is the
object that produces the COPY data to be given to the Manager's Receivers.
Using a Manager directly means that there is a need for more control over
the operation. The Manager is both a context manager and an iterator. The
context manager interfaces handle initialization and finalization of the COPY
state, and the iterator provides an event loop emitting information about the
amount of COPY data transferred this cycle. Normal usage takes the form::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
As an alternative to a for-loop inside a with-statement block, the `run` method
can be called to perform the operation::
>>> with source.xact(), destination.xact():
... copyman.CopyManager(producer, receiver).run()
However, there is little benefit beyond using the high-level
`postgresql.copyman.transfer` function.
Manager Interface Points
------------------------
Primarily, the `postgresql.copyman.CopyManager` provides a context manager and
an iterator for controlling the COPY operation.
``CopyManager.run()``
Perform the entire COPY operation.
``CopyManager.__enter__()``
Start the COPY operation. Connections taking part in the COPY should **not**
be used until ``__exit__`` is ran.
``CopyManager.__exit__(typ, val, tb)``
Finish the COPY operation. Fails in the case of an incomplete
COPY, or an untrapped exception. Either returns `None` or raises the generalized
exception, `postgresql.copyman.CopyFail`.
``CopyManager.__iter__()``
Returns the CopyManager instance.
``CopyManager.__next__()``
Transfer the next chunk of COPY data to the receivers. Yields a tuple
consisting of the number of messages and bytes transferred,
``(num_messages, num_bytes)``. Raises `StopIteration` when complete.
Raises `postgresql.copyman.ReceiverFault` when a Receiver raises an
exception.
Raises `postgresql.copyman.ProducerFault` when the Producer raises an
exception. The original exception is available via the exception's
``__context__`` attribute.
``CopyManager.reconcile(faulted_receiver)``
Reconcile a faulted receiver. When a receiver faults, it will no longer
be in the set of Receivers. This method is used to signal to the manager that the
problem has been corrected, and the receiver is again ready to receive.
``CopyManager.receivers``
The `builtins.set` of Receivers involved in the COPY operation.
``CopyManager.producer``
The Producer emitting the data to be given to the Receivers.
Faults
======
The CopyManager generalizes any exceptions that occur during transfer. While
inside the context manager, `postgresql.copyman.Fault` may be raised if a
Receiver or a Producer raises an exception. A `postgresql.copyman.ProducerFault`
in the case of the Producer, and `postgresql.copyman.ReceiverFault` in the case
of the Receivers.
.. note::
Faults are only raised by `postgresql.copyman.CopyManager.__next__`. The
``run()`` method will only raise `postgresql.copyman.CopyFail`.
Receiver Faults
---------------
The Manager assumes the Fault is fatal to a Receiver, and immediately removes
it from the set of target receivers. Additionally, if the Fault exception goes
untrapped, the copy will ultimately fail.
The Fault exception references the Manager that raised the exception, and the
actual exceptions that occurred associated with the Receiver that caused them.
In order to identify the exception that caused a Fault, the ``faults`` attribute
on the `postgresql.copyman.ReceiverFault` must be referenced::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... while copy.receivers:
... try:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
... break
... except copyman.ReceiverFault as cf:
... # Access the original exception using the receiver as the key.
... original_exception = cf.faults[receiver]
... if unknown_failure(original_exception):
... ...
... raise
ReceiverFault Properties
~~~~~~~~~~~~~~~~~~~~~~~~
The following attributes exist on `postgresql.copyman.ReceiverFault` instances:
``ReceiverFault.manager``
The subject `postgresql.copyman.CopyManager` instance.
``ReceiverFault.faults``
A dictionary mapping the Receiver to the exception raised by that Receiver.
Reconciliation
~~~~~~~~~~~~~~
When a `postgresql.copyman.ReceiverFault` is raised, the Manager immediately
removes the Receiver so that the COPY operation can continue. Continuation of
the COPY can occur by trapping the exception and continuing the iteration of the
Manager. However, if the fault is recoverable, the
`postgresql.copyman.CopyManager.reconcile` method must be used to reintroduce the
Receiver into the Manager's set. Faults must be trapped from within the
Manager's context::
>>> import socket
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... while copy.receivers:
... try:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
... except copyman.ReceiverFault as cf:
... if isinstance(cf.faults[receiver], socket.timeout):
... copy.reconcile(receiver)
... else:
... raise
Recovering from Faults does add significant complexity to a COPY operation,
so, often, it's best to avoid conditions in which reconciliable Faults may
occur.
Producer Faults
---------------
Producer faults are normally fatal to the COPY operation and should rarely be
trapped. However, the Manager makes no state changes when a Producer faults,
so, unlike Receiver Faults, no reconciliation process is necessary; rather,
if it's safe to continue, the Manager's iterator should continue to be
processed.
ProducerFault Properties
~~~~~~~~~~~~~~~~~~~~~~~~
The following attributes exist on `postgresql.copyman.ProducerFault` instances:
``ReceiverFault.manager``
The subject `postgresql.copyman.CopyManager`.
``ReceiverFault.__context__``
The original exception raised by the Producer.
Failures
========
When a COPY operation is aborted, either by an exception or by the iterator
being broken, a `postgresql.copyman.CopyFail` exception will be raised by the
Manager's ``__exit__()`` method. The `postgresql.copyman.CopyFail` exception
offers to record any exceptions that occur during the exit of the context
managers of the Producer and the Receivers.
CopyFail Properties
-------------------
The following properties exist on `postgresql.copyman.CopyFail` exceptions:
``CopyFail.manager``
The Manager whose COPY operation failed.
``CopyFail.receiver_faults``
A dictionary mapping a `postgresql.copyman.Receiver` to the exception raised
by that Receiver's ``__exit__``. `None` if no exceptions were raised by the
Receivers.
``CopyFail.producer_fault``
The exception Raised by the `postgresql.copyman.Producer`. `None` if none.
Producers
=========
The following Producers are available:
``postgresql.copyman.StatementProducer(postgresql.api.Statement)``
Given a Statement producing COPY data, construct a Producer.
``postgresql.copyman.IteratorProducer(collections.Iterator)``
Given an Iterator producing *chunks* of COPY lines, construct a Producer to
manage the data coming from the iterator.
Receivers
=========
``postgresql.copyman.StatementReceiver(postgresql.api.Statement)``
Given a Statement producing COPY data, construct a Producer.
``postgresql.copyman.CallReceiver(callable)``
Given a callable, construct a Receiver that will transmit COPY data in chunks
of lines. That is, the callable will be given a list of COPY lines for each
transfer cycle.
Terminology
===========
The following terms are regularly used to describe the implementation and
processes of the `postgresql.copyman` module:
Manager
The object used to manage data coming from a Producer and being given to the
Receivers. It also manages the necessary initialization and finalization steps
required by those factors.
Producer
The object used to produce the COPY data to be given to the Receivers. The
source.
Receiver
An object that consumes COPY data. A target.
Fault
Specifically, `postgresql.copyman.Fault` exceptions. A Fault is raised
when a Receiver or a Producer raises an exception during the COPY operation.
Reconciliation
Generally, the steps performed by the "reconcile" method on
`postgresql.copyman.CopyManager` instances. More precisely, the
necessary steps for a Receiver's reintroduction into the COPY operation after
a Fault.
Failed Copy
A failed copy is an aborted COPY operation. This occurs in situations of
untrapped exceptions or an incomplete COPY. Specifically, the COPY will be
noted as failed in cases where the Manager's iterator is *not* ran until
exhaustion.
Realignment
The process of providing compensating data to the Receivers so that the
connection will be on a message boundary. Occurs when the COPY operation
is aborted.

Sorry, the diff of this file is too big to display

Gotchas
=======
It is recognized that decisions were made that may not always be ideal for a
given user. In order to highlight those potential issues and hopefully bring
some sense into a confusing situation, this document was drawn.
Non-English Locales
-------------------
Many non-english locales are not supported due to the localization of the severity field
in messages and errors sent to the client. Internally, py-postgresql uses this to allow
client side filtering of messages and to identify FATAL connection errors that allow the
client to recognize that it should be expecting the connection to terminate.
Thread Safety
-------------
py-postgresql connection operations are not thread safe.
`client_encoding` setting should be altered carefully
-----------------------------------------------------
`postgresql.driver`'s streaming cursor implementation reads a fixed set of rows
when it queries the server for more. In order to optimize some situations, the
driver will send a request for more data, but makes no attempt to wait and
process the data as it is not yet needed. When the user comes back to read more
data from the cursor, it will then look at this new data. The problem being, if
`client_encoding` was switched, it may use the wrong codec to transform the
wire data into higher level Python objects(str).
To avoid this problem from ever happening, set the `client_encoding` early.
Furthermore, it is probably best to never change the `client_encoding` as the
driver automatically makes the necessary transformation to Python strings.
The user and password is correct, but it does not work when using `postgresql.driver`
-------------------------------------------------------------------------------------
This issue likely comes from the possibility that the information sent to the
server early in the negotiation phase may not be in an encoding that is
consistent with the server's encoding.
One problem is that PostgreSQL does not provide the client with the server
encoding early enough in the negotiation phase, and, therefore, is unable to
process the password data in a way that is consistent with the server's
expectations.
Another problem is that PostgreSQL takes much of the data in the startup message
as-is, so a decision about the best way to encode parameters is difficult.
The easy way to avoid *most* issues with this problem is to initialize the
database in the `utf-8` encoding. The driver defaults the expected server
encoding to `utf-8`. However, this can be overridden by creating the `Connector`
with a `server_encoding` parameter. Setting `server_encoding` to the proper
value of the target server will allow the driver to properly encode *some* of
the parameters. Also, any GUC parameters passed via the `settings` parameter
should use typed objects when possible to hint that the server encoding should
not be used on that parameter(`bytes`, for instance).
Backslash characters are being treated literally
------------------------------------------------
The driver enables standard compliant strings. Stop using non-standard features.
;)
If support for non-standard strings was provided it would require to the
driver to provide subjective quote interfaces(eg, db.quote_literal). Doing so is
not desirable as it introduces difficulties for the driver *and* the user.
Types without binary support in the driver are unsupported in arrays and records
--------------------------------------------------------------------------------
When an array or composite type is identified, `postgresql.protocol.typio`
ultimately chooses the binary format for the transfer of the column or
parameter. When this is done, PostgreSQL will pack or expect *all* the values
in binary format as well. If that binary format is not supported and the type
is not an string, it will fail to unpack the row or pack the appropriate data for
the element or attribute.
In most cases issues related to this can be avoided with explicit casts to text.
NOTICEs, WARNINGs, and other messages are too verbose
-----------------------------------------------------
For many situations, the information provided with database messages is
far too verbose. However, considering that py-postgresql is a programmer's
library, the default of high verbosity is taken with the express purpose of
allowing the programmer to "adjust the volume" until appropriate.
By default, py-postgresql adjusts the ``client_min_messages`` to only emit
messages at the WARNING level or higher--ERRORs, FATALs, and PANICs.
This reduces the number of messages generated by most connections dramatically.
If further customization is needed, the :ref:`db_messages` section has
information on overriding the default action taken with database messages.
Strange TypeError using load_rows() or load_chunks()
----------------------------------------------------
When a prepared statement is directly executed using ``__call__()``, it can easily
validate that the appropriate number of parameters are given to the function.
When ``load_rows()`` or ``load_chunks()`` is used, any tuple in the
the entire sequence can cause this TypeError during the loading process::
TypeError: inconsistent items, N processors and M items in row
This exception is raised by a generic processing routine whose functionality
is abstract in nature, so the message is abstract as well. It essentially means
that a tuple in the sequence given to the loading method had too many or too few
items.
py-postgresql
=============
py-postgresql is a project dedicated to improving the Python client interfaces to PostgreSQL.
At its core, py-postgresql provides a PG-API, `postgresql.api`, and
DB-API 2.0 interface for using a PostgreSQL database.
Contents
--------
.. toctree::
:maxdepth: 2
admin
driver
copyman
notifyman
alock
cluster
lib
clientparameters
gotchas
Reference
---------
.. toctree::
:maxdepth: 2
bin
reference
Changes
-------
.. toctree::
:maxdepth: 1
changes-v1.2
changes-v1.1
changes-v1.0
Sample Code
-----------
Using `postgresql.driver`::
>>> import postgresql
>>> db = postgresql.open("pq://user:password@host/name_of_database")
>>> db.execute("CREATE TABLE emp (emp_name text PRIMARY KEY, emp_salary numeric)")
>>>
>>> # Create the statements.
>>> make_emp = db.prepare("INSERT INTO emp VALUES ($1, $2)")
>>> raise_emp = db.prepare("UPDATE emp SET emp_salary = emp_salary + $2 WHERE emp_name = $1")
>>> get_emp_with_salary_lt = db.prepare("SELECT emp_name FROM emp WHERE emp_salay < $1")
>>>
>>> # Create some employees, but do it in a transaction--all or nothing.
>>> with db.xact():
... make_emp("John Doe", "150,000")
... make_emp("Jane Doe", "150,000")
... make_emp("Andrew Doe", "55,000")
... make_emp("Susan Doe", "60,000")
>>>
>>> # Give some raises
>>> with db.xact():
... for row in get_emp_with_salary_lt("125,000"):
... print(row["emp_name"])
... raise_emp(row["emp_name"], "10,000")
Of course, if DB-API 2.0 is desired, the module is located at
`postgresql.driver.dbapi20`. DB-API extends PG-API, so the features
illustrated above are available on DB-API connections.
See :ref:`db_interface` for more information.
Categories and Libraries
************************
This chapter discusses the usage and implementation of connection categories and
libraries. Originally these features were written with general purpose use in mind;
however, it is recommended that these features **not** be used in applications.
They are primarily used internally by the the driver and may be removed in the future.
Libraries are a collection of SQL statements that can be bound to a
connection. Libraries are *normally* bound directly to the connection object as
an attribute using a name specified by the library.
Libraries provide a common way for SQL statements to be managed outside of the
code that uses them. When using ILFs, this increases the portability of the SQL
by keeping the statements isolated from the Python code in an accessible format
that can be easily used by other languages or systems --- An ILF parser can be
implemented within a few dozen lines using basic text tools.
SQL statements defined by a Library are identified by their Symbol. These
symbols are named and annotated in order to allow the user to define how a
statement is to be used. The user may state the default execution method of
the statement object, or whether the symbol is to be preloaded at bind
time--these properties are Symbol Annotations.
The purpose of libraries are to provide a means to manage statements on
disk and at runtime. ILFs provide a means to reference a collection
of statements on disk, and, when loaded, the symbol bindings provides means to
reference a statement already prepared for use on a given connection.
The `postgresql.lib` package-module provides fundamental classes for supporting
categories and libraries.
Writing Libraries
=================
ILF files are the recommended way to build a library. These files use the
naming convention "lib{NAME}.sql". The prefix and suffix are used describe the
purpose of the file and to provide a hint to editors that SQL highlighting
should be used. The format of an ILF takes the form::
<Preface>
[name:type:method]
<statement>
...
Where multiple symbols may be defined. The Preface that comes before the first
symbol is an arbitrary block of text that should be used to describe the library.
This block is free-form, and should be considered a good place for some
general documentation.
Symbols are named and described using the contents of section markers:
``('[' ... ']')``. Section markers have three components: the symbol name,
the symbol type and the symbol method. Each of these components are separated
using a single colon, ``:``. All components are optional except the Symbol name.
For example::
[get_user_info]
SELECT * FROM user WHERE user_id = $1
[get_user_info_v2::]
SELECT * FROM user WHERE user_id = $1
In the above example, ``get_user_info`` and ``get_user_info_v2`` are identical.
Empty components indicate the default effect.
The second component in the section identifier is the symbol type. All Symbol
types are listed in `Symbol Types`_. This can be
used to specify what the section's contents are or when to bind the
symbol::
[get_user_info:preload]
SELECT * FROM user WHERE user_id = $1
This provides the Binding with the knowledge that the statement should be
prepared when the Library is bound. Therefore, when this Symbol's statement
is used for the first time, it will have already been prepared.
Another type is the ``const`` Symbol type. This defines a data Symbol whose
*statement results* will be resolved when the Library is bound::
[user_type_ids:const]
SELECT user_type_id, user_type FROM user_types;
Constant Symbols cannot take parameters as they are data properties. The
*result* of the above query is set to the Bindings' ``user_type_ids``
attribute::
>>> db.lib.user_type_ids
<sequence of (user_type_id, user_type)>
Where ``lib`` in the above is a Binding of the Library containing the
``user_type_ids`` Symbol.
Finally, procedures can be bound as symbols using the ``proc`` type::
[remove_user:proc]
remove_user(bigint)
All procedures symbols are loaded when the Library is bound. Procedure symbols
are special because the execution method is effectively specified by the
procedure itself.
The third component is the symbol ``method``. This defines the execution method
of the statement and ultimately what is returned when the Symbol is called at
runtime. All the execution methods are listed in `Symbol Execution Methods`_.
The default execution method is the default execution method of
`postgresql.api.PreparedStatement` objects; return the entire result set in a
list object::
[get_numbers]
SELECT i FROM generate_series(0, 100-1) AS g(i);
When bound::
>>> db.lib.get_numbers() == [(x,) for x in range(100)]
True
The transformation of range in the above is necessary as statements
return a sequence of row objects by default.
For large result-sets, fetching all the rows would be taxing on a system's
memory. The ``rows`` and ``chunks`` methods provide an iterator to rows produced
by a statement using a stream::
[get_some_rows::rows]
SELECT i FROM generate_series(0, 1000) AS g(i);
[get_some_chunks::chunks]
SELECT i FROM generate_series(0, 1000) AS g(i);
``rows`` means that the Symbol will return an iterator producing individual rows
of the result, and ``chunks`` means that the Symbol will return an iterator
producing sequences of rows of the result.
When bound::
>>> from itertools import chain
>>> list(db.lib.get_some_rows()) == list(chain.from_iterable(db.lib.get_some_chunks()))
True
Other methods include ``column`` and ``first``. The column method provides a
means to designate that the symbol should return an iterator of the values in
the first column instead of an iterator to the rows::
[another_generate_series_example::column]
SELECT i FROM generate_series(0, $1::int) AS g(i)
In use::
>>> list(db.lib.another_generate_series_example(100-1)) == list(range(100))
True
>>> list(db.lib.another_generate_series_example(10-1))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The ``first`` method provides direct access to simple results.
Specifically, the first column of the first row when there is only one column.
When there are multiple columns the first row is returned::
[get_one::first]
SELECT 1
[get_one_twice::first]
SELECT 1, 1
In use::
>>> db.lib.get_one() == 1
True
>>> db.lib.get_one_twice() == (1,1)
True
.. note::
``first`` should be used with care. When the result returns no rows, `None`
will be returned.
Using Libraries
===============
After a library is created, it must be loaded before it can be bound using
programmer interfaces. The `postgresql.lib.load` interface provides the
primary entry point for loading libraries.
When ``load`` is given a string, it identifies if a directory separator is in
the string, if there is it will treat the string as a *path* to the ILF to be
loaded. If no separator is found, it will treat the string as the library
name fragment and look for "lib{NAME}.sql" in the directories listed in
`postgresql.sys.libpath`.
Once a `postgresql.lib.Library` instance has been acquired, it can then be
bound to a connection for use. `postgresql.lib.Binding` is used to create an
object that provides and manages the Bound Symbols::
>>> import postgresql.lib as pg_lib
>>> lib = pg_lib.load(...)
>>> B = pg_lib.Binding(db, lib)
The ``B`` object in the above example provides the Library's Symbols as
attributes which can be called to in order to execute the Symbol's statement::
>>> B.symbol(param)
...
While it is sometimes necessary, manual creation of a Binding is discouraged.
Rather, `postgresql.lib.Category` objects should be used to manage the set of
Libraries to be bound to a connection.
Categories
----------
Libraries provide access to a collection of symbols; Bindings provide an
interface to the symbols with respect to a subject database. When a connection
is established, multiple Bindings may need to be created in order to fulfill
the requirements of the programmer. When a Binding is created, it exists in
isolation; this can be an inconvenience when access to both the Binding and
the Connection is necessary. Categories exist to provide a formal method for
defining the interface extensions on a `postgresql.api.Database`
instance(connection).
A Category is essentially a runtime-class for connections. It provides a
formal initialization procedure for connection objects at runtime. However,
the connection resource must be connected prior to category initialization.
Categories are sets of Libraries to be bound to a connection with optional name
substitutions. In order to create one directly, pass the Library instances to
`postgresql.lib.Category`::
>>> import postgresql.lib as pg_lib
>>> cat = pg_lib.Category(lib1, lib2, libN)
Where ``lib1``, ``lib2``, ``libN`` are `postgresql.lib.Library` instances;
usually created by `postgresql.lib.load`. Once created, categories can then
used by passing the ``category`` keyword to connection creation interfaces::
>>> import postgresql
>>> db = postgresql.open(category = cat)
The ``db`` object will now have Bindings for ``lib1``, ``lib2``, ..., and
``libN``.
Categories can alter the access point(attribute name) of Bindings. This is done
by instantiating the Category using keyword parameters::
>>> cat = pg_lib.Category(lib1, lib2, libname = libN)
At this point, when a connection is established as the category ``cat``,
``libN`` will be bound to the connection object on the attribute ``libname``
instead of the name defined by the library.
And a final illustration of Category usage::
>>> db = postgresql.open(category = pg_lib.Category(pg_lib.load('name')))
>>> db.name
<Library>
Symbol Types
============
The symbol type determines how a symbol is going to be treated by the Binding.
For instance, ``const`` symbols are resolved when the Library is bound and
the statement object is immediately discarded. Here is a list of symbol types
that can be used in ILF libraries:
``<default>`` (Empty component)
The symbol's statement will never change. This allows the Bound Symbol to
hold onto the `postgresql.api.PreparedStatement` object. When the symbol is
used again, it will refer to the existing prepared statement object.
``preload``
Like the default type, the Symbol is a simple statement, but it should be
loaded when the library is bound to the connection.
``const``
The statement takes no parameters and only needs to be executed once. This
will cause the statement to be executed when the library is bound and the
results of the statement will be set to the Binding using the symbol name so
that it may be used as a property by the user.
``proc``
The contents of the section is a procedure identifier. When this type is used
the symbol method *should not* be specified as the method annotation will be
automatically resolved based on the procedure's signature.
``transient``
The Symbol is a statement that should *not* be retained. Specifically, it is
a statement object that will be discarded when the user discard the referenced
Symbol. Used in cases where the statement is used once or very infrequently.
Symbol Execution Methods
========================
The Symbol Execution Method provides a way to specify how a statement is going
to be used. Specifically, which `postgresql.api.PreparedStatement` method
should be executed when a Bound Symbol is called. The following is a list of
the symbol execution methods and the effect it will have when invoked:
``<default>`` (Empty component)
Returns the entire result set in a single list object. If the statement does
not return rows, a ``(command, count)`` pair will be returned.
``rows``
Returns an iterator producing each row in the result set.
``chunks``
Returns an iterator producing "chunks" of rows in the result set.
``first``
Returns the first column of the first row if there is one column in the result
set. If there are multiple columns in the result set, the first row is
returned. If query is non-RETURNING DML--insert, update, or delete, the row
count is returned.
``column``
Returns an iterator to values in the first column. (Equivalent to
executing a statement as ``map(operator.itemgetter(0), ps.rows())``.)
``declare``
Returns a scrollable cursor, `postgresql.api.Cursor`, to the result set.
``load_chunks``
Takes an iterable row-chunks to be given to the statement. Returns `None`. If
the statement is a ``COPY ... FROM STDIN``, the iterable must produce chunks
of COPY lines.
``load_rows``
Takes an iterable rows to be given as parameters. If the statement is a ``COPY
... FROM STDIN``, the iterable must produce COPY lines.
Reference Symbols
=================
Reference Symbols provide a way to construct a Bound Symbol using the Symbol's
query. When invoked, A Reference Symbol's query is executed in order to produce
an SQL statement to be used as a Bound Symbol. In ILF files, a reference is
identified by its symbol name being prefixed with an ampersand::
[&refsym::first]
SELECT 'SELECT 1::int4'::text
Then executed::
>>> # Runs the 'refsym' SQL, and creates a Bound Symbol using the results.
>>> sym = lib.refsym()
>>> assert sym() == 1
The Reference Symbol's type and execution method are inherited by the created
Bound Symbol. With one exception, ``const`` reference symbols are
special in that they immediately resolved into the target Bound Symbol.
A Reference Symbol's source query *must* produce rows of text columns. Multiple
columns and multiple rows may be produced by the query, but they must be
character types as the results are promptly joined together with whitespace so
that the target statement may be prepared.
Reference Symbols are most likely to be used in dynamic DDL and DML situations,
or, somewhat more specifically, any query whose definition depends on a
generated column list.
Distributing and Usage
======================
For applications, distribution and management can easily be a custom
process. The application designates the library directory; the entry point
adds the path to the `postgresql.sys.libpath` list; a category is built; and, a
connection is made using the category.
For mere Python extensions, however, ``distutils`` has a feature that can
aid in ILF distribution. The ``package_data`` setup keyword can be used to
include ILF files alongside the Python modules that make up a project. See
http://docs.python.org/3.1/distutils/setupscript.html#installing-package-data
for more detailed information on the keyword parameter.
The recommended way to manage libraries for extending projects is to
create a package to contain them. For instance, consider the following layout::
project/
setup.py
pkg/
__init__.py
lib/
__init__.py
libthis.sql
libthat.sql
The project's SQL libraries are organized into a single package directory,
``lib``, so ``package_data`` would be configured::
package_data = {'pkg.lib': ['*.sql']}
Subsequently, the ``lib`` package initialization script can then be used to
load the libraries, and create any categories(``project/pkg/lib/__init__.py``)::
import os.path
import postgresql.lib as pg_lib
import postgresql.sys as pg_sys
libdir = os.path.dirname(__file__)
pg_sys.libpath.append(libdir)
libthis = pg_lib.load('this')
libthat = pg_lib.load('that')
stdcat = pg_lib.Category(libthis, libthat)
However, it can be undesirable to add the package directory to the global
`postgresql.sys.libpath` search paths. Direct path loading can be used in those
cases::
import os.path
import postgresql.lib as pg_lib
libdir = os.path.dirname(__file__)
libthis = pg_lib.load(os.path.join(libdir, 'libthis.sql'))
libthat = pg_lib.load(os.path.join(libdir, 'libthat.sql'))
stdcat = pg_lib.Category(libthis, libthat)
Using the established project context, a connection would then be created as::
from pkg.lib import stdcat
import postgresql as pg
db = pg.open(..., category = stdcat)
# And execute some fictitious symbols.
db.this.sym_from_libthis()
db.that.sym_from_libthat(...)
Audience and Motivation
=======================
This chapter covers advanced material. It is **not** recommended that categories
and libraries be used for trivial applications or introductory projects.
.. note::
Libraries and categories are not likely to be of interest to ORM or DB-API users.
With exception to ORMs or other similar abstractions, the most common pattern
for managing connections and statements is delegation::
class MyAppDB(object):
def __init__(self, connection):
self.connection = connection
def my_operation(self, op_arg1, op_arg2):
return self.connection.prepare(
"SELECT my_operation_proc($1,$2)",
)(op_arg1, op_arg2)
...
The straightforward nature is likeable, but the usage does not take advantage of
prepared statements. In order to do that an extra condition is necessary to see
if the statement has already been prepared::
...
def my_operation(self, op_arg1, op_arg2):
if self.hasattr(self, '_my_operation'):
ps = self._my_operation
else:
ps = self._my_operation = self.connection.prepare(
"SELECT my_operation_proc($1, $2)",
)
return ps(op_arg1, op_arg2)
...
There are many variations that can implement the above. It works and it's
simple, but it will be exhausting if repeated and error prone if the
initialization condition is not factored out. Additionally, if access to statement
metadata is needed, the above example is still lacking as it would require
execution of the statement and further protocol expectations to be established.
This is the province of libraries: direct database interface management.
Categories and Libraries are used to factor out and simplify
the above functionality so re-implementation is unnecessary. For example, an
ILF library containing the symbol::
[my_operation]
SELECT my_operation_proc($1, $2)
[<other_symbol>]
...
Will provide the same functionality as the ``my_operation`` method in the
latter Python implementation.
Terminology
===========
The following terms are used throughout this chapter:
Annotations
The information of about a Symbol describing what it is and how it should be
used.
Binding
An interface to the Symbols provided by a Library for use with a given
connection.
Bound Symbol
An interface to an individual Symbol ready for execution against the subject
database.
Bound Reference
An interface to an individual Reference Symbol that will produce a Bound
Symbol when executed.
ILF
INI-style Library Format. "lib{NAME}.sql" files.
Library
A collection of Symbols--mapping of names to SQL statements.
Local Symbol
A relative term used to denote a symbol that exists in the same library as
the subject symbol.
Preface
The block of text that comes before the first symbol in an ILF file.
Symbol
An named database operation provided by a Library. Usually, an SQL statement
with Annotations.
Reference Symbol
A Symbol whose SQL statement *produces* the source for a Bound Symbol.
Category
An object supporting a classification for connectors that provides database
initialization facilities for produced connections. For libraries,
`postgresql.lib.Category` objects are a set of Libraries,
`postgresql.lib.Library`.
.. _notifyman:
***********************
Notification Management
***********************
Relevant SQL commands: `NOTIFY <http://postgresql.org/docs/current/static/sql-notify.html>`_,
`LISTEN <http://postgresql.org/docs/current/static/sql-listen.html>`_,
`UNLISTEN <http://postgresql.org/docs/current/static/sql-unlisten.html>`_.
Asynchronous notifications offer a means for PostgreSQL to signal application
code. Often these notifications are used to signal cache invalidation. In 9.0
and greater, notifications may include a "payload" in which arbitrary data may
be delivered on a channel being listened to.
By default, received notifications will merely be appended to an internal
list on the connection object. This list will remain empty for the duration
of a connection *unless* the connection begins listening to a channel that
receives notifications.
The `postgresql.notifyman.NotificationManager` class is used to wait for
messages to come in on a set of connections, pick up the messages, and deliver
the messages to the object's user via the `collections.Iterator` protocol.
Listening on a Single Connection
================================
The ``db.iternotifies()`` method is a simplification of the notification manager. It
returns an iterator to the notifications received on the subject connection.
The iterator yields triples consisting of the ``channel`` being
notified, the ``payload`` sent with the notification, and the ``pid`` of the
backend that caused the notification::
>>> db.listen('for_rabbits')
>>> db.notify('for_rabbits')
>>> for x in db.iternotifies():
... channel, payload, pid = x
... break
>>> assert channel == 'for_rabbits'
True
>>> assert payload == ''
True
>>> assert pid == db.backend_id
True
The iterator, by default, will continue listening forever unless the connection
is terminated--thus the immediate ``break`` statement in the above loop. In
cases where some additional activity is necessary, a timeout parameter may be
given to the ``iternotifies`` method in order to allow "idle" events to occur
at the designated frequency::
>>> for x in db.iternotifies(0.5):
... if x is None:
... break
The above example illustrates that idle events are represented using `None`
objects. Idle events are guaranteed to occur *approximately* at the
specified interval--the ``timeout`` keyword parameter. In addition to
providing a means to do other processing or polling, they also offer a safe
break point for the loop. Internally, the iterator produced by the
``iternotifies`` method *is* a `NotificationManager`, which will localize the
notifications prior to emitting them via the iterator.
*It's not safe to break out of the loop, unless an idle event is being handled.*
If the loop is broken while a regular event is being processed, some events may
remain in the iterator. In order to consume those events, the iterator *must*
be accessible.
The iterator will be exhausted when the connection is closed, but if the
connection is closed during the loop, any remaining notifications *will*
be emitted prior to the loop ending, so it is important to be prepared to
handle exceptions or check for a closed connection.
In situations where multiple connections need to be watched, direct use of the
`NotificationManager` is necessary.
Listening on Multiple Connections
=================================
The `postgresql.notifyman.NotificationManager` class is used to manage
*connections* that are expecting to receive notifications. Instances are
iterators that yield the connection object and notifications received on the
connection or `None` in the case of an idle event. The manager emits events as
a pair; the connection object that received notifications, and *all* the
notifications picked up on that connection::
>>> from postgresql.notifyman import NotificationManager
>>> # Using ``nm`` to reference the manager from here on.
>>> nm = NotificationManager(db1, db2, ..., dbN)
>>> nm.settimeout(2)
>>> for x in nm:
... if x is None:
... # idle
... break
...
... db, notifies = x
... for channel, payload, pid in notifies:
... ...
The manager will continue to wait for and emit events so long as there are
good connections available in the set; it is possible for connections to be
added and removed at any time. Although, in rare circumstances, discarded
connections may still have pending events if it not removed during an idle
event. The ``connections`` attribute on `NotificationManager` objects is a
set object that may be used directly in order to add and remove connections
from the manager::
>>> y = []
>>> for x in nm:
... if x is None:
... if y:
... nm.connections.add(y[0])
... del y[0]
...
The notification manager is resilient; if a connection dies, it will discard the
connection from the set, and add it to the set of bad connections, the
``garbage`` attribute. In these cases, the idle event *should* be leveraged to
check for these failures if that's a concern. It is the user's
responsibility to explicitly handle the failure cases, and remove the bad
connections from the ``garbage`` set::
>>> for x in nm:
... if x is None:
... if nm.garbage:
... recovered = take_out_trash(nm.garbage)
... nm.connections.update(recovered)
... nm.garbage.clear()
... db, notifies = x
... for channel, payload, pid in notifies:
... ...
Explicitly removing connections from the set can also be a means to gracefully
terminate the event loop::
>>> for x in nm:
... if x in None:
... if done_listening is True:
... nm.connections.clear()
However, doing so inside the loop is not a requirement; it is safe to remove a
connection from the set at any point.
Notification Managers
=====================
The `postgresql.notifyman.NotificationManager` is an event loop that services
multiple connections. In cases where only one connection needs to be serviced,
the `postgresql.api.Database.iternotifies` method can be used to simplify the
process.
Notification Manager Constructors
---------------------------------
``NotificationManager(*connections, timeout = None)``
Create a NotificationManager instance that manages the notifications coming
from the given set of connections. The ``timeout`` keyword is optional and
can be configured using the ``settimeout`` method as well.
Notification Manager Interface Points
-------------------------------------
``NotificationManager.__iter__()``
Returns the instance; it is an iterator.
``NotificationManager.__next__()``
Normally, yield the pair, connection and notifications list, when the next
event is received. If a timeout is configured, `None` may be yielded to signal
an idle event. The notifications list is a list of triples:
``(channel, payload, pid)``.
``NotificationManager.settimeout(timeout : int)``
Set the amount of time to wait before the manager yields an idle event.
If zero, the manager will never wait and only yield notifications that are
immediately available.
If `None`, the manager will never emit idle events.
``NotificationManager.gettimeout() -> [int, None]``
Get the configured timeout; returns either `None`, or an `int`.
``NotificationManager.connections``
The set of connections that the manager is actively watching for
notifications. Connections may be added or removed from the set at any time.
``NotificationManager.garbage``
The set of connections that failed. Normally empty, but when a connection gets
an exceptional condition or explicitly raises an exception, it is removed from
the ``connections`` set, and placed in ``garbage``.
Zero Timeout
------------
When a timeout of zero, ``0``, is configured, the notification manager will
terminate early. Specifically, each connection will be polled for any pending
notifications, and once all of the collected notifications have been emitted
by the iterator, `StopIteration` will be raised. Notably, *no* idle events will
occur when the timeout is configured to zero.
Zero timeouts offer a means for the notification "queue" to be polled. Often,
this is the appropriate way to collect pending notifications on active
connections where using the connection exclusively for waiting is not
practical::
>>> notifies = list(db.iternotifies(0))
Or with a NotificationManager instance::
>>> nm.settimeout(0)
>>> db_notifies = list(nm)
In both cases of zero timeout, the iterator may be promptly discarded without
losing any events.
Summary of Characteristics
--------------------------
* The iterator will continue until the connections die.
* Objects yielded by the iterator are either `None`, an "idle event", or an
individual notification triple if using ``db.iternotifies()``, or a
``(db, notifies)`` pair if using the base `NotificationManager`.
* When a connection dies or raises an exception, it will be removed from
the ``nm.connections`` set and added to the ``nm.garbage`` set.
* The NotificationManager instance will *not* hold any notifications
during an idle event. Idle events offer a break point in which the manager
may be discarded.
* A timeout of zero will cause the iterator to only yield the events
that are pending right now, and promptly end. However, the same manager
object may be used again.
* A notification triple is a tuple consisting of ``(channel, payload, pid)``.
* Connections may be added and removed from the ``nm.connections`` set at
any time.
Reference
=========
:mod:`postgresql`
-----------------
.. automodule:: postgresql
.. autodata:: version
.. autodata:: version_info
.. autofunction:: open
:mod:`postgresql.api`
---------------------
.. automodule::
postgresql.api
:members:
:show-inheritance:
:mod:`postgresql.sys`
---------------------
.. automodule::
postgresql.sys
:members:
:show-inheritance:
:mod:`postgresql.string`
------------------------
.. automodule::
postgresql.string
:members:
:show-inheritance:
:mod:`postgresql.exceptions`
----------------------------
.. automodule::
postgresql.exceptions
:members:
:show-inheritance:
:mod:`postgresql.temporal`
--------------------------
.. automodule::
postgresql.temporal
:members:
:show-inheritance:
:mod:`postgresql.installation`
------------------------------
.. automodule::
postgresql.installation
:members:
:show-inheritance:
:mod:`postgresql.cluster`
-------------------------
.. automodule::
postgresql.cluster
:members:
:show-inheritance:
:mod:`postgresql.copyman`
-------------------------
.. automodule::
postgresql.copyman
:members:
:show-inheritance:
:mod:`postgresql.alock`
-----------------------
.. automodule::
postgresql.alock
:members:
:show-inheritance:
Metadata-Version: 2.1
Name: py-postgresql
Version: 1.2.2
Summary: PostgreSQL driver and tools library.
Home-page: http://github.com/python-postgres/fe
Author: James William Pye
Author-email: james.pye@gmail.com
Maintainer: James William Pye
Maintainer-email: james.pye@gmail.com
License: UNKNOWN
Description:
.. warning::
In v1.3, `postgresql.driver.dbapi20.connect` will now raise `ClientCannotConnectError` directly.
Exception traps around connect should still function, but the `__context__` attribute
on the error instance will be `None` in the usual failure case as it is no longer
incorrectly chained. Trapping `ClientCannotConnectError` ahead of `Error` should
allow both cases to co-exist in the event that data is being extracted from
the `ClientCannotConnectError`.
py-postgresql is a set of Python modules providing interfaces to various parts
of PostgreSQL. Primarily, it provides a pure-Python driver with some C optimizations for
querying a PostgreSQL database.
http://github.com/python-postgres/fe
Features:
* Prepared Statement driven interfaces.
* Cluster tools for creating and controlling a cluster.
* Support for most PostgreSQL types: composites, arrays, numeric, lots more.
* COPY support.
Sample PG-API Code::
>>> import postgresql
>>> db = postgresql.open('pq://user:password@host:port/database')
>>> db.execute("CREATE TABLE emp (emp_first_name text, emp_last_name text, emp_salary numeric)")
>>> make_emp = db.prepare("INSERT INTO emp VALUES ($1, $2, $3)")
>>> make_emp("John", "Doe", "75,322")
>>> with db.xact():
... make_emp("Jane", "Doe", "75,322")
... make_emp("Edward", "Johnson", "82,744")
...
There is a DB-API 2.0 module as well::
postgresql.driver.dbapi20
However, PG-API is recommended as it provides greater utility.
Once installed, try out the ``pg_python`` console script::
$ python3 -m postgresql.bin.pg_python -h localhost -p port -U theuser -d database_name
If a successful connection is made to the remote host, it will provide a Python
console with the database connection bound to the `db` name.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: License :: OSI Approved :: MIT License
Classifier: License :: OSI Approved :: Attribution Assurance License
Classifier: License :: OSI Approved :: Python Software Foundation License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Database
Description-Content-Type: text/x-rst
AUTHORS
LICENSE
MANIFEST.in
README
setup.py
postgresql/__init__.py
postgresql/alock.py
postgresql/api.py
postgresql/clientparameters.py
postgresql/cluster.py
postgresql/configfile.py
postgresql/copyman.py
postgresql/exceptions.py
postgresql/installation.py
postgresql/iri.py
postgresql/message.py
postgresql/notifyman.py
postgresql/pgpassfile.py
postgresql/project.py
postgresql/string.py
postgresql/sys.py
postgresql/temporal.py
postgresql/versionstring.py
postgresql/bin/__init__.py
postgresql/bin/pg_dotconf.py
postgresql/bin/pg_python.py
postgresql/documentation/__init__.py
postgresql/documentation/sphinx/admin.rst
postgresql/documentation/sphinx/alock.rst
postgresql/documentation/sphinx/bin.rst
postgresql/documentation/sphinx/changes-v1.0.rst
postgresql/documentation/sphinx/changes-v1.1.rst
postgresql/documentation/sphinx/changes-v1.2.rst
postgresql/documentation/sphinx/clientparameters.rst
postgresql/documentation/sphinx/cluster.rst
postgresql/documentation/sphinx/conf.py
postgresql/documentation/sphinx/copyman.rst
postgresql/documentation/sphinx/driver.rst
postgresql/documentation/sphinx/gotchas.rst
postgresql/documentation/sphinx/index.rst
postgresql/documentation/sphinx/lib.rst
postgresql/documentation/sphinx/notifyman.rst
postgresql/documentation/sphinx/reference.rst
postgresql/driver/__init__.py
postgresql/driver/dbapi20.py
postgresql/driver/k.py
postgresql/driver/pq3.py
postgresql/encodings/__init__.py
postgresql/encodings/aliases.py
postgresql/encodings/bytea.py
postgresql/lib/__init__.py
postgresql/lib/libsys.sql
postgresql/port/__init__.py
postgresql/port/signal1_msw.py
postgresql/port/_optimized/buffer.c
postgresql/port/_optimized/element3.c
postgresql/port/_optimized/functools.c
postgresql/port/_optimized/module.c
postgresql/port/_optimized/structlib.c
postgresql/port/_optimized/wirestate.c
postgresql/protocol/__init__.py
postgresql/protocol/buffer.py
postgresql/protocol/client3.py
postgresql/protocol/element3.py
postgresql/protocol/message_types.py
postgresql/protocol/pbuffer.py
postgresql/protocol/version.py
postgresql/protocol/xact3.py
postgresql/python/__init__.py
postgresql/python/command.py
postgresql/python/datetime.py
postgresql/python/decorlib.py
postgresql/python/doc.py
postgresql/python/element.py
postgresql/python/functools.py
postgresql/python/itertools.py
postgresql/python/msw.py
postgresql/python/os.py
postgresql/python/socket.py
postgresql/python/string.py
postgresql/python/structlib.py
postgresql/release/__init__.py
postgresql/release/distutils.py
postgresql/resolved/__init__.py
postgresql/resolved/crypt.py
postgresql/resolved/riparse.py
postgresql/test/__init__.py
postgresql/test/cursor_integrity.py
postgresql/test/perf_copy_io.py
postgresql/test/perf_query_io.py
postgresql/test/support.py
postgresql/test/test_alock.py
postgresql/test/test_bytea_codec.py
postgresql/test/test_cluster.py
postgresql/test/test_configfile.py
postgresql/test/test_connect.py
postgresql/test/test_copyman.py
postgresql/test/test_dbapi20.py
postgresql/test/test_driver.py
postgresql/test/test_exceptions.py
postgresql/test/test_installation.py
postgresql/test/test_iri.py
postgresql/test/test_lib.py
postgresql/test/test_notifyman.py
postgresql/test/test_optimized.py
postgresql/test/test_pgpassfile.py
postgresql/test/test_protocol.py
postgresql/test/test_python.py
postgresql/test/test_ssl_connect.py
postgresql/test/test_string.py
postgresql/test/test_types.py
postgresql/test/testall.py
postgresql/types/__init__.py
postgresql/types/bitwise.py
postgresql/types/geometry.py
postgresql/types/namedtuple.py
postgresql/types/io/__init__.py
postgresql/types/io/builtins.py
postgresql/types/io/contrib_hstore.py
postgresql/types/io/lib.py
postgresql/types/io/pg_bitwise.py
postgresql/types/io/pg_geometry.py
postgresql/types/io/pg_network.py
postgresql/types/io/pg_system.py
postgresql/types/io/stdlib_datetime.py
postgresql/types/io/stdlib_decimal.py
postgresql/types/io/stdlib_jsonb.py
postgresql/types/io/stdlib_uuid.py
postgresql/types/io/stdlib_xml_etree.py
py_postgresql.egg-info/PKG-INFO
py_postgresql.egg-info/SOURCES.txt
py_postgresql.egg-info/dependency_links.txt
py_postgresql.egg-info/top_level.txt
[egg_info]
tag_build =
tag_date = 0
+3
-8
Contributors:
James William Pye [faults are mostly mine] <x@jwp.io>
James William Pye [faults are mostly mine]
Elvis Pranskevichus

@@ -11,10 +11,5 @@ William Grzybowski [subjective paramstyle]

Further Credits
===============
Imported
========
When licenses match, people win. Code is occasionally imported from other
projects to enhance py-postgresql and to allow users to enjoy dependency free
installation.
DB-API 2.0 Test Case

@@ -21,0 +16,0 @@ --------------------

@@ -1,8 +0,1 @@

BSD Licensed Software
Unless stated otherwise, the contained software is
copyright 2004-2009, James Williame Pye.
For more information: http://python.projects.postgresql.org
Redistribution and use in source and binary forms,

@@ -9,0 +2,0 @@ with or without modification, are permitted provided

+17
-14

@@ -1,15 +0,25 @@

Metadata-Version: 1.1
Metadata-Version: 2.1
Name: py-postgresql
Version: 1.2.1
Version: 1.2.2
Summary: PostgreSQL driver and tools library.
Home-page: http://python.projects.postgresql.org/
Home-page: http://github.com/python-postgres/fe
Author: James William Pye
Author-email: python-general@pgfoundry.org
Author-email: james.pye@gmail.com
Maintainer: James William Pye
Maintainer-email: james.pye@gmail.com
License: UNKNOWN
Description:
.. warning::
In v1.3, `postgresql.driver.dbapi20.connect` will now raise `ClientCannotConnectError` directly.
Exception traps around connect should still function, but the `__context__` attribute
on the error instance will be `None` in the usual failure case as it is no longer
incorrectly chained. Trapping `ClientCannotConnectError` ahead of `Error` should
allow both cases to co-exist in the event that data is being extracted from
the `ClientCannotConnectError`.
py-postgresql is a set of Python modules providing interfaces to various parts
of PostgreSQL. Notably, it provides a pure-Python driver + C optimizations for
of PostgreSQL. Primarily, it provides a pure-Python driver with some C optimizations for
querying a PostgreSQL database.
http://python.projects.postgresql.org
http://github.com/python-postgres/fe

@@ -48,10 +58,2 @@ Features:

History
-------
py-postgresql is not yet another PostgreSQL driver, it's been in development for
years. py-postgresql is the Python 3 port of the ``pg_proboscis`` driver and
integration of the other ``pg/python`` projects.
Platform: UNKNOWN

@@ -69,1 +71,2 @@ Classifier: Development Status :: 5 - Production/Stable

Classifier: Topic :: Database
Description-Content-Type: text/x-rst
##
# py-postgresql root package
# http://python.projects.postgresql.org
# http://github.com/python-postgres/fe
##
"""
py-postgresql is a Python package for using PostgreSQL. This includes low-level
protocol tools, a driver(PG-API and DB-API), and cluster management tools.
protocol tools, a driver(PG-API and DB-API 2.0), and cluster management tools.
If it's not documented in the narratives, `postgresql.documentation.index`, then
the stability of the APIs should *not* be trusted.
See <http://postgresql.org> for more information about PostgreSQL.
See <http://postgresql.org> for more information about PostgreSQL and <http://python.org>
for information about Python.
"""

@@ -14,0 +12,0 @@ __all__ = [

@@ -157,3 +157,3 @@ ##

def envvars(environ = os.environ, modifier : "environment variable key modifier" = 'PG'.__add__):
def envvars(environ = os.environ, modifier = 'PG'.__add__):
"""

@@ -186,2 +186,4 @@ Create a clientparams dictionary from the given environment variables.

itself.
:param modifier: environment variable key modifier
"""

@@ -279,3 +281,5 @@ hostaddr = modifier('HOSTADDR')

def append_settings(option, opt_str, value, parser):
'split the string into a (key,value) pair tuple'
"""
split the string into a (key,value) pair tuple
"""
kv = value.split('=', 1)

@@ -373,7 +377,3 @@ if len(kv) != 2:

def resolve_password(
parameters : "a fully normalized set of client parameters(dict)",
getpass = getpass,
prompt_title = '',
):
def resolve_password(parameters, getpass = getpass, prompt_title = ''):
"""

@@ -393,2 +393,4 @@ Given a parameters dictionary, resolve the 'password' key.

given parameters.
:param parameters: a fully normalized set of client parameters(dict)
"""

@@ -578,3 +580,3 @@ prompt_for_password = parameters.pop('prompt_password', False)

default_pg_sysconfdir = None,
default_pg_service_filename = pg_service_filename
default_pg_service_filename = pg_service_filename
):

@@ -587,14 +589,23 @@ sysconfdir = environ.get(pg_sysconfdir_envvar, default_pg_sysconfdir)

def collect(
parsed_options : "options parsed using the `DefaultParser`" = None,
no_defaults : "Don't build-out defaults like 'user' from getpass.getuser()" = False,
environ : "environment variables to use, `None` to disable" = os.environ,
environ_prefix : "prefix to use for collecting environment variables" = 'PG',
default_pg_sysconfdir : "default 'PGSYSCONFDIR' to use" = None,
pg_service_file : "the pg-service file to actually use" = None,
prompt_title : "additional title to use if a prompt request is made" = '',
parameters : "base-client parameters to use(applied after defaults)" = (),
):
parsed_options = None,
no_defaults = False,
environ = os.environ,
environ_prefix = 'PG',
default_pg_sysconfdir = None,
pg_service_file = None,
prompt_title = '',
parameters = (),
):
"""
Build a normalized client parameters dictionary for use with a connection
construction interface.
:param parsed_options: options parsed using the `DefaultParser`
:param no_defaults: Don't build-out defaults like 'user' from getpass.getuser()
:param environ: environment variables to use, `None` to disable
:param environ_prefix: prefix to use for collecting environment variables
:param default_pg_sysconfdir: default 'PGSYSCONFDIR' to use
:param pg_service_file: the pg-service file to actually use
:param prompt_title: additional title to use if a prompt request is made
:param parameters: base-client parameters to use(applied after defaults)
"""

@@ -601,0 +612,0 @@ d_parameters = []

@@ -158,4 +158,4 @@ ##

def __init__(self,
installation : "installation object",
data_directory : "path to the data directory",
installation,
data_directory,
):

@@ -195,5 +195,4 @@ self.installation = installation

def init(self,
password : \
"Password to assign to the " \
"cluster's superuser(`user` keyword)." = None,
password = None,
timeout = None,
**kw

@@ -260,3 +259,3 @@ ):

bufsize = 1024 * 5, # not expecting this to ever be filled.
stdin = sp.PIPE,
stdin = None,
stdout = logfile,

@@ -266,15 +265,10 @@ # stderr is used to identify a reasonable error message.

)
# stdin is not used; it is not desirable for initdb to be attached.
p.stdin.close()
while True:
try:
rc = p.wait()
break
except OSError as e:
if e.errno != errno.EINTR:
raise
finally:
if p.stdout is not None:
p.stdout.close()
try:
stdout, stderr = p.communicate(timeout=timeout)
except sp.TimeoutExpired:
p.kill()
stdout, stderr = p.communicate()
finally:
rc = p.returncode

@@ -284,3 +278,3 @@ if rc != 0:

r = p.stderr.read().strip()
r = stderr
try:

@@ -293,2 +287,3 @@ msg = r.decode('utf-8')

])
raise InitDBError(

@@ -304,7 +299,2 @@ "initdb exited with non-zero status",

finally:
if p is not None:
for x in (p.stderr, p.stdin, p.stdout):
if x is not None:
x.close()
if supw_tmp is not None:

@@ -344,4 +334,4 @@ n = supw_tmp.name

def start(self,
logfile : "Where to send stderr" = None,
settings : "Mapping of runtime parameters" = None
logfile = None,
settings = None
):

@@ -584,4 +574,4 @@ """

def wait_until_started(self,
timeout : "how long to wait before throwing a timeout exception" = 10,
delay : "how long to sleep before re-testing" = 0.05,
timeout = 10,
delay = 0.05,
):

@@ -637,4 +627,4 @@ """

def wait_until_stopped(self,
timeout : "how long to wait before throwing a timeout exception" = 10,
delay : "how long to sleep before re-testing" = 0.05
timeout = 10,
delay = 0.05
):

@@ -641,0 +631,0 @@ """

@@ -327,2 +327,6 @@ ##

# Explicitly manage DB-API connected state to properly
# throw the already closed error. This will be active in 1.3.
_dbapi_connected_flag = False
def autocommit_set(self, val):

@@ -358,5 +362,6 @@ if val:

self._xact.start()
self._dbapi_connected_flag = True
def close(self):
if self.closed:
if self.closed:# and self._dbapi_connected_flag:
raise Error(

@@ -367,2 +372,3 @@ "connection already closed",

)
self._dbapi_connected_flag = True
super().close()

@@ -405,2 +411,5 @@

Create a DB-API connection using the given parameters.
Due to the way defaults are populated, when connecting to a local filesystem socket
using the `unix` keyword parameter, `host` and `port` must also be set to ``None``.
"""

@@ -407,0 +416,0 @@ std_params = pg_param.collect(prompt_title = None)

@@ -11,3 +11,2 @@ ##

import subprocess
import io
import errno

@@ -22,4 +21,4 @@ from itertools import cycle, chain

# Get the output from the given command.
# *args are transformed into "long options", '--' + x
def get_command_output(exe, *args):
# Variable arguments are transformed into "long options", '--' + x
def get_command_output(exe, *args, encoding='utf-8', timeout=8):
pa = list(exe) + [

@@ -31,21 +30,19 @@ '--' + x.strip() for x in args if x is not None

stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
stdin = subprocess.PIPE,
stderr = None,
stdin = None,
shell = False
)
p.stdin.close()
p.stderr.close()
while True:
try:
rv = p.wait()
break
except OSError as e:
if e.errno != errno.EINTR:
raise
if rv != 0:
try:
stdout, stderr = p.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
p.kill()
stdout, stderr = p.communicate(timeout=2)
if p.returncode != 0:
return None
with p.stdout, io.TextIOWrapper(p.stdout) as txt:
return txt.read()
def pg_config_dictionary(*pg_config_path):
return stdout.decode(encoding)
def pg_config_dictionary(*pg_config_path, encoding='utf-8', timeout=8):
"""

@@ -56,3 +53,3 @@ Create a dictionary of the information available in the given

"""
default_output = get_command_output(pg_config_path)
default_output = get_command_output(pg_config_path, encoding=encoding, timeout=timeout)
if default_output is not None:

@@ -74,3 +71,3 @@ d = {}

opt = []
for l in get_command_output(pg_config_path, 'help').splitlines():
for l in get_command_output(pg_config_path, 'help', encoding=encoding, timeout=timeout).splitlines():
dash_pos = l.find('--')

@@ -87,4 +84,4 @@ if dash_pos == -1:

d=dict(zip(opt, get_command_output(pg_config_path, *opt).splitlines()))
d['version'] = get_command_output(pg_config_path, 'version').strip()
d=dict(zip(opt, get_command_output(pg_config_path, *opt, encoding=encoding, timeout=timeout).splitlines()))
d['version'] = get_command_output(pg_config_path, 'version', encoding=encoding, timeout=timeout).strip()
return d

@@ -91,0 +88,0 @@

@@ -49,3 +49,3 @@ ##

else:
cpd['host'] = host[1:-1]
cpd['host'] = host
else:

@@ -52,0 +52,0 @@ cpd['host'] = fieldproc(host)

@@ -103,3 +103,3 @@ /*

{
int32_t current = 0;
uint32_t current = 0;
struct p_list *pl;

@@ -106,0 +106,0 @@

@@ -1,14 +0,12 @@

'project information'
"""
Project information.
"""
#: project name
name = 'py-postgresql'
identity = 'http://github.com/python-postgres/fe'
#: IRI based project identity
identity = 'http://python.projects.postgresql.org/'
meaculpa = 'Python+Postgres'
contact = 'python-general@pgfoundry.org'
abstract = 'Driver and tools library for PostgreSQL'
version_info = (1, 2, 1)
version_info = (1, 2, 2)
version = '.'.join(map(str, version_info))
##
# .protocol.element3
##
'PQ version 3.0 elements'
"""
PQ version 3.0 elements.
"""
import sys

@@ -303,3 +305,5 @@ import os

class Ready(Message):
'Ready for new query'
"""
Ready for new query message.
"""
type = message_types[b'Z'[0]]

@@ -323,3 +327,3 @@ possible_states = (

"""
Notification message
Notification message.

@@ -358,3 +362,5 @@ Used by PQ to emit INFO, NOTICE, and WARNING messages among other

class Error(Notice):
"""Incoming error"""
"""
Error information message.
"""
type = message_types[b'E'[0]]

@@ -374,3 +380,5 @@ __slots__ = ()

class FunctionResult(Message):
"""Function result value"""
"""
Function result value.
"""
type = message_types[b'V'[0]]

@@ -401,3 +409,5 @@ __slots__ = ('result',)

class AttributeTypes(TupleMessage):
"""Tuple attribute types"""
"""
Tuple attribute types.
"""
type = message_types[b't'[0]]

@@ -418,3 +428,5 @@ __slots__ = ()

class TupleDescriptor(TupleMessage):
"""Tuple description"""
"""
Tuple structure description.
"""
type = message_types[b'T'[0]]

@@ -451,3 +463,5 @@ struct = Struct("!LhLhlh")

class Tuple(TupleMessage):
"""Incoming tuple"""
"""
Tuple Data.
"""
type = message_types[b'D'[0]]

@@ -490,3 +504,5 @@ __slots__ = ()

class KillInformation(Message):
'Backend cancellation information'
"""
Backend cancellation information.
"""
type = message_types[b'K'[0]]

@@ -508,3 +524,5 @@ struct = Struct("!LL")

class CancelRequest(KillInformation):
'Abort the query in the specified backend'
"""
Abort the query in the specified backend.
"""
type = b''

@@ -531,3 +549,5 @@ from .version import CancelRequestCode as version

class NegotiateSSL(Message):
"Discover backend's SSL support"
"""
Discover backend's SSL support.
"""
type = b''

@@ -618,3 +638,5 @@ from .version import NegotiateSSLCode as version

class Authentication(Message):
"""Authentication(request, salt)"""
"""
Authentication(request, salt)
"""
type = message_types[b'R'[0]]

@@ -635,3 +657,5 @@ __slots__ = ('request', 'salt')

class Password(StringMessage):
'Password supplement'
"""
Password supplement.
"""
type = message_types[b'p'[0]]

@@ -641,3 +665,5 @@ __slots__ = ('data',)

class Disconnect(EmptyMessage):
'Close the connection'
"""
Connection closed message.
"""
type = message_types[b'X'[0]]

@@ -649,3 +675,5 @@ __slots__ = ()

class Flush(EmptyMessage):
'Flush'
"""
Flush message.
"""
type = message_types[b'H'[0]]

@@ -657,3 +685,5 @@ __slots__ = ()

class Synchronize(EmptyMessage):
'Synchronize'
"""
Synchronize.
"""
type = message_types[b'S'[0]]

@@ -665,3 +695,5 @@ __slots__ = ()

class Query(StringMessage):
"""Execute the query with the given arguments"""
"""
Execute the query with the given arguments.
"""
type = message_types[b'Q'[0]]

@@ -671,3 +703,5 @@ __slots__ = ('data',)

class Parse(Message):
"""Parse a query with the specified argument types"""
"""
Parse a query with the specified argument types.
"""
type = message_types[b'P'[0]]

@@ -761,3 +795,5 @@ __slots__ = ('name', 'statement', 'argtypes')

class Execute(Message):
"""Fetch results from the specified Portal"""
"""
Fetch results from the specified Portal.
"""
type = message_types[b'E'[0]]

@@ -779,3 +815,5 @@ __slots__ = ('name', 'max')

class Describe(StringMessage):
"""Describe a Portal or Prepared Statement"""
"""
Request a description of a Portal or Prepared Statement.
"""
type = message_types[b'D'[0]]

@@ -806,3 +844,5 @@ __slots__ = ('data',)

class Close(StringMessage):
"""Generic Close"""
"""
Generic Close
"""
type = message_types[b'C'[0]]

@@ -825,3 +865,5 @@ __slots__ = ()

class CloseStatement(Close):
"""Close the specified Statement"""
"""
Close the specified Statement
"""
subtype = message_types[b'S'[0]]

@@ -831,3 +873,5 @@ __slots__ = ()

class ClosePortal(Close):
"""Close the specified Portal"""
"""
Close the specified Portal
"""
subtype = message_types[b'P'[0]]

@@ -837,3 +881,6 @@ __slots__ = ()

class Function(Message):
"""Execute the specified function with the given arguments"""
"""
Execute the specified function with the given arguments
"""
type = message_types[b'F'[0]]

@@ -907,3 +954,5 @@ __slots__ = ('oid', 'aformats', 'arguments', 'rformat')

class CopyToBegin(CopyBegin):
"""Begin copying to"""
"""
Begin copying to.
"""
type = message_types[b'H'[0]]

@@ -913,3 +962,5 @@ __slots__ = ('format', 'formats')

class CopyFromBegin(CopyBegin):
"""Begin copying from"""
"""
Begin copying from.
"""
type = message_types[b'G'[0]]

@@ -916,0 +967,0 @@ __slots__ = ('format', 'formats')

##
# .protocol.version
##
'PQ version class'
"""
PQ version class used by startup messages.
"""
from struct import Struct

@@ -9,3 +11,4 @@ version_struct = Struct('!HH')

class Version(tuple):
"""Version((major, minor)) -> Version
"""
Version((major, minor)) -> Version

@@ -17,3 +20,3 @@ Version serializer and parser.

def __new__(subtype, major_minor : '(major, minor)'):
def __new__(subtype, major_minor):
(major, minor) = major_minor

@@ -20,0 +23,0 @@ major = int(major)

@@ -235,3 +235,3 @@ ##

return
else:
else:
self.authok = self.authtype

@@ -238,0 +238,0 @@

@@ -8,3 +8,2 @@ ##

import socket
import math
import errno

@@ -55,3 +54,5 @@ import ssl

def secure(self, socket : socket.socket) -> ssl.SSLSocket:
"secure a socket with SSL"
"""
Secure a socket with SSL.
"""
if self.socket_secure is not None:

@@ -74,5 +75,5 @@ return ssl.wrap_socket(socket, **self.socket_secure)

def __init__(self,
socket_create : "positional parameters given to socket.socket()",
socket_connect : "parameter given to socket.connect()",
socket_secure : "keywords given to ssl.wrap_socket" = None,
socket_create,
socket_connect,
socket_secure = None,
):

@@ -87,34 +88,17 @@ self.socket_create = socket_create

def find_available_port(
interface : "attempt to bind to interface" = 'localhost',
address_family : "address family to use (default: AF_INET)" = socket.AF_INET,
limit : "Number tries to make before giving up" = 1024,
port_range = (6600, 56600)
) -> (int, None):
interface = 'localhost',
address_family = socket.AF_INET,
):
"""
Find an available port on the given interface for the given address family.
Returns a port number that was successfully bound to or `None` if the
attempt limit was reached.
"""
i = 0
while i < limit:
i += 1
port = (
math.floor(
random.random() * (port_range[1] - port_range[0])
) + port_range[0]
)
s = socket.socket(address_family, socket.SOCK_STREAM,)
try:
s.bind(('localhost', port))
s.close()
except socket.error as e:
s.close()
if e.errno in (errno.EACCES, errno.EADDRINUSE, errno.EINTR):
# try again
continue
break
else:
port = None
port = None
s = socket.socket(address_family, socket.SOCK_STREAM,)
try:
s.bind(('localhost', 0))
port = s.getsockname()[1]
finally:
s.close()
return port

@@ -16,10 +16,21 @@ ##

from ..project import version, name, identity as url
from distutils.core import Extension, Command
try:
from setuptools import Extension, Command
except ImportError as e:
from distutils.core import Extension, Command
LONG_DESCRIPTION = """
.. warning::
In v1.3, `postgresql.driver.dbapi20.connect` will now raise `ClientCannotConnectError` directly.
Exception traps around connect should still function, but the `__context__` attribute
on the error instance will be `None` in the usual failure case as it is no longer
incorrectly chained. Trapping `ClientCannotConnectError` ahead of `Error` should
allow both cases to co-exist in the event that data is being extracted from
the `ClientCannotConnectError`.
py-postgresql is a set of Python modules providing interfaces to various parts
of PostgreSQL. Notably, it provides a pure-Python driver + C optimizations for
of PostgreSQL. Primarily, it provides a pure-Python driver with some C optimizations for
querying a PostgreSQL database.
http://python.projects.postgresql.org
http://github.com/python-postgres/fe

@@ -57,10 +68,2 @@ Features:

console with the database connection bound to the `db` name.
History
-------
py-postgresql is not yet another PostgreSQL driver, it's been in development for
years. py-postgresql is the Python 3 port of the ``pg_proboscis`` driver and
integration of the other ``pg/python`` projects.
"""

@@ -169,6 +172,7 @@

'long_description' : LONG_DESCRIPTION,
'long_description_content_type' : 'text/x-rst',
'author' : 'James William Pye',
'author_email' : 'x@jwp.name',
'author_email' : 'james.pye@gmail.com',
'maintainer' : 'James William Pye',
'maintainer_email' : 'python-general@pgfoundry.org',
'maintainer_email' : 'james.pye@gmail.com',
'url' : url,

@@ -175,0 +179,0 @@ 'classifiers' : CLASSIFIERS,

@@ -9,2 +9,3 @@ ##

import atexit
import builtins
from collections import deque

@@ -114,2 +115,3 @@ from .cluster import Cluster, ClusterError

vi = installation.version_info
cluster = Cluster(installation, self.cluster_path,)

@@ -127,5 +129,6 @@

# Configure
self.cluster_port = find_available_port()
if self.cluster_port is None:
try:
self.cluster_port = find_available_port()
except:
# Rely on chain.
raise ClusterError(

@@ -136,2 +139,6 @@ 'could not find a port for the test cluster on localhost',

if vi[:2] > (9,6):
# Default changed in 10.x
cluster.settings['max_wal_senders'] = '0'
cluster.settings.update(dict(

@@ -144,2 +151,3 @@ port = str(self.cluster_port),

log_min_messages = 'FATAL',
max_prepared_transactions = '10',
))

@@ -156,6 +164,2 @@

cluster.settings.update(dict(
max_prepared_transactions = '10',
))
# Start it up.

@@ -186,3 +190,3 @@ with open(self.logfile, 'w') as lfo:

# The new builtins.
builtins = {
local_builtins = {
'db' : c,

@@ -201,4 +205,4 @@ 'prepare' : c.prepare,

current = {
k : __builtins__[k] for k in self.builtins_keys
if k in __builtins__
k : builtins.__dict__[k] for k in self.builtins_keys
if k in builtins.__dict__
}

@@ -208,8 +212,8 @@ self.builtins_stack.append((current, []))

# Store and push.
self.builtins_stack.append((builtins, extras))
__builtins__.update(builtins)
self.builtins_stack.append((local_builtins, extras))
builtins.__dict__.update(local_builtins)
self.sandbox_id += 1
def pop(self, exc, drop_schema = 'DROP SCHEMA sandbox{0} CASCADE'.format):
builtins, extras = self.builtins_stack.pop()
local_builtins, extras = self.builtins_stack.pop()
self.sandbox_id -= 1

@@ -219,3 +223,3 @@

if len(self.builtins_stack) > 1:
__builtins__.update(self.builtins_stack[-1][0])
builtins.__dict__.update(self.builtins_stack[-1][0])
else:

@@ -225,6 +229,6 @@ previous = self.builtins_stack.popleft()

if x in previous:
__builtins__[x] = previous[x]
builtins.__dict__[x] = previous[x]
else:
# Wasn't set before.
__builtins__.pop(x, None)
builtins.__dict__.pop(x, None)

@@ -235,3 +239,3 @@ # close popped connection, but only if we're not in an interrupt.

# Interrupt then close. Just in case something is lingering.
for xdb in [builtins['db']] + list(extras):
for xdb in [local_builtins['db']] + list(extras):
if xdb.closed is False:

@@ -238,0 +242,0 @@ # In order for a clean close of the connection,

@@ -33,3 +33,4 @@ ##

if self.cluster.installation.version_info[:2] >= (9, 3):
vi = self.cluster.installation.version_info[:2]
if vi >= (9, 3):
usd = 'unix_socket_directories'

@@ -39,2 +40,5 @@ else:

if vi > (9, 6):
self.cluster.settings['max_wal_senders'] = '0'
self.cluster.settings.update({

@@ -41,0 +45,0 @@ 'max_connections' : '8',

@@ -54,3 +54,3 @@ ##

self.cluster_path = \
'py_unittest_pg_cluster_' \
'pypg_test_' \
+ str(os.getpid()) + getattr(self, 'cluster_path_suffix', '')

@@ -72,2 +72,4 @@

self.disable_replication = self.installation.version_info[:2] > (9, 6)
def configure_cluster(self):

@@ -84,2 +86,3 @@ self.cluster_port = find_available_port()

listen_addresses += ',::1'
self.cluster.settings.update(dict(

@@ -94,2 +97,7 @@ port = str(self.cluster_port),

if self.disable_replication:
self.cluster.settings.update({
'max_wal_senders': '0',
})
if self.cluster.installation.version_info[:2] < (9, 3):

@@ -164,12 +172,23 @@ self.cluster.settings.update(dict(

mk_common_users = """
CREATE USER md5 WITH ENCRYPTED PASSWORD 'md5_password';
CREATE USER password WITH ENCRYPTED PASSWORD 'password_password';
CREATE USER trusted;
"""
mk_crypt_user = """
-- crypt doesn't work with encrypted passwords:
-- http://www.postgresql.org/docs/8.2/interactive/auth-methods.html#AUTH-PASSWORD
CREATE USER crypt WITH UNENCRYPTED PASSWORD 'crypt_password';
"""
def __init__(self, *args, **kw):
super().__init__(*args,**kw)
# 8.4 nixed this.
self.do_crypt = self.cluster.installation.version_info < (8,4)
vi = self.cluster.installation.version_info
self.check_crypt_user = (vi < (8,4))
def configure_cluster(self):
super().configure_cluster()
self.cluster.settings.update({
'log_min_messages' : 'log',
})
self.cluster.settings['log_min_messages'] = 'log'

@@ -181,3 +200,4 @@ # Configure the hba file with the supported methods.

hosts.append('0::0/0')
methods = ['md5', 'password'] + (['crypt'] if self.do_crypt else [])
methods = ['md5', 'password'] + (['crypt'] if self.check_crypt_user else [])
for h in hosts:

@@ -190,2 +210,3 @@ for m in methods:

)])
# trusted

@@ -203,23 +224,8 @@ hba.writelines(["local all all trust\n"])

super().initialize_database()
with self.cluster.connection(user = 'test') as db:
db.execute(
"""
CREATE USER md5 WITH
ENCRYPTED PASSWORD 'md5_password'
;
db.execute(self.mk_common_users)
if self.check_crypt_user:
db.execute(self.mk_crypt_user)
-- crypt doesn't work with encrypted passwords:
-- http://www.postgresql.org/docs/8.2/interactive/auth-methods.html#AUTH-PASSWORD
CREATE USER crypt WITH
UNENCRYPTED PASSWORD 'crypt_password'
;
CREATE USER password WITH
ENCRYPTED PASSWORD 'password_password'
;
CREATE USER trusted;
"""
)
def test_pg_open_SQL_ASCII(self):

@@ -375,3 +381,3 @@ # postgresql.open

if self.do_crypt:
if self.check_crypt_user:
CRYPT = dbapi20.connect(

@@ -416,2 +422,13 @@ user = 'crypt',

def test_dbapi_connect_failure(self):
host, port = self.cluster.address()
badlogin = (lambda: dbapi20.connect(
user = '--',
database = '--',
password = '...',
host = host, port = port,
**self.params
))
self.assertRaises(pg_exc.ClientCannotConnectError, badlogin)
def test_IP4_connect(self):

@@ -462,3 +479,3 @@ C = pg_driver.default.ip4(

def test_crypt_connect(self):
if self.do_crypt:
if self.check_crypt_user:
c = self.cluster.connection(

@@ -465,0 +482,0 @@ user = 'crypt',

@@ -57,4 +57,4 @@ ##

This implementation tests Gadfly, but the TestCase
is structured so that other self.drivers can subclass this
test case to ensure compiliance with the DB-API. It is
is structured so that other self.drivers can subclass this
test case to ensure compiliance with the DB-API. It is
expected that this TestCase may be expanded in the future

@@ -69,5 +69,5 @@ if ambiguities or edge conditions are discovered.

import dbapi20
import dbapi20
class mytest(dbapi20.DatabaseAPI20Test):
[...]
[...]

@@ -103,6 +103,6 @@ __rcs_id__ = 'Id: dbapi20.py,v 1.10 2003/10/09 03:14:14 zenzen Exp'

for ddl in (self.xddl1, self.xddl2):
try:
try:
cur.execute(ddl)
con.commit()
except self.driver.Error:
except self.driver.Error:
# Assume table didn't exist. Other tests will check if

@@ -109,0 +109,0 @@ # execute is busted.

@@ -1815,3 +1815,3 @@ ##

# It just exercises the code path.
db.typio.identify(contrib_hstore = 'pg_catalog.reltime')
db.typio.identify(contrib_hstore = 'pg_catalog.text')

@@ -1818,0 +1818,0 @@ @pg_tmp

@@ -87,2 +87,18 @@ ##

class test_iri(unittest.TestCase):
def testIP6Hosts(self):
"""
Validate that IPv6 hosts are properly extracted.
"""
s = [
('pq://[::1]/db', '::1'),
('pq://[::1]:1234/db', '::1'),
('pq://[1:2:3::1]/db', '1:2:3::1'),
('pq://[1:2:3::1]:1234/db', '1:2:3::1'),
('pq://[]:1234/db', ''),
('pq://[]/db', ''),
]
for i, h in s:
p = pg_iri.parse(i)
self.assertEqual(p['host'], h)
def testPresentPasswordObscure(self):

@@ -89,0 +105,0 @@ "password is present in IRI, and obscure it"

@@ -142,5 +142,4 @@ ##

def testFindAvailable(self):
# the port is randomly generated, so make a few trials before
# determining success.
for i in range(100):
# Host sanity check; this is likely fragile.
for i in range(4):
portnum = find_available_port()

@@ -147,0 +146,0 @@ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

+19
-2
About
=====
py-postgresql is a Python 3 package providing modules to work with PostgreSQL.
py-postgresql is a Python 3 package providing modules for working with PostgreSQL.
This includes a high-level driver, and many other tools that support a developer
working with PostgreSQL databases.
For a high performance async interface, MagicStack's asyncpg
http://github.com/MagicStack/asyncpg should be considered.
py-postgresql, currently, does not have direct support for high-level async
interfaces provided by recent versions of Python. Future versions may change this.
Errata
------
.. warning::
In v1.3, `postgresql.driver.dbapi20.connect` will now raise `ClientCannotConnectError` directly.
Exception traps around connect should still function, but the `__context__` attribute
on the error instance will be `None` in the usual failure case as it is no longer
incorrectly chained. Trapping `ClientCannotConnectError` ahead of `Error` should
allow both cases to co-exist in the event that data is being extracted from
the `ClientCannotConnectError`.
Installation

@@ -38,3 +55,3 @@ ------------

http://python.projects.postgresql.org
http://py-postgresql.readthedocs.io

@@ -41,0 +58,0 @@ Or, you can read them in your pager: python -m postgresql.documentation.index

@@ -28,3 +28,6 @@ #!/usr/bin/env python

if __name__ == '__main__':
from distutils.core import setup
try:
from setuptools import setup
except ImportError as e:
from distutils.core import setup
setup(**defaults)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Overview: module code &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../index.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>All modules for which code is available</h1>
<ul><li><a href="postgresql.html">postgresql</a></li>
<ul><li><a href="postgresql/alock.html">postgresql.alock</a></li>
<li><a href="postgresql/api.html">postgresql.api</a></li>
<li><a href="postgresql/cluster.html">postgresql.cluster</a></li>
<li><a href="postgresql/copyman.html">postgresql.copyman</a></li>
<li><a href="postgresql/exceptions.html">postgresql.exceptions</a></li>
<li><a href="postgresql/installation.html">postgresql.installation</a></li>
<li><a href="postgresql/string.html">postgresql.string</a></li>
<li><a href="postgresql/sys.html">postgresql.sys</a></li>
<li><a href="postgresql/temporal.html">postgresql.temporal</a></li>
</ul></ul>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../index.html" />
<link rel="up" title="Module code" href="index.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="index.html" accesskey="U">Module code</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># py-postgresql root package</span>
<span class="c"># http://python.projects.postgresql.org</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">py-postgresql is a Python package for using PostgreSQL. This includes low-level</span>
<span class="sd">protocol tools, a driver(PG-API and DB-API), and cluster management tools.</span>
<span class="sd">If it&#39;s not documented in the narratives, `postgresql.documentation.index`, then</span>
<span class="sd">the stability of the APIs should *not* be trusted.</span>
<span class="sd">See &lt;http://postgresql.org&gt; for more information about PostgreSQL.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&#39;__author__&#39;</span><span class="p">,</span>
<span class="s">&#39;__date__&#39;</span><span class="p">,</span>
<span class="s">&#39;__version__&#39;</span><span class="p">,</span>
<span class="s">&#39;__docformat__&#39;</span><span class="p">,</span>
<span class="s">&#39;version&#39;</span><span class="p">,</span>
<span class="s">&#39;version_info&#39;</span><span class="p">,</span>
<span class="s">&#39;open&#39;</span><span class="p">,</span>
<span class="p">]</span>
<span class="c">#: The version string of py-postgresql.</span>
<span class="n">version</span> <span class="o">=</span> <span class="s">&#39;&#39;</span> <span class="c"># overridden by subsequent import from .project.</span>
<span class="c">#: The version triple of py-postgresql: (major, minor, patch).</span>
<span class="n">version_info</span> <span class="o">=</span> <span class="p">()</span> <span class="c"># overridden by subsequent import from .project.</span>
<span class="c"># Optional.</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">.project</span> <span class="kn">import</span> <span class="n">version_info</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> \
<span class="n">author</span> <span class="k">as</span> <span class="n">__author__</span><span class="p">,</span> <span class="n">date</span> <span class="k">as</span> <span class="n">__date__</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="n">version</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c"># Avoid importing these until requested.</span>
<span class="n">_pg_iri</span> <span class="o">=</span> <span class="n">_pg_driver</span> <span class="o">=</span> <span class="n">_pg_param</span> <span class="o">=</span> <span class="bp">None</span>
<div class="viewcode-block" id="open"><a class="viewcode-back" href="../reference.html#postgresql.open">[docs]</a><span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="n">iri</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">prompt_title</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Create a `postgresql.api.Connection` to the server referenced by the given</span>
<span class="sd"> `iri`::</span>
<span class="sd"> &gt;&gt;&gt; import postgresql</span>
<span class="sd"> # General Format:</span>
<span class="sd"> &gt;&gt;&gt; db = postgresql.open(&#39;pq://user:password@host:port/database&#39;)</span>
<span class="sd"> # Connect to &#39;postgres&#39; at localhost.</span>
<span class="sd"> &gt;&gt;&gt; db = postgresql.open(&#39;localhost/postgres&#39;)</span>
<span class="sd"> Connection keywords can also be used with `open`. See the narratives for</span>
<span class="sd"> more information.</span>
<span class="sd"> The `prompt_title` keyword is ignored. `open` will never prompt for</span>
<span class="sd"> the password unless it is explicitly instructed to do so.</span>
<span class="sd"> (Note: &quot;pq&quot; is the name of the protocol used to communicate with PostgreSQL)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">global</span> <span class="n">_pg_iri</span><span class="p">,</span> <span class="n">_pg_driver</span><span class="p">,</span> <span class="n">_pg_param</span>
<span class="k">if</span> <span class="n">_pg_iri</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">iri</span> <span class="k">as</span> <span class="n">_pg_iri</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">driver</span> <span class="k">as</span> <span class="n">_pg_driver</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">clientparameters</span> <span class="k">as</span> <span class="n">_pg_param</span>
<span class="n">return_connector</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">if</span> <span class="n">iri</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">if</span> <span class="n">iri</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;&amp;&#39;</span><span class="p">):</span>
<span class="n">return_connector</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">iri</span> <span class="o">=</span> <span class="n">iri</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="n">iri_params</span> <span class="o">=</span> <span class="n">_pg_iri</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">iri</span><span class="p">)</span>
<span class="n">iri_params</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;path&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">iri_params</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">std_params</span> <span class="o">=</span> <span class="n">_pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">prompt_title</span> <span class="o">=</span> <span class="bp">None</span><span class="p">)</span>
<span class="c"># If unix is specified, it&#39;s going to conflict with any standard</span>
<span class="c"># settings, so remove them right here.</span>
<span class="k">if</span> <span class="s">&#39;unix&#39;</span> <span class="ow">in</span> <span class="n">kw</span> <span class="ow">or</span> <span class="s">&#39;unix&#39;</span> <span class="ow">in</span> <span class="n">iri_params</span><span class="p">:</span>
<span class="n">std_params</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;host&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">std_params</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;port&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">_pg_param</span><span class="o">.</span><span class="n">normalize</span><span class="p">(</span>
<span class="nb">list</span><span class="p">(</span><span class="n">_pg_param</span><span class="o">.</span><span class="n">denormalize_parameters</span><span class="p">(</span><span class="n">std_params</span><span class="p">))</span> <span class="o">+</span> \
<span class="nb">list</span><span class="p">(</span><span class="n">_pg_param</span><span class="o">.</span><span class="n">denormalize_parameters</span><span class="p">(</span><span class="n">iri_params</span><span class="p">))</span> <span class="o">+</span> \
<span class="nb">list</span><span class="p">(</span><span class="n">_pg_param</span><span class="o">.</span><span class="n">denormalize_parameters</span><span class="p">(</span><span class="n">kw</span><span class="p">))</span>
<span class="p">)</span>
<span class="n">_pg_param</span><span class="o">.</span><span class="n">resolve_password</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
<span class="n">C</span> <span class="o">=</span> <span class="n">_pg_driver</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="o">**</span><span class="n">params</span><span class="p">)</span>
<span class="k">if</span> <span class="n">return_connector</span> <span class="ow">is</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">return</span> <span class="n">C</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">c</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="k">return</span> <span class="n">c</span>
</div>
<span class="n">__docformat__</span> <span class="o">=</span> <span class="s">&#39;reStructuredText&#39;</span>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="index.html" >Module code</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql.alock &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../../index.html" />
<link rel="up" title="postgresql" href="../postgresql.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" accesskey="U">postgresql</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql.alock</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># .alock - Advisory Locks</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Tools for Advisory Locks</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">abstractmethod</span><span class="p">,</span> <span class="n">abstractproperty</span>
<span class="kn">from</span> <span class="nn">.python.element</span> <span class="kn">import</span> <span class="n">Element</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&#39;ALock&#39;</span><span class="p">,</span>
<span class="s">&#39;ExclusiveLock&#39;</span><span class="p">,</span>
<span class="s">&#39;ShareLock&#39;</span><span class="p">,</span>
<span class="p">]</span>
<div class="viewcode-block" id="ALock"><a class="viewcode-back" href="../../reference.html#postgresql.alock.ALock">[docs]</a><span class="k">class</span> <span class="nc">ALock</span><span class="p">(</span><span class="n">Element</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Advisory Lock class for managing the acquisition and release of a sequence</span>
<span class="sd"> of PostgreSQL advisory locks.</span>
<span class="sd"> ALock()&#39;s are fairly consistent with threading.RLock()&#39;s. They can be</span>
<span class="sd"> acquired multiple times, and they must be released the same number of times</span>
<span class="sd"> for the lock to actually be released.</span>
<span class="sd"> A notably difference is that ALock&#39;s manage a sequence of lock identifiers.</span>
<span class="sd"> This means that a given ALock() may represent multiple advisory locks.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">_e_factors</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;database&#39;</span><span class="p">,</span> <span class="s">&#39;identifiers&#39;</span><span class="p">,)</span>
<span class="n">_e_label</span> <span class="o">=</span> <span class="s">&#39;ALOCK&#39;</span>
<span class="k">def</span> <span class="nf">_e_metas</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>
<span class="n">headfmt</span> <span class="o">=</span> <span class="s">&quot;{1} [{0}]&quot;</span><span class="o">.</span><span class="n">format</span>
<span class="p">):</span>
<span class="k">yield</span> <span class="bp">None</span><span class="p">,</span> <span class="n">headfmt</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">state</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">mode</span><span class="p">)</span>
<span class="nd">@abstractproperty</span>
<div class="viewcode-block" id="ALock.mode"><a class="viewcode-back" href="../../reference.html#postgresql.alock.ALock.mode">[docs]</a> <span class="k">def</span> <span class="nf">mode</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> The mode of the lock class.</span>
<span class="sd"> &quot;&quot;&quot;</span>
</div>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">__select_statements__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Implemented by subclasses to return the statements to try, acquire, and</span>
<span class="sd"> release the advisory lock.</span>
<span class="sd"> Returns a triple of callables where each callable takes two arguments,</span>
<span class="sd"> the lock-id pairs, and then the int8 lock-ids.</span>
<span class="sd"> ``(try, acquire, release)``.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">_split_lock_identifiers</span><span class="p">(</span><span class="n">idseq</span><span class="p">):</span>
<span class="c"># lame O(2)</span>
<span class="n">id_pairs</span> <span class="o">=</span> <span class="p">[</span>
<span class="nb">list</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">if</span> <span class="n">x</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">int</span> <span class="k">else</span> <span class="p">[</span><span class="bp">None</span><span class="p">,</span><span class="bp">None</span><span class="p">]</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">idseq</span>
<span class="p">]</span>
<span class="n">ids</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">x</span> <span class="k">if</span> <span class="n">x</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="nb">int</span> <span class="k">else</span> <span class="bp">None</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">idseq</span>
<span class="p">]</span>
<span class="k">return</span> <span class="p">(</span><span class="n">id_pairs</span><span class="p">,</span> <span class="n">ids</span><span class="p">)</span>
<div class="viewcode-block" id="ALock.acquire"><a class="viewcode-back" href="../../reference.html#postgresql.alock.ALock.acquire">[docs]</a> <span class="k">def</span> <span class="nf">acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">blocking</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="nb">len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Acquire the locks using the configured identifiers.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="c"># _count is zero, so the locks need to be acquired.</span>
<span class="n">wait</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">blocking</span><span class="p">)</span>
<span class="k">if</span> <span class="n">wait</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_acquire</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_id_pairs</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ids</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># grab the success of each lock id. if some were</span>
<span class="c"># unsuccessful, then the ones that were successful need to be</span>
<span class="c"># released.</span>
<span class="n">r</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_try</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_id_pairs</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ids</span><span class="p">)</span>
<span class="c"># accumulate the identifiers that *did* lock</span>
<span class="n">release_seq</span> <span class="o">=</span> <span class="p">[</span>
<span class="nb">id</span> <span class="k">for</span> <span class="n">didlock</span><span class="p">,</span> <span class="nb">id</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">identifiers</span><span class="p">)</span> <span class="k">if</span> <span class="n">didlock</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="p">]</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">release_seq</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">identifiers</span><span class="p">):</span>
<span class="c"># some failed, so release the acquired and return False</span>
<span class="c">#</span>
<span class="c"># reverse in case there is another waiting for all.</span>
<span class="c"># that is, release last-to-first so that if another is waiting</span>
<span class="c"># on the same seq that it should be able to acquire all of</span>
<span class="c"># them once the contended lock is released.</span>
<span class="n">release_seq</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_release</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="o">.</span><span class="n">_split_lock_identifiers</span><span class="p">(</span><span class="n">release_seq</span><span class="p">))</span>
<span class="c"># unable to acquire all.</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="bp">True</span>
</div>
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
<span class="k">return</span> <span class="bp">self</span>
<div class="viewcode-block" id="ALock.release"><a class="viewcode-back" href="../../reference.html#postgresql.alock.ALock.release">[docs]</a> <span class="k">def</span> <span class="nf">release</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Release the locks using the configured identifiers.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&quot;cannot release un-acquired lock&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">closed</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="c"># if the database has been closed, or the count will</span>
<span class="c"># remain non-zero, there is no need to release.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_release</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_id_pairs</span><span class="p">),</span> <span class="nb">reversed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_ids</span><span class="p">))</span>
<span class="c"># decrement the count nonetheless.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">-</span> <span class="mi">1</span>
</div>
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">typ</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">tb</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
<div class="viewcode-block" id="ALock.locked"><a class="viewcode-back" href="../../reference.html#postgresql.alock.ALock.locked">[docs]</a> <span class="k">def</span> <span class="nf">locked</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Whether the locks have been acquired. This method is sensitive to the</span>
<span class="sd"> connection&#39;s state. If the connection is closed, it will return False.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">closed</span><span class="p">)</span>
</div>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">state</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s">&#39;locked&#39;</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">locked</span><span class="p">()</span> <span class="k">else</span> <span class="s">&#39;unlocked&#39;</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">database</span><span class="p">,</span> <span class="o">*</span><span class="n">identifiers</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Initialize the lock object to manage a sequence of advisory locks</span>
<span class="sd"> for use with the given database.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="o">.</span><span class="n">connection</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">database</span> <span class="o">=</span> <span class="n">database</span>
<span class="bp">self</span><span class="o">.</span><span class="n">identifiers</span> <span class="o">=</span> <span class="n">identifiers</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_id_pairs</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ids</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_split_lock_identifiers</span><span class="p">(</span><span class="n">identifiers</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_try</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_acquire</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_release</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__select_statements__</span><span class="p">()</span>
</div>
<span class="k">class</span> <span class="nc">ShareLock</span><span class="p">(</span><span class="n">ALock</span><span class="p">):</span>
<span class="n">mode</span> <span class="o">=</span> <span class="s">&#39;share&#39;</span>
<span class="k">def</span> <span class="nf">__select_statements__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">try_advisory_shared</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">acquire_advisory_shared</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">release_advisory_shared</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">class</span> <span class="nc">ExclusiveLock</span><span class="p">(</span><span class="n">ALock</span><span class="p">):</span>
<span class="n">mode</span> <span class="o">=</span> <span class="s">&#39;exclusive&#39;</span>
<span class="k">def</span> <span class="nf">__select_statements__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">try_advisory_exclusive</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">acquire_advisory_exclusive</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">database</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">release_advisory_exclusive</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" >postgresql</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql.installation &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../../index.html" />
<link rel="up" title="postgresql" href="../postgresql.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" accesskey="U">postgresql</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql.installation</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># .installation</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Collect and access PostgreSQL installation information.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">os.path</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">io</span>
<span class="kn">import</span> <span class="nn">errno</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">cycle</span><span class="p">,</span> <span class="n">chain</span>
<span class="kn">from</span> <span class="nn">operator</span> <span class="kn">import</span> <span class="n">itemgetter</span>
<span class="kn">from</span> <span class="nn">.python.os</span> <span class="kn">import</span> <span class="n">find_executable</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span> <span class="n">platform_exe</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">versionstring</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">api</span> <span class="k">as</span> <span class="n">pg_api</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">string</span> <span class="k">as</span> <span class="n">pg_str</span>
<span class="c"># Get the output from the given command.</span>
<span class="c"># *args are transformed into &quot;long options&quot;, &#39;--&#39; + x</span>
<span class="k">def</span> <span class="nf">get_command_output</span><span class="p">(</span><span class="n">exe</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pa</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">exe</span><span class="p">)</span> <span class="o">+</span> <span class="p">[</span>
<span class="s">&#39;--&#39;</span> <span class="o">+</span> <span class="n">x</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">args</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span>
<span class="p">]</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">pa</span><span class="p">,</span>
<span class="n">close_fds</span> <span class="o">=</span> <span class="n">close_fds</span><span class="p">,</span>
<span class="n">stdout</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">stderr</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">stdin</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">shell</span> <span class="o">=</span> <span class="bp">False</span>
<span class="p">)</span>
<span class="n">p</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">p</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">rv</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
<span class="k">break</span>
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">errno</span><span class="o">.</span><span class="n">EINTR</span><span class="p">:</span>
<span class="k">raise</span>
<span class="k">if</span> <span class="n">rv</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="k">with</span> <span class="n">p</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">io</span><span class="o">.</span><span class="n">TextIOWrapper</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">stdout</span><span class="p">)</span> <span class="k">as</span> <span class="n">txt</span><span class="p">:</span>
<span class="k">return</span> <span class="n">txt</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<div class="viewcode-block" id="pg_config_dictionary"><a class="viewcode-back" href="../../reference.html#postgresql.installation.pg_config_dictionary">[docs]</a><span class="k">def</span> <span class="nf">pg_config_dictionary</span><span class="p">(</span><span class="o">*</span><span class="n">pg_config_path</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Create a dictionary of the information available in the given</span>
<span class="sd"> pg_config_path. This provides a one-shot solution to fetching information</span>
<span class="sd"> from the pg_config binary. Returns a dictionary object.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">default_output</span> <span class="o">=</span> <span class="n">get_command_output</span><span class="p">(</span><span class="n">pg_config_path</span><span class="p">)</span>
<span class="k">if</span> <span class="n">default_output</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">default_output</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">x</span> <span class="ow">or</span> <span class="n">x</span><span class="o">.</span><span class="n">isspace</span><span class="p">()</span> <span class="ow">or</span> <span class="n">x</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&#39;=&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="c"># keep it semi-consistent with instance</span>
<span class="n">d</span><span class="p">[</span><span class="n">k</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()]</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">return</span> <span class="n">d</span>
<span class="c"># Support for 8.0 pg_config and earlier.</span>
<span class="c"># This requires three invocations of pg_config:</span>
<span class="c"># First --help, to get the -- options available,</span>
<span class="c"># Second, all the -- options except version.</span>
<span class="c"># Third, --version as it appears to be exclusive in some cases.</span>
<span class="n">opt</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">get_command_output</span><span class="p">(</span><span class="n">pg_config_path</span><span class="p">,</span> <span class="s">&#39;help&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
<span class="n">dash_pos</span> <span class="o">=</span> <span class="n">l</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&#39;--&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">dash_pos</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">sp_pos</span> <span class="o">=</span> <span class="n">l</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&#39; &#39;</span><span class="p">,</span> <span class="n">dash_pos</span><span class="p">)</span>
<span class="c"># the dashes are added by the call command</span>
<span class="n">opt</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">l</span><span class="p">[</span><span class="n">dash_pos</span><span class="o">+</span><span class="mi">2</span><span class="p">:</span><span class="n">sp_pos</span><span class="p">])</span>
<span class="k">if</span> <span class="s">&#39;help&#39;</span> <span class="ow">in</span> <span class="n">opt</span><span class="p">:</span>
<span class="n">opt</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s">&#39;help&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="s">&#39;version&#39;</span> <span class="ow">in</span> <span class="n">opt</span><span class="p">:</span>
<span class="n">opt</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s">&#39;version&#39;</span><span class="p">)</span>
<span class="n">d</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">opt</span><span class="p">,</span> <span class="n">get_command_output</span><span class="p">(</span><span class="n">pg_config_path</span><span class="p">,</span> <span class="o">*</span><span class="n">opt</span><span class="p">)</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()))</span>
<span class="n">d</span><span class="p">[</span><span class="s">&#39;version&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_command_output</span><span class="p">(</span><span class="n">pg_config_path</span><span class="p">,</span> <span class="s">&#39;version&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">return</span> <span class="n">d</span>
<span class="c">##</span>
<span class="c"># Build a key-value pair list of the configure options.</span>
<span class="c"># If the item is quoted, mind the quotes.</span></div>
<span class="k">def</span> <span class="nf">parse_configure_options</span><span class="p">(</span><span class="n">confopt</span><span class="p">,</span> <span class="n">quotes</span> <span class="o">=</span> <span class="s">&#39;</span><span class="se">\&#39;</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="n">dash_and_quotes</span> <span class="o">=</span> <span class="s">&#39;-</span><span class="se">\&#39;</span><span class="s">&quot;&#39;</span><span class="p">):</span>
<span class="c"># This is not a robust solution, but it will usually work.</span>
<span class="c"># Chances are that there is a quote at the beginning of this string.</span>
<span class="c"># However, in the windows pg_config.exe, this appears to be absent.</span>
<span class="k">if</span> <span class="n">confopt</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">quotes</span><span class="p">:</span>
<span class="c"># quote at the beginning. assume it&#39;s used consistently.</span>
<span class="n">quote</span> <span class="o">=</span> <span class="n">confopt</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">1</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">confopt</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">:]</span> <span class="ow">in</span> <span class="n">quotes</span><span class="p">:</span>
<span class="c"># quote at the end?</span>
<span class="n">quote</span> <span class="o">=</span> <span class="n">confopt</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># fallback to something. :(</span>
<span class="n">quote</span> <span class="o">=</span> <span class="s">&quot;&#39;&quot;</span>
<span class="c">##</span>
<span class="c"># This is using the wrong kind of split, but the pg_config</span>
<span class="c"># output has been consistent enough for this to work.</span>
<span class="n">parts</span> <span class="o">=</span> <span class="n">pg_str</span><span class="o">.</span><span class="n">split_using</span><span class="p">(</span><span class="n">confopt</span><span class="p">,</span> <span class="n">quote</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39; &#39;</span><span class="p">)</span>
<span class="n">qq</span> <span class="o">=</span> <span class="n">quote</span> <span class="o">*</span> <span class="mi">2</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">parts</span><span class="p">:</span>
<span class="k">if</span> <span class="n">qq</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
<span class="c"># singularize the quotes</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">qq</span><span class="p">,</span> <span class="n">quote</span><span class="p">)</span>
<span class="c"># remove the quotes around &#39;--&#39; from option.</span>
<span class="c"># if it splits once, the &#39;1&#39; index will</span>
<span class="c"># be `True`, indicating that the flag was given, but</span>
<span class="c"># was not given a value.</span>
<span class="n">kv</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="n">dash_and_quotes</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">[</span><span class="bp">True</span><span class="p">]</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">kv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;-&#39;</span><span class="p">,</span><span class="s">&#39;_&#39;</span><span class="p">)</span>
<span class="c"># Ignore empty keys.</span>
<span class="k">if</span> <span class="n">key</span><span class="p">:</span>
<span class="k">yield</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">kv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<div class="viewcode-block" id="default_pg_config"><a class="viewcode-back" href="../../reference.html#postgresql.installation.default_pg_config">[docs]</a><span class="k">def</span> <span class="nf">default_pg_config</span><span class="p">(</span><span class="n">execname</span> <span class="o">=</span> <span class="s">&#39;pg_config&#39;</span><span class="p">,</span> <span class="n">envkey</span> <span class="o">=</span> <span class="s">&#39;PGINSTALLATION&#39;</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get the default `pg_config` executable on the system.</span>
<span class="sd"> If &#39;PGINSTALLATION&#39; is in the environment, use it.</span>
<span class="sd"> Otherwise, look through the system&#39;s PATH environment.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">pg_config_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">envkey</span><span class="p">)</span>
<span class="k">if</span> <span class="n">pg_config_path</span><span class="p">:</span>
<span class="c"># Trust PGINSTALLATION.</span>
<span class="k">return</span> <span class="n">platform_exe</span><span class="p">(</span><span class="n">pg_config_path</span><span class="p">)</span>
<span class="k">return</span> <span class="n">find_executable</span><span class="p">(</span><span class="n">execname</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Installation"><a class="viewcode-back" href="../../reference.html#postgresql.installation.Installation">[docs]</a><span class="k">class</span> <span class="nc">Installation</span><span class="p">(</span><span class="n">pg_api</span><span class="o">.</span><span class="n">Installation</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Class providing a Python interface to PostgreSQL installation information.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">version</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">version_info</span> <span class="o">=</span> <span class="bp">None</span>
<span class="nb">type</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">configure_options</span> <span class="o">=</span> <span class="bp">None</span>
<span class="c">#: The pg_config information dictionary.</span>
<span class="n">info</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">pg_executables</span> <span class="o">=</span> <span class="p">(</span>
<span class="s">&#39;pg_config&#39;</span><span class="p">,</span>
<span class="s">&#39;psql&#39;</span><span class="p">,</span>
<span class="s">&#39;initdb&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_resetxlog&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_controldata&#39;</span><span class="p">,</span>
<span class="s">&#39;clusterdb&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_ctl&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_dump&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_dumpall&#39;</span><span class="p">,</span>
<span class="s">&#39;postgres&#39;</span><span class="p">,</span>
<span class="s">&#39;postmaster&#39;</span><span class="p">,</span>
<span class="s">&#39;reindexdb&#39;</span><span class="p">,</span>
<span class="s">&#39;vacuumdb&#39;</span><span class="p">,</span>
<span class="s">&#39;ipcclean&#39;</span><span class="p">,</span>
<span class="s">&#39;createdb&#39;</span><span class="p">,</span>
<span class="s">&#39;ecpg&#39;</span><span class="p">,</span>
<span class="s">&#39;createuser&#39;</span><span class="p">,</span>
<span class="s">&#39;createlang&#39;</span><span class="p">,</span>
<span class="s">&#39;droplang&#39;</span><span class="p">,</span>
<span class="s">&#39;dropuser&#39;</span><span class="p">,</span>
<span class="s">&#39;pg_restore&#39;</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">pg_libraries</span> <span class="o">=</span> <span class="p">(</span>
<span class="s">&#39;libpq&#39;</span><span class="p">,</span>
<span class="s">&#39;libecpg&#39;</span><span class="p">,</span>
<span class="s">&#39;libpgtypes&#39;</span><span class="p">,</span>
<span class="s">&#39;libecpg_compat&#39;</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">pg_directories</span> <span class="o">=</span> <span class="p">(</span>
<span class="s">&#39;bindir&#39;</span><span class="p">,</span>
<span class="s">&#39;docdir&#39;</span><span class="p">,</span>
<span class="s">&#39;includedir&#39;</span><span class="p">,</span>
<span class="s">&#39;pkgincludedir&#39;</span><span class="p">,</span>
<span class="s">&#39;includedir_server&#39;</span><span class="p">,</span>
<span class="s">&#39;libdir&#39;</span><span class="p">,</span>
<span class="s">&#39;pkglibdir&#39;</span><span class="p">,</span>
<span class="s">&#39;localedir&#39;</span><span class="p">,</span>
<span class="s">&#39;mandir&#39;</span><span class="p">,</span>
<span class="s">&#39;sharedir&#39;</span><span class="p">,</span>
<span class="s">&#39;sysconfdir&#39;</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">_e_metas</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">configure_options</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
<span class="n">l</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span> <span class="o">=</span> <span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
<span class="k">yield</span> <span class="p">(</span><span class="s">&#39;version&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span><span class="p">)</span>
<span class="k">if</span> <span class="n">l</span><span class="p">:</span>
<span class="k">yield</span> <span class="p">(</span><span class="s">&#39;configure_options&#39;</span><span class="p">,</span>
<span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">((</span>
<span class="n">k</span> <span class="k">if</span> <span class="n">v</span> <span class="ow">is</span> <span class="bp">True</span> <span class="k">else</span> <span class="n">k</span> <span class="o">+</span> <span class="s">&#39;=&#39;</span> <span class="o">+</span> <span class="n">v</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">l</span>
<span class="p">))</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="s">&quot;{mod}.{name}({info!r})&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">):</span>
<span class="k">return</span> <span class="n">format</span><span class="p">(</span>
<span class="n">mod</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__module__</span><span class="p">,</span>
<span class="n">name</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span>
<span class="n">info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">info</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">info</span> <span class="p">:</span> <span class="nb">dict</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Initialize the Installation using the given information dictionary.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">info</span> <span class="o">=</span> <span class="n">info</span>
<span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">info</span><span class="p">[</span><span class="s">&quot;version&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">vs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">version_info</span> <span class="o">=</span> <span class="n">versionstring</span><span class="o">.</span><span class="n">normalize</span><span class="p">(</span><span class="n">versionstring</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">vs</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">configure_options</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
<span class="n">parse_configure_options</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;configure&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">))</span>
<span class="p">)</span>
<span class="c"># collect the paths in a dictionary first</span>
<span class="bp">self</span><span class="o">.</span><span class="n">paths</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="n">exists</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span>
<span class="n">join</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg_directories</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">paths</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="c"># find all the PG executables that exist for the installation.</span>
<span class="n">bindir_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;bindir&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">bindir_path</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">paths</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pg_executables</span><span class="p">,</span> <span class="n">cycle</span><span class="p">((</span><span class="bp">None</span><span class="p">,))))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg_executables</span><span class="p">:</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">platform_exe</span><span class="p">(</span><span class="n">join</span><span class="p">(</span><span class="n">bindir_path</span><span class="p">,</span> <span class="n">k</span><span class="p">))</span>
<span class="k">if</span> <span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">paths</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">path</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">paths</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__dict__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">paths</span><span class="p">)</span>
<span class="nd">@property</span>
<div class="viewcode-block" id="Installation.ssl"><a class="viewcode-back" href="../../reference.html#postgresql.installation.Installation.ssl">[docs]</a> <span class="k">def</span> <span class="nf">ssl</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Whether the installation was compiled with SSL support.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="s">&#39;with_openssl&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">configure_options</span>
</div></div>
<div class="viewcode-block" id="default"><a class="viewcode-back" href="../../reference.html#postgresql.installation.default">[docs]</a><span class="k">def</span> <span class="nf">default</span><span class="p">(</span><span class="n">typ</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get the default Installation.</span>
<span class="sd"> Uses default_pg_config() to identify the executable.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">default_pg_config</span><span class="p">()</span>
<span class="k">if</span> <span class="n">path</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="k">return</span> <span class="n">typ</span><span class="p">(</span><span class="n">pg_config_dictionary</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>
</div>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">pg_config_dictionary</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">default</span><span class="p">()</span>
<span class="kn">from</span> <span class="nn">.python.element</span> <span class="kn">import</span> <span class="n">format_element</span>
<span class="k">print</span><span class="p">(</span><span class="n">format_element</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" >postgresql</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql.string &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../../index.html" />
<link rel="up" title="postgresql" href="../postgresql.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" accesskey="U">postgresql</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql.string</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># .string</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">String split and join operations for dealing with literals and identifiers.</span>
<span class="sd">Notably, the functions in this module are intended to be used for simple</span>
<span class="sd">use-cases. It attempts to stay away from &quot;real&quot; parsing and simply provides</span>
<span class="sd">functions for common needs, like the ability to identify unquoted portions of a</span>
<span class="sd">query string so that logic or transformations can be applied to only unquoted</span>
<span class="sd">portions. Scanning for statement terminators, or safely interpolating</span>
<span class="sd">identifiers.</span>
<span class="sd">All functions deal with strict quoting rules.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">re</span>
<div class="viewcode-block" id="escape_literal"><a class="viewcode-back" href="../../reference.html#postgresql.string.escape_literal">[docs]</a><span class="k">def</span> <span class="nf">escape_literal</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="s">&quot;Replace every instance of &#39; with &#39;&#39;&quot;</span>
<span class="k">return</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&quot;&#39;&quot;</span><span class="p">,</span> <span class="s">&quot;&#39;&#39;&quot;</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="quote_literal"><a class="viewcode-back" href="../../reference.html#postgresql.string.quote_literal">[docs]</a><span class="k">def</span> <span class="nf">quote_literal</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="s">&quot;Escape the literal and wrap it in [single] quotations&quot;</span>
<span class="k">return</span> <span class="s">&quot;&#39;&quot;</span> <span class="o">+</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&quot;&#39;&quot;</span><span class="p">,</span> <span class="s">&quot;&#39;&#39;&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot;&#39;&quot;</span>
</div>
<div class="viewcode-block" id="escape_ident"><a class="viewcode-back" href="../../reference.html#postgresql.string.escape_ident">[docs]</a><span class="k">def</span> <span class="nf">escape_ident</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="s">&#39;Replace every instance of &quot; with &quot;&quot;&#39;</span>
<span class="k">return</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s">&#39;&quot;&quot;&#39;</span><span class="p">)</span>
</div>
<span class="k">def</span> <span class="nf">needs_quoting</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="k">return</span> <span class="ow">not</span> <span class="p">(</span><span class="n">text</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">text</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">isdecimal</span><span class="p">()</span> <span class="ow">and</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span> <span class="s">&#39;a&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">isalnum</span><span class="p">())</span>
<div class="viewcode-block" id="quote_ident"><a class="viewcode-back" href="../../reference.html#postgresql.string.quote_ident">[docs]</a><span class="k">def</span> <span class="nf">quote_ident</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="s">&quot;Replace every instance of &#39;&quot;&#39; with &#39;&quot;&quot;&#39; *and* place &#39;&quot;&#39; on each end&quot;</span>
<span class="k">return</span> <span class="s">&#39;&quot;&#39;</span> <span class="o">+</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s">&#39;&quot;&quot;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;&quot;&#39;</span>
</div>
<div class="viewcode-block" id="quote_ident_if_needed"><a class="viewcode-back" href="../../reference.html#postgresql.string.quote_ident_if_needed">[docs]</a><span class="k">def</span> <span class="nf">quote_ident_if_needed</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If needed, replace every instance of &#39;&quot;&#39; with &#39;&quot;&quot;&#39; *and* place &#39;&quot;&#39; on each end.</span>
<span class="sd"> Otherwise, just return the text.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">quote_ident</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> <span class="k">if</span> <span class="n">needs_quoting</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> <span class="k">else</span> <span class="n">text</span>
</div>
<span class="n">quote_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">r&quot;&quot;&quot;(?xu)</span>
<span class="s"> E&#39;(?:&#39;&#39;|\\.|[^&#39;])*(?:&#39;|$) (?# Backslash escapes E&#39;str&#39;)</span>
<span class="s">| &#39;(?:&#39;&#39;|[^&#39;])*(?:&#39;|$) (?# Regular literals &#39;str&#39;)</span>
<span class="s">| &quot;(?:&quot;&quot;|[^&quot;])*(?:&quot;|$) (?# Identifiers &quot;str&quot;)</span>
<span class="s">| (\$(?:[^0-9$]\w*)?\$).*?(?:\1|$) (?# Dollar quotes $$str$$)</span>
<span class="s">&quot;&quot;&quot;</span><span class="p">)</span>
<div class="viewcode-block" id="split"><a class="viewcode-back" href="../../reference.html#postgresql.string.split">[docs]</a><span class="k">def</span> <span class="nf">split</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> split the string up by into non-quoted and quoted portions. Zero and even</span>
<span class="sd"> numbered indexes are unquoted portions, while odd indexes are quoted</span>
<span class="sd"> portions. </span>
<span class="sd"> Unquoted portions are regular strings, whereas quoted portions are</span>
<span class="sd"> pair-tuples specifying the quotation mechanism and the content thereof.</span>
<span class="sd"> &gt;&gt;&gt; list(split(&quot;select $$foobar$$&quot;))</span>
<span class="sd"> [&#39;select &#39;, (&#39;$$&#39;, &#39;foobar&#39;), &#39;&#39;]</span>
<span class="sd"> If the split ends on a quoted section, it means the string&#39;s quote was not</span>
<span class="sd"> terminated. Subsequently, there will be an even number of objects in the</span>
<span class="sd"> list.</span>
<span class="sd"> Quotation errors are detected, but never raised. Rather it&#39;s up to the user</span>
<span class="sd"> to identify the best course of action for the given split.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">lastend</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">re</span> <span class="o">=</span> <span class="n">quote_re</span>
<span class="n">scan</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">scanner</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="n">match</span> <span class="o">=</span> <span class="n">scan</span><span class="o">.</span><span class="n">search</span><span class="p">()</span>
<span class="k">while</span> <span class="n">match</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="c"># text preceding the quotation</span>
<span class="k">yield</span> <span class="n">text</span><span class="p">[</span><span class="n">lastend</span><span class="p">:</span><span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()]</span>
<span class="c"># the dollar quote, if any</span>
<span class="n">dq</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groups</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">dq</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">endoff</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">dq</span><span class="p">)</span>
<span class="n">quote</span> <span class="o">=</span> <span class="n">dq</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">quote</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">endoff</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">text</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()]</span>
<span class="k">if</span> <span class="n">q</span> <span class="o">==</span> <span class="s">&#39;E&#39;</span><span class="p">:</span>
<span class="n">quote</span> <span class="o">=</span> <span class="s">&quot;E&#39;&quot;</span>
<span class="n">end</span> <span class="o">=</span> <span class="s">&quot;&#39;&quot;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">q</span>
<span class="c"># If the end is not the expected quote, it consumed</span>
<span class="c"># the end. Be sure to check that the match&#39;s end - end offset</span>
<span class="c"># is *not* the start, ie an empty quotation at the end of the string.</span>
<span class="k">if</span> <span class="n">text</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span><span class="o">-</span><span class="n">endoff</span><span class="p">:</span><span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()]</span> <span class="o">!=</span> <span class="n">end</span> \
<span class="ow">or</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="n">endoff</span> <span class="o">==</span> <span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">():</span>
<span class="k">yield</span> <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">text</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span><span class="o">+</span><span class="nb">len</span><span class="p">(</span><span class="n">quote</span><span class="p">):])</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">yield</span> <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">text</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span><span class="o">+</span><span class="nb">len</span><span class="p">(</span><span class="n">quote</span><span class="p">):</span><span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span><span class="o">-</span><span class="n">endoff</span><span class="p">])</span>
<span class="n">lastend</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span>
<span class="n">match</span> <span class="o">=</span> <span class="n">scan</span><span class="o">.</span><span class="n">search</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># balanced quotes, yield the rest</span>
<span class="k">yield</span> <span class="n">text</span><span class="p">[</span><span class="n">lastend</span><span class="p">:]</span>
</div>
<div class="viewcode-block" id="unsplit"><a class="viewcode-back" href="../../reference.html#postgresql.string.unsplit">[docs]</a><span class="k">def</span> <span class="nf">unsplit</span><span class="p">(</span><span class="n">splitted_iter</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> catenate a split string. This is needed to handle the special</span>
<span class="sd"> cases created by pg.string.split(). (Run-away quotations, primarily)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
<span class="n">quoted</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">splitted_iter</span><span class="p">)</span>
<span class="n">endq</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">i</span><span class="p">:</span>
<span class="n">s</span> <span class="o">+=</span> <span class="n">endq</span> <span class="o">+</span> <span class="n">x</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">q</span><span class="p">,</span> <span class="n">qtext</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">s</span> <span class="o">+=</span> <span class="n">q</span> <span class="o">+</span> <span class="n">qtext</span>
<span class="k">if</span> <span class="n">q</span> <span class="o">==</span> <span class="s">&quot;E&#39;&quot;</span><span class="p">:</span>
<span class="n">endq</span> <span class="o">=</span> <span class="s">&quot;&#39;&quot;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">endq</span> <span class="o">=</span> <span class="n">q</span>
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">return</span> <span class="n">s</span>
</div>
<div class="viewcode-block" id="split_using"><a class="viewcode-back" href="../../reference.html#postgresql.string.split_using">[docs]</a><span class="k">def</span> <span class="nf">split_using</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">quote</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="n">maxsplit</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> split the string on the seperator ignoring the separator in quoted areas.</span>
<span class="sd"> This is only useful for simple quoted strings. Dollar quotes, and backslash</span>
<span class="sd"> escapes are not supported.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">escape</span> <span class="o">=</span> <span class="n">quote</span> <span class="o">*</span> <span class="mi">2</span>
<span class="n">esclen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">escape</span><span class="p">)</span>
<span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">tl</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">tl</span>
<span class="c"># Fast path: No quotes? Do a simple split.</span>
<span class="k">if</span> <span class="n">quote</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">text</span><span class="p">:</span>
<span class="k">return</span> <span class="n">text</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">,</span> <span class="n">maxsplit</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="o">!=</span> <span class="n">maxsplit</span><span class="p">:</span>
<span class="c"># Look for the separator first</span>
<span class="n">nextsep</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">sep</span><span class="p">,</span> <span class="n">offset</span><span class="p">)</span>
<span class="k">if</span> <span class="n">nextsep</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="c"># it&#39;s over. there are no more seps</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># There&#39;s a sep ahead, but is there a quoted section before it?</span>
<span class="n">nextquote</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">nextsep</span><span class="p">)</span>
<span class="k">while</span> <span class="n">nextquote</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="c"># Yep, there&#39;s a quote before the sep;</span>
<span class="c"># need to eat the escaped portion.</span>
<span class="n">nextquote</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">nextquote</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,)</span>
<span class="k">while</span> <span class="n">nextquote</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="k">if</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">escape</span><span class="p">,</span> <span class="n">nextquote</span><span class="p">,</span> <span class="n">nextquote</span><span class="o">+</span><span class="n">esclen</span><span class="p">)</span> <span class="o">!=</span> <span class="n">nextquote</span><span class="p">:</span>
<span class="c"># Not an escape, so it&#39;s the end.</span>
<span class="k">break</span>
<span class="c"># Look for another quote past the escape quote.</span>
<span class="n">nextquote</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">nextquote</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># the sep was located in the escape, and</span>
<span class="c"># the escape consumed the rest of the string.</span>
<span class="n">nextsep</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">break</span>
<span class="n">nextsep</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">sep</span><span class="p">,</span> <span class="n">nextquote</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">nextsep</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="c"># it&#39;s over. there are no more seps</span>
<span class="c"># [likely they were consumed by the escape]</span>
<span class="k">break</span>
<span class="n">nextquote</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">nextquote</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nextsep</span><span class="p">)</span>
<span class="k">if</span> <span class="n">nextsep</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">l</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">text</span><span class="p">[</span><span class="n">offset</span><span class="p">:</span><span class="n">nextsep</span><span class="p">])</span>
<span class="n">offset</span> <span class="o">=</span> <span class="n">nextsep</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">l</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">text</span><span class="p">[</span><span class="n">offset</span><span class="p">:])</span>
<span class="k">return</span> <span class="n">l</span>
</div>
<div class="viewcode-block" id="split_ident"><a class="viewcode-back" href="../../reference.html#postgresql.string.split_ident">[docs]</a><span class="k">def</span> <span class="nf">split_ident</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39;,&#39;</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="s">&#39;&quot;&#39;</span><span class="p">,</span> <span class="n">maxsplit</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Split a series of identifiers using the specified separator.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">nr</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">split_using</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">quote</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="n">sep</span><span class="p">,</span> <span class="n">maxsplit</span> <span class="o">=</span> <span class="n">maxsplit</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">if</span> <span class="n">x</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">x</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s">&quot;unterminated identifier quotation&quot;</span><span class="p">,</span> <span class="n">x</span>
<span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">nr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&quot;&quot;&#39;</span><span class="p">,</span> <span class="s">&#39;&quot;&#39;</span><span class="p">))</span>
<span class="k">elif</span> <span class="n">needs_quoting</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s">&quot;non-ident characters in unquoted identifier&quot;</span><span class="p">,</span> <span class="n">x</span>
<span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># postgres implies a lower, so to stay consistent</span>
<span class="c"># with it on qname joins, lower the unquoted identifier now.</span>
<span class="n">nr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="k">return</span> <span class="n">nr</span>
</div>
<div class="viewcode-block" id="split_qname"><a class="viewcode-back" href="../../reference.html#postgresql.string.split_qname">[docs]</a><span class="k">def</span> <span class="nf">split_qname</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">maxsplit</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Call to .split_ident() with a &#39;.&#39; sep parameter.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">split_ident</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">maxsplit</span> <span class="o">=</span> <span class="n">maxsplit</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39;.&#39;</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="qname"><a class="viewcode-back" href="../../reference.html#postgresql.string.qname">[docs]</a><span class="k">def</span> <span class="nf">qname</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="s">&quot;Quote the identifiers and join them using &#39;.&#39;&quot;</span>
<span class="k">return</span> <span class="s">&#39;.&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">quote_ident</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">args</span><span class="p">])</span>
</div>
<span class="k">def</span> <span class="nf">qname_if_needed</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="k">return</span> <span class="s">&#39;.&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">quote_ident_if_needed</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">args</span><span class="p">])</span>
<div class="viewcode-block" id="split_sql"><a class="viewcode-back" href="../../reference.html#postgresql.string.split_sql">[docs]</a><span class="k">def</span> <span class="nf">split_sql</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39;;&#39;</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Given SQL, safely split using the given separator.</span>
<span class="sd"> Notably, this yields fully split text. This should be used instead of</span>
<span class="sd"> split_sql_str() when quoted sections need be still be isolated.</span>
<span class="sd"> &gt;&gt;&gt; list(split_sql(&#39;select $$1$$ AS &quot;foo;&quot;; select 2;&#39;))</span>
<span class="sd"> [[&#39;select &#39;, (&#39;$$&#39;, &#39;1&#39;), &#39; AS &#39;, (&#39;&quot;&#39;, &#39;foo;&#39;), &#39;&#39;], (&#39; select 2&#39;,), [&#39;&#39;]]</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">split</span><span class="p">(</span><span class="n">sql</span><span class="p">))</span>
<span class="n">cur</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">i</span><span class="p">:</span>
<span class="n">sections</span> <span class="o">=</span> <span class="n">part</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sections</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">cur</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">cur</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sections</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">yield</span> <span class="n">cur</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sections</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">yield</span> <span class="p">(</span><span class="n">x</span><span class="p">,)</span>
<span class="n">cur</span> <span class="o">=</span> <span class="p">[</span><span class="n">sections</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">cur</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">cur</span><span class="p">:</span>
<span class="k">yield</span> <span class="n">cur</span>
</div>
<div class="viewcode-block" id="split_sql_str"><a class="viewcode-back" href="../../reference.html#postgresql.string.split_sql_str">[docs]</a><span class="k">def</span> <span class="nf">split_sql_str</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">&#39;;&#39;</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Identical to split_sql but yields unsplit text.</span>
<span class="sd"> &gt;&gt;&gt; list(split_sql_str(&#39;select $$1$$ AS &quot;foo;&quot;; select 2;&#39;))</span>
<span class="sd"> [&#39;select $$1$$ AS &quot;foo;&quot;&#39;, &#39; select 2&#39;, &#39;&#39;]</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">split_sql</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">sep</span> <span class="o">=</span> <span class="n">sep</span><span class="p">):</span>
<span class="k">yield</span> <span class="n">unsplit</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></div>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" >postgresql</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql.sys &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../../index.html" />
<link rel="up" title="postgresql" href="../postgresql.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" accesskey="U">postgresql</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql.sys</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># .sys</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">py-postgresql system functions and data.</span>
<span class="sd">Data</span>
<span class="sd">----</span>
<span class="sd"> ``libpath``</span>
<span class="sd"> The local file system paths that contain query libraries.</span>
<span class="sd">Overridable Functions</span>
<span class="sd">---------------------</span>
<span class="sd"> excformat</span>
<span class="sd"> Information that makes up an exception&#39;s displayed &quot;body&quot;.</span>
<span class="sd"> Effectively, the implementation of `postgresql.exception.Error.__str__`</span>
<span class="sd"> msghook</span>
<span class="sd"> Display a message.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">traceback</span>
<span class="kn">from</span> <span class="nn">.python.element</span> <span class="kn">import</span> <span class="n">format_element</span>
<span class="kn">from</span> <span class="nn">.python.string</span> <span class="kn">import</span> <span class="n">indent</span>
<span class="n">libpath</span> <span class="o">=</span> <span class="p">[]</span>
<div class="viewcode-block" id="default_errformat"><a class="viewcode-back" href="../../reference.html#postgresql.sys.default_errformat">[docs]</a><span class="k">def</span> <span class="nf">default_errformat</span><span class="p">(</span><span class="n">val</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Built-in error formatter. DON&#39;T TOUCH!</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">it</span> <span class="o">=</span> <span class="n">val</span><span class="o">.</span><span class="n">_e_metas</span><span class="p">()</span>
<span class="k">if</span> <span class="n">val</span><span class="o">.</span><span class="n">creator</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="c"># Protect against element traceback failures.</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">after</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">+</span> <span class="n">format_element</span><span class="p">(</span><span class="n">val</span><span class="o">.</span><span class="n">creator</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">after</span> <span class="o">=</span> <span class="s">&#39;Element Traceback of </span><span class="si">%r</span><span class="s"> caused exception:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span><span class="p">(</span>
<span class="nb">type</span><span class="p">(</span><span class="n">val</span><span class="o">.</span><span class="n">creator</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span>
<span class="n">os</span><span class="o">.</span><span class="n">linesep</span>
<span class="p">)</span>
<span class="n">after</span> <span class="o">+=</span> <span class="n">indent</span><span class="p">(</span><span class="n">traceback</span><span class="o">.</span><span class="n">format_exc</span><span class="p">())</span>
<span class="n">after</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">+</span> <span class="n">indent</span><span class="p">(</span><span class="n">after</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">after</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
<span class="k">return</span> <span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span> \
<span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">+</span> <span class="s">&#39; &#39;</span> \
<span class="o">+</span> <span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">+</span> <span class="s">&#39; &#39;</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
<span class="n">k</span> <span class="o">+</span> <span class="s">&#39;: &#39;</span> <span class="o">+</span> <span class="n">v</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">it</span>
<span class="p">)</span> <span class="o">+</span> <span class="n">after</span>
</div>
<div class="viewcode-block" id="default_msghook"><a class="viewcode-back" href="../../reference.html#postgresql.sys.default_msghook">[docs]</a><span class="k">def</span> <span class="nf">default_msghook</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">format_message</span> <span class="o">=</span> <span class="n">format_element</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Built-in message hook. DON&#39;T TOUCH!</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">closed</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">format_message</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">sys</span><span class="o">.</span><span class="n">excepthook</span><span class="p">(</span><span class="o">*</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">())</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="c"># gasp.</span>
<span class="k">pass</span>
</div>
<div class="viewcode-block" id="errformat"><a class="viewcode-back" href="../../reference.html#postgresql.sys.errformat">[docs]</a><span class="k">def</span> <span class="nf">errformat</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Raised Database Error formatter pointing to default_excformat.</span>
<span class="sd"> Override if you like. All postgresql.exceptions.Error&#39;s are formatted using</span>
<span class="sd"> this function.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">default_errformat</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="msghook"><a class="viewcode-back" href="../../reference.html#postgresql.sys.msghook">[docs]</a><span class="k">def</span> <span class="nf">msghook</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Message hook pointing to default_msghook.</span>
<span class="sd"> Override if you like. All untrapped messages raised by</span>
<span class="sd"> driver connections come here to be printed to stderr.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">default_msghook</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="reset_errformat"><a class="viewcode-back" href="../../reference.html#postgresql.sys.reset_errformat">[docs]</a><span class="k">def</span> <span class="nf">reset_errformat</span><span class="p">(</span><span class="n">with_func</span> <span class="o">=</span> <span class="n">errformat</span><span class="p">):</span>
<span class="s">&#39;restore the original excformat function&#39;</span>
<span class="k">global</span> <span class="n">errformat</span>
<span class="n">errformat</span> <span class="o">=</span> <span class="n">with_func</span>
</div>
<div class="viewcode-block" id="reset_msghook"><a class="viewcode-back" href="../../reference.html#postgresql.sys.reset_msghook">[docs]</a><span class="k">def</span> <span class="nf">reset_msghook</span><span class="p">(</span><span class="n">with_func</span> <span class="o">=</span> <span class="n">msghook</span><span class="p">):</span>
<span class="s">&#39;restore the original msghook function&#39;</span>
<span class="k">global</span> <span class="n">msghook</span>
<span class="n">msghook</span> <span class="o">=</span> <span class="n">with_func</span></div>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" >postgresql</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>postgresql.temporal &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="../../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="../../index.html" />
<link rel="up" title="postgresql" href="../postgresql.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" accesskey="U">postgresql</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for postgresql.temporal</h1><div class="highlight"><pre>
<span class="c">##</span>
<span class="c"># .temporal - manage the temporary cluster</span>
<span class="c">##</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Temporary PostgreSQL cluster for the process.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">atexit</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
<span class="kn">from</span> <span class="nn">.cluster</span> <span class="kn">import</span> <span class="n">Cluster</span><span class="p">,</span> <span class="n">ClusterError</span>
<span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">installation</span>
<span class="kn">from</span> <span class="nn">.python.socket</span> <span class="kn">import</span> <span class="n">find_available_port</span>
<div class="viewcode-block" id="Temporal"><a class="viewcode-back" href="../../reference.html#postgresql.temporal.Temporal">[docs]</a><span class="k">class</span> <span class="nc">Temporal</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Manages a temporary cluster for the duration of the process.</span>
<span class="sd"> Instances of this class reference a distinct cluster. These clusters are</span>
<span class="sd"> transient; they will only exist until the process exits.</span>
<span class="sd"> Usage::</span>
<span class="sd"> &gt;&gt;&gt; from postgresql.temporal import pg_tmp</span>
<span class="sd"> &gt;&gt;&gt; with pg_tmp:</span>
<span class="sd"> ... ps = db.prepare(&#39;SELECT 1&#39;)</span>
<span class="sd"> ... assert ps.first() == 1</span>
<span class="sd"> Or `pg_tmp` can decorate a method or function.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c">#: Format the cluster directory name.</span>
<span class="n">cluster_dirname</span> <span class="o">=</span> <span class="s">&#39;pg_tmp_{0}_{1}&#39;</span><span class="o">.</span><span class="n">format</span>
<span class="n">cluster</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">_init_pid_</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">_local_id_</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">builtins_keys</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">&#39;connector&#39;</span><span class="p">,</span>
<span class="s">&#39;db&#39;</span><span class="p">,</span>
<span class="s">&#39;do&#39;</span><span class="p">,</span>
<span class="s">&#39;xact&#39;</span><span class="p">,</span>
<span class="s">&#39;proc&#39;</span><span class="p">,</span>
<span class="s">&#39;settings&#39;</span><span class="p">,</span>
<span class="s">&#39;prepare&#39;</span><span class="p">,</span>
<span class="s">&#39;sqlexec&#39;</span><span class="p">,</span>
<span class="s">&#39;newdb&#39;</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span> <span class="o">=</span> <span class="n">deque</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c"># identifier for keeping temporary instances unique.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">_local_id_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_id</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">_local_id_</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">callable</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">in_pg_temporal_context</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="k">with</span> <span class="bp">self</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">callable</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="nb">callable</span><span class="p">,</span> <span class="s">&#39;__name__&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">n</span><span class="p">:</span>
<span class="n">in_pg_temporal_context</span><span class="o">.</span><span class="n">__name__</span> <span class="o">=</span> <span class="n">n</span>
<span class="k">return</span> <span class="n">in_pg_temporal_context</span>
<span class="k">def</span> <span class="nf">destroy</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c"># Don&#39;t destroy if it&#39;s not the initializing process.</span>
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_init_pid_</span><span class="p">:</span>
<span class="c"># Kill all the open connections.</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">cluster</span><span class="o">.</span><span class="n">connection</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="s">&#39;test&#39;</span><span class="p">,</span> <span class="n">database</span> <span class="o">=</span> <span class="s">&#39;template1&#39;</span><span class="p">,)</span>
<span class="k">with</span> <span class="n">c</span><span class="p">:</span>
<span class="k">if</span> <span class="n">c</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="p">(</span><span class="mi">9</span><span class="p">,</span><span class="mi">1</span><span class="p">):</span>
<span class="n">c</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">terminate_backends</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">c</span><span class="o">.</span><span class="n">sys</span><span class="o">.</span><span class="n">terminate_backends_92</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="c"># Doesn&#39;t matter much if it fails.</span>
<span class="k">pass</span>
<span class="n">cluster</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cluster</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_init_pid_</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">if</span> <span class="n">cluster</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">wait_until_stopped</span><span class="p">(</span><span class="n">timeout</span> <span class="o">=</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">drop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>
<span class="n">installation_factory</span> <span class="o">=</span> <span class="n">installation</span><span class="o">.</span><span class="n">default</span><span class="p">,</span>
<span class="n">inshint</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">&#39;hint&#39;</span> <span class="p">:</span> <span class="s">&quot;Try setting the PGINSTALLATION &quot;</span> \
<span class="s">&quot;environment variable to the `pg_config` path&quot;</span>
<span class="p">}</span>
<span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">return</span>
<span class="c">##</span>
<span class="c"># Hasn&#39;t been created yet, but doesn&#39;t matter.</span>
<span class="c"># On exit, obliterate the cluster directory.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_init_pid_</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
<span class="n">atexit</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">destroy</span><span class="p">)</span>
<span class="c"># [$HOME|.]/.pg_tmpdb_{pid}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cluster_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
<span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HOME&#39;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">getcwd</span><span class="p">()),</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cluster_dirname</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_init_pid_</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_id</span><span class="p">)</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logfile</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cluster_path</span><span class="p">,</span> <span class="s">&#39;logfile&#39;</span><span class="p">)</span>
<span class="n">installation</span> <span class="o">=</span> <span class="n">installation_factory</span><span class="p">()</span>
<span class="k">if</span> <span class="n">installation</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">ClusterError</span><span class="p">(</span>
<span class="s">&#39;could not find the default pg_config&#39;</span><span class="p">,</span> <span class="n">details</span> <span class="o">=</span> <span class="n">inshint</span>
<span class="p">)</span>
<span class="n">cluster</span> <span class="o">=</span> <span class="n">Cluster</span><span class="p">(</span><span class="n">installation</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster_path</span><span class="p">,)</span>
<span class="c"># If it exists already, destroy it.</span>
<span class="k">if</span> <span class="n">cluster</span><span class="o">.</span><span class="n">initialized</span><span class="p">():</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">drop</span><span class="p">()</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="s">&#39;utf-8&#39;</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">init</span><span class="p">(</span>
<span class="n">user</span> <span class="o">=</span> <span class="s">&#39;test&#39;</span><span class="p">,</span> <span class="c"># Consistent username.</span>
<span class="n">encoding</span> <span class="o">=</span> <span class="n">cluster</span><span class="o">.</span><span class="n">encoding</span><span class="p">,</span>
<span class="n">logfile</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span>
<span class="c"># Configure</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cluster_port</span> <span class="o">=</span> <span class="n">find_available_port</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster_port</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">ClusterError</span><span class="p">(</span>
<span class="s">&#39;could not find a port for the test cluster on localhost&#39;</span><span class="p">,</span>
<span class="n">creator</span> <span class="o">=</span> <span class="n">cluster</span>
<span class="p">)</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">port</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cluster_port</span><span class="p">),</span>
<span class="n">max_connections</span> <span class="o">=</span> <span class="s">&#39;20&#39;</span><span class="p">,</span>
<span class="n">shared_buffers</span> <span class="o">=</span> <span class="s">&#39;200&#39;</span><span class="p">,</span>
<span class="n">listen_addresses</span> <span class="o">=</span> <span class="s">&#39;localhost&#39;</span><span class="p">,</span>
<span class="n">log_destination</span> <span class="o">=</span> <span class="s">&#39;stderr&#39;</span><span class="p">,</span>
<span class="n">log_min_messages</span> <span class="o">=</span> <span class="s">&#39;FATAL&#39;</span><span class="p">,</span>
<span class="n">unix_socket_directory</span> <span class="o">=</span> <span class="n">cluster</span><span class="o">.</span><span class="n">data_directory</span><span class="p">,</span>
<span class="p">))</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">max_prepared_transactions</span> <span class="o">=</span> <span class="s">&#39;10&#39;</span><span class="p">,</span>
<span class="p">))</span>
<span class="c"># Start it up.</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">logfile</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">lfo</span><span class="p">:</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="n">logfile</span> <span class="o">=</span> <span class="n">lfo</span><span class="p">)</span>
<span class="n">cluster</span><span class="o">.</span><span class="n">wait_until_started</span><span class="p">()</span>
<span class="c"># Initialize template1 and the test user database.</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">cluster</span><span class="o">.</span><span class="n">connection</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="s">&#39;test&#39;</span><span class="p">,</span> <span class="n">database</span> <span class="o">=</span> <span class="s">&#39;template1&#39;</span><span class="p">,)</span>
<span class="k">with</span> <span class="n">c</span><span class="p">:</span>
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;create database test&#39;</span><span class="p">)</span>
<span class="c"># It&#39;s ready.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cluster</span> <span class="o">=</span> <span class="n">cluster</span>
<span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span><span class="o">.</span><span class="n">connection</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="s">&#39;test&#39;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="n">extras</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">new_pg_tmp_connection</span><span class="p">(</span><span class="n">l</span> <span class="o">=</span> <span class="n">extras</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">c</span><span class="p">,</span> <span class="n">sbid</span> <span class="o">=</span> <span class="s">&#39;sandbox&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)):</span>
<span class="c"># Used to create a new connection that will be closed</span>
<span class="c"># when the context stack is popped along with &#39;db&#39;.</span>
<span class="n">l</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">clone</span><span class="p">())</span>
<span class="n">l</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="s">&#39;search_path&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">sbid</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;,&#39;</span> <span class="o">+</span> <span class="n">l</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="s">&#39;search_path&#39;</span><span class="p">]</span>
<span class="k">return</span> <span class="n">l</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="c"># The new builtins.</span>
<span class="n">builtins</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">&#39;db&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="p">,</span>
<span class="s">&#39;prepare&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">prepare</span><span class="p">,</span>
<span class="s">&#39;xact&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">xact</span><span class="p">,</span>
<span class="s">&#39;sqlexec&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">,</span>
<span class="s">&#39;do&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">do</span><span class="p">,</span>
<span class="s">&#39;settings&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">settings</span><span class="p">,</span>
<span class="s">&#39;proc&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">proc</span><span class="p">,</span>
<span class="s">&#39;connector&#39;</span> <span class="p">:</span> <span class="n">c</span><span class="o">.</span><span class="n">connector</span><span class="p">,</span>
<span class="s">&#39;new&#39;</span> <span class="p">:</span> <span class="n">new_pg_tmp_connection</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="p">:</span>
<span class="c"># Store any of those set or not set.</span>
<span class="n">current</span> <span class="o">=</span> <span class="p">{</span>
<span class="n">k</span> <span class="p">:</span> <span class="n">__builtins__</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">builtins_keys</span>
<span class="k">if</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">__builtins__</span>
<span class="p">}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">current</span><span class="p">,</span> <span class="p">[]))</span>
<span class="c"># Store and push.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">builtins</span><span class="p">,</span> <span class="n">extras</span><span class="p">))</span>
<span class="n">__builtins__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">builtins</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">pop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">drop_schema</span> <span class="o">=</span> <span class="s">&#39;DROP SCHEMA sandbox{0} CASCADE&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">):</span>
<span class="n">builtins</span><span class="p">,</span> <span class="n">extras</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="c"># restore __builtins__</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">__builtins__</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">previous</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">builtins_stack</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">builtins_keys</span><span class="p">:</span>
<span class="k">if</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">previous</span><span class="p">:</span>
<span class="n">__builtins__</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">previous</span><span class="p">[</span><span class="n">x</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># Wasn&#39;t set before.</span>
<span class="n">__builtins__</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="c"># close popped connection, but only if we&#39;re not in an interrupt.</span>
<span class="c"># However, temporal will always terminate all backends atexit.</span>
<span class="k">if</span> <span class="n">exc</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">exc</span><span class="p">,</span> <span class="ne">Exception</span><span class="p">):</span>
<span class="c"># Interrupt then close. Just in case something is lingering.</span>
<span class="k">for</span> <span class="n">xdb</span> <span class="ow">in</span> <span class="p">[</span><span class="n">builtins</span><span class="p">[</span><span class="s">&#39;db&#39;</span><span class="p">]]</span> <span class="o">+</span> <span class="nb">list</span><span class="p">(</span><span class="n">extras</span><span class="p">):</span>
<span class="k">if</span> <span class="n">xdb</span><span class="o">.</span><span class="n">closed</span> <span class="ow">is</span> <span class="bp">False</span><span class="p">:</span>
<span class="c"># In order for a clean close of the connection,</span>
<span class="c"># interrupt before closing. It is still</span>
<span class="c"># possible for the close to block, but less likely.</span>
<span class="n">xdb</span><span class="o">.</span><span class="n">interrupt</span><span class="p">()</span>
<span class="n">xdb</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="c"># Interrupted and closed all the other connections at this level;</span>
<span class="c"># now remove the sandbox schema.</span>
<span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span><span class="o">.</span><span class="n">connection</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="s">&#39;test&#39;</span><span class="p">)</span>
<span class="k">with</span> <span class="n">c</span><span class="p">:</span>
<span class="c"># Use a new connection so that the state of</span>
<span class="c"># the context connection will not have to be</span>
<span class="c"># contended with.</span>
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">drop_schema</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="c"># interrupt</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">db</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;CREATE SCHEMA sandbox&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span><span class="p">))</span>
<span class="n">db</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="s">&#39;search_path&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;sandbox&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sandbox_id</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;,&#39;</span> <span class="o">+</span> <span class="n">db</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="s">&#39;search_path&#39;</span><span class="p">]</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c"># failed to initialize sandbox schema; pop it.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">raise</span>
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">tb</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="c">#: The process&#39; temporary cluster.</span></div>
<span class="n">pg_tmp</span> <span class="o">=</span> <span class="n">Temporal</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
<li><a href="../postgresql.html" >postgresql</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
Administration
==============
This chapter covers the administration of py-postgresql. This includes
installation and other aspects of working with py-postgresql such as
environment variables and configuration files.
Installation
------------
py-postgresql uses Python's distutils package to manage the build and
installation process of the package. The normal entry point for
this is the ``setup.py`` script contained in the root project directory.
After extracting the archive and changing the into the project's directory,
installation is normally as simple as::
$ python3 ./setup.py install
However, if you need to install for use with a particular version of python,
just use the path of the executable that should be used::
$ /usr/opt/bin/python3 ./setup.py install
Environment
-----------
These environment variables effect the operation of the package:
============== ===============================================================================
PGINSTALLATION The path to the ``pg_config`` executable of the installation to use by default.
============== ===============================================================================
.. _alock:
**************
Advisory Locks
**************
.. warning:: `postgresql.alock` is a new feature in v1.0.
`Explicit Locking in PostgreSQL <http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS>`_.
PostgreSQL's advisory locks offer a cooperative synchronization primitive.
These are used in cases where an application needs access to a resource, but
using table locks may cause interference with other operations that can be
safely performed alongside the application-level, exclusive operation.
Advisory locks can be used by directly executing the stored procedures in the
database or by using the :class:`postgresql.alock.ALock` subclasses, which
provides a context manager that uses those stored procedures.
Currently, only two subclasses exist. Each represents the lock mode
supported by PostgreSQL's advisory locks:
* :class:`postgresql.alock.ShareLock`
* :class:`postgresql.alock.ExclusiveLock`
Acquiring ALocks
================
An ALock instance represents a sequence of advisory locks. A single ALock can
acquire and release multiple advisory locks by creating the instance with
multiple lock identifiers::
>>> from postgresql import alock
>>> table1_oid = 192842
>>> table2_oid = 192849
>>> l = alock.ExclusiveLock(db, (table1_oid, 0), (table2_oid, 0))
>>> l.acquire()
>>> ...
>>> l.release()
:class:`postgresql.alock.ALock` is similar to :class:`threading.RLock`; in
order for an ALock to be released, it must be released the number of times it
has been acquired. ALocks are associated with and survived by their session.
Much like how RLocks are associated with the thread they are acquired in:
acquiring an ALock again will merely increment its count.
PostgreSQL allows advisory locks to be identified using a pair of `int4` or a
single `int8`. ALock instances represent a *sequence* of those identifiers::
>>> from postgresql import alock
>>> ids = [(0,0), 0, 1]
>>> with alock.ShareLock(db, *ids):
... ...
Both types of identifiers may be used within the same ALock, and, regardless of
their type, will be aquired in the order that they were given to the class'
constructor. In the above example, ``(0,0)`` is acquired first, then ``0``, and
lastly ``1``.
ALocks
======
`postgresql.alock.ALock` is abstract; it defines the interface and some common
functionality. The lock mode is selected by choosing the appropriate subclass.
There are two:
``postgresql.alock.ExclusiveLock(database, *identifiers)``
Instantiate an ALock object representing the `identifiers` for use with the
`database`. Exclusive locks will conflict with other exclusive locks and share
locks.
``postgresql.alock.ShareLock(database, *identifiers)``
Instantiate an ALock object representing the `identifiers` for use with the
`database`. Share locks can be acquired when a share lock with the same
identifier has been acquired by another backend. However, an exclusive lock
with the same identifier will conflict.
ALock Interface Points
----------------------
Methods and properties available on :class:`postgresql.alock.ALock` instances:
``alock.acquire(blocking = True)``
Acquire the advisory locks represented by the ``alock`` object. If blocking is
`True`, the default, the method will block until locks on *all* the
identifiers have been acquired.
If blocking is `False`, acquisition may not block, and success will be
indicated by the returned object: `True` if *all* lock identifiers were
acquired and `False` if any of the lock identifiers could not be acquired.
``alock.release()``
Release the advisory locks represented by the ``alock`` object. If the lock
has not been acquired, a `RuntimeError` will be raised.
``alock.locked()``
Returns a boolean describing whether the locks are held or not. This will
return `False` if the lock connection has been closed.
``alock.__enter__()``
Alias to ``acquire``; context manager protocol. Always blocking.
``alock.__exit__(typ, val, tb)``
Alias to ``release``; context manager protocol.
Commands
********
This chapter discusses the usage of the available console scripts.
postgresql.bin.pg_python
========================
The ``pg_python`` command provides a simple way to write Python scripts against a
single target database. It acts like the regular Python console command, but
takes standard PostgreSQL options as well to specify the client parameters
to make establish connection with. The Python environment is then augmented
with the following built-ins:
``db``
The PG-API connection object.
``xact``
``db.xact``, the transaction creator.
``settings``
``db.settings``
``prepare``
``db.prepare``, the statement creator.
``proc``
``db.proc``
``do``
``db.do``, execute a single DO statement.
``sqlexec``
``db.execute``, execute multiple SQL statements (``None`` is always returned)
pg_python Usage
---------------
Usage: postgresql.bin.pg_python [connection options] [script] ...
Options:
--unix=UNIX path to filesystem socket
--ssl-mode=SSLMODE SSL requirement for connectivity: require, prefer,
allow, disable
-s SETTINGS, --setting=SETTINGS
run-time parameters to set upon connecting
-I PQ_IRI, --iri=PQ_IRI
database locator string
[pq://user:password@host:port/database?setting=value]
-h HOST, --host=HOST database server host
-p PORT, --port=PORT database server port
-U USER, --username=USER
user name to connect as
-W, --password prompt for password
-d DATABASE, --database=DATABASE
database's name
--pq-trace=PQ_TRACE trace PQ protocol transmissions
-C PYTHON_CONTEXT, --context=PYTHON_CONTEXT
Python context code to run[file://,module:,<code>]
-m PYTHON_MAIN Python module to run as script(__main__)
-c PYTHON_MAIN Python expression to run(__main__)
--version show program's version number and exit
--help show this help message and exit
Interactive Console Backslash Commands
--------------------------------------
Inspired by ``psql``::
>>> \?
Backslash Commands:
\? Show this help message.
\E Edit a file or a temporary script.
\e Edit and Execute the file directly in the context.
\i Execute a Python script within the interpreter's context.
\set Configure environment variables. \set without arguments to show all
\x Execute the Python command within this process.
pg_python Examples
------------------
Module execution taking advantage of the new built-ins::
$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit "prepare('SELECT 1').first()"
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 1.35 msec per loop
$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit -s "ps=prepare('SELECT 1')" "ps.first()"
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 442 usec per loop
Simple interactive usage::
$ python3 -m postgresql.bin.pg_python -h localhost -W
Password for pg_python[pq://jwp@localhost:5432]:
>>> ps = prepare('select 1')
>>> ps.first()
1
>>> c = ps()
>>> c.read()
[(1,)]
>>> ps.close()
>>> import sys
>>> sys.exit(0)
postgresql.bin.pg_dotconf
=========================
pg_dotconf is used to modify a PostgreSQL cluster's configuration file.
It provides a means to apply settings specified from the command line and from a
file referenced using the ``-f`` option.
.. warning::
``include`` directives in configuration files are *completely* ignored. If
modification of an included file is desired, the command must be applied to
that specific file.
pg_dotconf Usage
----------------
Usage: postgresql.bin.pg_dotconf [--stdout] [-f filepath] postgresql.conf ([param=val]|[param])*
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-f SETTINGS, --file=SETTINGS
A file of settings to *apply* to the given
"postgresql.conf"
--stdout Redirect the product to standard output instead of
writing back to the "postgresql.conf" file
Examples
--------
Modifying a simple configuration file::
$ echo "setting = value" >pg.conf
# change 'setting'
$ python3 -m postgresql.bin.pg_dotconf pg.conf setting=newvalue
$ cat pg.conf
setting = 'newvalue'
# new settings are appended to the file
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting=value
$ cat pg.conf
setting = 'newvalue'
another_setting = 'value'
# comment a setting
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting
$ cat pg.conf
setting = 'newvalue'
#another_setting = 'value'
When a setting is given on the command line, it must been seen as one argument
to the command, so it's *very* important to avoid invocations like::
$ python3 -m postgresql.bin.pg_dotconf pg.conf setting = value
ERROR: invalid setting, '=' after 'setting'
HINT: Settings must take the form 'setting=value' or 'setting_name_to_comment'. Settings must also be received as a single argument.
Changes in v1.0
===============
1.0.4 in development
--------------------
* Alter how changes are represented in documentation to simplify merging.
1.0.3 released on 2011-09-24
----------------------------
* Use raise x from y to generalize exceptions. (Elvis Pranskevichus)
* Alter postgresql.string.quote_ident to always quote. (Elvis Pranskevichus)
* Add postgresql.string.quote_ident_if_necessary (Modification of Elvis Pranskevichus' patch)
* Many postgresql.string bug fixes (Elvis Pranskevichus)
* Correct ResourceWarnings improving Python 3.2 support. (jwp)
* Add test command to setup.py (Elvis Pranskevichus)
1.0.2 released on 2010-09-18
----------------------------
* Add support for DOMAINs in registered composites. (Elvis Pranskevichus)
* Properly raise StopIteration in Cursor.__next__. (Elvis Pranskevichus)
* Add Cluster Management documentation.
* Release savepoints after rolling them back.
* Fix Startup() usage for Python 3.2.
* Emit deprecation warning when 'gid' is given to xact().
* Compensate for Python3.2's ElementTree API changes.
1.0.1 released on 2010-04-24
----------------------------
* Fix unpacking of array NULLs. (Elvis Pranskevichus)
* Fix .first()'s handling of counts and commands.
Bad logic caused zero-counts to return the command tag.
* Don't interrupt and close a temporal connection if it's not open.
* Use the Driver's typio attribute for TypeIO overrides. (Elvis Pranskevichus)
1.0 released on 2010-03-27
--------------------------
* **DEPRECATION**: Removed 2PC support documentation.
* **DEPRECATION**: Removed pg_python and pg_dotconf 'scripts'.
They are still accessible by python3 -m postgresql.bin.pg_*
* Add support for binary hstore.
* Add support for user service files.
* Implement a Copy manager for direct connection-to-connection COPY operations.
* Added db.do() method for DO-statement support(convenience method).
* Set the default client_min_messages level to WARNING.
NOTICEs are often not desired by programmers, and py-postgresql's
high verbosity further irritates that case.
* Added postgresql.project module to provide project information.
Project name, author, version, etc.
* Increased default recvsize and chunksize for improved performance.
* 'D' messages are special cased as builtins.tuples instead of
protocol.element3.Tuple
* Alter Statement.chunks() to return chunks of builtins.tuple. Being
an interface intended for speed, types.Row() impedes its performance.
* Fix handling of infinity values with timestamptz, timestamp, and date.
[Bug reported by Axel Rau.]
* Correct representation of PostgreSQL ARRAYs by properly recording
lowerbounds and upperbounds. Internally, sub-ARRAYs have their own
element lists.
* Implement a NotificationManager for managing the NOTIFYs received
by a connection. The class can manage NOTIFYs from multiple
connections, whereas the db.wait() method is tailored for single targets.
* Implement an ALock class for managing advisory locks using the
threading.Lock APIs. [Feedback from Valentine Gogichashvili]
* Implement reference symbols. Allow libraries to define symbols that
are used to create queries that inherit the original symbol's type and
execution method. ``db.prepare(db.prepare(...).first())``
* Fix handling of unix domain sockets by pg.open and driver.connect.
[Reported by twitter.com/rintavarustus]
* Fix typo/dropped parts of a raise LoadError in .lib.
[Reported by Vlad Pranskevichus]
* Fix db.tracer and pg_python's --pq-trace=
* Fix count return from .first() method. Failed to provide an empty
tuple for the rformats of the bind statement.
[Reported by dou dou]
Changes in v1.1
===============
1.1.0
-----
* Remove two-phase commit interfaces per deprecation in v1.0.
For proper two phase commit use, a lock manager must be employed that
the implementation did nothing to accommodate for.
* Add support for unpacking anonymous records (Elvis)
* Support PostgreSQL 9.2 (Elvis)
* Python 3.3 Support (Elvis)
* Add column execution method. (jwp)
* Add one-shot statement interface. Connection.query.* (jwp)
* Modify the inet/cidr support by relying on the ipaddress module introduced in Python 3.3 (Google's ipaddr project)
The existing implementation relied on simple str() representation supported by the
socket module. Unfortunately, MS Windows' socket library does not appear to support the
necessary functionality, or Python's socket module does not expose it. ipaddress fixes
the problem.
.. note::
The `ipaddress` module is now required for local inet and cidr. While it is
of "preliminary" status, the ipaddr project has been around for some time and
well supported. ipaddress appears to be the safest way forward for native
network types.
Client Parameters
*****************
.. warning:: **The interfaces dealing with optparse are subject to change in 1.0**.
There are various sources of parameters used by PostgreSQL client applications.
The `postgresql.clientparameters` module provides a means for collecting and
managing those parameters.
Connection creation interfaces in `postgresql.driver` are purposefully simple.
All parameters taken by those interfaces are keywords, and are taken
literally; if a parameter is not given, it will effectively be `None`.
libpq-based drivers tend differ as they inherit some default client parameters
from the environment. Doing this by default is undesirable as it can cause
trivial failures due to unexpected parameter inheritance. However, using these
parameters from the environment and other sources are simply expected in *some*
cases: `postgresql.open`, `postgresql.bin.pg_python`, and other high-level
utilities. The `postgresql.clientparameters` module provides a means to collect
them into one dictionary object for subsequent application to a connection
creation interface.
`postgresql.clientparameters` is primarily useful to script authors that want to
provide an interface consistent with PostgreSQL commands like ``psql``.
Collecting Parameters
=====================
The primary entry points in `postgresql.clientparameters` are
`postgresql.clientparameters.collect` and
`postgresql.clientparameters.resolve_password`.
For most purposes, ``collect`` will suffice. By default, it will prompt for the
password if instructed to(``-W``). Therefore, ``resolve_password`` need not be
used in most cases::
>>> import sys
>>> import postgresql.clientparameters as pg_param
>>> p = pg_param.DefaultParser()
>>> co, ca = p.parse_args(sys.argv[1:])
>>> params = pg_param.collect(parsed_options = co)
The `postgresql.clientparameters` module is executable, so you can see the
results of the above snippet by::
$ python -m postgresql.clientparameters -h localhost -U a_db_user -ssearch_path=public
{'host': 'localhost',
'password': None,
'port': 5432,
'settings': {'search_path': 'public'},
'user': 'a_db_user'}
`postgresql.clientparameters.collect`
--------------------------------------
Build a client parameter dictionary from the environment and parsed command
line options. The following is a list of keyword arguments that ``collect`` will
accept:
``parsed_options``
Options parsed by `postgresql.clientparameters.StandardParser` or
`postgresql.clientparameters.DefaultParser` instances.
``no_defaults``
When `True`, don't include defaults like ``pgpassfile`` and ``user``.
Defaults to `False`.
``environ``
Environment variables to extract client parameter variables from.
Defaults to `os.environ` and expects a `collections.Mapping` interface.
``environ_prefix``
Environment variable prefix to use. Defaults to "PG". This allows the
collection of non-standard environment variables whose keys are partially
consistent with the standard variants. e.g. "PG_SRC_USER", "PG_SRC_HOST",
etc.
``default_pg_sysconfdir``
The location of the pg_service.conf file. The ``PGSYSCONFDIR`` environment
variable will override this. When a default installation is present,
``PGINSTALLATION``, it should be set to this.
``pg_service_file``
Explicit location of the service file. This will override the "sysconfdir"
based path.
``prompt_title``
Descriptive title to use if a password prompt is needed. `None` to disable
password resolution entirely. Setting this to `None` will also disable
pgpassfile lookups, so it is necessary that further processing occurs when
this is `None`.
``parameters``
Base client parameters to use. These are set after the *defaults* are
collected. (The defaults that can be disabled by ``no_defaults``).
If ``prompt_title`` is not set to `None`, it will prompt for the password when
instructed to do by the ``prompt_password`` key in the parameters::
>>> import postgresql.clientparameters as pg_param
>>> p = pg_param.collect(prompt_title = 'my_prompt!', parameters = {'prompt_password':True})
Password for my_prompt![pq://jwp@localhost:5432]:
>>> p
{'host': 'localhost', 'user': 'jwp', 'password': 'secret', 'port': 5432}
If `None`, it will leave the necessary password resolution information in the
parameters dictionary for ``resolve_password``::
>>> p = pg_param.collect(prompt_title = None, parameters = {'prompt_password':True})
>>> p
{'pgpassfile': '/Users/jwp/.pgpass', 'prompt_password': True, 'host': 'localhost', 'user': 'jwp', 'port': 5432}
Of course, ``'prompt_password'`` is normally specified when ``parsed_options``
received a ``-W`` option from the command line::
>>> op = pg_param.DefaultParser()
>>> co, ca = op.parse_args(['-W'])
>>> p = pg_param.collect(parsed_options = co)
>>> p=pg_param.collect(parsed_options = co)
Password for [pq://jwp@localhost:5432]:
>>> p
{'host': 'localhost', 'user': 'jwp', 'password': 'secret', 'port': 5432}
>>>
`postgresql.clientparameters.resolve_password`
----------------------------------------------
Resolve the password for the given client parameters dictionary returned by
``collect``. By default, this function need not be used as ``collect`` will
resolve the password by default. `resolve_password` accepts the following
arguments:
``parameters``
First positional argument. Normalized client parameters dictionary to update
in-place with the resolved password. If the 'prompt_password' key is in
``parameters``, it will prompt regardless(normally comes from ``-W``).
``getpass``
Function to call to prompt for the password. Defaults to `getpass.getpass`.
``prompt_title``
Additional title to use if a prompt is requested. This can also be specified
in the ``parameters`` as the ``prompt_title`` key. This *augments* the IRI
display on the prompt. Defaults to an empty string, ``''``.
The resolution process is effected by the contents of the given ``parameters``.
Notable keywords:
``prompt_password``
If present in the given parameters, the user will be prompted for the using
the given ``getpass`` function. This disables the password file lookup
process.
``prompt_title``
This states a default prompt title to use. If the ``prompt_title`` keyword
argument is given to ``resolve_password``, this will not be used.
``pgpassfile``
The PostgreSQL password file to lookup the password in. If the ``password``
parameter is present, this will not be used.
When resolution occurs, the ``prompt_password``, ``prompt_title``, and
``pgpassfile`` keys are *removed* from the given parameters dictionary::
>>> p=pg_param.collect(prompt_title = None)
>>> p
{'pgpassfile': '/Users/jwp/.pgpass', 'host': 'localhost', 'user': 'jwp', 'port': 5432}
>>> pg_param.resolve_password(p)
>>> p
{'host': 'localhost', 'password': 'secret', 'user': 'jwp', 'port': 5432}
Defaults
========
The following is a list of default parameters provided by ``collect`` and the
sources of their values:
==================== ===================================================================
Key Value
==================== ===================================================================
``'user'`` `getpass.getuser()` or ``'postgres'``
``'host'`` `postgresql.clientparameters.default_host` (``'localhost'``)
``'port'`` `postgresql.clientparameters.default_port` (``5432``)
``'pgpassfile'`` ``"$HOME/.pgpassfile"`` or ``[PGDATA]`` + ``'pgpass.conf'`` (Win32)
``'sslcrtfile'`` ``[PGDATA]`` + ``'postgresql.crt'``
``'sslkeyfile'`` ``[PGDATA]`` + ``'postgresql.key'``
``'sslrootcrtfile'`` ``[PGDATA]`` + ``'root.crt'``
``'sslrootcrlfile'`` ``[PGDATA]`` + ``'root.crl'``
==================== ===================================================================
``[PGDATA]`` referenced in the above table is a directory whose path is platform
dependent. On most systems, it is ``"$HOME/.postgresql"``, but on Windows based
systems it is ``"%APPDATA%\postgresql"``
.. note::
[PGDATA] is *not* an environment variable.
.. _pg_envvars:
PostgreSQL Environment Variables
================================
The following is a list of environment variables that will be collected by the
`postgresql.clientparameter.collect` function using "PG" as the
``environ_prefix`` and the keyword that it will be mapped to:
===================== ======================================
Environment Variable Keyword
===================== ======================================
``PGUSER`` ``'user'``
``PGDATABASE`` ``'database'``
``PGHOST`` ``'host'``
``PGPORT`` ``'port'``
``PGPASSWORD`` ``'password'``
``PGSSLMODE`` ``'sslmode'``
``PGSSLKEY`` ``'sslkey'``
``PGCONNECT_TIMEOUT`` ``'connect_timeout'``
``PGREALM`` ``'kerberos4_realm'``
``PGKRBSRVNAME`` ``'kerberos5_service'``
``PGPASSFILE`` ``'pgpassfile'``
``PGTZ`` ``'settings' = {'timezone': }``
``PGDATESTYLE`` ``'settings' = {'datestyle': }``
``PGCLIENTENCODING`` ``'settings' = {'client_encoding': }``
``PGGEQO`` ``'settings' = {'geqo': }``
===================== ======================================
.. _pg_passfile:
PostgreSQL Password File
========================
The password file is a simple newline separated list of ``:`` separated fields. It
is located at ``$HOME/.pgpass`` for most systems and at
``%APPDATA%\postgresql\pgpass.conf`` for Windows based systems. However, the
``PGPASSFILE`` environment variable may be used to override that location.
The lines in the file must be in the following form::
hostname:port:database:username:password
A single asterisk, ``*``, may be used to indicate that any value will match the
field. However, this only effects fields other than ``password``.
See http://www.postgresql.org/docs/current/static/libpq-pgpass.html for more
details.
Client parameters produced by ``collect`` that have not been processed
by ``resolve_password`` will include a ``'pgpassfile'`` key. This is the value
that ``resolve_password`` will use to locate the pgpassfile to interrogate if a
password key is not present and it is not instructed to prompt for a password.
.. warning::
Connection creation interfaces will *not* resolve ``'pgpassfile'``, so it is
important that the parameters produced by ``collect()`` are properly processed
before an attempt is made to establish a connection.
.. _cluster_management:
******************
Cluster Management
******************
py-postgresql provides cluster management tools in order to give the user
fine-grained control over a PostgreSQL cluster and access to information about an
installation of PostgreSQL.
.. _installation:
Installations
=============
`postgresql.installation.Installation` objects are primarily used to
access PostgreSQL installation information. Normally, they are created using a
dictionary constructed from the output of the pg_config_ executable::
from postgresql.installation import Installation, pg_config_dictionary
pg_install = Installation(pg_config_dictionary('/usr/local/pgsql/bin/pg_config'))
The extraction of pg_config_ information is isolated from Installation
instantiation in order to allow Installations to be created from arbitrary
dictionaries. This can be useful in cases where the installation layout is
inconsistent with the standard PostgreSQL installation layout, or if a faux
Installation needs to be created for testing purposes.
Installation Interface Points
-----------------------------
``Installation(info)``
Instantiate an Installation using the given information. Normally, this
information is extracted from a pg_config_ executable using
`postgresql.installation.pg_config_dictionary`::
info = pg_config_dictionary('/usr/local/pgsql/bin/pg_config')
pg_install = Installation(info)
``Installation.version``
The installation's version string::
pg_install.version
'PostgreSQL 9.0devel'
``Installation.version_info``
A tuple containing the version's ``(major, minor, patch, state, level)``.
Where ``major``, ``minor``, ``patch``, and ``level`` are `int` objects, and
``state`` is a `str` object::
pg_install.version_info
(9, 0, 0, 'devel', 0)
``Installation.ssl``
A `bool` indicating whether or not the installation has SSL support.
``Installation.configure_options``
The options given to the ``configure`` script that built the installation. The
options are represented using a dictionary object whose keys are normalized
long option names, and whose values are the option's argument. If the option
takes no argument, `True` will be used as the value.
The normalization of the long option names consists of removing the preceding
dashes, lowering the string, and replacing any dashes with underscores. For
instance, ``--enable-debug`` will be ``enable_debug``::
pg_install.configure_options
{'enable_debug': True, 'with_libxml': True,
'enable_cassert': True, 'with_libedit_preferred': True,
'prefix': '/src/build/pg90', 'with_openssl': True,
'enable_integer_datetimes': True, 'enable_depend': True}
``Installation.paths``
The paths of the installation as a dictionary where the keys are the path
identifiers and the values are the absolute file system paths. For instance,
``'bindir'`` is associated with ``$PREFIX/bin``, ``'libdir'`` is associated
with ``$PREFIX/lib``, etc. The paths included in this dictionary are
listed on the class' attributes: `Installation.pg_directories` and
`Installation.pg_executables`.
The keys that point to installation directories are: ``bindir``, ``docdir``,
``includedir``, ``pkgincludedir``, ``includedir_server``, ``libdir``,
``pkglibdir``, ``localedir``, ``mandir``, ``sharedir``, and ``sysconfdir``.
The keys that point to installation executables are: ``pg_config``, ``psql``,
``initdb``, ``pg_resetxlog``, ``pg_controldata``, ``clusterdb``, ``pg_ctl``,
``pg_dump``, ``pg_dumpall``, ``postgres``, ``postmaster``, ``reindexdb``,
``vacuumdb``, ``ipcclean``, ``createdb``, ``ecpg``, ``createuser``,
``createlang``, ``droplang``, ``dropuser``, and ``pg_restore``.
.. note:: If the executable does not exist, the value will be `None` instead
of an absoluate path.
To get the path to the psql_ executable::
from postgresql.installation import Installation
pg_install = Installation('/usr/local/pgsql/bin/pg_config')
psql_path = pg_install.paths['psql']
Clusters
========
`postgresql.cluster.Cluster` is the class used to manage a PostgreSQL
cluster--a data directory created by initdb_. A Cluster represents a data
directory with respect to a given installation of PostgreSQL, so
creating a `postgresql.cluster.Cluster` object requires a
`postgresql.installation.Installation`, and a
file system path to the data directory.
In part, a `postgresql.cluster.Cluster` is the Python programmer's variant of
the pg_ctl_ command. However, it goes beyond the basic process control
functionality and extends into initialization and configuration as well.
A Cluster manages the server process using the `subprocess` module and
signals. The `subprocess.Popen` object, ``Cluster.daemon_process``, is
retained when the Cluster starts the server process itself. This gives
the Cluster access to the result code of server process when it exits, and the
ability to redirect stderr and stdout to a parameterized file object using
subprocess features.
Despite its use of `subprocess`, Clusters can control a server process
that was *not* started by the Cluster's ``start`` method.
Initializing Clusters
---------------------
`postgresql.cluster.Cluster` provides a method for initializing a
`Cluster`'s data directory, ``init``. This method provides a Python interface to
the PostgreSQL initdb_ command.
``init`` is a regular method and accepts a few keyword parameters. Normally,
parameters are directly mapped to initdb_ command options. However, ``password``
makes use of initdb's capability to read the superuser's password from a file.
To do this, a temporary file is allocated internally by the method::
from postgresql.installation import Installation, pg_config_dictionary
from postgresql.cluster import Cluster
pg_install = Installation(pg_config_dictionary('/usr/local/pgsql/bin/pg_config'))
pg_cluster = Cluster(pg_install, 'pg_data')
pg_cluster.init(user = 'pg', password = 'secret', encoding = 'utf-8')
The init method will block until the initdb command is complete. Once
initialized, the Cluster may be configured.
Configuring Clusters
--------------------
A Cluster's `configuration file`_ can be manipulated using the
`Cluster.settings` mapping. The mapping's methods will always access the
configuration file, so it may be desirable to cache repeat reads. Also, if
multiple settings are being applied, using the ``update()`` method may be
important to avoid writing the entire file multiple times::
pg_cluster.settings.update({'listen_addresses' : 'localhost', 'port' : '6543'})
Similarly, to avoid opening and reading the entire file multiple times,
`Cluster.settings.getset` should be used to retrieve multiple settings::
d = pg_cluster.settings.getset(set(('listen_addresses', 'port')))
d
{'listen_addresses' : 'localhost', 'port' : '6543'}
Values contained in ``settings`` are always Python strings::
assert pg_cluster.settings['max_connections'].__class__ is str
The ``postgresql.conf`` file is only one part of the server configuration.
Structured access and manipulation of the pg_hba_ file is not
supported. Clusters only provide the file path to the pg_hba_ file::
hba = open(pg_cluster.hba_file)
If the configuration of the Cluster is altered while the server process is
running, it may be necessary to signal the process that configuration changes
have been made. This signal can be sent using the ``Cluster.reload()`` method.
``Cluster.reload()`` will send a SIGHUP signal to the server process. However,
not all changes to configuration settings can go into effect after calling
``Cluster.reload()``. In those cases, the server process will need to be
shutdown and started again.
Controlling Clusters
--------------------
The server process of a Cluster object can be controlled with the ``start()``,
``stop()``, ``shutdown()``, ``kill()``, and ``restart()`` methods.
These methods start the server process, signal the server process, or, in the
case of restart, a combination of the two.
When a Cluster starts the server process, it's ran as a subprocess. Therefore,
if the current process exits, the server process will exit as well. ``start()``
does *not* automatically daemonize the server process.
.. note:: Under Microsoft Windows, above does not hold true. The server process
will continue running despite the exit of the parent process.
To terminate a server process, one of these three methods should be called:
``stop``, ``shutdown``, or ``kill``. ``stop`` is a graceful shutdown and will
*wait for all clients to disconnect* before shutting down. ``shutdown`` will
close any open connections and safely shutdown the server process.
``kill`` will immediately terminate the server process leading to recovery upon
starting the server process again.
.. note:: Using ``kill`` may cause shared memory to be leaked.
Normally, `Cluster.shutdown` is the appropriate way to terminate a server
process.
Cluster Interface Points
------------------------
Methods and properties available on `postgresql.cluster.Cluster` instances:
``Cluster(installation, data_directory)``
Create a `postgresql.cluster.Cluster` object for the specified
`postgresql.installation.Installation`, and ``data_directory``.
The ``data_directory`` must be an absoluate file system path. The directory
does *not* need to exist. The ``init()`` method may later be used to create
the cluster.
``Cluster.installation``
The Cluster's `postgresql.installation.Installation` instance.
``Cluster.data_directory``
The absolute path to the PostgreSQL data directory.
This directory may not exist.
``Cluster.init([encoding = None[, user = None[, password = None]]])``
Run the `initdb`_ executable of the configured installation to initialize the
cluster at the configured data directory, `Cluster.data_directory`.
``encoding`` is mapped to ``-E``, the default database encoding. By default,
the encoding is determined from the environment's locale.
``user`` is mapped to ``-U``, the database superuser name. By default, the
current user's name.
``password`` is ultimately mapped to ``--pwfile``. The argument given to the
long option is actually a path to the temporary file that holds the given
password.
Raises `postgresql.cluster.InitDBError` when initdb_ returns a non-zero result
code.
Raises `postgresql.cluster.ClusterInitializationError` when there is no
initdb_ in the Installation.
``Cluster.initialized()``
Whether or not the data directory exists, *and* if it looks like a PostgreSQL
data directory. Meaning, the directory must contain a ``postgresql.conf`` file
and a ``base`` directory.
``Cluster.drop()``
Shutdown the Cluster's server process and completely remove the
`Cluster.data_directory` from the file system.
``Cluster.pid()``
The server's process identifier as a Python `int`. `None` if there is no
server process running.
This is a method rather than a property as it may read the PID from a file
in cases where the server process was not started by the Cluster.
``Cluster.start([logfile = None[, settings = None]])``
Start the PostgreSQL server process for the Cluster if it is not
already running. This will execute postgres_ as a subprocess.
If ``logfile``, an opened and writable file object, is given, stderr and
stdout will be redirected to that file. By default, both stderr and stdout are
closed.
If ``settings`` is given, the mapping or sequence of pairs will be used as
long options to the subprocess. For each item, ``--{key}={value}`` will be
given as an argument to the subprocess.
``Cluster.running()``
Whether or not the cluster's server process is running. Returns `True` or
`False`. Even if `True` is returned, it does *not* mean that the server
process is ready to accept connections.
``Cluster.ready_for_connections()``
Whether or not the Cluster is ready to accept connections. Usually called
after `Cluster.start`.
Returns `True` when the Cluster can accept connections, `False` when it
cannot, and `None` if the Cluster's server process is not running at all.
``Cluster.wait_until_started([timeout = 10[, delay = 0.05]])``
Blocks the process until the cluster is identified as being ready for
connections. Usually called after ``Cluster.start()``.
Raises `postgresql.cluster.ClusterNotRunningError` if the server process is
not running at all.
Raises `postgresql.cluster.ClusterTimeoutError` if
`Cluster.ready_for_connections()` does not return `True` within the given
`timeout` period.
Raises `postgresql.cluster.ClusterStartupError` if the server process
terminates while polling for readiness.
``timeout`` and ``delay`` are both in seconds. Where ``timeout`` is the
maximum time to wait for the Cluster to be ready for connections, and
``delay`` is the time to sleep between calls to
`Cluster.ready_for_connections()`.
``Cluster.stop()``
Signal the cluster to shutdown when possible. The *server* will wait for all
clients to disconnect before shutting down.
``Cluster.shutdown()``
Signal the cluster to shutdown immediately. Any open client connections will
be closed.
``Cluster.kill()``
Signal the absolute destruction of the server process(SIGKILL).
*This will require recovery when the cluster is started again.*
*Shared memory may be leaked.*
``Cluster.wait_until_stopped([timeout = 10[, delay = 0.05]])``
Blocks the process until the cluster is identified as being shutdown. Usually
called after `Cluster.stop` or `Cluster.shutdown`.
Raises `postgresql.cluster.ClusterTimeoutError` if
`Cluster.ready_for_connections` does not return `None` within the given
`timeout` period.
``Cluster.reload()``
Signal the server that it should reload its configuration files(SIGHUP).
Usually called after manipulating `Cluster.settings` or modifying the
contents of `Cluster.hba_file`.
``Cluster.restart([logfile = None[, settings = None[, timeout = 10]]])``
Stop the server process, wait until it is stopped, start the server
process, and wait until it has started.
.. note:: This calls ``Cluster.stop()``, so it will wait until clients
disconnect before starting up again.
The ``logfile`` and ``settings`` parameters will be given to `Cluster.start`.
``timeout`` will be given to `Cluster.wait_until_stopped` and
`Cluster.wait_until_started`.
``Cluster.settings``
A `collections.Mapping` interface to the ``postgresql.conf`` file of the
cluster.
A notable extension to the mapping interface is the ``getset`` method. This
method will return a dictionary object containing the settings whose names
were contained in the `set` object given to the method.
This method should be used when multiple settings need to be retrieved from
the configuration file.
``Cluster.hba_file``
The path to the cluster's pg_hba_ file. This property respects the HBA file
location setting in ``postgresql.conf``. Usually, ``$PGDATA/pg_hba.conf``.
``Cluster.daemon_path``
The path to the executable to use to start the server process.
``Cluster.daemon_process``
The `subprocess.Popen` instance of the server process. `None` if the server
process was not started or was not started using the Cluster object.
.. _pg_hba: http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html
.. _pg_config: http://www.postgresql.org/docs/current/static/app-pgconfig.html
.. _initdb: http://www.postgresql.org/docs/current/static/app-initdb.html
.. _psql: http://www.postgresql.org/docs/current/static/app-psql.html
.. _postgres: http://www.postgresql.org/docs/current/static/app-postgres.html
.. _pg_ctl: http://www.postgresql.org/docs/current/static/app-pg-ctl.html
.. _configuration file: http://www.postgresql.org/docs/current/static/runtime-config.html
.. _pg_copyman:
***************
Copy Management
***************
The `postgresql.copyman` module provides a way to quickly move COPY data coming
from one connection to many connections. Alternatively, it can be sourced
by arbitrary iterators and target arbitrary callables.
Statement execution methods offer a way for running COPY operations
with iterators, but the cost of allocating objects for each row is too
significant for transferring gigabytes of COPY data from one connection to
another. The interfaces available on statement objects are primarily intended to
be used when transferring COPY data to and from arbitrary Python
objects.
Direct connection-to-connection COPY operations can be performed using the
high-level `postgresql.copyman.transfer` function::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> total_rows, total_bytes = copyman.transfer(send_stmt, receive_stmt)
However, if more control is needed, the `postgresql.copyman.CopyManager` class
should be used directly.
Copy Managers
=============
The `postgresql.copyman.CopyManager` class manages the Producer and the
Receivers involved in a COPY operation. Normally,
`postgresql.copyman.StatementProducer` and
`postgresql.copyman.StatementReceiver` instances. Naturally, a Producer is the
object that produces the COPY data to be given to the Manager's Receivers.
Using a Manager directly means that there is a need for more control over
the operation. The Manager is both a context manager and an iterator. The
context manager interfaces handle initialization and finalization of the COPY
state, and the iterator provides an event loop emitting information about the
amount of COPY data transferred this cycle. Normal usage takes the form::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
As an alternative to a for-loop inside a with-statement block, the `run` method
can be called to perform the operation::
>>> with source.xact(), destination.xact():
... copyman.CopyManager(producer, receiver).run()
However, there is little benefit beyond using the high-level
`postgresql.copyman.transfer` function.
Manager Interface Points
------------------------
Primarily, the `postgresql.copyman.CopyManager` provides a context manager and
an iterator for controlling the COPY operation.
``CopyManager.run()``
Perform the entire COPY operation.
``CopyManager.__enter__()``
Start the COPY operation. Connections taking part in the COPY should **not**
be used until ``__exit__`` is ran.
``CopyManager.__exit__(typ, val, tb)``
Finish the COPY operation. Fails in the case of an incomplete
COPY, or an untrapped exception. Either returns `None` or raises the generalized
exception, `postgresql.copyman.CopyFail`.
``CopyManager.__iter__()``
Returns the CopyManager instance.
``CopyManager.__next__()``
Transfer the next chunk of COPY data to the receivers. Yields a tuple
consisting of the number of messages and bytes transferred,
``(num_messages, num_bytes)``. Raises `StopIteration` when complete.
Raises `postgresql.copyman.ReceiverFault` when a Receiver raises an
exception.
Raises `postgresql.copyman.ProducerFault` when the Producer raises an
exception. The original exception is available via the exception's
``__context__`` attribute.
``CopyManager.reconcile(faulted_receiver)``
Reconcile a faulted receiver. When a receiver faults, it will no longer
be in the set of Receivers. This method is used to signal to the manager that the
problem has been corrected, and the receiver is again ready to receive.
``CopyManager.receivers``
The `builtins.set` of Receivers involved in the COPY operation.
``CopyManager.producer``
The Producer emitting the data to be given to the Receivers.
Faults
======
The CopyManager generalizes any exceptions that occur during transfer. While
inside the context manager, `postgresql.copyman.Fault` may be raised if a
Receiver or a Producer raises an exception. A `postgresql.copyman.ProducerFault`
in the case of the Producer, and `postgresql.copyman.ReceiverFault` in the case
of the Receivers.
.. note::
Faults are only raised by `postgresql.copyman.CopyManager.__next__`. The
``run()`` method will only raise `postgresql.copyman.CopyFail`.
Receiver Faults
---------------
The Manager assumes the Fault is fatal to a Receiver, and immediately removes
it from the set of target receivers. Additionally, if the Fault exception goes
untrapped, the copy will ultimately fail.
The Fault exception references the Manager that raised the exception, and the
actual exceptions that occurred associated with the Receiver that caused them.
In order to identify the exception that caused a Fault, the ``faults`` attribute
on the `postgresql.copyman.ReceiverFault` must be referenced::
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... while copy.receivers:
... try:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
... break
... except copyman.ReceiverFault as cf:
... # Access the original exception using the receiver as the key.
... original_exception = cf.faults[receiver]
... if unknown_failure(original_exception):
... ...
... raise
ReceiverFault Properties
~~~~~~~~~~~~~~~~~~~~~~~~
The following attributes exist on `postgresql.copyman.ReceiverFault` instances:
``ReceiverFault.manager``
The subject `postgresql.copyman.CopyManager` instance.
``ReceiverFault.faults``
A dictionary mapping the Receiver to the exception raised by that Receiver.
Reconciliation
~~~~~~~~~~~~~~
When a `postgresql.copyman.ReceiverFault` is raised, the Manager immediately
removes the Receiver so that the COPY operation can continue. Continuation of
the COPY can occur by trapping the exception and continuing the iteration of the
Manager. However, if the fault is recoverable, the
`postgresql.copyman.CopyManager.reconcile` method must be used to reintroduce the
Receiver into the Manager's set. Faults must be trapped from within the
Manager's context::
>>> import socket
>>> from postgresql import copyman
>>> send_stmt = source.prepare("COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT")
>>> destination.execute("CREATE TEMP TABLE loading_table (i int8)")
>>> receive_stmt = destination.prepare("COPY loading_table FROM STDIN")
>>> producer = copyman.StatementProducer(send_stmt)
>>> receiver = copyman.StatementReceiver(receive_stmt)
>>>
>>> with source.xact(), destination.xact():
... with copyman.CopyManager(producer, receiver) as copy:
... while copy.receivers:
... try:
... for num_messages, num_bytes in copy:
... update_rate(num_bytes)
... except copyman.ReceiverFault as cf:
... if isinstance(cf.faults[receiver], socket.timeout):
... copy.reconcile(receiver)
... else:
... raise
Recovering from Faults does add significant complexity to a COPY operation,
so, often, it's best to avoid conditions in which reconciliable Faults may
occur.
Producer Faults
---------------
Producer faults are normally fatal to the COPY operation and should rarely be
trapped. However, the Manager makes no state changes when a Producer faults,
so, unlike Receiver Faults, no reconciliation process is necessary; rather,
if it's safe to continue, the Manager's iterator should continue to be
processed.
ProducerFault Properties
~~~~~~~~~~~~~~~~~~~~~~~~
The following attributes exist on `postgresql.copyman.ProducerFault` instances:
``ReceiverFault.manager``
The subject `postgresql.copyman.CopyManager`.
``ReceiverFault.__context__``
The original exception raised by the Producer.
Failures
========
When a COPY operation is aborted, either by an exception or by the iterator
being broken, a `postgresql.copyman.CopyFail` exception will be raised by the
Manager's ``__exit__()`` method. The `postgresql.copyman.CopyFail` exception
offers to record any exceptions that occur during the exit of the context
managers of the Producer and the Receivers.
CopyFail Properties
-------------------
The following properties exist on `postgresql.copyman.CopyFail` exceptions:
``CopyFail.manager``
The Manager whose COPY operation failed.
``CopyFail.receiver_faults``
A dictionary mapping a `postgresql.copyman.Receiver` to the exception raised
by that Receiver's ``__exit__``. `None` if no exceptions were raised by the
Receivers.
``CopyFail.producer_fault``
The exception Raised by the `postgresql.copyman.Producer`. `None` if none.
Producers
=========
The following Producers are available:
``postgresql.copyman.StatementProducer(postgresql.api.Statement)``
Given a Statement producing COPY data, construct a Producer.
``postgresql.copyman.IteratorProducer(collections.Iterator)``
Given an Iterator producing *chunks* of COPY lines, construct a Producer to
manage the data coming from the iterator.
Receivers
=========
``postgresql.copyman.StatementReceiver(postgresql.api.Statement)``
Given a Statement producing COPY data, construct a Producer.
``postgresql.copyman.CallReceiver(callable)``
Given a callable, construct a Receiver that will transmit COPY data in chunks
of lines. That is, the callable will be given a list of COPY lines for each
transfer cycle.
Terminology
===========
The following terms are regularly used to describe the implementation and
processes of the `postgresql.copyman` module:
Manager
The object used to manage data coming from a Producer and being given to the
Receivers. It also manages the necessary initialization and finalization steps
required by those factors.
Producer
The object used to produce the COPY data to be given to the Receivers. The
source.
Receiver
An object that consumes COPY data. A target.
Fault
Specifically, `postgresql.copyman.Fault` exceptions. A Fault is raised
when a Receiver or a Producer raises an exception during the COPY operation.
Reconciliation
Generally, the steps performed by the "reconcile" method on
`postgresql.copyman.CopyManager` instances. More precisely, the
necessary steps for a Receiver's reintroduction into the COPY operation after
a Fault.
Failed Copy
A failed copy is an aborted COPY operation. This occurs in situations of
untrapped exceptions or an incomplete COPY. Specifically, the COPY will be
noted as failed in cases where the Manager's iterator is *not* ran until
exhaustion.
Realignment
The process of providing compensating data to the Receivers so that the
connection will be on a message boundary. Occurs when the COPY operation
is aborted.

Sorry, the diff of this file is too big to display

Gotchas
=======
It is recognized that decisions were made that may not always be ideal for a
given user. In order to highlight those potential issues and hopefully bring
some sense into a confusing situation, this document was drawn.
Non-English Locales
-------------------
Many non-english locales are not supported due to the localization of the severity field
in messages and errors sent to the client. Internally, py-postgresql uses this to allow
client side filtering of messages and to identify FATAL connection errors that allow the
client to recognize that it should be expecting the connection to terminate.
Thread Safety
-------------
py-postgresql connection operations are not thread safe.
`client_encoding` setting should be altered carefully
-----------------------------------------------------
`postgresql.driver`'s streaming cursor implementation reads a fixed set of rows
when it queries the server for more. In order to optimize some situations, the
driver will send a request for more data, but makes no attempt to wait and
process the data as it is not yet needed. When the user comes back to read more
data from the cursor, it will then look at this new data. The problem being, if
`client_encoding` was switched, it may use the wrong codec to transform the
wire data into higher level Python objects(str).
To avoid this problem from ever happening, set the `client_encoding` early.
Furthermore, it is probably best to never change the `client_encoding` as the
driver automatically makes the necessary transformation to Python strings.
The user and password is correct, but it does not work when using `postgresql.driver`
-------------------------------------------------------------------------------------
This issue likely comes from the possibility that the information sent to the
server early in the negotiation phase may not be in an encoding that is
consistent with the server's encoding.
One problem is that PostgreSQL does not provide the client with the server
encoding early enough in the negotiation phase, and, therefore, is unable to
process the password data in a way that is consistent with the server's
expectations.
Another problem is that PostgreSQL takes much of the data in the startup message
as-is, so a decision about the best way to encode parameters is difficult.
The easy way to avoid *most* issues with this problem is to initialize the
database in the `utf-8` encoding. The driver defaults the expected server
encoding to `utf-8`. However, this can be overridden by creating the `Connector`
with a `server_encoding` parameter. Setting `server_encoding` to the proper
value of the target server will allow the driver to properly encode *some* of
the parameters. Also, any GUC parameters passed via the `settings` parameter
should use typed objects when possible to hint that the server encoding should
not be used on that parameter(`bytes`, for instance).
Backslash characters are being treated literally
------------------------------------------------
The driver enables standard compliant strings. Stop using non-standard features.
;)
If support for non-standard strings was provided it would require to the
driver to provide subjective quote interfaces(eg, db.quote_literal). Doing so is
not desirable as it introduces difficulties for the driver *and* the user.
Types without binary support in the driver are unsupported in arrays and records
--------------------------------------------------------------------------------
When an array or composite type is identified, `postgresql.protocol.typio`
ultimately chooses the binary format for the transfer of the column or
parameter. When this is done, PostgreSQL will pack or expect *all* the values
in binary format as well. If that binary format is not supported and the type
is not an string, it will fail to unpack the row or pack the appropriate data for
the element or attribute.
In most cases issues related to this can be avoided with explicit casts to text.
NOTICEs, WARNINGs, and other messages are too verbose
-----------------------------------------------------
For many situations, the information provided with database messages is
far too verbose. However, considering that py-postgresql is a programmer's
library, the default of high verbosity is taken with the express purpose of
allowing the programmer to "adjust the volume" until appropriate.
By default, py-postgresql adjusts the ``client_min_messages`` to only emit
messages at the WARNING level or higher--ERRORs, FATALs, and PANICs.
This reduces the number of messages generated by most connections dramatically.
If further customization is needed, the :ref:`db_messages` section has
information on overriding the default action taken with database messages.
Strange TypeError using load_rows() or load_chunks()
----------------------------------------------------
When a prepared statement is directly executed using ``__call__()``, it can easily
validate that the appropriate number of parameters are given to the function.
When ``load_rows()`` or ``load_chunks()`` is used, any tuple in the
the entire sequence can cause this TypeError during the loading process::
TypeError: inconsistent items, N processors and M items in row
This exception is raised by a generic processing routine whose functionality
is abstract in nature, so the message is abstract as well. It essentially means
that a tuple in the sequence given to the loading method had too many or too few
items.
py-postgresql
=============
py-postgresql is a project dedicated to improving the Python client interfaces to PostgreSQL.
At its core, py-postgresql provides a PG-API, `postgresql.api`, and
DB-API 2.0 interface for using a PostgreSQL database.
Contents
--------
.. toctree::
:maxdepth: 2
admin
driver
copyman
notifyman
alock
cluster
lib
clientparameters
gotchas
Reference
---------
.. toctree::
:maxdepth: 2
bin
reference
Changes
-------
.. toctree::
:maxdepth: 1
changes-v1.1
changes-v1.0
Sample Code
-----------
Using `postgresql.driver`::
>>> import postgresql
>>> db = postgresql.open("pq://user:password@host/name_of_database")
>>> db.execute("CREATE TABLE emp (emp_name text PRIMARY KEY, emp_salary numeric)")
>>>
>>> # Create the statements.
>>> make_emp = db.prepare("INSERT INTO emp VALUES ($1, $2)")
>>> raise_emp = db.prepare("UPDATE emp SET emp_salary = emp_salary + $2 WHERE emp_name = $1")
>>> get_emp_with_salary_lt = db.prepare("SELECT emp_name FROM emp WHERE emp_salay < $1")
>>>
>>> # Create some employees, but do it in a transaction--all or nothing.
>>> with db.xact():
... make_emp("John Doe", "150,000")
... make_emp("Jane Doe", "150,000")
... make_emp("Andrew Doe", "55,000")
... make_emp("Susan Doe", "60,000")
>>>
>>> # Give some raises
>>> with db.xact():
... for row in get_emp_with_salary_lt("125,000"):
... print(row["emp_name"])
... raise_emp(row["emp_name"], "10,000")
Of course, if DB-API 2.0 is desired, the module is located at
`postgresql.driver.dbapi20`. DB-API extends PG-API, so the features
illustrated above are available on DB-API connections.
See :ref:`db_interface` for more information.
Categories and Libraries
************************
This chapter discusses the usage and implementation of connection categories and
libraries.
.. note::
First-time users are encouraged to read the `Audience and Motivation`_
section first.
Libraries are a collection of SQL statements that can be bound to a
connection. Libraries are *normally* bound directly to the connection object as
an attribute using a name specified by the library.
Libraries provide a common way for SQL statements to be managed outside of the
code that uses them. When using ILFs, this increases the portability of the SQL
by keeping the statements isolated from the Python code in an accessible format
that can be easily used by other languages or systems --- An ILF parser can be
implemented within a few dozen lines using basic text tools.
SQL statements defined by a Library are identified by their Symbol. These
symbols are named and annotated in order to allow the user to define how a
statement is to be used. The user may state the default execution method of
the statement object, or whether the symbol is to be preloaded at bind
time--these properties are Symbol Annotations.
The purpose of libraries are to provide a means to manage statements on
disk and at runtime. ILFs provide a means to reference a collection
of statements on disk, and, when loaded, the symbol bindings provides means to
reference a statement already prepared for use on a given connection.
The `postgresql.lib` package-module provides fundamental classes for supporting
categories and libraries.
Writing Libraries
=================
ILF files are the recommended way to build a library. These files use the
naming convention "lib{NAME}.sql". The prefix and suffix are used describe the
purpose of the file and to provide a hint to editors that SQL highlighting
should be used. The format of an ILF takes the form::
<Preface>
[name:type:method]
<statement>
...
Where multiple symbols may be defined. The Preface that comes before the first
symbol is an arbitrary block of text that should be used to describe the library.
This block is free-form, and should be considered a good place for some
general documentation.
Symbols are named and described using the contents of section markers:
``('[' ... ']')``. Section markers have three components: the symbol name,
the symbol type and the symbol method. Each of these components are separated
using a single colon, ``:``. All components are optional except the Symbol name.
For example::
[get_user_info]
SELECT * FROM user WHERE user_id = $1
[get_user_info_v2::]
SELECT * FROM user WHERE user_id = $1
In the above example, ``get_user_info`` and ``get_user_info_v2`` are identical.
Empty components indicate the default effect.
The second component in the section identifier is the symbol type. All Symbol
types are listed in `Symbol Types`_. This can be
used to specify what the section's contents are or when to bind the
symbol::
[get_user_info:preload]
SELECT * FROM user WHERE user_id = $1
This provides the Binding with the knowledge that the statement should be
prepared when the Library is bound. Therefore, when this Symbol's statement
is used for the first time, it will have already been prepared.
Another type is the ``const`` Symbol type. This defines a data Symbol whose
*statement results* will be resolved when the Library is bound::
[user_type_ids:const]
SELECT user_type_id, user_type FROM user_types;
Constant Symbols cannot take parameters as they are data properties. The
*result* of the above query is set to the Bindings' ``user_type_ids``
attribute::
>>> db.lib.user_type_ids
<sequence of (user_type_id, user_type)>
Where ``lib`` in the above is a Binding of the Library containing the
``user_type_ids`` Symbol.
Finally, procedures can be bound as symbols using the ``proc`` type::
[remove_user:proc]
remove_user(bigint)
All procedures symbols are loaded when the Library is bound. Procedure symbols
are special because the execution method is effectively specified by the
procedure itself.
The third component is the symbol ``method``. This defines the execution method
of the statement and ultimately what is returned when the Symbol is called at
runtime. All the execution methods are listed in `Symbol Execution Methods`_.
The default execution method is the default execution method of
`postgresql.api.PreparedStatement` objects; return the entire result set in a
list object::
[get_numbers]
SELECT i FROM generate_series(0, 100-1) AS g(i);
When bound::
>>> db.lib.get_numbers() == [(x,) for x in range(100)]
True
The transformation of range in the above is necessary as statements
return a sequence of row objects by default.
For large result-sets, fetching all the rows would be taxing on a system's
memory. The ``rows`` and ``chunks`` methods provide an iterator to rows produced
by a statement using a stream::
[get_some_rows::rows]
SELECT i FROM generate_series(0, 1000) AS g(i);
[get_some_chunks::chunks]
SELECT i FROM generate_series(0, 1000) AS g(i);
``rows`` means that the Symbol will return an iterator producing individual rows
of the result, and ``chunks`` means that the Symbol will return an iterator
producing sequences of rows of the result.
When bound::
>>> from itertools import chain
>>> list(db.lib.get_some_rows()) == list(chain.from_iterable(db.lib.get_some_chunks()))
True
Other methods include ``column`` and ``first``. The column method provides a
means to designate that the symbol should return an iterator of the values in
the first column instead of an iterator to the rows::
[another_generate_series_example::column]
SELECT i FROM generate_series(0, $1::int) AS g(i)
In use::
>>> list(db.lib.another_generate_series_example(100-1)) == list(range(100))
True
>>> list(db.lib.another_generate_series_example(10-1))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The ``first`` method provides direct access to simple results.
Specifically, the first column of the first row when there is only one column.
When there are multiple columns the first row is returned::
[get_one::first]
SELECT 1
[get_one_twice::first]
SELECT 1, 1
In use::
>>> db.lib.get_one() == 1
True
>>> db.lib.get_one_twice() == (1,1)
True
.. note::
``first`` should be used with care. When the result returns no rows, `None`
will be returned.
Using Libraries
===============
After a library is created, it must be loaded before it can be bound using
programmer interfaces. The `postgresql.lib.load` interface provides the
primary entry point for loading libraries.
When ``load`` is given a string, it identifies if a directory separator is in
the string, if there is it will treat the string as a *path* to the ILF to be
loaded. If no separator is found, it will treat the string as the library
name fragment and look for "lib{NAME}.sql" in the directories listed in
`postgresql.sys.libpath`.
Once a `postgresql.lib.Library` instance has been acquired, it can then be
bound to a connection for use. `postgresql.lib.Binding` is used to create an
object that provides and manages the Bound Symbols::
>>> import postgresql.lib as pg_lib
>>> lib = pg_lib.load(...)
>>> B = pg_lib.Binding(db, lib)
The ``B`` object in the above example provides the Library's Symbols as
attributes which can be called to in order to execute the Symbol's statement::
>>> B.symbol(param)
...
While it is sometimes necessary, manual creation of a Binding is discouraged.
Rather, `postgresql.lib.Category` objects should be used to manage the set of
Libraries to be bound to a connection.
Categories
----------
Libraries provide access to a collection of symbols; Bindings provide an
interface to the symbols with respect to a subject database. When a connection
is established, multiple Bindings may need to be created in order to fulfill
the requirements of the programmer. When a Binding is created, it exists in
isolation; this can be an inconvenience when access to both the Binding and
the Connection is necessary. Categories exist to provide a formal method for
defining the interface extensions on a `postgresql.api.Database`
instance(connection).
A Category is essentially a runtime-class for connections. It provides a
formal initialization procedure for connection objects at runtime. However,
the connection resource must be connected prior to category initialization.
Categories are sets of Libraries to be bound to a connection with optional name
substitutions. In order to create one directly, pass the Library instances to
`postgresql.lib.Category`::
>>> import postgresql.lib as pg_lib
>>> cat = pg_lib.Category(lib1, lib2, libN)
Where ``lib1``, ``lib2``, ``libN`` are `postgresql.lib.Library` instances;
usually created by `postgresql.lib.load`. Once created, categories can then
used by passing the ``category`` keyword to connection creation interfaces::
>>> import postgresql
>>> db = postgresql.open(category = cat)
The ``db`` object will now have Bindings for ``lib1``, ``lib2``, ..., and
``libN``.
Categories can alter the access point(attribute name) of Bindings. This is done
by instantiating the Category using keyword parameters::
>>> cat = pg_lib.Category(lib1, lib2, libname = libN)
At this point, when a connection is established as the category ``cat``,
``libN`` will be bound to the connection object on the attribute ``libname``
instead of the name defined by the library.
And a final illustration of Category usage::
>>> db = postgresql.open(category = pg_lib.Category(pg_lib.load('name')))
>>> db.name
<Library>
Symbol Types
============
The symbol type determines how a symbol is going to be treated by the Binding.
For instance, ``const`` symbols are resolved when the Library is bound and
the statement object is immediately discarded. Here is a list of symbol types
that can be used in ILF libraries:
``<default>`` (Empty component)
The symbol's statement will never change. This allows the Bound Symbol to
hold onto the `postgresql.api.PreparedStatement` object. When the symbol is
used again, it will refer to the existing prepared statement object.
``preload``
Like the default type, the Symbol is a simple statement, but it should be
loaded when the library is bound to the connection.
``const``
The statement takes no parameters and only needs to be executed once. This
will cause the statement to be executed when the library is bound and the
results of the statement will be set to the Binding using the symbol name so
that it may be used as a property by the user.
``proc``
The contents of the section is a procedure identifier. When this type is used
the symbol method *should not* be specified as the method annotation will be
automatically resolved based on the procedure's signature.
``transient``
The Symbol is a statement that should *not* be retained. Specifically, it is
a statement object that will be discarded when the user discard the referenced
Symbol. Used in cases where the statement is used once or very infrequently.
Symbol Execution Methods
========================
The Symbol Execution Method provides a way to specify how a statement is going
to be used. Specifically, which `postgresql.api.PreparedStatement` method
should be executed when a Bound Symbol is called. The following is a list of
the symbol execution methods and the effect it will have when invoked:
``<default>`` (Empty component)
Returns the entire result set in a single list object. If the statement does
not return rows, a ``(command, count)`` pair will be returned.
``rows``
Returns an iterator producing each row in the result set.
``chunks``
Returns an iterator producing "chunks" of rows in the result set.
``first``
Returns the first column of the first row if there is one column in the result
set. If there are multiple columns in the result set, the first row is
returned. If query is non-RETURNING DML--insert, update, or delete, the row
count is returned.
``column``
Returns an iterator to values in the first column. (Equivalent to
executing a statement as ``map(operator.itemgetter(0), ps.rows())``.)
``declare``
Returns a scrollable cursor, `postgresql.api.Cursor`, to the result set.
``load_chunks``
Takes an iterable row-chunks to be given to the statement. Returns `None`. If
the statement is a ``COPY ... FROM STDIN``, the iterable must produce chunks
of COPY lines.
``load_rows``
Takes an iterable rows to be given as parameters. If the statement is a ``COPY
... FROM STDIN``, the iterable must produce COPY lines.
Reference Symbols
=================
Reference Symbols provide a way to construct a Bound Symbol using the Symbol's
query. When invoked, A Reference Symbol's query is executed in order to produce
an SQL statement to be used as a Bound Symbol. In ILF files, a reference is
identified by its symbol name being prefixed with an ampersand::
[&refsym::first]
SELECT 'SELECT 1::int4'::text
Then executed::
>>> # Runs the 'refsym' SQL, and creates a Bound Symbol using the results.
>>> sym = lib.refsym()
>>> assert sym() == 1
The Reference Symbol's type and execution method are inherited by the created
Bound Symbol. With one exception, ``const`` reference symbols are
special in that they immediately resolved into the target Bound Symbol.
A Reference Symbol's source query *must* produce rows of text columns. Multiple
columns and multiple rows may be produced by the query, but they must be
character types as the results are promptly joined together with whitespace so
that the target statement may be prepared.
Reference Symbols are most likely to be used in dynamic DDL and DML situations,
or, somewhat more specifically, any query whose definition depends on a
generated column list.
Distributing and Usage
======================
For applications, distribution and management can easily be a custom
process. The application designates the library directory; the entry point
adds the path to the `postgresql.sys.libpath` list; a category is built; and, a
connection is made using the category.
For mere Python extensions, however, ``distutils`` has a feature that can
aid in ILF distribution. The ``package_data`` setup keyword can be used to
include ILF files alongside the Python modules that make up a project. See
http://docs.python.org/3.1/distutils/setupscript.html#installing-package-data
for more detailed information on the keyword parameter.
The recommended way to manage libraries for extending projects is to
create a package to contain them. For instance, consider the following layout::
project/
setup.py
pkg/
__init__.py
lib/
__init__.py
libthis.sql
libthat.sql
The project's SQL libraries are organized into a single package directory,
``lib``, so ``package_data`` would be configured::
package_data = {'pkg.lib': ['*.sql']}
Subsequently, the ``lib`` package initialization script can then be used to
load the libraries, and create any categories(``project/pkg/lib/__init__.py``)::
import os.path
import postgresql.lib as pg_lib
import postgresql.sys as pg_sys
libdir = os.path.dirname(__file__)
pg_sys.libpath.append(libdir)
libthis = pg_lib.load('this')
libthat = pg_lib.load('that')
stdcat = pg_lib.Category(libthis, libthat)
However, it can be undesirable to add the package directory to the global
`postgresql.sys.libpath` search paths. Direct path loading can be used in those
cases::
import os.path
import postgresql.lib as pg_lib
libdir = os.path.dirname(__file__)
libthis = pg_lib.load(os.path.join(libdir, 'libthis.sql'))
libthat = pg_lib.load(os.path.join(libdir, 'libthat.sql'))
stdcat = pg_lib.Category(libthis, libthat)
Using the established project context, a connection would then be created as::
from pkg.lib import stdcat
import postgresql as pg
db = pg.open(..., category = stdcat)
# And execute some fictitious symbols.
db.this.sym_from_libthis()
db.that.sym_from_libthat(...)
Audience and Motivation
=======================
This chapter covers advanced material. It is **not** recommended that categories
and libraries be used for trivial applications or introductory projects.
.. note::
Libraries and categories are not likely to be of interest to ORM or DB-API users.
With exception to ORMs or other similar abstractions, the most common pattern
for managing connections and statements is delegation::
class MyAppDB(object):
def __init__(self, connection):
self.connection = connection
def my_operation(self, op_arg1, op_arg2):
return self.connection.prepare(
"SELECT my_operation_proc($1,$2)",
)(op_arg1, op_arg2)
...
The straightforward nature is likeable, but the usage does not take advantage of
prepared statements. In order to do that an extra condition is necessary to see
if the statement has already been prepared::
...
def my_operation(self, op_arg1, op_arg2):
if self.hasattr(self, '_my_operation'):
ps = self._my_operation
else:
ps = self._my_operation = self.connection.prepare(
"SELECT my_operation_proc($1, $2)",
)
return ps(op_arg1, op_arg2)
...
There are many variations that can implement the above. It works and it's
simple, but it will be exhausting if repeated and error prone if the
initialization condition is not factored out. Additionally, if access to statement
metadata is needed, the above example is still lacking as it would require
execution of the statement and further protocol expectations to be established.
This is the province of libraries: direct database interface management.
Categories and Libraries are used to factor out and simplify
the above functionality so re-implementation is unnecessary. For example, an
ILF library containing the symbol::
[my_operation]
SELECT my_operation_proc($1, $2)
[<other_symbol>]
...
Will provide the same functionality as the ``my_operation`` method in the
latter Python implementation.
Terminology
===========
The following terms are used throughout this chapter:
Annotations
The information of about a Symbol describing what it is and how it should be
used.
Binding
An interface to the Symbols provided by a Library for use with a given
connection.
Bound Symbol
An interface to an individual Symbol ready for execution against the subject
database.
Bound Reference
An interface to an individual Reference Symbol that will produce a Bound
Symbol when executed.
ILF
INI-style Library Format. "lib{NAME}.sql" files.
Library
A collection of Symbols--mapping of names to SQL statements.
Local Symbol
A relative term used to denote a symbol that exists in the same library as
the subject symbol.
Preface
The block of text that comes before the first symbol in an ILF file.
Symbol
An named database operation provided by a Library. Usually, an SQL statement
with Annotations.
Reference Symbol
A Symbol whose SQL statement *produces* the source for a Bound Symbol.
Category
An object supporting a classification for connectors that provides database
initialization facilities for produced connections. For libraries,
`postgresql.lib.Category` objects are a set of Libraries,
`postgresql.lib.Library`.
.. _notifyman:
***********************
Notification Management
***********************
Relevant SQL commands: `NOTIFY <http://postgresql.org/docs/current/static/sql-notify.html>`_,
`LISTEN <http://postgresql.org/docs/current/static/sql-listen.html>`_,
`UNLISTEN <http://postgresql.org/docs/current/static/sql-unlisten.html>`_.
Asynchronous notifications offer a means for PostgreSQL to signal application
code. Often these notifications are used to signal cache invalidation. In 9.0
and greater, notifications may include a "payload" in which arbitrary data may
be delivered on a channel being listened to.
By default, received notifications will merely be appended to an internal
list on the connection object. This list will remain empty for the duration
of a connection *unless* the connection begins listening to a channel that
receives notifications.
The `postgresql.notifyman.NotificationManager` class is used to wait for
messages to come in on a set of connections, pick up the messages, and deliver
the messages to the object's user via the `collections.Iterator` protocol.
Listening on a Single Connection
================================
The ``db.iternotifies()`` method is a simplification of the notification manager. It
returns an iterator to the notifications received on the subject connection.
The iterator yields triples consisting of the ``channel`` being
notified, the ``payload`` sent with the notification, and the ``pid`` of the
backend that caused the notification::
>>> db.listen('for_rabbits')
>>> db.notify('for_rabbits')
>>> for x in db.iternotifies():
... channel, payload, pid = x
... break
>>> assert channel == 'for_rabbits'
True
>>> assert payload == ''
True
>>> assert pid == db.backend_id
True
The iterator, by default, will continue listening forever unless the connection
is terminated--thus the immediate ``break`` statement in the above loop. In
cases where some additional activity is necessary, a timeout parameter may be
given to the ``iternotifies`` method in order to allow "idle" events to occur
at the designated frequency::
>>> for x in db.iternotifies(0.5):
... if x is None:
... break
The above example illustrates that idle events are represented using `None`
objects. Idle events are guaranteed to occur *approximately* at the
specified interval--the ``timeout`` keyword parameter. In addition to
providing a means to do other processing or polling, they also offer a safe
break point for the loop. Internally, the iterator produced by the
``iternotifies`` method *is* a `NotificationManager`, which will localize the
notifications prior to emitting them via the iterator.
*It's not safe to break out of the loop, unless an idle event is being handled.*
If the loop is broken while a regular event is being processed, some events may
remain in the iterator. In order to consume those events, the iterator *must*
be accessible.
The iterator will be exhausted when the connection is closed, but if the
connection is closed during the loop, any remaining notifications *will*
be emitted prior to the loop ending, so it is important to be prepared to
handle exceptions or check for a closed connection.
In situations where multiple connections need to be watched, direct use of the
`NotificationManager` is necessary.
Listening on Multiple Connections
=================================
The `postgresql.notifyman.NotificationManager` class is used to manage
*connections* that are expecting to receive notifications. Instances are
iterators that yield the connection object and notifications received on the
connection or `None` in the case of an idle event. The manager emits events as
a pair; the connection object that received notifications, and *all* the
notifications picked up on that connection::
>>> from postgresql.notifyman import NotificationManager
>>> # Using ``nm`` to reference the manager from here on.
>>> nm = NotificationManager(db1, db2, ..., dbN)
>>> nm.settimeout(2)
>>> for x in nm:
... if x is None:
... # idle
... break
...
... db, notifies = x
... for channel, payload, pid in notifies:
... ...
The manager will continue to wait for and emit events so long as there are
good connections available in the set; it is possible for connections to be
added and removed at any time. Although, in rare circumstances, discarded
connections may still have pending events if it not removed during an idle
event. The ``connections`` attribute on `NotificationManager` objects is a
set object that may be used directly in order to add and remove connections
from the manager::
>>> y = []
>>> for x in nm:
... if x is None:
... if y:
... nm.connections.add(y[0])
... del y[0]
...
The notification manager is resilient; if a connection dies, it will discard the
connection from the set, and add it to the set of bad connections, the
``garbage`` attribute. In these cases, the idle event *should* be leveraged to
check for these failures if that's a concern. It is the user's
responsibility to explicitly handle the failure cases, and remove the bad
connections from the ``garbage`` set::
>>> for x in nm:
... if x is None:
... if nm.garbage:
... recovered = take_out_trash(nm.garbage)
... nm.connections.update(recovered)
... nm.garbage.clear()
... db, notifies = x
... for channel, payload, pid in notifies:
... ...
Explicitly removing connections from the set can also be a means to gracefully
terminate the event loop::
>>> for x in nm:
... if x in None:
... if done_listening is True:
... nm.connections.clear()
However, doing so inside the loop is not a requirement; it is safe to remove a
connection from the set at any point.
Notification Managers
=====================
The `postgresql.notifyman.NotificationManager` is an event loop that services
multiple connections. In cases where only one connection needs to be serviced,
the `postgresql.api.Database.iternotifies` method can be used to simplify the
process.
Notification Manager Constructors
---------------------------------
``NotificationManager(*connections, timeout = None)``
Create a NotificationManager instance that manages the notifications coming
from the given set of connections. The ``timeout`` keyword is optional and
can be configured using the ``settimeout`` method as well.
Notification Manager Interface Points
-------------------------------------
``NotificationManager.__iter__()``
Returns the instance; it is an iterator.
``NotificationManager.__next__()``
Normally, yield the pair, connection and notifications list, when the next
event is received. If a timeout is configured, `None` may be yielded to signal
an idle event. The notifications list is a list of triples:
``(channel, payload, pid)``.
``NotificationManager.settimeout(timeout : int)``
Set the amount of time to wait before the manager yields an idle event.
If zero, the manager will never wait and only yield notifications that are
immediately available.
If `None`, the manager will never emit idle events.
``NotificationManager.gettimeout() -> [int, None]``
Get the configured timeout; returns either `None`, or an `int`.
``NotificationManager.connections``
The set of connections that the manager is actively watching for
notifications. Connections may be added or removed from the set at any time.
``NotificationManager.garbage``
The set of connections that failed. Normally empty, but when a connection gets
an exceptional condition or explicitly raises an exception, it is removed from
the ``connections`` set, and placed in ``garbage``.
Zero Timeout
------------
When a timeout of zero, ``0``, is configured, the notification manager will
terminate early. Specifically, each connection will be polled for any pending
notifications, and once all of the collected notifications have been emitted
by the iterator, `StopIteration` will be raised. Notably, *no* idle events will
occur when the timeout is configured to zero.
Zero timeouts offer a means for the notification "queue" to be polled. Often,
this is the appropriate way to collect pending notifications on active
connections where using the connection exclusively for waiting is not
practical::
>>> notifies = list(db.iternotifies(0))
Or with a NotificationManager instance::
>>> nm.settimeout(0)
>>> db_notifies = list(nm)
In both cases of zero timeout, the iterator may be promptly discarded without
losing any events.
Summary of Characteristics
--------------------------
* The iterator will continue until the connections die.
* Objects yielded by the iterator are either `None`, an "idle event", or an
individual notification triple if using ``db.iternotifies()``, or a
``(db, notifies)`` pair if using the base `NotificationManager`.
* When a connection dies or raises an exception, it will be removed from
the ``nm.connections`` set and added to the ``nm.garbage`` set.
* The NotificationManager instance will *not* hold any notifications
during an idle event. Idle events offer a break point in which the manager
may be discarded.
* A timeout of zero will cause the iterator to only yield the events
that are pending right now, and promptly end. However, the same manager
object may be used again.
* A notification triple is a tuple consisting of ``(channel, payload, pid)``.
* Connections may be added and removed from the ``nm.connections`` set at
any time.
Reference
=========
:mod:`postgresql`
-----------------
.. automodule:: postgresql
.. autodata:: version
.. autodata:: version_info
.. autofunction:: open
:mod:`postgresql.api`
---------------------
.. automodule::
postgresql.api
:members:
:show-inheritance:
:mod:`postgresql.sys`
---------------------
.. automodule::
postgresql.sys
:members:
:show-inheritance:
:mod:`postgresql.string`
------------------------
.. automodule::
postgresql.string
:members:
:show-inheritance:
:mod:`postgresql.exceptions`
----------------------------
.. automodule::
postgresql.exceptions
:members:
:show-inheritance:
:mod:`postgresql.temporal`
--------------------------
.. automodule::
postgresql.temporal
:members:
:show-inheritance:
:mod:`postgresql.installation`
------------------------------
.. automodule::
postgresql.installation
:members:
:show-inheritance:
:mod:`postgresql.cluster`
-------------------------
.. automodule::
postgresql.cluster
:members:
:show-inheritance:
:mod:`postgresql.copyman`
-------------------------
.. automodule::
postgresql.copyman
:members:
:show-inheritance:
:mod:`postgresql.alock`
-----------------------
.. automodule::
postgresql.alock
:members:
:show-inheritance:

Sorry, the diff of this file is not supported yet

/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox input[type="text"] {
width: 170px;
}
div.sphinxsidebar #searchbox input[type="submit"] {
width: 30px;
}
img {
border: 0;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- general body styles --------------------------------------------------- */
a.headerlink {
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.field-list ul {
padding-left: 1em;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px 7px 0 7px;
background-color: #ffe;
width: 40%;
float: right;
}
p.sidebar-title {
font-weight: bold;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
border: 0;
border-collapse: collapse;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dt:target, .highlighted {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.refcount {
color: #060;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

/*
* default.css_t
* ~~~~~~~~~~~~~
*
* Sphinx stylesheet -- default theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: sans-serif;
font-size: 100%;
background-color: #11303d;
color: #000;
margin: 0;
padding: 0;
}
div.document {
background-color: #1c4e63;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: #ffffff;
color: #000000;
padding: 0 20px 30px 20px;
}
div.footer {
color: #ffffff;
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #ffffff;
text-decoration: underline;
}
div.related {
background-color: #133f52;
line-height: 30px;
color: #ffffff;
}
div.related a {
color: #ffffff;
}
div.sphinxsidebar {
}
div.sphinxsidebar h3 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h3 a {
color: #ffffff;
}
div.sphinxsidebar h4 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: #ffffff;
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
color: #ffffff;
}
div.sphinxsidebar a {
color: #98dbcc;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
/* -- hyperlink styles ------------------------------------------------------ */
a {
color: #355f7c;
text-decoration: none;
}
a:visited {
color: #355f7c;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* -- body styles ----------------------------------------------------------- */
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: 'Trebuchet MS', sans-serif;
background-color: #f2f2f2;
font-weight: normal;
color: #20435c;
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
line-height: 130%;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 5px;
background-color: #eeffcc;
color: #333333;
line-height: 120%;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
th {
background-color: #ede;
}
.warning tt {
background: #efc2c2;
}
.note tt {
background: #d6d6d6;
}
.viewcode-back {
font-family: sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*/
jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' ');
}
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s == 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* small function to check if an array contains
* a given item.
*/
jQuery.contains = function(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item)
return true;
}
return false;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
var span = document.createElement("span");
span.className = className;
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this);
});
}
}
return this.each(function() {
highlight(this);
});
};
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated == 'undefined')
return string;
return (typeof translated == 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated == 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('<p class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) == 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this == '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

.highlight .hll { background-color: #ffffcc }
.highlight { background: #eeffcc; }
.highlight .c { color: #408090; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #007020 } /* Comment.Preproc */
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #303030 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #902000 } /* Keyword.Type */
.highlight .m { color: #208050 } /* Literal.Number */
.highlight .s { color: #4070a0 } /* Literal.String */
.highlight .na { color: #4070a0 } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nf { color: #06287e } /* Name.Function */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #208050 } /* Literal.Number.Float */
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
.highlight .sr { color: #235388 } /* Literal.String.Regex */
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
/*
* searchtools.js_t
* ~~~~~~~~~~~~~~~~
*
* Sphinx JavaScript utilties for the full-text search.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, hlwords is the list of normal, unstemmed
* words. the first one is used to find the occurance, the
* latter for highlighting it.
*/
jQuery.makeSearchSummary = function(text, keywords, hlwords) {
var textLower = text.toLowerCase();
var start = 0;
$.each(keywords, function() {
var i = textLower.indexOf(this.toLowerCase());
if (i > -1)
start = i;
});
start = Math.max(start - 120, 0);
var excerpt = ((start > 0) ? '...' : '') +
$.trim(text.substr(start, 240)) +
((start + 240 - text.length) ? '...' : '');
var rv = $('<div class="context"></div>').text(excerpt);
$.each(hlwords, function() {
rv = rv.highlightText(this, 'highlighted');
});
return rv;
}
/**
* Porter Stemmer
*/
var Stemmer = function() {
var step2list = {
ational: 'ate',
tional: 'tion',
enci: 'ence',
anci: 'ance',
izer: 'ize',
bli: 'ble',
alli: 'al',
entli: 'ent',
eli: 'e',
ousli: 'ous',
ization: 'ize',
ation: 'ate',
ator: 'ate',
alism: 'al',
iveness: 'ive',
fulness: 'ful',
ousness: 'ous',
aliti: 'al',
iviti: 'ive',
biliti: 'ble',
logi: 'log'
};
var step3list = {
icate: 'ic',
ative: '',
alize: 'al',
iciti: 'ic',
ical: 'ic',
ful: '',
ness: ''
};
var c = "[^aeiou]"; // consonant
var v = "[aeiouy]"; // vowel
var C = c + "[^aeiouy]*"; // consonant sequence
var V = v + "[aeiou]*"; // vowel sequence
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
var s_v = "^(" + C + ")?" + v; // vowel in stem
this.stemWord = function (w) {
var stem;
var suffix;
var firstch;
var origword = w;
if (w.length < 3)
return w;
var re;
var re2;
var re3;
var re4;
firstch = w.substr(0,1);
if (firstch == "y")
w = firstch.toUpperCase() + w.substr(1);
// Step 1a
re = /^(.+?)(ss|i)es$/;
re2 = /^(.+?)([^s])s$/;
if (re.test(w))
w = w.replace(re,"$1$2");
else if (re2.test(w))
w = w.replace(re2,"$1$2");
// Step 1b
re = /^(.+?)eed$/;
re2 = /^(.+?)(ed|ing)$/;
if (re.test(w)) {
var fp = re.exec(w);
re = new RegExp(mgr0);
if (re.test(fp[1])) {
re = /.$/;
w = w.replace(re,"");
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
re2 = new RegExp(s_v);
if (re2.test(stem)) {
w = stem;
re2 = /(at|bl|iz)$/;
re3 = new RegExp("([^aeiouylsz])\\1$");
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re2.test(w))
w = w + "e";
else if (re3.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
else if (re4.test(w))
w = w + "e";
}
}
// Step 1c
re = /^(.+?)y$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(s_v);
if (re.test(stem))
w = stem + "i";
}
// Step 2
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step2list[suffix];
}
// Step 3
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step3list[suffix];
}
// Step 4
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
re2 = /^(.+?)(s|t)(ion)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
if (re.test(stem))
w = stem;
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1] + fp[2];
re2 = new RegExp(mgr1);
if (re2.test(stem))
w = stem;
}
// Step 5
re = /^(.+?)e$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
re2 = new RegExp(meq1);
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
w = stem;
}
re = /ll$/;
re2 = new RegExp(mgr1);
if (re.test(w) && re2.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
// and turn initial Y back to y
if (firstch == "y")
w = firstch.toLowerCase() + w.substr(1);
return w;
}
}
/**
* Search Module
*/
var Search = {
_index : null,
_queued_query : null,
_pulse_status : -1,
init : function() {
var params = $.getQueryParameters();
if (params.q) {
var query = params.q[0];
$('input[name="q"]')[0].value = query;
this.performSearch(query);
}
},
loadIndex : function(url) {
$.ajax({type: "GET", url: url, data: null, success: null,
dataType: "script", cache: true});
},
setIndex : function(index) {
var q;
this._index = index;
if ((q = this._queued_query) !== null) {
this._queued_query = null;
Search.query(q);
}
},
hasIndex : function() {
return this._index !== null;
},
deferQuery : function(query) {
this._queued_query = query;
},
stopPulse : function() {
this._pulse_status = 0;
},
startPulse : function() {
if (this._pulse_status >= 0)
return;
function pulse() {
Search._pulse_status = (Search._pulse_status + 1) % 4;
var dotString = '';
for (var i = 0; i < Search._pulse_status; i++)
dotString += '.';
Search.dots.text(dotString);
if (Search._pulse_status > -1)
window.setTimeout(pulse, 500);
};
pulse();
},
/**
* perform a search for something
*/
performSearch : function(query) {
// create the required interface elements
this.out = $('#search-results');
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
this.dots = $('<span></span>').appendTo(this.title);
this.status = $('<p style="display: none"></p>').appendTo(this.out);
this.output = $('<ul class="search"/>').appendTo(this.out);
$('#search-progress').text(_('Preparing search...'));
this.startPulse();
// index already loaded, the browser was quick!
if (this.hasIndex())
this.query(query);
else
this.deferQuery(query);
},
query : function(query) {
var stopwords = ["but","is","it","will","their","if","into","that","then","was","they","these","by","no","be","in","near","this","with","and","to","the","such","a","of","there","on","for","or","are","not","as","at"];
// Stem the searchterms and add them to the correct list
var stemmer = new Stemmer();
var searchterms = [];
var excluded = [];
var hlterms = [];
var tmp = query.split(/\s+/);
var objectterms = [];
for (var i = 0; i < tmp.length; i++) {
if (tmp[i] != "") {
objectterms.push(tmp[i].toLowerCase());
}
if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
tmp[i] == "") {
// skip this "word"
continue;
}
// stem the word
var word = stemmer.stemWord(tmp[i]).toLowerCase();
// select the correct list
if (word[0] == '-') {
var toAppend = excluded;
word = word.substr(1);
}
else {
var toAppend = searchterms;
hlterms.push(tmp[i].toLowerCase());
}
// only add if not already in the list
if (!$.contains(toAppend, word))
toAppend.push(word);
};
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
// console.debug('SEARCH: searching for:');
// console.info('required: ', searchterms);
// console.info('excluded: ', excluded);
// prepare search
var filenames = this._index.filenames;
var titles = this._index.titles;
var terms = this._index.terms;
var fileMap = {};
var files = null;
// different result priorities
var importantResults = [];
var objectResults = [];
var regularResults = [];
var unimportantResults = [];
$('#search-progress').empty();
// lookup as object
for (var i = 0; i < objectterms.length; i++) {
var others = [].concat(objectterms.slice(0,i),
objectterms.slice(i+1, objectterms.length))
var results = this.performObjectSearch(objectterms[i], others);
// Assume first word is most likely to be the object,
// other words more likely to be in description.
// Therefore put matches for earlier words first.
// (Results are eventually used in reverse order).
objectResults = results[0].concat(objectResults);
importantResults = results[1].concat(importantResults);
unimportantResults = results[2].concat(unimportantResults);
}
// perform the search on the required terms
for (var i = 0; i < searchterms.length; i++) {
var word = searchterms[i];
// no match but word was a required one
if ((files = terms[word]) == null)
break;
if (files.length == undefined) {
files = [files];
}
// create the mapping
for (var j = 0; j < files.length; j++) {
var file = files[j];
if (file in fileMap)
fileMap[file].push(word);
else
fileMap[file] = [word];
}
}
// now check if the files don't contain excluded terms
for (var file in fileMap) {
var valid = true;
// check if all requirements are matched
if (fileMap[file].length != searchterms.length)
continue;
// ensure that none of the excluded terms is in the
// search result.
for (var i = 0; i < excluded.length; i++) {
if (terms[excluded[i]] == file ||
$.contains(terms[excluded[i]] || [], file)) {
valid = false;
break;
}
}
// if we have still a valid result we can add it
// to the result list
if (valid)
regularResults.push([filenames[file], titles[file], '', null]);
}
// delete unused variables in order to not waste
// memory until list is retrieved completely
delete filenames, titles, terms;
// now sort the regular results descending by title
regularResults.sort(function(a, b) {
var left = a[1].toLowerCase();
var right = b[1].toLowerCase();
return (left > right) ? -1 : ((left < right) ? 1 : 0);
});
// combine all results
var results = unimportantResults.concat(regularResults)
.concat(objectResults).concat(importantResults);
// print the results
var resultCount = results.length;
function displayNextItem() {
// results left, load the summary and display it
if (results.length) {
var item = results.pop();
var listItem = $('<li style="display:none"></li>');
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX == '') {
// dirhtml builder
var dirname = item[0] + '/';
if (dirname.match(/\/index\/$/)) {
dirname = dirname.substring(0, dirname.length-6);
} else if (dirname == 'index/') {
dirname = '';
}
listItem.append($('<a/>').attr('href',
DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
highlightstring + item[2]).html(item[1]));
} else {
// normal html builders
listItem.append($('<a/>').attr('href',
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
highlightstring + item[2]).html(item[1]));
}
if (item[3]) {
listItem.append($('<span> (' + item[3] + ')</span>'));
Search.output.append(listItem);
listItem.slideDown(5, function() {
displayNextItem();
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
$.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
item[0] + '.txt', function(data) {
if (data != '') {
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
Search.output.append(listItem);
}
listItem.slideDown(5, function() {
displayNextItem();
});
}, "text");
} else {
// no source available, just display title
Search.output.append(listItem);
listItem.slideDown(5, function() {
displayNextItem();
});
}
}
// search finished, update title and status message
else {
Search.stopPulse();
Search.title.text(_('Search Results'));
if (!resultCount)
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
else
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
Search.status.fadeIn(500);
}
}
displayNextItem();
},
performObjectSearch : function(object, otherterms) {
var filenames = this._index.filenames;
var objects = this._index.objects;
var objnames = this._index.objnames;
var titles = this._index.titles;
var importantResults = [];
var objectResults = [];
var unimportantResults = [];
for (var prefix in objects) {
for (var name in objects[prefix]) {
var fullname = (prefix ? prefix + '.' : '') + name;
if (fullname.toLowerCase().indexOf(object) > -1) {
var match = objects[prefix][name];
var objname = objnames[match[1]][2];
var title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
if (otherterms.length > 0) {
var haystack = (prefix + ' ' + name + ' ' +
objname + ' ' + title).toLowerCase();
var allfound = true;
for (var i = 0; i < otherterms.length; i++) {
if (haystack.indexOf(otherterms[i]) == -1) {
allfound = false;
break;
}
}
if (!allfound) {
continue;
}
}
var descr = objname + _(', in ') + title;
anchor = match[3];
if (anchor == '')
anchor = fullname;
else if (anchor == '-')
anchor = objnames[match[1]][1] + '-' + fullname;
result = [filenames[match[0]], fullname, '#'+anchor, descr];
switch (match[2]) {
case 1: objectResults.push(result); break;
case 0: importantResults.push(result); break;
case 2: unimportantResults.push(result); break;
}
}
}
}
// sort results descending
objectResults.sort(function(a, b) {
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
});
importantResults.sort(function(a, b) {
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
});
unimportantResults.sort(function(a, b) {
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
});
return [importantResults, objectResults, unimportantResults]
}
}
$(document).ready(function() {
Search.init();
});
/*
* sidebar.js
* ~~~~~~~~~~
*
* This script makes the Sphinx sidebar collapsible.
*
* .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
* in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
* used to collapse and expand the sidebar.
*
* When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
* and the width of the sidebar and the margin-left of the document
* are decreased. When the sidebar is expanded the opposite happens.
* This script saves a per-browser/per-session cookie used to
* remember the position of the sidebar among the pages.
* Once the browser is closed the cookie is deleted and the position
* reset to the default (expanded).
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
$(function() {
// global elements used by the functions.
// the 'sidebarbutton' element is defined as global after its
// creation, in the add_sidebar_button function
var bodywrapper = $('.bodywrapper');
var sidebar = $('.sphinxsidebar');
var sidebarwrapper = $('.sphinxsidebarwrapper');
// for some reason, the document has no sidebar; do not run into errors
if (!sidebar.length) return;
// original margin-left of the bodywrapper and width of the sidebar
// with the sidebar expanded
var bw_margin_expanded = bodywrapper.css('margin-left');
var ssb_width_expanded = sidebar.width();
// margin-left of the bodywrapper and width of the sidebar
// with the sidebar collapsed
var bw_margin_collapsed = '.8em';
var ssb_width_collapsed = '.8em';
// colors used by the current theme
var dark_color = $('.related').css('background-color');
var light_color = $('.document').css('background-color');
function sidebar_is_collapsed() {
return sidebarwrapper.is(':not(:visible)');
}
function toggle_sidebar() {
if (sidebar_is_collapsed())
expand_sidebar();
else
collapse_sidebar();
}
function collapse_sidebar() {
sidebarwrapper.hide();
sidebar.css('width', ssb_width_collapsed);
bodywrapper.css('margin-left', bw_margin_collapsed);
sidebarbutton.css({
'margin-left': '0',
'height': bodywrapper.height()
});
sidebarbutton.find('span').text('»');
sidebarbutton.attr('title', _('Expand sidebar'));
document.cookie = 'sidebar=collapsed';
}
function expand_sidebar() {
bodywrapper.css('margin-left', bw_margin_expanded);
sidebar.css('width', ssb_width_expanded);
sidebarwrapper.show();
sidebarbutton.css({
'margin-left': ssb_width_expanded-12,
'height': bodywrapper.height()
});
sidebarbutton.find('span').text('«');
sidebarbutton.attr('title', _('Collapse sidebar'));
document.cookie = 'sidebar=expanded';
}
function add_sidebar_button() {
sidebarwrapper.css({
'float': 'left',
'margin-right': '0',
'width': ssb_width_expanded - 28
});
// create the button
sidebar.append(
'<div id="sidebarbutton"><span>&laquo;</span></div>'
);
var sidebarbutton = $('#sidebarbutton');
light_color = sidebarbutton.css('background-color');
// find the height of the viewport to center the '<<' in the page
var viewport_height;
if (window.innerHeight)
viewport_height = window.innerHeight;
else
viewport_height = $(window).height();
sidebarbutton.find('span').css({
'display': 'block',
'margin-top': (viewport_height - sidebar.position().top - 20) / 2
});
sidebarbutton.click(toggle_sidebar);
sidebarbutton.attr('title', _('Collapse sidebar'));
sidebarbutton.css({
'color': '#FFFFFF',
'border-left': '1px solid ' + dark_color,
'font-size': '1.2em',
'cursor': 'pointer',
'height': bodywrapper.height(),
'padding-top': '1px',
'margin-left': ssb_width_expanded - 12
});
sidebarbutton.hover(
function () {
$(this).css('background-color', dark_color);
},
function () {
$(this).css('background-color', light_color);
}
);
}
function set_position_from_cookie() {
if (!document.cookie)
return;
var items = document.cookie.split(';');
for(var k=0; k<items.length; k++) {
var key_val = items[k].split('=');
var key = key_val[0];
if (key == 'sidebar') {
var value = key_val[1];
if ((value == 'collapsed') && (!sidebar_is_collapsed()))
collapse_sidebar();
else if ((value == 'expanded') && (sidebar_is_collapsed()))
expand_sidebar();
}
}
}
add_sidebar_button();
var sidebarbutton = $('#sidebarbutton');
set_position_from_cookie();
});
// Underscore.js 0.5.5
// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the terms of the MIT license.
// Portions of Underscore are inspired by or borrowed from Prototype.js,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore/
(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e<f;e++)c.call(d,
a[e],e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);
var f=b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
d);var e=true;b.each(a,function(f,g,h){(e=e&&c.call(d,f,g,h))||b.breakLoop()});return e};b.any=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.some))return a.some(c,d);var e=false;b.each(a,function(f,g,h){if(e=c.call(d,f,g,h))b.breakLoop()});return e};b.include=function(a,c){if(b.isArray(a))return b.indexOf(a,c)!=-1;var d=false;b.each(a,function(e){if(d=e===c)b.breakLoop()});return d};b.invoke=function(a,c){var d=b.rest(arguments,2);return b.map(a,function(e){return(c?e[c]:e).apply(e,d)})};b.pluck=
function(a,c){return b.map(a,function(d){return d[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,
function(e,f,g){return{value:e,criteria:c.call(d,e,f,g)}}).sort(function(e,f){e=e.criteria;f=f.criteria;return e<f?-1:e>f?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?(e=g+1):(f=g)}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return a;if(b.isArguments(a))return k.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=function(a,c,d){return c&&!d?k.call(a,
0,c):a[0]};b.rest=function(a,c,d){return k.call(a,b.isUndefined(c)||d?1:c)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.select(a,function(c){return!!c})};b.flatten=function(a){return b.reduce(a,[],function(c,d){if(b.isArray(d))return c.concat(b.flatten(d));c.push(d);return c})};b.without=function(a){var c=b.rest(arguments);return b.select(a,function(d){return!b.include(c,d)})};b.uniq=function(a,c){return b.reduce(a,[],function(d,e,f){if(0==f||(c===true?b.last(d)!=e:!b.include(d,
e)))d.push(e);return d})};b.intersect=function(a){var c=b.rest(arguments);return b.select(b.uniq(a),function(d){return b.all(c,function(e){return b.indexOf(e,d)>=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e<c;e++)d[e]=b.pluck(a,String(e));return d};b.indexOf=function(a,c){if(a.indexOf)return a.indexOf(c);for(var d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a.lastIndexOf)return a.lastIndexOf(c);for(var d=
a.length;d--;)if(a[d]===c)return d;return-1};b.range=function(a,c,d){var e=b.toArray(arguments),f=e.length<=1;a=f?0:e[0];c=f?e[0]:e[1];d=e[2]||1;e=Math.ceil((c-a)/d);if(e<=0)return[];e=new Array(e);f=a;for(var g=0;1;f+=d){if((d>0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)});
return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length);
var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false;
if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length==
0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!b.isArray(a)&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&&
a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.template=function(a,c){a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g,
" ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments);
o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})();
th.field-name {
font-weight: normal;
background: inherit;
font-variant: small-caps;
font-size: small;
}
td.field-body ul li strong {
font-weight: normal;
border-bottom-width: 1px;
border-bottom-style: dashed;
border-bottom-color: darkgreen;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

/*
* websupport.js
* ~~~~~~~~~~~~~
*
* sphinx.websupport utilties for all documentation.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
(function($) {
$.fn.autogrow = function() {
return this.each(function() {
var textarea = this;
$.fn.autogrow.resize(textarea);
$(textarea)
.focus(function() {
textarea.interval = setInterval(function() {
$.fn.autogrow.resize(textarea);
}, 500);
})
.blur(function() {
clearInterval(textarea.interval);
});
});
};
$.fn.autogrow.resize = function(textarea) {
var lineHeight = parseInt($(textarea).css('line-height'), 10);
var lines = textarea.value.split('\n');
var columns = textarea.cols;
var lineCount = 0;
$.each(lines, function() {
lineCount += Math.ceil(this.length / columns) || 1;
});
var height = lineHeight * (lineCount + 1);
$(textarea).css('height', height);
};
})(jQuery);
(function($) {
var comp, by;
function init() {
initEvents();
initComparator();
}
function initEvents() {
$('a.comment-close').live("click", function(event) {
event.preventDefault();
hide($(this).attr('id').substring(2));
});
$('a.vote').live("click", function(event) {
event.preventDefault();
handleVote($(this));
});
$('a.reply').live("click", function(event) {
event.preventDefault();
openReply($(this).attr('id').substring(2));
});
$('a.close-reply').live("click", function(event) {
event.preventDefault();
closeReply($(this).attr('id').substring(2));
});
$('a.sort-option').live("click", function(event) {
event.preventDefault();
handleReSort($(this));
});
$('a.show-proposal').live("click", function(event) {
event.preventDefault();
showProposal($(this).attr('id').substring(2));
});
$('a.hide-proposal').live("click", function(event) {
event.preventDefault();
hideProposal($(this).attr('id').substring(2));
});
$('a.show-propose-change').live("click", function(event) {
event.preventDefault();
showProposeChange($(this).attr('id').substring(2));
});
$('a.hide-propose-change').live("click", function(event) {
event.preventDefault();
hideProposeChange($(this).attr('id').substring(2));
});
$('a.accept-comment').live("click", function(event) {
event.preventDefault();
acceptComment($(this).attr('id').substring(2));
});
$('a.delete-comment').live("click", function(event) {
event.preventDefault();
deleteComment($(this).attr('id').substring(2));
});
$('a.comment-markup').live("click", function(event) {
event.preventDefault();
toggleCommentMarkupBox($(this).attr('id').substring(2));
});
}
/**
* Set comp, which is a comparator function used for sorting and
* inserting comments into the list.
*/
function setComparator() {
// If the first three letters are "asc", sort in ascending order
// and remove the prefix.
if (by.substring(0,3) == 'asc') {
var i = by.substring(3);
comp = function(a, b) { return a[i] - b[i]; };
} else {
// Otherwise sort in descending order.
comp = function(a, b) { return b[by] - a[by]; };
}
// Reset link styles and format the selected sort option.
$('a.sel').attr('href', '#').removeClass('sel');
$('a.by' + by).removeAttr('href').addClass('sel');
}
/**
* Create a comp function. If the user has preferences stored in
* the sortBy cookie, use those, otherwise use the default.
*/
function initComparator() {
by = 'rating'; // Default to sort by rating.
// If the sortBy cookie is set, use that instead.
if (document.cookie.length > 0) {
var start = document.cookie.indexOf('sortBy=');
if (start != -1) {
start = start + 7;
var end = document.cookie.indexOf(";", start);
if (end == -1) {
end = document.cookie.length;
by = unescape(document.cookie.substring(start, end));
}
}
}
setComparator();
}
/**
* Show a comment div.
*/
function show(id) {
$('#ao' + id).hide();
$('#ah' + id).show();
var context = $.extend({id: id}, opts);
var popup = $(renderTemplate(popupTemplate, context)).hide();
popup.find('textarea[name="proposal"]').hide();
popup.find('a.by' + by).addClass('sel');
var form = popup.find('#cf' + id);
form.submit(function(event) {
event.preventDefault();
addComment(form);
});
$('#s' + id).after(popup);
popup.slideDown('fast', function() {
getComments(id);
});
}
/**
* Hide a comment div.
*/
function hide(id) {
$('#ah' + id).hide();
$('#ao' + id).show();
var div = $('#sc' + id);
div.slideUp('fast', function() {
div.remove();
});
}
/**
* Perform an ajax request to get comments for a node
* and insert the comments into the comments tree.
*/
function getComments(id) {
$.ajax({
type: 'GET',
url: opts.getCommentsURL,
data: {node: id},
success: function(data, textStatus, request) {
var ul = $('#cl' + id);
var speed = 100;
$('#cf' + id)
.find('textarea[name="proposal"]')
.data('source', data.source);
if (data.comments.length === 0) {
ul.html('<li>No comments yet.</li>');
ul.data('empty', true);
} else {
// If there are comments, sort them and put them in the list.
var comments = sortComments(data.comments);
speed = data.comments.length * 100;
appendComments(comments, ul);
ul.data('empty', false);
}
$('#cn' + id).slideUp(speed + 200);
ul.slideDown(speed);
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem retrieving the comments.');
},
dataType: 'json'
});
}
/**
* Add a comment via ajax and insert the comment into the comment tree.
*/
function addComment(form) {
var node_id = form.find('input[name="node"]').val();
var parent_id = form.find('input[name="parent"]').val();
var text = form.find('textarea[name="comment"]').val();
var proposal = form.find('textarea[name="proposal"]').val();
if (text == '') {
showError('Please enter a comment.');
return;
}
// Disable the form that is being submitted.
form.find('textarea,input').attr('disabled', 'disabled');
// Send the comment to the server.
$.ajax({
type: "POST",
url: opts.addCommentURL,
dataType: 'json',
data: {
node: node_id,
parent: parent_id,
text: text,
proposal: proposal
},
success: function(data, textStatus, error) {
// Reset the form.
if (node_id) {
hideProposeChange(node_id);
}
form.find('textarea')
.val('')
.add(form.find('input'))
.removeAttr('disabled');
var ul = $('#cl' + (node_id || parent_id));
if (ul.data('empty')) {
$(ul).empty();
ul.data('empty', false);
}
insertComment(data.comment);
var ao = $('#ao' + node_id);
ao.find('img').attr({'src': opts.commentBrightImage});
if (node_id) {
// if this was a "root" comment, remove the commenting box
// (the user can get it back by reopening the comment popup)
$('#ca' + node_id).slideUp();
}
},
error: function(request, textStatus, error) {
form.find('textarea,input').removeAttr('disabled');
showError('Oops, there was a problem adding the comment.');
}
});
}
/**
* Recursively append comments to the main comment list and children
* lists, creating the comment tree.
*/
function appendComments(comments, ul) {
$.each(comments, function() {
var div = createCommentDiv(this);
ul.append($(document.createElement('li')).html(div));
appendComments(this.children, div.find('ul.comment-children'));
// To avoid stagnating data, don't store the comments children in data.
this.children = null;
div.data('comment', this);
});
}
/**
* After adding a new comment, it must be inserted in the correct
* location in the comment tree.
*/
function insertComment(comment) {
var div = createCommentDiv(comment);
// To avoid stagnating data, don't store the comments children in data.
comment.children = null;
div.data('comment', comment);
var ul = $('#cl' + (comment.node || comment.parent));
var siblings = getChildren(ul);
var li = $(document.createElement('li'));
li.hide();
// Determine where in the parents children list to insert this comment.
for(i=0; i < siblings.length; i++) {
if (comp(comment, siblings[i]) <= 0) {
$('#cd' + siblings[i].id)
.parent()
.before(li.html(div));
li.slideDown('fast');
return;
}
}
// If we get here, this comment rates lower than all the others,
// or it is the only comment in the list.
ul.append(li.html(div));
li.slideDown('fast');
}
function acceptComment(id) {
$.ajax({
type: 'POST',
url: opts.acceptCommentURL,
data: {id: id},
success: function(data, textStatus, request) {
$('#cm' + id).fadeOut('fast');
$('#cd' + id).removeClass('moderate');
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem accepting the comment.');
}
});
}
function deleteComment(id) {
$.ajax({
type: 'POST',
url: opts.deleteCommentURL,
data: {id: id},
success: function(data, textStatus, request) {
var div = $('#cd' + id);
if (data == 'delete') {
// Moderator mode: remove the comment and all children immediately
div.slideUp('fast', function() {
div.remove();
});
return;
}
// User mode: only mark the comment as deleted
div
.find('span.user-id:first')
.text('[deleted]').end()
.find('div.comment-text:first')
.text('[deleted]').end()
.find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
.remove();
var comment = div.data('comment');
comment.username = '[deleted]';
comment.text = '[deleted]';
div.data('comment', comment);
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem deleting the comment.');
}
});
}
function showProposal(id) {
$('#sp' + id).hide();
$('#hp' + id).show();
$('#pr' + id).slideDown('fast');
}
function hideProposal(id) {
$('#hp' + id).hide();
$('#sp' + id).show();
$('#pr' + id).slideUp('fast');
}
function showProposeChange(id) {
$('#pc' + id).hide();
$('#hc' + id).show();
var textarea = $('#pt' + id);
textarea.val(textarea.data('source'));
$.fn.autogrow.resize(textarea[0]);
textarea.slideDown('fast');
}
function hideProposeChange(id) {
$('#hc' + id).hide();
$('#pc' + id).show();
var textarea = $('#pt' + id);
textarea.val('').removeAttr('disabled');
textarea.slideUp('fast');
}
function toggleCommentMarkupBox(id) {
$('#mb' + id).toggle();
}
/** Handle when the user clicks on a sort by link. */
function handleReSort(link) {
var classes = link.attr('class').split(/\s+/);
for (var i=0; i<classes.length; i++) {
if (classes[i] != 'sort-option') {
by = classes[i].substring(2);
}
}
setComparator();
// Save/update the sortBy cookie.
var expiration = new Date();
expiration.setDate(expiration.getDate() + 365);
document.cookie= 'sortBy=' + escape(by) +
';expires=' + expiration.toUTCString();
$('ul.comment-ul').each(function(index, ul) {
var comments = getChildren($(ul), true);
comments = sortComments(comments);
appendComments(comments, $(ul).empty());
});
}
/**
* Function to process a vote when a user clicks an arrow.
*/
function handleVote(link) {
if (!opts.voting) {
showError("You'll need to login to vote.");
return;
}
var id = link.attr('id');
if (!id) {
// Didn't click on one of the voting arrows.
return;
}
// If it is an unvote, the new vote value is 0,
// Otherwise it's 1 for an upvote, or -1 for a downvote.
var value = 0;
if (id.charAt(1) != 'u') {
value = id.charAt(0) == 'u' ? 1 : -1;
}
// The data to be sent to the server.
var d = {
comment_id: id.substring(2),
value: value
};
// Swap the vote and unvote links.
link.hide();
$('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
.show();
// The div the comment is displayed in.
var div = $('div#cd' + d.comment_id);
var data = div.data('comment');
// If this is not an unvote, and the other vote arrow has
// already been pressed, unpress it.
if ((d.value !== 0) && (data.vote === d.value * -1)) {
$('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
$('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
}
// Update the comments rating in the local data.
data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
data.vote = d.value;
div.data('comment', data);
// Change the rating text.
div.find('.rating:first')
.text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
// Send the vote information to the server.
$.ajax({
type: "POST",
url: opts.processVoteURL,
data: d,
error: function(request, textStatus, error) {
showError('Oops, there was a problem casting that vote.');
}
});
}
/**
* Open a reply form used to reply to an existing comment.
*/
function openReply(id) {
// Swap out the reply link for the hide link
$('#rl' + id).hide();
$('#cr' + id).show();
// Add the reply li to the children ul.
var div = $(renderTemplate(replyTemplate, {id: id})).hide();
$('#cl' + id)
.prepend(div)
// Setup the submit handler for the reply form.
.find('#rf' + id)
.submit(function(event) {
event.preventDefault();
addComment($('#rf' + id));
closeReply(id);
})
.find('input[type=button]')
.click(function() {
closeReply(id);
});
div.slideDown('fast', function() {
$('#rf' + id).find('textarea').focus();
});
}
/**
* Close the reply form opened with openReply.
*/
function closeReply(id) {
// Remove the reply div from the DOM.
$('#rd' + id).slideUp('fast', function() {
$(this).remove();
});
// Swap out the hide link for the reply link
$('#cr' + id).hide();
$('#rl' + id).show();
}
/**
* Recursively sort a tree of comments using the comp comparator.
*/
function sortComments(comments) {
comments.sort(comp);
$.each(comments, function() {
this.children = sortComments(this.children);
});
return comments;
}
/**
* Get the children comments from a ul. If recursive is true,
* recursively include childrens' children.
*/
function getChildren(ul, recursive) {
var children = [];
ul.children().children("[id^='cd']")
.each(function() {
var comment = $(this).data('comment');
if (recursive)
comment.children = getChildren($(this).find('#cl' + comment.id), true);
children.push(comment);
});
return children;
}
/** Create a div to display a comment in. */
function createCommentDiv(comment) {
if (!comment.displayed && !opts.moderator) {
return $('<div class="moderate">Thank you! Your comment will show up '
+ 'once it is has been approved by a moderator.</div>');
}
// Prettify the comment rating.
comment.pretty_rating = comment.rating + ' point' +
(comment.rating == 1 ? '' : 's');
// Make a class (for displaying not yet moderated comments differently)
comment.css_class = comment.displayed ? '' : ' moderate';
// Create a div for this comment.
var context = $.extend({}, opts, comment);
var div = $(renderTemplate(commentTemplate, context));
// If the user has voted on this comment, highlight the correct arrow.
if (comment.vote) {
var direction = (comment.vote == 1) ? 'u' : 'd';
div.find('#' + direction + 'v' + comment.id).hide();
div.find('#' + direction + 'u' + comment.id).show();
}
if (opts.moderator || comment.text != '[deleted]') {
div.find('a.reply').show();
if (comment.proposal_diff)
div.find('#sp' + comment.id).show();
if (opts.moderator && !comment.displayed)
div.find('#cm' + comment.id).show();
if (opts.moderator || (opts.username == comment.username))
div.find('#dc' + comment.id).show();
}
return div;
}
/**
* A simple template renderer. Placeholders such as <%id%> are replaced
* by context['id'] with items being escaped. Placeholders such as <#id#>
* are not escaped.
*/
function renderTemplate(template, context) {
var esc = $(document.createElement('div'));
function handle(ph, escape) {
var cur = context;
$.each(ph.split('.'), function() {
cur = cur[this];
});
return escape ? esc.text(cur || "").html() : cur;
}
return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
return handle(arguments[2], arguments[1] == '%' ? true : false);
});
}
/** Flash an error message briefly. */
function showError(message) {
$(document.createElement('div')).attr({'class': 'popup-error'})
.append($(document.createElement('div'))
.attr({'class': 'error-message'}).text(message))
.appendTo('body')
.fadeIn("slow")
.delay(2000)
.fadeOut("slow");
}
/** Add a link the user uses to open the comments popup. */
$.fn.comment = function() {
return this.each(function() {
var id = $(this).attr('id').substring(1);
var count = COMMENT_METADATA[id];
var title = count + ' comment' + (count == 1 ? '' : 's');
var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
var addcls = count == 0 ? ' nocomment' : '';
$(this)
.append(
$(document.createElement('a')).attr({
href: '#',
'class': 'sphinx-comment-open' + addcls,
id: 'ao' + id
})
.append($(document.createElement('img')).attr({
src: image,
alt: 'comment',
title: title
}))
.click(function(event) {
event.preventDefault();
show($(this).attr('id').substring(2));
})
)
.append(
$(document.createElement('a')).attr({
href: '#',
'class': 'sphinx-comment-close hidden',
id: 'ah' + id
})
.append($(document.createElement('img')).attr({
src: opts.closeCommentImage,
alt: 'close',
title: 'close'
}))
.click(function(event) {
event.preventDefault();
hide($(this).attr('id').substring(2));
})
);
});
};
var opts = {
processVoteURL: '/_process_vote',
addCommentURL: '/_add_comment',
getCommentsURL: '/_get_comments',
acceptCommentURL: '/_accept_comment',
deleteCommentURL: '/_delete_comment',
commentImage: '/static/_static/comment.png',
closeCommentImage: '/static/_static/comment-close.png',
loadingImage: '/static/_static/ajax-loader.gif',
commentBrightImage: '/static/_static/comment-bright.png',
upArrow: '/static/_static/up.png',
downArrow: '/static/_static/down.png',
upArrowPressed: '/static/_static/up-pressed.png',
downArrowPressed: '/static/_static/down-pressed.png',
voting: false,
moderator: false
};
if (typeof COMMENT_OPTIONS != "undefined") {
opts = jQuery.extend(opts, COMMENT_OPTIONS);
}
var popupTemplate = '\
<div class="sphinx-comments" id="sc<%id%>">\
<p class="sort-options">\
Sort by:\
<a href="#" class="sort-option byrating">best rated</a>\
<a href="#" class="sort-option byascage">newest</a>\
<a href="#" class="sort-option byage">oldest</a>\
</p>\
<div class="comment-header">Comments</div>\
<div class="comment-loading" id="cn<%id%>">\
loading comments... <img src="<%loadingImage%>" alt="" /></div>\
<ul id="cl<%id%>" class="comment-ul"></ul>\
<div id="ca<%id%>">\
<p class="add-a-comment">Add a comment\
(<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
<div class="comment-markup-box" id="mb<%id%>">\
reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
<tt>``code``</tt>, \
code blocks: <tt>::</tt> and an indented block after blank line</div>\
<form method="post" id="cf<%id%>" class="comment-form" action="">\
<textarea name="comment" cols="80"></textarea>\
<p class="propose-button">\
<a href="#" id="pc<%id%>" class="show-propose-change">\
Propose a change &#9657;\
</a>\
<a href="#" id="hc<%id%>" class="hide-propose-change">\
Propose a change &#9663;\
</a>\
</p>\
<textarea name="proposal" id="pt<%id%>" cols="80"\
spellcheck="false"></textarea>\
<input type="submit" value="Add comment" />\
<input type="hidden" name="node" value="<%id%>" />\
<input type="hidden" name="parent" value="" />\
</form>\
</div>\
</div>';
var commentTemplate = '\
<div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
<div class="vote">\
<div class="arrow">\
<a href="#" id="uv<%id%>" class="vote" title="vote up">\
<img src="<%upArrow%>" />\
</a>\
<a href="#" id="uu<%id%>" class="un vote" title="vote up">\
<img src="<%upArrowPressed%>" />\
</a>\
</div>\
<div class="arrow">\
<a href="#" id="dv<%id%>" class="vote" title="vote down">\
<img src="<%downArrow%>" id="da<%id%>" />\
</a>\
<a href="#" id="du<%id%>" class="un vote" title="vote down">\
<img src="<%downArrowPressed%>" />\
</a>\
</div>\
</div>\
<div class="comment-content">\
<p class="tagline comment">\
<span class="user-id"><%username%></span>\
<span class="rating"><%pretty_rating%></span>\
<span class="delta"><%time.delta%></span>\
</p>\
<div class="comment-text comment"><#text#></div>\
<p class="comment-opts comment">\
<a href="#" class="reply hidden" id="rl<%id%>">reply &#9657;</a>\
<a href="#" class="close-reply" id="cr<%id%>">reply &#9663;</a>\
<a href="#" id="sp<%id%>" class="show-proposal">proposal &#9657;</a>\
<a href="#" id="hp<%id%>" class="hide-proposal">proposal &#9663;</a>\
<a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
<span id="cm<%id%>" class="moderation hidden">\
<a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
</span>\
</p>\
<pre class="proposal" id="pr<%id%>">\
<#proposal_diff#>\
</pre>\
<ul class="comment-children" id="cl<%id%>"></ul>\
</div>\
<div class="clearleft"></div>\
</div>\
</div>';
var replyTemplate = '\
<li>\
<div class="reply-div" id="rd<%id%>">\
<form id="rf<%id%>">\
<textarea name="comment" cols="80"></textarea>\
<input type="submit" value="Add reply" />\
<input type="button" value="Cancel" />\
<input type="hidden" name="parent" value="<%id%>" />\
<input type="hidden" name="node" value="" />\
</form>\
</div>\
</li>';
$(document).ready(function() {
init();
});
})(jQuery);
$(document).ready(function() {
// add comment anchors for all paragraphs that are commentable
$('.sphinx-has-comment').comment();
// highlight search words in search results
$("div.context").each(function() {
var params = $.getQueryParameters();
var terms = (params.q) ? params.q[0].split(/\s+/) : [];
var result = $(this);
$.each(terms, function() {
result.highlightText(this.toLowerCase(), 'highlighted');
});
});
// directly open comment window if requested
var anchor = document.location.hash;
if (anchor.substring(0, 9) == '#comment-') {
$('#ao' + anchor.substring(9)).click();
document.location.hash = '#s' + anchor.substring(9);
}
});

Sorry, the diff of this file is not supported yet

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Administration &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Driver" href="driver.html" />
<link rel="prev" title="py-postgresql" href="index.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="driver.html" title="Driver"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="py-postgresql"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="administration">
<h1>Administration<a class="headerlink" href="#administration" title="Permalink to this headline">¶</a></h1>
<p>This chapter covers the administration of py-postgresql. This includes
installation and other aspects of working with py-postgresql such as
environment variables and configuration files.</p>
<div class="section" id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
<p>py-postgresql uses Python&#8217;s distutils package to manage the build and
installation process of the package. The normal entry point for
this is the <tt class="docutils literal"><span class="pre">setup.py</span></tt> script contained in the root project directory.</p>
<p>After extracting the archive and changing the into the project&#8217;s directory,
installation is normally as simple as:</p>
<div class="highlight-python"><pre>$ python3 ./setup.py install</pre>
</div>
<p>However, if you need to install for use with a particular version of python,
just use the path of the executable that should be used:</p>
<div class="highlight-python"><pre>$ /usr/opt/bin/python3 ./setup.py install</pre>
</div>
</div>
<div class="section" id="environment">
<h2>Environment<a class="headerlink" href="#environment" title="Permalink to this headline">¶</a></h2>
<p>These environment variables effect the operation of the package:</p>
<blockquote>
<div><table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>PGINSTALLATION</td>
<td>The path to the <tt class="docutils literal"><span class="pre">pg_config</span></tt> executable of the installation to use by default.</td>
</tr>
</tbody>
</table>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Administration</a><ul>
<li><a class="reference internal" href="#installation">Installation</a></li>
<li><a class="reference internal" href="#environment">Environment</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">py-postgresql</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="driver.html"
title="next chapter">Driver</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/admin.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="driver.html" title="Driver"
>next</a> |</li>
<li class="right" >
<a href="index.html" title="py-postgresql"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Advisory Locks &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Cluster Management" href="cluster.html" />
<link rel="prev" title="Notification Management" href="notifyman.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="cluster.html" title="Cluster Management"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="notifyman.html" title="Notification Management"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="advisory-locks">
<span id="alock"></span><h1>Advisory Locks<a class="headerlink" href="#advisory-locks" title="Permalink to this headline">¶</a></h1>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last"><cite>postgresql.alock</cite> is a new feature in v1.0.</p>
</div>
<p><a class="reference external" href="http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS">Explicit Locking in PostgreSQL</a>.</p>
<p>PostgreSQL&#8217;s advisory locks offer a cooperative synchronization primitive.
These are used in cases where an application needs access to a resource, but
using table locks may cause interference with other operations that can be
safely performed alongside the application-level, exclusive operation.</p>
<p>Advisory locks can be used by directly executing the stored procedures in the
database or by using the <a class="reference internal" href="reference.html#postgresql.alock.ALock" title="postgresql.alock.ALock"><tt class="xref py py-class docutils literal"><span class="pre">postgresql.alock.ALock</span></tt></a> subclasses, which
provides a context manager that uses those stored procedures.</p>
<p>Currently, only two subclasses exist. Each represents the lock mode
supported by PostgreSQL&#8217;s advisory locks:</p>
<blockquote>
<div><ul class="simple">
<li><tt class="xref py py-class docutils literal"><span class="pre">postgresql.alock.ShareLock</span></tt></li>
<li><tt class="xref py py-class docutils literal"><span class="pre">postgresql.alock.ExclusiveLock</span></tt></li>
</ul>
</div></blockquote>
<div class="section" id="acquiring-alocks">
<h2>Acquiring ALocks<a class="headerlink" href="#acquiring-alocks" title="Permalink to this headline">¶</a></h2>
<p>An ALock instance represents a sequence of advisory locks. A single ALock can
acquire and release multiple advisory locks by creating the instance with
multiple lock identifiers:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">alock</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">table1_oid</span> <span class="o">=</span> <span class="mi">192842</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">table2_oid</span> <span class="o">=</span> <span class="mi">192849</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">l</span> <span class="o">=</span> <span class="n">alock</span><span class="o">.</span><span class="n">ExclusiveLock</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="p">(</span><span class="n">table1_oid</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="n">table2_oid</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">l</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="o">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">l</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
</pre></div>
</div>
<p><a class="reference internal" href="reference.html#postgresql.alock.ALock" title="postgresql.alock.ALock"><tt class="xref py py-class docutils literal"><span class="pre">postgresql.alock.ALock</span></tt></a> is similar to <tt class="xref py py-class docutils literal"><span class="pre">threading.RLock</span></tt>; in
order for an ALock to be released, it must be released the number of times it
has been acquired. ALocks are associated with and survived by their session.
Much like how RLocks are associated with the thread they are acquired in:
acquiring an ALock again will merely increment its count.</p>
<p>PostgreSQL allows advisory locks to be identified using a pair of <cite>int4</cite> or a
single <cite>int8</cite>. ALock instances represent a <em>sequence</em> of those identifiers:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">alock</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ids</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">alock</span><span class="o">.</span><span class="n">ShareLock</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="o">*</span><span class="n">ids</span><span class="p">):</span>
<span class="gp">... </span> <span class="o">...</span>
</pre></div>
</div>
<p>Both types of identifiers may be used within the same ALock, and, regardless of
their type, will be aquired in the order that they were given to the class&#8217;
constructor. In the above example, <tt class="docutils literal"><span class="pre">(0,0)</span></tt> is acquired first, then <tt class="docutils literal"><span class="pre">0</span></tt>, and
lastly <tt class="docutils literal"><span class="pre">1</span></tt>.</p>
</div>
<div class="section" id="alocks">
<h2>ALocks<a class="headerlink" href="#alocks" title="Permalink to this headline">¶</a></h2>
<p><cite>postgresql.alock.ALock</cite> is abstract; it defines the interface and some common
functionality. The lock mode is selected by choosing the appropriate subclass.</p>
<p>There are two:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">postgresql.alock.ExclusiveLock(database,</span> <span class="pre">*identifiers)</span></tt></dt>
<dd>Instantiate an ALock object representing the <cite>identifiers</cite> for use with the
<cite>database</cite>. Exclusive locks will conflict with other exclusive locks and share
locks.</dd>
<dt><tt class="docutils literal"><span class="pre">postgresql.alock.ShareLock(database,</span> <span class="pre">*identifiers)</span></tt></dt>
<dd>Instantiate an ALock object representing the <cite>identifiers</cite> for use with the
<cite>database</cite>. Share locks can be acquired when a share lock with the same
identifier has been acquired by another backend. However, an exclusive lock
with the same identifier will conflict.</dd>
</dl>
</div></blockquote>
<div class="section" id="alock-interface-points">
<h3>ALock Interface Points<a class="headerlink" href="#alock-interface-points" title="Permalink to this headline">¶</a></h3>
<p>Methods and properties available on <a class="reference internal" href="reference.html#postgresql.alock.ALock" title="postgresql.alock.ALock"><tt class="xref py py-class docutils literal"><span class="pre">postgresql.alock.ALock</span></tt></a> instances:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">alock.acquire(blocking</span> <span class="pre">=</span> <span class="pre">True)</span></tt></dt>
<dd><p class="first">Acquire the advisory locks represented by the <tt class="docutils literal"><span class="pre">alock</span></tt> object. If blocking is
<cite>True</cite>, the default, the method will block until locks on <em>all</em> the
identifiers have been acquired.</p>
<p class="last">If blocking is <cite>False</cite>, acquisition may not block, and success will be
indicated by the returned object: <cite>True</cite> if <em>all</em> lock identifiers were
acquired and <cite>False</cite> if any of the lock identifiers could not be acquired.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">alock.release()</span></tt></dt>
<dd>Release the advisory locks represented by the <tt class="docutils literal"><span class="pre">alock</span></tt> object. If the lock
has not been acquired, a <cite>RuntimeError</cite> will be raised.</dd>
<dt><tt class="docutils literal"><span class="pre">alock.locked()</span></tt></dt>
<dd>Returns a boolean describing whether the locks are held or not. This will
return <cite>False</cite> if the lock connection has been closed.</dd>
<dt><tt class="docutils literal"><span class="pre">alock.__enter__()</span></tt></dt>
<dd>Alias to <tt class="docutils literal"><span class="pre">acquire</span></tt>; context manager protocol. Always blocking.</dd>
<dt><tt class="docutils literal"><span class="pre">alock.__exit__(typ,</span> <span class="pre">val,</span> <span class="pre">tb)</span></tt></dt>
<dd>Alias to <tt class="docutils literal"><span class="pre">release</span></tt>; context manager protocol.</dd>
</dl>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Advisory Locks</a><ul>
<li><a class="reference internal" href="#acquiring-alocks">Acquiring ALocks</a></li>
<li><a class="reference internal" href="#alocks">ALocks</a><ul>
<li><a class="reference internal" href="#alock-interface-points">ALock Interface Points</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="notifyman.html"
title="previous chapter">Notification Management</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="cluster.html"
title="next chapter">Cluster Management</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/alock.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="cluster.html" title="Cluster Management"
>next</a> |</li>
<li class="right" >
<a href="notifyman.html" title="Notification Management"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Commands &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Reference" href="reference.html" />
<link rel="prev" title="Gotchas" href="gotchas.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="reference.html" title="Reference"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="gotchas.html" title="Gotchas"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="commands">
<h1>Commands<a class="headerlink" href="#commands" title="Permalink to this headline">¶</a></h1>
<p>This chapter discusses the usage of the available console scripts.</p>
<div class="section" id="postgresql-bin-pg-python">
<h2>postgresql.bin.pg_python<a class="headerlink" href="#postgresql-bin-pg-python" title="Permalink to this headline">¶</a></h2>
<p>The <tt class="docutils literal"><span class="pre">pg_python</span></tt> command provides a simple way to write Python scripts against a
single target database. It acts like the regular Python console command, but
takes standard PostgreSQL options as well to specify the client parameters
to make establish connection with. The Python environment is then augmented
with the following built-ins:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">db</span></tt></dt>
<dd>The PG-API connection object.</dd>
<dt><tt class="docutils literal"><span class="pre">xact</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.xact</span></tt>, the transaction creator.</dd>
<dt><tt class="docutils literal"><span class="pre">settings</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.settings</span></tt></dd>
<dt><tt class="docutils literal"><span class="pre">prepare</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.prepare</span></tt>, the statement creator.</dd>
<dt><tt class="docutils literal"><span class="pre">proc</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.proc</span></tt></dd>
<dt><tt class="docutils literal"><span class="pre">do</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.do</span></tt>, execute a single DO statement.</dd>
<dt><tt class="docutils literal"><span class="pre">sqlexec</span></tt></dt>
<dd><tt class="docutils literal"><span class="pre">db.execute</span></tt>, execute multiple SQL statements (<tt class="docutils literal"><span class="pre">None</span></tt> is always returned)</dd>
</dl>
</div></blockquote>
<div class="section" id="pg-python-usage">
<h3>pg_python Usage<a class="headerlink" href="#pg-python-usage" title="Permalink to this headline">¶</a></h3>
<p>Usage: postgresql.bin.pg_python [connection options] [script] ...</p>
<dl class="docutils">
<dt>Options:</dt>
<dd><table class="first last docutils option-list" frame="void" rules="none">
<col class="option" />
<col class="description" />
<tbody valign="top">
<tr><td class="option-group">
<kbd><span class="option">--unix=<var>UNIX</var></span></kbd></td>
<td>path to filesystem socket</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--ssl-mode=<var>SSLMODE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>SSL requirement for connectivity: require, prefer,
allow, disable</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-s <var>SETTINGS</var></span>, <span class="option">--setting=<var>SETTINGS</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>run-time parameters to set upon connecting</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-I <var>PQ_IRI</var></span>, <span class="option">--iri=<var>PQ_IRI</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>database locator string
[pq://user:password&#64;host:port/database?setting=value]</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-h <var>HOST</var></span>, <span class="option">--host=<var>HOST</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>database server host</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-p <var>PORT</var></span>, <span class="option">--port=<var>PORT</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>database server port</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-U <var>USER</var></span>, <span class="option">--username=<var>USER</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>user name to connect as</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-W</span>, <span class="option">--password</span></kbd></td>
<td>prompt for password</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-d <var>DATABASE</var></span>, <span class="option">--database=<var>DATABASE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>database&#8217;s name</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--pq-trace=<var>PQ_TRACE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>trace PQ protocol transmissions</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-C <var>PYTHON_CONTEXT</var></span>, <span class="option">--context=<var>PYTHON_CONTEXT</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>Python context code to run[<a class="reference external" href="file://,module">file://,module</a>:,&lt;code&gt;]</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-m <var>PYTHON_MAIN</var></span></kbd></td>
<td>Python module to run as script(__main__)</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-c <var>PYTHON_MAIN</var></span></kbd></td>
<td>Python expression to run(__main__)</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--version</span></kbd></td>
<td>show program&#8217;s version number and exit</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--help</span></kbd></td>
<td>show this help message and exit</td></tr>
</tbody>
</table>
</dd>
</dl>
</div>
<div class="section" id="interactive-console-backslash-commands">
<h3>Interactive Console Backslash Commands<a class="headerlink" href="#interactive-console-backslash-commands" title="Permalink to this headline">¶</a></h3>
<p>Inspired by <tt class="docutils literal"><span class="pre">psql</span></tt>:</p>
<div class="highlight-python"><pre>&gt;&gt;&gt; \?
Backslash Commands:
\? Show this help message.
\E Edit a file or a temporary script.
\e Edit and Execute the file directly in the context.
\i Execute a Python script within the interpreter&#x27;s context.
\set Configure environment variables. \set without arguments to show all
\x Execute the Python command within this process.</pre>
</div>
</div>
<div class="section" id="pg-python-examples">
<h3>pg_python Examples<a class="headerlink" href="#pg-python-examples" title="Permalink to this headline">¶</a></h3>
<p>Module execution taking advantage of the new built-ins:</p>
<div class="highlight-python"><pre>$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit &quot;prepare(&#x27;SELECT 1&#x27;).first()&quot;
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 1.35 msec per loop
$ python3 -m postgresql.bin.pg_python -h localhost -W -m timeit -s &quot;ps=prepare(&#x27;SELECT 1&#x27;)&quot; &quot;ps.first()&quot;
Password for pg_python[pq://jwp@localhost:5432]:
1000 loops, best of 3: 442 usec per loop</pre>
</div>
<p>Simple interactive usage:</p>
<div class="highlight-python"><pre>$ python3 -m postgresql.bin.pg_python -h localhost -W
Password for pg_python[pq://jwp@localhost:5432]:
&gt;&gt;&gt; ps = prepare(&#x27;select 1&#x27;)
&gt;&gt;&gt; ps.first()
1
&gt;&gt;&gt; c = ps()
&gt;&gt;&gt; c.read()
[(1,)]
&gt;&gt;&gt; ps.close()
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.exit(0)</pre>
</div>
</div>
</div>
<div class="section" id="postgresql-bin-pg-dotconf">
<h2>postgresql.bin.pg_dotconf<a class="headerlink" href="#postgresql-bin-pg-dotconf" title="Permalink to this headline">¶</a></h2>
<p>pg_dotconf is used to modify a PostgreSQL cluster&#8217;s configuration file.
It provides a means to apply settings specified from the command line and from a
file referenced using the <tt class="docutils literal"><span class="pre">-f</span></tt> option.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last"><tt class="docutils literal"><span class="pre">include</span></tt> directives in configuration files are <em>completely</em> ignored. If
modification of an included file is desired, the command must be applied to
that specific file.</p>
</div>
<div class="section" id="pg-dotconf-usage">
<h3>pg_dotconf Usage<a class="headerlink" href="#pg-dotconf-usage" title="Permalink to this headline">¶</a></h3>
<p>Usage: postgresql.bin.pg_dotconf [&#8211;stdout] [-f filepath] postgresql.conf ([param=val]|[param])*</p>
<dl class="docutils">
<dt>Options:</dt>
<dd><table class="first last docutils option-list" frame="void" rules="none">
<col class="option" />
<col class="description" />
<tbody valign="top">
<tr><td class="option-group">
<kbd><span class="option">--version</span></kbd></td>
<td>show program&#8217;s version number and exit</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-h</span>, <span class="option">--help</span></kbd></td>
<td>show this help message and exit</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-f <var>SETTINGS</var></span>, <span class="option">--file=<var>SETTINGS</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>A file of settings to <em>apply</em> to the given
&#8220;postgresql.conf&#8221;</td></tr>
<tr><td class="option-group">
<kbd><span class="option">--stdout</span></kbd></td>
<td>Redirect the product to standard output instead of
writing back to the &#8220;postgresql.conf&#8221; file</td></tr>
</tbody>
</table>
</dd>
</dl>
</div>
<div class="section" id="examples">
<h3>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h3>
<p>Modifying a simple configuration file:</p>
<div class="highlight-python"><pre>$ echo &quot;setting = value&quot; &gt;pg.conf
# change &#x27;setting&#x27;
$ python3 -m postgresql.bin.pg_dotconf pg.conf setting=newvalue
$ cat pg.conf
setting = &#x27;newvalue&#x27;
# new settings are appended to the file
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting=value
$ cat pg.conf
setting = &#x27;newvalue&#x27;
another_setting = &#x27;value&#x27;
# comment a setting
$ python3 -m postgresql.bin.pg_dotconf pg.conf another_setting
$ cat pg.conf
setting = &#x27;newvalue&#x27;
#another_setting = &#x27;value&#x27;</pre>
</div>
<p>When a setting is given on the command line, it must been seen as one argument
to the command, so it&#8217;s <em>very</em> important to avoid invocations like:</p>
<div class="highlight-python"><pre>$ python3 -m postgresql.bin.pg_dotconf pg.conf setting = value
ERROR: invalid setting, &#x27;=&#x27; after &#x27;setting&#x27;
HINT: Settings must take the form &#x27;setting=value&#x27; or &#x27;setting_name_to_comment&#x27;. Settings must also be received as a single argument.</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Commands</a><ul>
<li><a class="reference internal" href="#postgresql-bin-pg-python">postgresql.bin.pg_python</a><ul>
<li><a class="reference internal" href="#pg-python-usage">pg_python Usage</a></li>
<li><a class="reference internal" href="#interactive-console-backslash-commands">Interactive Console Backslash Commands</a></li>
<li><a class="reference internal" href="#pg-python-examples">pg_python Examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#postgresql-bin-pg-dotconf">postgresql.bin.pg_dotconf</a><ul>
<li><a class="reference internal" href="#pg-dotconf-usage">pg_dotconf Usage</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="gotchas.html"
title="previous chapter">Gotchas</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="reference.html"
title="next chapter">Reference</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/bin.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="reference.html" title="Reference"
>next</a> |</li>
<li class="right" >
<a href="gotchas.html" title="Gotchas"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Changes in v1.0 &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="prev" title="Changes in v1.1" href="changes-v1.1.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="changes-v1.1.html" title="Changes in v1.1"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="changes-in-v1-0">
<h1>Changes in v1.0<a class="headerlink" href="#changes-in-v1-0" title="Permalink to this headline">¶</a></h1>
<div class="section" id="in-development">
<h2>1.0.4 in development<a class="headerlink" href="#in-development" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>Alter how changes are represented in documentation to simplify merging.</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="released-on-2011-09-24">
<h2>1.0.3 released on 2011-09-24<a class="headerlink" href="#released-on-2011-09-24" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>Use raise x from y to generalize exceptions. (Elvis Pranskevichus)</li>
<li>Alter postgresql.string.quote_ident to always quote. (Elvis Pranskevichus)</li>
<li>Add postgresql.string.quote_ident_if_necessary (Modification of Elvis Pranskevichus&#8217; patch)</li>
<li>Many postgresql.string bug fixes (Elvis Pranskevichus)</li>
<li>Correct ResourceWarnings improving Python 3.2 support. (jwp)</li>
<li>Add test command to setup.py (Elvis Pranskevichus)</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="released-on-2010-09-18">
<h2>1.0.2 released on 2010-09-18<a class="headerlink" href="#released-on-2010-09-18" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>Add support for DOMAINs in registered composites. (Elvis Pranskevichus)</li>
<li>Properly raise StopIteration in Cursor.__next__. (Elvis Pranskevichus)</li>
<li>Add Cluster Management documentation.</li>
<li>Release savepoints after rolling them back.</li>
<li>Fix Startup() usage for Python 3.2.</li>
<li>Emit deprecation warning when &#8216;gid&#8217; is given to xact().</li>
<li>Compensate for Python3.2&#8217;s ElementTree API changes.</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="released-on-2010-04-24">
<h2>1.0.1 released on 2010-04-24<a class="headerlink" href="#released-on-2010-04-24" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>Fix unpacking of array NULLs. (Elvis Pranskevichus)</li>
<li>Fix .first()&#8217;s handling of counts and commands.
Bad logic caused zero-counts to return the command tag.</li>
<li>Don&#8217;t interrupt and close a temporal connection if it&#8217;s not open.</li>
<li>Use the Driver&#8217;s typio attribute for TypeIO overrides. (Elvis Pranskevichus)</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="released-on-2010-03-27">
<h2>1.0 released on 2010-03-27<a class="headerlink" href="#released-on-2010-03-27" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li><strong>DEPRECATION</strong>: Removed 2PC support documentation.</li>
<li><strong>DEPRECATION</strong>: Removed pg_python and pg_dotconf &#8216;scripts&#8217;.
They are still accessible by python3 -m postgresql.bin.pg_*</li>
<li>Add support for binary hstore.</li>
<li>Add support for user service files.</li>
<li>Implement a Copy manager for direct connection-to-connection COPY operations.</li>
<li>Added db.do() method for DO-statement support(convenience method).</li>
<li>Set the default client_min_messages level to WARNING.
NOTICEs are often not desired by programmers, and py-postgresql&#8217;s
high verbosity further irritates that case.</li>
<li>Added postgresql.project module to provide project information.
Project name, author, version, etc.</li>
<li>Increased default recvsize and chunksize for improved performance.</li>
<li>&#8216;D&#8217; messages are special cased as builtins.tuples instead of
protocol.element3.Tuple</li>
<li>Alter Statement.chunks() to return chunks of builtins.tuple. Being
an interface intended for speed, types.Row() impedes its performance.</li>
<li>Fix handling of infinity values with timestamptz, timestamp, and date.
[Bug reported by Axel Rau.]</li>
<li>Correct representation of PostgreSQL ARRAYs by properly recording
lowerbounds and upperbounds. Internally, sub-ARRAYs have their own
element lists.</li>
<li>Implement a NotificationManager for managing the NOTIFYs received
by a connection. The class can manage NOTIFYs from multiple
connections, whereas the db.wait() method is tailored for single targets.</li>
<li>Implement an ALock class for managing advisory locks using the
threading.Lock APIs. [Feedback from Valentine Gogichashvili]</li>
<li>Implement reference symbols. Allow libraries to define symbols that
are used to create queries that inherit the original symbol&#8217;s type and
execution method. <tt class="docutils literal"><span class="pre">db.prepare(db.prepare(...).first())</span></tt></li>
<li>Fix handling of unix domain sockets by pg.open and driver.connect.
[Reported by twitter.com/rintavarustus]</li>
<li>Fix typo/dropped parts of a raise LoadError in .lib.
[Reported by Vlad Pranskevichus]</li>
<li>Fix db.tracer and pg_python&#8217;s &#8211;pq-trace=</li>
<li>Fix count return from .first() method. Failed to provide an empty
tuple for the rformats of the bind statement.
[Reported by dou dou]</li>
</ul>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Changes in v1.0</a><ul>
<li><a class="reference internal" href="#in-development">1.0.4 in development</a></li>
<li><a class="reference internal" href="#released-on-2011-09-24">1.0.3 released on 2011-09-24</a></li>
<li><a class="reference internal" href="#released-on-2010-09-18">1.0.2 released on 2010-09-18</a></li>
<li><a class="reference internal" href="#released-on-2010-04-24">1.0.1 released on 2010-04-24</a></li>
<li><a class="reference internal" href="#released-on-2010-03-27">1.0 released on 2010-03-27</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="changes-v1.1.html"
title="previous chapter">Changes in v1.1</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/changes-v1.0.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="changes-v1.1.html" title="Changes in v1.1"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Changes in v1.1 &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Changes in v1.0" href="changes-v1.0.html" />
<link rel="prev" title="Reference" href="reference.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="changes-v1.0.html" title="Changes in v1.0"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="reference.html" title="Reference"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="changes-in-v1-1">
<h1>Changes in v1.1<a class="headerlink" href="#changes-in-v1-1" title="Permalink to this headline">¶</a></h1>
<div class="section" id="id1">
<h2>1.1.0<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><ul class="simple">
<li>Remove two-phase commit interfaces per deprecation in v1.0.
For proper two phase commit use, a lock manager must be employed that
the implementation did nothing to accommodate for.</li>
<li>Add support for unpacking anonymous records (Elvis)</li>
<li>Support PostgreSQL 9.2 (Elvis)</li>
<li>Python 3.3 Support (Elvis)</li>
<li>Add column execution method. (jwp)</li>
<li>Add one-shot statement interface. Connection.query.* (jwp)</li>
<li>Modify the inet/cidr support by relying on the ipaddress module introduced in Python 3.3 (Google&#8217;s ipaddr project)
The existing implementation relied on simple str() representation supported by the
socket module. Unfortunately, MS Windows&#8217; socket library does not appear to support the
necessary functionality, or Python&#8217;s socket module does not expose it. ipaddress fixes
the problem.</li>
</ul>
</div></blockquote>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The <cite>ipaddress</cite> module is now required for local inet and cidr. While it is
of &#8220;preliminary&#8221; status, the ipaddr project has been around for some time and
well supported. ipaddress appears to be the safest way forward for native
network types.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Changes in v1.1</a><ul>
<li><a class="reference internal" href="#id1">1.1.0</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="reference.html"
title="previous chapter">Reference</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="changes-v1.0.html"
title="next chapter">Changes in v1.0</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/changes-v1.1.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="changes-v1.0.html" title="Changes in v1.0"
>next</a> |</li>
<li class="right" >
<a href="reference.html" title="Reference"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Client Parameters &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Gotchas" href="gotchas.html" />
<link rel="prev" title="Categories and Libraries" href="lib.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gotchas.html" title="Gotchas"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="lib.html" title="Categories and Libraries"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="client-parameters">
<h1>Client Parameters<a class="headerlink" href="#client-parameters" title="Permalink to this headline">¶</a></h1>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last"><strong>The interfaces dealing with optparse are subject to change in 1.0</strong>.</p>
</div>
<p>There are various sources of parameters used by PostgreSQL client applications.
The <cite>postgresql.clientparameters</cite> module provides a means for collecting and
managing those parameters.</p>
<p>Connection creation interfaces in <cite>postgresql.driver</cite> are purposefully simple.
All parameters taken by those interfaces are keywords, and are taken
literally; if a parameter is not given, it will effectively be <cite>None</cite>.
libpq-based drivers tend differ as they inherit some default client parameters
from the environment. Doing this by default is undesirable as it can cause
trivial failures due to unexpected parameter inheritance. However, using these
parameters from the environment and other sources are simply expected in <em>some</em>
cases: <cite>postgresql.open</cite>, <cite>postgresql.bin.pg_python</cite>, and other high-level
utilities. The <cite>postgresql.clientparameters</cite> module provides a means to collect
them into one dictionary object for subsequent application to a connection
creation interface.</p>
<p><cite>postgresql.clientparameters</cite> is primarily useful to script authors that want to
provide an interface consistent with PostgreSQL commands like <tt class="docutils literal"><span class="pre">psql</span></tt>.</p>
<div class="section" id="collecting-parameters">
<h2>Collecting Parameters<a class="headerlink" href="#collecting-parameters" title="Permalink to this headline">¶</a></h2>
<p>The primary entry points in <cite>postgresql.clientparameters</cite> are
<cite>postgresql.clientparameters.collect</cite> and
<cite>postgresql.clientparameters.resolve_password</cite>.</p>
<p>For most purposes, <tt class="docutils literal"><span class="pre">collect</span></tt> will suffice. By default, it will prompt for the
password if instructed to(<tt class="docutils literal"><span class="pre">-W</span></tt>). Therefore, <tt class="docutils literal"><span class="pre">resolve_password</span></tt> need not be
used in most cases:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql.clientparameters</span> <span class="kn">as</span> <span class="nn">pg_param</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">DefaultParser</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">co</span><span class="p">,</span> <span class="n">ca</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">parse_args</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">params</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">parsed_options</span> <span class="o">=</span> <span class="n">co</span><span class="p">)</span>
</pre></div>
</div>
<p>The <cite>postgresql.clientparameters</cite> module is executable, so you can see the
results of the above snippet by:</p>
<div class="highlight-python"><pre>$ python -m postgresql.clientparameters -h localhost -U a_db_user -ssearch_path=public
{&#x27;host&#x27;: &#x27;localhost&#x27;,
&#x27;password&#x27;: None,
&#x27;port&#x27;: 5432,
&#x27;settings&#x27;: {&#x27;search_path&#x27;: &#x27;public&#x27;},
&#x27;user&#x27;: &#x27;a_db_user&#x27;}</pre>
</div>
<div class="section" id="postgresql-clientparameters-collect">
<h3><cite>postgresql.clientparameters.collect</cite><a class="headerlink" href="#postgresql-clientparameters-collect" title="Permalink to this headline">¶</a></h3>
<p>Build a client parameter dictionary from the environment and parsed command
line options. The following is a list of keyword arguments that <tt class="docutils literal"><span class="pre">collect</span></tt> will
accept:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">parsed_options</span></tt></dt>
<dd>Options parsed by <cite>postgresql.clientparameters.StandardParser</cite> or
<cite>postgresql.clientparameters.DefaultParser</cite> instances.</dd>
<dt><tt class="docutils literal"><span class="pre">no_defaults</span></tt></dt>
<dd>When <cite>True</cite>, don&#8217;t include defaults like <tt class="docutils literal"><span class="pre">pgpassfile</span></tt> and <tt class="docutils literal"><span class="pre">user</span></tt>.
Defaults to <cite>False</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">environ</span></tt></dt>
<dd>Environment variables to extract client parameter variables from.
Defaults to <cite>os.environ</cite> and expects a <cite>collections.Mapping</cite> interface.</dd>
<dt><tt class="docutils literal"><span class="pre">environ_prefix</span></tt></dt>
<dd>Environment variable prefix to use. Defaults to &#8220;PG&#8221;. This allows the
collection of non-standard environment variables whose keys are partially
consistent with the standard variants. e.g. &#8220;PG_SRC_USER&#8221;, &#8220;PG_SRC_HOST&#8221;,
etc.</dd>
<dt><tt class="docutils literal"><span class="pre">default_pg_sysconfdir</span></tt></dt>
<dd>The location of the pg_service.conf file. The <tt class="docutils literal"><span class="pre">PGSYSCONFDIR</span></tt> environment
variable will override this. When a default installation is present,
<tt class="docutils literal"><span class="pre">PGINSTALLATION</span></tt>, it should be set to this.</dd>
<dt><tt class="docutils literal"><span class="pre">pg_service_file</span></tt></dt>
<dd>Explicit location of the service file. This will override the &#8220;sysconfdir&#8221;
based path.</dd>
<dt><tt class="docutils literal"><span class="pre">prompt_title</span></tt></dt>
<dd>Descriptive title to use if a password prompt is needed. <cite>None</cite> to disable
password resolution entirely. Setting this to <cite>None</cite> will also disable
pgpassfile lookups, so it is necessary that further processing occurs when
this is <cite>None</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">parameters</span></tt></dt>
<dd>Base client parameters to use. These are set after the <em>defaults</em> are
collected. (The defaults that can be disabled by <tt class="docutils literal"><span class="pre">no_defaults</span></tt>).</dd>
</dl>
</div></blockquote>
<p>If <tt class="docutils literal"><span class="pre">prompt_title</span></tt> is not set to <cite>None</cite>, it will prompt for the password when
instructed to do by the <tt class="docutils literal"><span class="pre">prompt_password</span></tt> key in the parameters:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql.clientparameters</span> <span class="kn">as</span> <span class="nn">pg_param</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">prompt_title</span> <span class="o">=</span> <span class="s">&#39;my_prompt!&#39;</span><span class="p">,</span> <span class="n">parameters</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;prompt_password&#39;</span><span class="p">:</span><span class="bp">True</span><span class="p">})</span>
<span class="go">Password for my_prompt![pq://jwp@localhost:5432]:</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">{&#39;host&#39;: &#39;localhost&#39;, &#39;user&#39;: &#39;jwp&#39;, &#39;password&#39;: &#39;secret&#39;, &#39;port&#39;: 5432}</span>
</pre></div>
</div>
<p>If <cite>None</cite>, it will leave the necessary password resolution information in the
parameters dictionary for <tt class="docutils literal"><span class="pre">resolve_password</span></tt>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">prompt_title</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">parameters</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;prompt_password&#39;</span><span class="p">:</span><span class="bp">True</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">{&#39;pgpassfile&#39;: &#39;/Users/jwp/.pgpass&#39;, &#39;prompt_password&#39;: True, &#39;host&#39;: &#39;localhost&#39;, &#39;user&#39;: &#39;jwp&#39;, &#39;port&#39;: 5432}</span>
</pre></div>
</div>
<p>Of course, <tt class="docutils literal"><span class="pre">'prompt_password'</span></tt> is normally specified when <tt class="docutils literal"><span class="pre">parsed_options</span></tt>
received a <tt class="docutils literal"><span class="pre">-W</span></tt> option from the command line:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">op</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">DefaultParser</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">co</span><span class="p">,</span> <span class="n">ca</span> <span class="o">=</span> <span class="n">op</span><span class="o">.</span><span class="n">parse_args</span><span class="p">([</span><span class="s">&#39;-W&#39;</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">parsed_options</span> <span class="o">=</span> <span class="n">co</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">=</span><span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">parsed_options</span> <span class="o">=</span> <span class="n">co</span><span class="p">)</span>
<span class="go">Password for [pq://jwp@localhost:5432]:</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">{&#39;host&#39;: &#39;localhost&#39;, &#39;user&#39;: &#39;jwp&#39;, &#39;password&#39;: &#39;secret&#39;, &#39;port&#39;: 5432}</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
</div>
<div class="section" id="postgresql-clientparameters-resolve-password">
<h3><cite>postgresql.clientparameters.resolve_password</cite><a class="headerlink" href="#postgresql-clientparameters-resolve-password" title="Permalink to this headline">¶</a></h3>
<p>Resolve the password for the given client parameters dictionary returned by
<tt class="docutils literal"><span class="pre">collect</span></tt>. By default, this function need not be used as <tt class="docutils literal"><span class="pre">collect</span></tt> will
resolve the password by default. <cite>resolve_password</cite> accepts the following
arguments:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">parameters</span></tt></dt>
<dd>First positional argument. Normalized client parameters dictionary to update
in-place with the resolved password. If the &#8216;prompt_password&#8217; key is in
<tt class="docutils literal"><span class="pre">parameters</span></tt>, it will prompt regardless(normally comes from <tt class="docutils literal"><span class="pre">-W</span></tt>).</dd>
<dt><tt class="docutils literal"><span class="pre">getpass</span></tt></dt>
<dd>Function to call to prompt for the password. Defaults to <cite>getpass.getpass</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">prompt_title</span></tt></dt>
<dd>Additional title to use if a prompt is requested. This can also be specified
in the <tt class="docutils literal"><span class="pre">parameters</span></tt> as the <tt class="docutils literal"><span class="pre">prompt_title</span></tt> key. This <em>augments</em> the IRI
display on the prompt. Defaults to an empty string, <tt class="docutils literal"><span class="pre">''</span></tt>.</dd>
</dl>
</div></blockquote>
<p>The resolution process is effected by the contents of the given <tt class="docutils literal"><span class="pre">parameters</span></tt>.
Notable keywords:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">prompt_password</span></tt></dt>
<dd>If present in the given parameters, the user will be prompted for the using
the given <tt class="docutils literal"><span class="pre">getpass</span></tt> function. This disables the password file lookup
process.</dd>
<dt><tt class="docutils literal"><span class="pre">prompt_title</span></tt></dt>
<dd>This states a default prompt title to use. If the <tt class="docutils literal"><span class="pre">prompt_title</span></tt> keyword
argument is given to <tt class="docutils literal"><span class="pre">resolve_password</span></tt>, this will not be used.</dd>
<dt><tt class="docutils literal"><span class="pre">pgpassfile</span></tt></dt>
<dd>The PostgreSQL password file to lookup the password in. If the <tt class="docutils literal"><span class="pre">password</span></tt>
parameter is present, this will not be used.</dd>
</dl>
</div></blockquote>
<p>When resolution occurs, the <tt class="docutils literal"><span class="pre">prompt_password</span></tt>, <tt class="docutils literal"><span class="pre">prompt_title</span></tt>, and
<tt class="docutils literal"><span class="pre">pgpassfile</span></tt> keys are <em>removed</em> from the given parameters dictionary:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">=</span><span class="n">pg_param</span><span class="o">.</span><span class="n">collect</span><span class="p">(</span><span class="n">prompt_title</span> <span class="o">=</span> <span class="bp">None</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">{&#39;pgpassfile&#39;: &#39;/Users/jwp/.pgpass&#39;, &#39;host&#39;: &#39;localhost&#39;, &#39;user&#39;: &#39;jwp&#39;, &#39;port&#39;: 5432}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pg_param</span><span class="o">.</span><span class="n">resolve_password</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">{&#39;host&#39;: &#39;localhost&#39;, &#39;password&#39;: &#39;secret&#39;, &#39;user&#39;: &#39;jwp&#39;, &#39;port&#39;: 5432}</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="defaults">
<h2>Defaults<a class="headerlink" href="#defaults" title="Permalink to this headline">¶</a></h2>
<p>The following is a list of default parameters provided by <tt class="docutils literal"><span class="pre">collect</span></tt> and the
sources of their values:</p>
<blockquote>
<div><table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Key</th>
<th class="head">Value</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">'user'</span></tt></td>
<td><cite>getpass.getuser()</cite> or <tt class="docutils literal"><span class="pre">'postgres'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">'host'</span></tt></td>
<td><cite>postgresql.clientparameters.default_host</cite> (<tt class="docutils literal"><span class="pre">'localhost'</span></tt>)</td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">'port'</span></tt></td>
<td><cite>postgresql.clientparameters.default_port</cite> (<tt class="docutils literal"><span class="pre">5432</span></tt>)</td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">'pgpassfile'</span></tt></td>
<td><tt class="docutils literal"><span class="pre">&quot;$HOME/.pgpassfile&quot;</span></tt> or <tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> + <tt class="docutils literal"><span class="pre">'pgpass.conf'</span></tt> (Win32)</td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">'sslcrtfile'</span></tt></td>
<td><tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> + <tt class="docutils literal"><span class="pre">'postgresql.crt'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">'sslkeyfile'</span></tt></td>
<td><tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> + <tt class="docutils literal"><span class="pre">'postgresql.key'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">'sslrootcrtfile'</span></tt></td>
<td><tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> + <tt class="docutils literal"><span class="pre">'root.crt'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">'sslrootcrlfile'</span></tt></td>
<td><tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> + <tt class="docutils literal"><span class="pre">'root.crl'</span></tt></td>
</tr>
</tbody>
</table>
</div></blockquote>
<p><tt class="docutils literal"><span class="pre">[PGDATA]</span></tt> referenced in the above table is a directory whose path is platform
dependent. On most systems, it is <tt class="docutils literal"><span class="pre">&quot;$HOME/.postgresql&quot;</span></tt>, but on Windows based
systems it is <tt class="docutils literal"><span class="pre">&quot;%APPDATA%\postgresql&quot;</span></tt></p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">[PGDATA] is <em>not</em> an environment variable.</p>
</div>
</div>
<div class="section" id="postgresql-environment-variables">
<span id="pg-envvars"></span><h2>PostgreSQL Environment Variables<a class="headerlink" href="#postgresql-environment-variables" title="Permalink to this headline">¶</a></h2>
<p>The following is a list of environment variables that will be collected by the
<cite>postgresql.clientparameter.collect</cite> function using &#8220;PG&#8221; as the
<tt class="docutils literal"><span class="pre">environ_prefix</span></tt> and the keyword that it will be mapped to:</p>
<blockquote>
<div><table border="1" class="docutils">
<colgroup>
<col width="36%" />
<col width="64%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Environment Variable</th>
<th class="head">Keyword</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGUSER</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'user'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGDATABASE</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'database'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGHOST</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'host'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGPORT</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'port'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGPASSWORD</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'password'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGSSLMODE</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'sslmode'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGSSLKEY</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'sslkey'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGCONNECT_TIMEOUT</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'connect_timeout'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGREALM</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'kerberos4_realm'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGKRBSRVNAME</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'kerberos5_service'</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGPASSFILE</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'pgpassfile'</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGTZ</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'settings'</span> <span class="pre">=</span> <span class="pre">{'timezone':</span> <span class="pre">}</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGDATESTYLE</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'settings'</span> <span class="pre">=</span> <span class="pre">{'datestyle':</span> <span class="pre">}</span></tt></td>
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">PGCLIENTENCODING</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'settings'</span> <span class="pre">=</span> <span class="pre">{'client_encoding':</span> <span class="pre">}</span></tt></td>
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">PGGEQO</span></tt></td>
<td><tt class="docutils literal"><span class="pre">'settings'</span> <span class="pre">=</span> <span class="pre">{'geqo':</span> <span class="pre">}</span></tt></td>
</tr>
</tbody>
</table>
</div></blockquote>
</div>
<div class="section" id="postgresql-password-file">
<span id="pg-passfile"></span><h2>PostgreSQL Password File<a class="headerlink" href="#postgresql-password-file" title="Permalink to this headline">¶</a></h2>
<p>The password file is a simple newline separated list of <tt class="docutils literal"><span class="pre">:</span></tt> separated fields. It
is located at <tt class="docutils literal"><span class="pre">$HOME/.pgpass</span></tt> for most systems and at
<tt class="docutils literal"><span class="pre">%APPDATA%\postgresql\pgpass.conf</span></tt> for Windows based systems. However, the
<tt class="docutils literal"><span class="pre">PGPASSFILE</span></tt> environment variable may be used to override that location.</p>
<p>The lines in the file must be in the following form:</p>
<div class="highlight-python"><pre>hostname:port:database:username:password</pre>
</div>
<p>A single asterisk, <tt class="docutils literal"><span class="pre">*</span></tt>, may be used to indicate that any value will match the
field. However, this only effects fields other than <tt class="docutils literal"><span class="pre">password</span></tt>.</p>
<p>See <a class="reference external" href="http://www.postgresql.org/docs/current/static/libpq-pgpass.html">http://www.postgresql.org/docs/current/static/libpq-pgpass.html</a> for more
details.</p>
<p>Client parameters produced by <tt class="docutils literal"><span class="pre">collect</span></tt> that have not been processed
by <tt class="docutils literal"><span class="pre">resolve_password</span></tt> will include a <tt class="docutils literal"><span class="pre">'pgpassfile'</span></tt> key. This is the value
that <tt class="docutils literal"><span class="pre">resolve_password</span></tt> will use to locate the pgpassfile to interrogate if a
password key is not present and it is not instructed to prompt for a password.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">Connection creation interfaces will <em>not</em> resolve <tt class="docutils literal"><span class="pre">'pgpassfile'</span></tt>, so it is
important that the parameters produced by <tt class="docutils literal"><span class="pre">collect()</span></tt> are properly processed
before an attempt is made to establish a connection.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Client Parameters</a><ul>
<li><a class="reference internal" href="#collecting-parameters">Collecting Parameters</a><ul>
<li><a class="reference internal" href="#postgresql-clientparameters-collect"><cite>postgresql.clientparameters.collect</cite></a></li>
<li><a class="reference internal" href="#postgresql-clientparameters-resolve-password"><cite>postgresql.clientparameters.resolve_password</cite></a></li>
</ul>
</li>
<li><a class="reference internal" href="#defaults">Defaults</a></li>
<li><a class="reference internal" href="#postgresql-environment-variables">PostgreSQL Environment Variables</a></li>
<li><a class="reference internal" href="#postgresql-password-file">PostgreSQL Password File</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="lib.html"
title="previous chapter">Categories and Libraries</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="gotchas.html"
title="next chapter">Gotchas</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/clientparameters.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gotchas.html" title="Gotchas"
>next</a> |</li>
<li class="right" >
<a href="lib.html" title="Categories and Libraries"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Cluster Management &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Categories and Libraries" href="lib.html" />
<link rel="prev" title="Advisory Locks" href="alock.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="lib.html" title="Categories and Libraries"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="alock.html" title="Advisory Locks"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="cluster-management">
<span id="id1"></span><h1>Cluster Management<a class="headerlink" href="#cluster-management" title="Permalink to this headline">¶</a></h1>
<p>py-postgresql provides cluster management tools in order to give the user
fine-grained control over a PostgreSQL cluster and access to information about an
installation of PostgreSQL.</p>
<div class="section" id="installations">
<span id="installation"></span><h2>Installations<a class="headerlink" href="#installations" title="Permalink to this headline">¶</a></h2>
<p><cite>postgresql.installation.Installation</cite> objects are primarily used to
access PostgreSQL installation information. Normally, they are created using a
dictionary constructed from the output of the <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-pgconfig.html">pg_config</a> executable:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">postgresql.installation</span> <span class="kn">import</span> <span class="n">Installation</span><span class="p">,</span> <span class="n">pg_config_dictionary</span>
<span class="n">pg_install</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">(</span><span class="n">pg_config_dictionary</span><span class="p">(</span><span class="s">&#39;/usr/local/pgsql/bin/pg_config&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>The extraction of <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-pgconfig.html">pg_config</a> information is isolated from Installation
instantiation in order to allow Installations to be created from arbitrary
dictionaries. This can be useful in cases where the installation layout is
inconsistent with the standard PostgreSQL installation layout, or if a faux
Installation needs to be created for testing purposes.</p>
<div class="section" id="installation-interface-points">
<h3>Installation Interface Points<a class="headerlink" href="#installation-interface-points" title="Permalink to this headline">¶</a></h3>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">Installation(info)</span></tt></dt>
<dd><p class="first">Instantiate an Installation using the given information. Normally, this
information is extracted from a <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-pgconfig.html">pg_config</a> executable using
<cite>postgresql.installation.pg_config_dictionary</cite>:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="n">info</span> <span class="o">=</span> <span class="n">pg_config_dictionary</span><span class="p">(</span><span class="s">&#39;/usr/local/pgsql/bin/pg_config&#39;</span><span class="p">)</span>
<span class="n">pg_install</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">(</span><span class="n">info</span><span class="p">)</span>
</pre></div>
</div>
</dd>
<dt><tt class="docutils literal"><span class="pre">Installation.version</span></tt></dt>
<dd><p class="first">The installation&#8217;s version string:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="n">pg_install</span><span class="o">.</span><span class="n">version</span>
<span class="s">&#39;PostgreSQL 9.0devel&#39;</span>
</pre></div>
</div>
</dd>
<dt><tt class="docutils literal"><span class="pre">Installation.version_info</span></tt></dt>
<dd><p class="first">A tuple containing the version&#8217;s <tt class="docutils literal"><span class="pre">(major,</span> <span class="pre">minor,</span> <span class="pre">patch,</span> <span class="pre">state,</span> <span class="pre">level)</span></tt>.
Where <tt class="docutils literal"><span class="pre">major</span></tt>, <tt class="docutils literal"><span class="pre">minor</span></tt>, <tt class="docutils literal"><span class="pre">patch</span></tt>, and <tt class="docutils literal"><span class="pre">level</span></tt> are <cite>int</cite> objects, and
<tt class="docutils literal"><span class="pre">state</span></tt> is a <cite>str</cite> object:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="n">pg_install</span><span class="o">.</span><span class="n">version_info</span>
<span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s">&#39;devel&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
</dd>
<dt><tt class="docutils literal"><span class="pre">Installation.ssl</span></tt></dt>
<dd>A <cite>bool</cite> indicating whether or not the installation has SSL support.</dd>
<dt><tt class="docutils literal"><span class="pre">Installation.configure_options</span></tt></dt>
<dd><p class="first">The options given to the <tt class="docutils literal"><span class="pre">configure</span></tt> script that built the installation. The
options are represented using a dictionary object whose keys are normalized
long option names, and whose values are the option&#8217;s argument. If the option
takes no argument, <cite>True</cite> will be used as the value.</p>
<p>The normalization of the long option names consists of removing the preceding
dashes, lowering the string, and replacing any dashes with underscores. For
instance, <tt class="docutils literal"><span class="pre">--enable-debug</span></tt> will be <tt class="docutils literal"><span class="pre">enable_debug</span></tt>:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="n">pg_install</span><span class="o">.</span><span class="n">configure_options</span>
<span class="p">{</span><span class="s">&#39;enable_debug&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="s">&#39;with_libxml&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
<span class="s">&#39;enable_cassert&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="s">&#39;with_libedit_preferred&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
<span class="s">&#39;prefix&#39;</span><span class="p">:</span> <span class="s">&#39;/src/build/pg90&#39;</span><span class="p">,</span> <span class="s">&#39;with_openssl&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
<span class="s">&#39;enable_integer_datetimes&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="s">&#39;enable_depend&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">}</span>
</pre></div>
</div>
</dd>
<dt><tt class="docutils literal"><span class="pre">Installation.paths</span></tt></dt>
<dd><p class="first">The paths of the installation as a dictionary where the keys are the path
identifiers and the values are the absolute file system paths. For instance,
<tt class="docutils literal"><span class="pre">'bindir'</span></tt> is associated with <tt class="docutils literal"><span class="pre">$PREFIX/bin</span></tt>, <tt class="docutils literal"><span class="pre">'libdir'</span></tt> is associated
with <tt class="docutils literal"><span class="pre">$PREFIX/lib</span></tt>, etc. The paths included in this dictionary are
listed on the class&#8217; attributes: <cite>Installation.pg_directories</cite> and
<cite>Installation.pg_executables</cite>.</p>
<p>The keys that point to installation directories are: <tt class="docutils literal"><span class="pre">bindir</span></tt>, <tt class="docutils literal"><span class="pre">docdir</span></tt>,
<tt class="docutils literal"><span class="pre">includedir</span></tt>, <tt class="docutils literal"><span class="pre">pkgincludedir</span></tt>, <tt class="docutils literal"><span class="pre">includedir_server</span></tt>, <tt class="docutils literal"><span class="pre">libdir</span></tt>,
<tt class="docutils literal"><span class="pre">pkglibdir</span></tt>, <tt class="docutils literal"><span class="pre">localedir</span></tt>, <tt class="docutils literal"><span class="pre">mandir</span></tt>, <tt class="docutils literal"><span class="pre">sharedir</span></tt>, and <tt class="docutils literal"><span class="pre">sysconfdir</span></tt>.</p>
<p>The keys that point to installation executables are: <tt class="docutils literal"><span class="pre">pg_config</span></tt>, <tt class="docutils literal"><span class="pre">psql</span></tt>,
<tt class="docutils literal"><span class="pre">initdb</span></tt>, <tt class="docutils literal"><span class="pre">pg_resetxlog</span></tt>, <tt class="docutils literal"><span class="pre">pg_controldata</span></tt>, <tt class="docutils literal"><span class="pre">clusterdb</span></tt>, <tt class="docutils literal"><span class="pre">pg_ctl</span></tt>,
<tt class="docutils literal"><span class="pre">pg_dump</span></tt>, <tt class="docutils literal"><span class="pre">pg_dumpall</span></tt>, <tt class="docutils literal"><span class="pre">postgres</span></tt>, <tt class="docutils literal"><span class="pre">postmaster</span></tt>, <tt class="docutils literal"><span class="pre">reindexdb</span></tt>,
<tt class="docutils literal"><span class="pre">vacuumdb</span></tt>, <tt class="docutils literal"><span class="pre">ipcclean</span></tt>, <tt class="docutils literal"><span class="pre">createdb</span></tt>, <tt class="docutils literal"><span class="pre">ecpg</span></tt>, <tt class="docutils literal"><span class="pre">createuser</span></tt>,
<tt class="docutils literal"><span class="pre">createlang</span></tt>, <tt class="docutils literal"><span class="pre">droplang</span></tt>, <tt class="docutils literal"><span class="pre">dropuser</span></tt>, and <tt class="docutils literal"><span class="pre">pg_restore</span></tt>.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">If the executable does not exist, the value will be <cite>None</cite> instead
of an absoluate path.</p>
</div>
<p>To get the path to the <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-psql.html">psql</a> executable:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">postgresql.installation</span> <span class="kn">import</span> <span class="n">Installation</span>
<span class="n">pg_install</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">(</span><span class="s">&#39;/usr/local/pgsql/bin/pg_config&#39;</span><span class="p">)</span>
<span class="n">psql_path</span> <span class="o">=</span> <span class="n">pg_install</span><span class="o">.</span><span class="n">paths</span><span class="p">[</span><span class="s">&#39;psql&#39;</span><span class="p">]</span>
</pre></div>
</div>
</dd>
</dl>
</div></blockquote>
</div>
</div>
<div class="section" id="clusters">
<h2>Clusters<a class="headerlink" href="#clusters" title="Permalink to this headline">¶</a></h2>
<p><cite>postgresql.cluster.Cluster</cite> is the class used to manage a PostgreSQL
cluster&#8211;a data directory created by <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a>. A Cluster represents a data
directory with respect to a given installation of PostgreSQL, so
creating a <cite>postgresql.cluster.Cluster</cite> object requires a
<cite>postgresql.installation.Installation</cite>, and a
file system path to the data directory.</p>
<p>In part, a <cite>postgresql.cluster.Cluster</cite> is the Python programmer&#8217;s variant of
the <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-pg-ctl.html">pg_ctl</a> command. However, it goes beyond the basic process control
functionality and extends into initialization and configuration as well.</p>
<p>A Cluster manages the server process using the <cite>subprocess</cite> module and
signals. The <cite>subprocess.Popen</cite> object, <tt class="docutils literal"><span class="pre">Cluster.daemon_process</span></tt>, is
retained when the Cluster starts the server process itself. This gives
the Cluster access to the result code of server process when it exits, and the
ability to redirect stderr and stdout to a parameterized file object using
subprocess features.</p>
<p>Despite its use of <cite>subprocess</cite>, Clusters can control a server process
that was <em>not</em> started by the Cluster&#8217;s <tt class="docutils literal"><span class="pre">start</span></tt> method.</p>
<div class="section" id="initializing-clusters">
<h3>Initializing Clusters<a class="headerlink" href="#initializing-clusters" title="Permalink to this headline">¶</a></h3>
<p><cite>postgresql.cluster.Cluster</cite> provides a method for initializing a
<cite>Cluster</cite>&#8216;s data directory, <tt class="docutils literal"><span class="pre">init</span></tt>. This method provides a Python interface to
the PostgreSQL <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a> command.</p>
<p><tt class="docutils literal"><span class="pre">init</span></tt> is a regular method and accepts a few keyword parameters. Normally,
parameters are directly mapped to <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a> command options. However, <tt class="docutils literal"><span class="pre">password</span></tt>
makes use of initdb&#8217;s capability to read the superuser&#8217;s password from a file.
To do this, a temporary file is allocated internally by the method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">postgresql.installation</span> <span class="kn">import</span> <span class="n">Installation</span><span class="p">,</span> <span class="n">pg_config_dictionary</span>
<span class="kn">from</span> <span class="nn">postgresql.cluster</span> <span class="kn">import</span> <span class="n">Cluster</span>
<span class="n">pg_install</span> <span class="o">=</span> <span class="n">Installation</span><span class="p">(</span><span class="n">pg_config_dictionary</span><span class="p">(</span><span class="s">&#39;/usr/local/pgsql/bin/pg_config&#39;</span><span class="p">))</span>
<span class="n">pg_cluster</span> <span class="o">=</span> <span class="n">Cluster</span><span class="p">(</span><span class="n">pg_install</span><span class="p">,</span> <span class="s">&#39;pg_data&#39;</span><span class="p">)</span>
<span class="n">pg_cluster</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="n">user</span> <span class="o">=</span> <span class="s">&#39;pg&#39;</span><span class="p">,</span> <span class="n">password</span> <span class="o">=</span> <span class="s">&#39;secret&#39;</span><span class="p">,</span> <span class="n">encoding</span> <span class="o">=</span> <span class="s">&#39;utf-8&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>The init method will block until the initdb command is complete. Once
initialized, the Cluster may be configured.</p>
</div>
<div class="section" id="configuring-clusters">
<h3>Configuring Clusters<a class="headerlink" href="#configuring-clusters" title="Permalink to this headline">¶</a></h3>
<p>A Cluster&#8217;s <a class="reference external" href="http://www.postgresql.org/docs/current/static/runtime-config.html">configuration file</a> can be manipulated using the
<cite>Cluster.settings</cite> mapping. The mapping&#8217;s methods will always access the
configuration file, so it may be desirable to cache repeat reads. Also, if
multiple settings are being applied, using the <tt class="docutils literal"><span class="pre">update()</span></tt> method may be
important to avoid writing the entire file multiple times:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">pg_cluster</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s">&#39;listen_addresses&#39;</span> <span class="p">:</span> <span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="s">&#39;port&#39;</span> <span class="p">:</span> <span class="s">&#39;6543&#39;</span><span class="p">})</span>
</pre></div>
</div>
<p>Similarly, to avoid opening and reading the entire file multiple times,
<cite>Cluster.settings.getset</cite> should be used to retrieve multiple settings:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">pg_cluster</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">getset</span><span class="p">(</span><span class="nb">set</span><span class="p">((</span><span class="s">&#39;listen_addresses&#39;</span><span class="p">,</span> <span class="s">&#39;port&#39;</span><span class="p">)))</span>
<span class="n">d</span>
<span class="p">{</span><span class="s">&#39;listen_addresses&#39;</span> <span class="p">:</span> <span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="s">&#39;port&#39;</span> <span class="p">:</span> <span class="s">&#39;6543&#39;</span><span class="p">}</span>
</pre></div>
</div>
<p>Values contained in <tt class="docutils literal"><span class="pre">settings</span></tt> are always Python strings:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">assert</span> <span class="n">pg_cluster</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="s">&#39;max_connections&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="nb">str</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">postgresql.conf</span></tt> file is only one part of the server configuration.
Structured access and manipulation of the <a class="reference external" href="http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html">pg_hba</a> file is not
supported. Clusters only provide the file path to the <a class="reference external" href="http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html">pg_hba</a> file:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">hba</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">pg_cluster</span><span class="o">.</span><span class="n">hba_file</span><span class="p">)</span>
</pre></div>
</div>
<p>If the configuration of the Cluster is altered while the server process is
running, it may be necessary to signal the process that configuration changes
have been made. This signal can be sent using the <tt class="docutils literal"><span class="pre">Cluster.reload()</span></tt> method.
<tt class="docutils literal"><span class="pre">Cluster.reload()</span></tt> will send a SIGHUP signal to the server process. However,
not all changes to configuration settings can go into effect after calling
<tt class="docutils literal"><span class="pre">Cluster.reload()</span></tt>. In those cases, the server process will need to be
shutdown and started again.</p>
</div>
<div class="section" id="controlling-clusters">
<h3>Controlling Clusters<a class="headerlink" href="#controlling-clusters" title="Permalink to this headline">¶</a></h3>
<p>The server process of a Cluster object can be controlled with the <tt class="docutils literal"><span class="pre">start()</span></tt>,
<tt class="docutils literal"><span class="pre">stop()</span></tt>, <tt class="docutils literal"><span class="pre">shutdown()</span></tt>, <tt class="docutils literal"><span class="pre">kill()</span></tt>, and <tt class="docutils literal"><span class="pre">restart()</span></tt> methods.
These methods start the server process, signal the server process, or, in the
case of restart, a combination of the two.</p>
<p>When a Cluster starts the server process, it&#8217;s ran as a subprocess. Therefore,
if the current process exits, the server process will exit as well. <tt class="docutils literal"><span class="pre">start()</span></tt>
does <em>not</em> automatically daemonize the server process.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Under Microsoft Windows, above does not hold true. The server process
will continue running despite the exit of the parent process.</p>
</div>
<p>To terminate a server process, one of these three methods should be called:
<tt class="docutils literal"><span class="pre">stop</span></tt>, <tt class="docutils literal"><span class="pre">shutdown</span></tt>, or <tt class="docutils literal"><span class="pre">kill</span></tt>. <tt class="docutils literal"><span class="pre">stop</span></tt> is a graceful shutdown and will
<em>wait for all clients to disconnect</em> before shutting down. <tt class="docutils literal"><span class="pre">shutdown</span></tt> will
close any open connections and safely shutdown the server process.
<tt class="docutils literal"><span class="pre">kill</span></tt> will immediately terminate the server process leading to recovery upon
starting the server process again.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Using <tt class="docutils literal"><span class="pre">kill</span></tt> may cause shared memory to be leaked.</p>
</div>
<p>Normally, <cite>Cluster.shutdown</cite> is the appropriate way to terminate a server
process.</p>
</div>
<div class="section" id="cluster-interface-points">
<h3>Cluster Interface Points<a class="headerlink" href="#cluster-interface-points" title="Permalink to this headline">¶</a></h3>
<p>Methods and properties available on <cite>postgresql.cluster.Cluster</cite> instances:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">Cluster(installation,</span> <span class="pre">data_directory)</span></tt></dt>
<dd><p class="first">Create a <cite>postgresql.cluster.Cluster</cite> object for the specified
<cite>postgresql.installation.Installation</cite>, and <tt class="docutils literal"><span class="pre">data_directory</span></tt>.</p>
<p class="last">The <tt class="docutils literal"><span class="pre">data_directory</span></tt> must be an absoluate file system path. The directory
does <em>not</em> need to exist. The <tt class="docutils literal"><span class="pre">init()</span></tt> method may later be used to create
the cluster.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.installation</span></tt></dt>
<dd>The Cluster&#8217;s <cite>postgresql.installation.Installation</cite> instance.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.data_directory</span></tt></dt>
<dd>The absolute path to the PostgreSQL data directory.
This directory may not exist.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.init([encoding</span> <span class="pre">=</span> <span class="pre">None[,</span> <span class="pre">user</span> <span class="pre">=</span> <span class="pre">None[,</span> <span class="pre">password</span> <span class="pre">=</span> <span class="pre">None]]])</span></tt></dt>
<dd><p class="first">Run the <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a> executable of the configured installation to initialize the
cluster at the configured data directory, <cite>Cluster.data_directory</cite>.</p>
<p><tt class="docutils literal"><span class="pre">encoding</span></tt> is mapped to <tt class="docutils literal"><span class="pre">-E</span></tt>, the default database encoding. By default,
the encoding is determined from the environment&#8217;s locale.</p>
<p><tt class="docutils literal"><span class="pre">user</span></tt> is mapped to <tt class="docutils literal"><span class="pre">-U</span></tt>, the database superuser name. By default, the
current user&#8217;s name.</p>
<p><tt class="docutils literal"><span class="pre">password</span></tt> is ultimately mapped to <tt class="docutils literal"><span class="pre">--pwfile</span></tt>. The argument given to the
long option is actually a path to the temporary file that holds the given
password.</p>
<p>Raises <cite>postgresql.cluster.InitDBError</cite> when <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a> returns a non-zero result
code.</p>
<p class="last">Raises <cite>postgresql.cluster.ClusterInitializationError</cite> when there is no
<a class="reference external" href="http://www.postgresql.org/docs/current/static/app-initdb.html">initdb</a> in the Installation.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.initialized()</span></tt></dt>
<dd>Whether or not the data directory exists, <em>and</em> if it looks like a PostgreSQL
data directory. Meaning, the directory must contain a <tt class="docutils literal"><span class="pre">postgresql.conf</span></tt> file
and a <tt class="docutils literal"><span class="pre">base</span></tt> directory.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.drop()</span></tt></dt>
<dd>Shutdown the Cluster&#8217;s server process and completely remove the
<cite>Cluster.data_directory</cite> from the file system.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.pid()</span></tt></dt>
<dd>The server&#8217;s process identifier as a Python <cite>int</cite>. <cite>None</cite> if there is no
server process running.
This is a method rather than a property as it may read the PID from a file
in cases where the server process was not started by the Cluster.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.start([logfile</span> <span class="pre">=</span> <span class="pre">None[,</span> <span class="pre">settings</span> <span class="pre">=</span> <span class="pre">None]])</span></tt></dt>
<dd><p class="first">Start the PostgreSQL server process for the Cluster if it is not
already running. This will execute <a class="reference external" href="http://www.postgresql.org/docs/current/static/app-postgres.html">postgres</a> as a subprocess.</p>
<p>If <tt class="docutils literal"><span class="pre">logfile</span></tt>, an opened and writable file object, is given, stderr and
stdout will be redirected to that file. By default, both stderr and stdout are
closed.</p>
<p class="last">If <tt class="docutils literal"><span class="pre">settings</span></tt> is given, the mapping or sequence of pairs will be used as
long options to the subprocess. For each item, <tt class="docutils literal"><span class="pre">--{key}={value}</span></tt> will be
given as an argument to the subprocess.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.running()</span></tt></dt>
<dd>Whether or not the cluster&#8217;s server process is running. Returns <cite>True</cite> or
<cite>False</cite>. Even if <cite>True</cite> is returned, it does <em>not</em> mean that the server
process is ready to accept connections.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.ready_for_connections()</span></tt></dt>
<dd><p class="first">Whether or not the Cluster is ready to accept connections. Usually called
after <cite>Cluster.start</cite>.</p>
<p class="last">Returns <cite>True</cite> when the Cluster can accept connections, <cite>False</cite> when it
cannot, and <cite>None</cite> if the Cluster&#8217;s server process is not running at all.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.wait_until_started([timeout</span> <span class="pre">=</span> <span class="pre">10[,</span> <span class="pre">delay</span> <span class="pre">=</span> <span class="pre">0.05]])</span></tt></dt>
<dd><p class="first">Blocks the process until the cluster is identified as being ready for
connections. Usually called after <tt class="docutils literal"><span class="pre">Cluster.start()</span></tt>.</p>
<p>Raises <cite>postgresql.cluster.ClusterNotRunningError</cite> if the server process is
not running at all.</p>
<p>Raises <cite>postgresql.cluster.ClusterTimeoutError</cite> if
<cite>Cluster.ready_for_connections()</cite> does not return <cite>True</cite> within the given
<cite>timeout</cite> period.</p>
<p>Raises <cite>postgresql.cluster.ClusterStartupError</cite> if the server process
terminates while polling for readiness.</p>
<p class="last"><tt class="docutils literal"><span class="pre">timeout</span></tt> and <tt class="docutils literal"><span class="pre">delay</span></tt> are both in seconds. Where <tt class="docutils literal"><span class="pre">timeout</span></tt> is the
maximum time to wait for the Cluster to be ready for connections, and
<tt class="docutils literal"><span class="pre">delay</span></tt> is the time to sleep between calls to
<cite>Cluster.ready_for_connections()</cite>.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.stop()</span></tt></dt>
<dd>Signal the cluster to shutdown when possible. The <em>server</em> will wait for all
clients to disconnect before shutting down.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.shutdown()</span></tt></dt>
<dd>Signal the cluster to shutdown immediately. Any open client connections will
be closed.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.kill()</span></tt></dt>
<dd>Signal the absolute destruction of the server process(SIGKILL).
<em>This will require recovery when the cluster is started again.</em>
<em>Shared memory may be leaked.</em></dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.wait_until_stopped([timeout</span> <span class="pre">=</span> <span class="pre">10[,</span> <span class="pre">delay</span> <span class="pre">=</span> <span class="pre">0.05]])</span></tt></dt>
<dd><p class="first">Blocks the process until the cluster is identified as being shutdown. Usually
called after <cite>Cluster.stop</cite> or <cite>Cluster.shutdown</cite>.</p>
<p class="last">Raises <cite>postgresql.cluster.ClusterTimeoutError</cite> if
<cite>Cluster.ready_for_connections</cite> does not return <cite>None</cite> within the given
<cite>timeout</cite> period.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.reload()</span></tt></dt>
<dd>Signal the server that it should reload its configuration files(SIGHUP).
Usually called after manipulating <cite>Cluster.settings</cite> or modifying the
contents of <cite>Cluster.hba_file</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.restart([logfile</span> <span class="pre">=</span> <span class="pre">None[,</span> <span class="pre">settings</span> <span class="pre">=</span> <span class="pre">None[,</span> <span class="pre">timeout</span> <span class="pre">=</span> <span class="pre">10]]])</span></tt></dt>
<dd><p class="first">Stop the server process, wait until it is stopped, start the server
process, and wait until it has started.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">This calls <tt class="docutils literal"><span class="pre">Cluster.stop()</span></tt>, so it will wait until clients
disconnect before starting up again.</p>
</div>
<p class="last">The <tt class="docutils literal"><span class="pre">logfile</span></tt> and <tt class="docutils literal"><span class="pre">settings</span></tt> parameters will be given to <cite>Cluster.start</cite>.
<tt class="docutils literal"><span class="pre">timeout</span></tt> will be given to <cite>Cluster.wait_until_stopped</cite> and
<cite>Cluster.wait_until_started</cite>.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.settings</span></tt></dt>
<dd><p class="first">A <cite>collections.Mapping</cite> interface to the <tt class="docutils literal"><span class="pre">postgresql.conf</span></tt> file of the
cluster.</p>
<p class="last">A notable extension to the mapping interface is the <tt class="docutils literal"><span class="pre">getset</span></tt> method. This
method will return a dictionary object containing the settings whose names
were contained in the <cite>set</cite> object given to the method.
This method should be used when multiple settings need to be retrieved from
the configuration file.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.hba_file</span></tt></dt>
<dd>The path to the cluster&#8217;s <a class="reference external" href="http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html">pg_hba</a> file. This property respects the HBA file
location setting in <tt class="docutils literal"><span class="pre">postgresql.conf</span></tt>. Usually, <tt class="docutils literal"><span class="pre">$PGDATA/pg_hba.conf</span></tt>.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.daemon_path</span></tt></dt>
<dd>The path to the executable to use to start the server process.</dd>
<dt><tt class="docutils literal"><span class="pre">Cluster.daemon_process</span></tt></dt>
<dd>The <cite>subprocess.Popen</cite> instance of the server process. <cite>None</cite> if the server
process was not started or was not started using the Cluster object.</dd>
</dl>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Cluster Management</a><ul>
<li><a class="reference internal" href="#installations">Installations</a><ul>
<li><a class="reference internal" href="#installation-interface-points">Installation Interface Points</a></li>
</ul>
</li>
<li><a class="reference internal" href="#clusters">Clusters</a><ul>
<li><a class="reference internal" href="#initializing-clusters">Initializing Clusters</a></li>
<li><a class="reference internal" href="#configuring-clusters">Configuring Clusters</a></li>
<li><a class="reference internal" href="#controlling-clusters">Controlling Clusters</a></li>
<li><a class="reference internal" href="#cluster-interface-points">Cluster Interface Points</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="alock.html"
title="previous chapter">Advisory Locks</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="lib.html"
title="next chapter">Categories and Libraries</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/cluster.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="lib.html" title="Categories and Libraries"
>next</a> |</li>
<li class="right" >
<a href="alock.html" title="Advisory Locks"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Copy Management &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Notification Management" href="notifyman.html" />
<link rel="prev" title="Driver" href="driver.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="notifyman.html" title="Notification Management"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="driver.html" title="Driver"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="copy-management">
<span id="pg-copyman"></span><h1>Copy Management<a class="headerlink" href="#copy-management" title="Permalink to this headline">¶</a></h1>
<p>The <cite>postgresql.copyman</cite> module provides a way to quickly move COPY data coming
from one connection to many connections. Alternatively, it can be sourced
by arbitrary iterators and target arbitrary callables.</p>
<p>Statement execution methods offer a way for running COPY operations
with iterators, but the cost of allocating objects for each row is too
significant for transferring gigabytes of COPY data from one connection to
another. The interfaces available on statement objects are primarily intended to
be used when transferring COPY data to and from arbitrary Python
objects.</p>
<p>Direct connection-to-connection COPY operations can be performed using the
high-level <cite>postgresql.copyman.transfer</cite> function:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">copyman</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">send_stmt</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">destination</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TEMP TABLE loading_table (i int8)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receive_stmt</span> <span class="o">=</span> <span class="n">destination</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY loading_table FROM STDIN&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">total_rows</span><span class="p">,</span> <span class="n">total_bytes</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">transfer</span><span class="p">(</span><span class="n">send_stmt</span><span class="p">,</span> <span class="n">receive_stmt</span><span class="p">)</span>
</pre></div>
</div>
<p>However, if more control is needed, the <cite>postgresql.copyman.CopyManager</cite> class
should be used directly.</p>
<div class="section" id="copy-managers">
<h2>Copy Managers<a class="headerlink" href="#copy-managers" title="Permalink to this headline">¶</a></h2>
<p>The <cite>postgresql.copyman.CopyManager</cite> class manages the Producer and the
Receivers involved in a COPY operation. Normally,
<cite>postgresql.copyman.StatementProducer</cite> and
<cite>postgresql.copyman.StatementReceiver</cite> instances. Naturally, a Producer is the
object that produces the COPY data to be given to the Manager&#8217;s Receivers.</p>
<p>Using a Manager directly means that there is a need for more control over
the operation. The Manager is both a context manager and an iterator. The
context manager interfaces handle initialization and finalization of the COPY
state, and the iterator provides an event loop emitting information about the
amount of COPY data transferred this cycle. Normal usage takes the form:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">copyman</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">send_stmt</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">destination</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TEMP TABLE loading_table (i int8)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receive_stmt</span> <span class="o">=</span> <span class="n">destination</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY loading_table FROM STDIN&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">producer</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementProducer</span><span class="p">(</span><span class="n">send_stmt</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receiver</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementReceiver</span><span class="p">(</span><span class="n">receive_stmt</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">source</span><span class="o">.</span><span class="n">xact</span><span class="p">(),</span> <span class="n">destination</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">with</span> <span class="n">copyman</span><span class="o">.</span><span class="n">CopyManager</span><span class="p">(</span><span class="n">producer</span><span class="p">,</span> <span class="n">receiver</span><span class="p">)</span> <span class="k">as</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">num_messages</span><span class="p">,</span> <span class="n">num_bytes</span> <span class="ow">in</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">update_rate</span><span class="p">(</span><span class="n">num_bytes</span><span class="p">)</span>
</pre></div>
</div>
<p>As an alternative to a for-loop inside a with-statement block, the <cite>run</cite> method
can be called to perform the operation:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">source</span><span class="o">.</span><span class="n">xact</span><span class="p">(),</span> <span class="n">destination</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="n">copyman</span><span class="o">.</span><span class="n">CopyManager</span><span class="p">(</span><span class="n">producer</span><span class="p">,</span> <span class="n">receiver</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>However, there is little benefit beyond using the high-level
<cite>postgresql.copyman.transfer</cite> function.</p>
<div class="section" id="manager-interface-points">
<h3>Manager Interface Points<a class="headerlink" href="#manager-interface-points" title="Permalink to this headline">¶</a></h3>
<p>Primarily, the <cite>postgresql.copyman.CopyManager</cite> provides a context manager and
an iterator for controlling the COPY operation.</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">CopyManager.run()</span></tt></dt>
<dd>Perform the entire COPY operation.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.__enter__()</span></tt></dt>
<dd>Start the COPY operation. Connections taking part in the COPY should <strong>not</strong>
be used until <tt class="docutils literal"><span class="pre">__exit__</span></tt> is ran.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.__exit__(typ,</span> <span class="pre">val,</span> <span class="pre">tb)</span></tt></dt>
<dd>Finish the COPY operation. Fails in the case of an incomplete
COPY, or an untrapped exception. Either returns <cite>None</cite> or raises the generalized
exception, <cite>postgresql.copyman.CopyFail</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.__iter__()</span></tt></dt>
<dd>Returns the CopyManager instance.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.__next__()</span></tt></dt>
<dd><p class="first">Transfer the next chunk of COPY data to the receivers. Yields a tuple
consisting of the number of messages and bytes transferred,
<tt class="docutils literal"><span class="pre">(num_messages,</span> <span class="pre">num_bytes)</span></tt>. Raises <cite>StopIteration</cite> when complete.</p>
<p class="last">Raises <cite>postgresql.copyman.ReceiverFault</cite> when a Receiver raises an
exception.
Raises <cite>postgresql.copyman.ProducerFault</cite> when the Producer raises an
exception. The original exception is available via the exception&#8217;s
<tt class="docutils literal"><span class="pre">__context__</span></tt> attribute.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.reconcile(faulted_receiver)</span></tt></dt>
<dd>Reconcile a faulted receiver. When a receiver faults, it will no longer
be in the set of Receivers. This method is used to signal to the manager that the
problem has been corrected, and the receiver is again ready to receive.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.receivers</span></tt></dt>
<dd>The <cite>builtins.set</cite> of Receivers involved in the COPY operation.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyManager.producer</span></tt></dt>
<dd>The Producer emitting the data to be given to the Receivers.</dd>
</dl>
</div></blockquote>
</div>
</div>
<div class="section" id="faults">
<h2>Faults<a class="headerlink" href="#faults" title="Permalink to this headline">¶</a></h2>
<p>The CopyManager generalizes any exceptions that occur during transfer. While
inside the context manager, <cite>postgresql.copyman.Fault</cite> may be raised if a
Receiver or a Producer raises an exception. A <cite>postgresql.copyman.ProducerFault</cite>
in the case of the Producer, and <cite>postgresql.copyman.ReceiverFault</cite> in the case
of the Receivers.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Faults are only raised by <cite>postgresql.copyman.CopyManager.__next__</cite>. The
<tt class="docutils literal"><span class="pre">run()</span></tt> method will only raise <cite>postgresql.copyman.CopyFail</cite>.</p>
</div>
<div class="section" id="receiver-faults">
<h3>Receiver Faults<a class="headerlink" href="#receiver-faults" title="Permalink to this headline">¶</a></h3>
<p>The Manager assumes the Fault is fatal to a Receiver, and immediately removes
it from the set of target receivers. Additionally, if the Fault exception goes
untrapped, the copy will ultimately fail.</p>
<p>The Fault exception references the Manager that raised the exception, and the
actual exceptions that occurred associated with the Receiver that caused them.</p>
<p>In order to identify the exception that caused a Fault, the <tt class="docutils literal"><span class="pre">faults</span></tt> attribute
on the <cite>postgresql.copyman.ReceiverFault</cite> must be referenced:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">copyman</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">send_stmt</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">destination</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TEMP TABLE loading_table (i int8)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receive_stmt</span> <span class="o">=</span> <span class="n">destination</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY loading_table FROM STDIN&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">producer</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementProducer</span><span class="p">(</span><span class="n">send_stmt</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receiver</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementReceiver</span><span class="p">(</span><span class="n">receive_stmt</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">source</span><span class="o">.</span><span class="n">xact</span><span class="p">(),</span> <span class="n">destination</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">with</span> <span class="n">copyman</span><span class="o">.</span><span class="n">CopyManager</span><span class="p">(</span><span class="n">producer</span><span class="p">,</span> <span class="n">receiver</span><span class="p">)</span> <span class="k">as</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">while</span> <span class="n">copy</span><span class="o">.</span><span class="n">receivers</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">num_messages</span><span class="p">,</span> <span class="n">num_bytes</span> <span class="ow">in</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">update_rate</span><span class="p">(</span><span class="n">num_bytes</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">break</span>
<span class="gp">... </span> <span class="k">except</span> <span class="n">copyman</span><span class="o">.</span><span class="n">ReceiverFault</span> <span class="k">as</span> <span class="n">cf</span><span class="p">:</span>
<span class="gp">... </span> <span class="c"># Access the original exception using the receiver as the key.</span>
<span class="gp">... </span> <span class="n">original_exception</span> <span class="o">=</span> <span class="n">cf</span><span class="o">.</span><span class="n">faults</span><span class="p">[</span><span class="n">receiver</span><span class="p">]</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">unknown_failure</span><span class="p">(</span><span class="n">original_exception</span><span class="p">):</span>
<span class="gp">... </span> <span class="o">...</span>
<span class="gp">... </span> <span class="k">raise</span>
</pre></div>
</div>
<div class="section" id="receiverfault-properties">
<h4>ReceiverFault Properties<a class="headerlink" href="#receiverfault-properties" title="Permalink to this headline">¶</a></h4>
<p>The following attributes exist on <cite>postgresql.copyman.ReceiverFault</cite> instances:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">ReceiverFault.manager</span></tt></dt>
<dd>The subject <cite>postgresql.copyman.CopyManager</cite> instance.</dd>
<dt><tt class="docutils literal"><span class="pre">ReceiverFault.faults</span></tt></dt>
<dd>A dictionary mapping the Receiver to the exception raised by that Receiver.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="reconciliation">
<h4>Reconciliation<a class="headerlink" href="#reconciliation" title="Permalink to this headline">¶</a></h4>
<p>When a <cite>postgresql.copyman.ReceiverFault</cite> is raised, the Manager immediately
removes the Receiver so that the COPY operation can continue. Continuation of
the COPY can occur by trapping the exception and continuing the iteration of the
Manager. However, if the fault is recoverable, the
<cite>postgresql.copyman.CopyManager.reconcile</cite> method must be used to reintroduce the
Receiver into the Manager&#8217;s set. Faults must be trapped from within the
Manager&#8217;s context:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">socket</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql</span> <span class="kn">import</span> <span class="n">copyman</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">send_stmt</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY (SELECT i FROM generate_series(1, 1000000) AS g(i)) TO STDOUT&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">destination</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TEMP TABLE loading_table (i int8)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receive_stmt</span> <span class="o">=</span> <span class="n">destination</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;COPY loading_table FROM STDIN&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">producer</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementProducer</span><span class="p">(</span><span class="n">send_stmt</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">receiver</span> <span class="o">=</span> <span class="n">copyman</span><span class="o">.</span><span class="n">StatementReceiver</span><span class="p">(</span><span class="n">receive_stmt</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">source</span><span class="o">.</span><span class="n">xact</span><span class="p">(),</span> <span class="n">destination</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">with</span> <span class="n">copyman</span><span class="o">.</span><span class="n">CopyManager</span><span class="p">(</span><span class="n">producer</span><span class="p">,</span> <span class="n">receiver</span><span class="p">)</span> <span class="k">as</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">while</span> <span class="n">copy</span><span class="o">.</span><span class="n">receivers</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">num_messages</span><span class="p">,</span> <span class="n">num_bytes</span> <span class="ow">in</span> <span class="n">copy</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">update_rate</span><span class="p">(</span><span class="n">num_bytes</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">except</span> <span class="n">copyman</span><span class="o">.</span><span class="n">ReceiverFault</span> <span class="k">as</span> <span class="n">cf</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">cf</span><span class="o">.</span><span class="n">faults</span><span class="p">[</span><span class="n">receiver</span><span class="p">],</span> <span class="n">socket</span><span class="o">.</span><span class="n">timeout</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">copy</span><span class="o">.</span><span class="n">reconcile</span><span class="p">(</span><span class="n">receiver</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span>
</pre></div>
</div>
<p>Recovering from Faults does add significant complexity to a COPY operation,
so, often, it&#8217;s best to avoid conditions in which reconciliable Faults may
occur.</p>
</div>
</div>
<div class="section" id="producer-faults">
<h3>Producer Faults<a class="headerlink" href="#producer-faults" title="Permalink to this headline">¶</a></h3>
<p>Producer faults are normally fatal to the COPY operation and should rarely be
trapped. However, the Manager makes no state changes when a Producer faults,
so, unlike Receiver Faults, no reconciliation process is necessary; rather,
if it&#8217;s safe to continue, the Manager&#8217;s iterator should continue to be
processed.</p>
<div class="section" id="producerfault-properties">
<h4>ProducerFault Properties<a class="headerlink" href="#producerfault-properties" title="Permalink to this headline">¶</a></h4>
<p>The following attributes exist on <cite>postgresql.copyman.ProducerFault</cite> instances:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">ReceiverFault.manager</span></tt></dt>
<dd>The subject <cite>postgresql.copyman.CopyManager</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">ReceiverFault.__context__</span></tt></dt>
<dd>The original exception raised by the Producer.</dd>
</dl>
</div></blockquote>
</div>
</div>
</div>
<div class="section" id="failures">
<h2>Failures<a class="headerlink" href="#failures" title="Permalink to this headline">¶</a></h2>
<p>When a COPY operation is aborted, either by an exception or by the iterator
being broken, a <cite>postgresql.copyman.CopyFail</cite> exception will be raised by the
Manager&#8217;s <tt class="docutils literal"><span class="pre">__exit__()</span></tt> method. The <cite>postgresql.copyman.CopyFail</cite> exception
offers to record any exceptions that occur during the exit of the context
managers of the Producer and the Receivers.</p>
<div class="section" id="copyfail-properties">
<h3>CopyFail Properties<a class="headerlink" href="#copyfail-properties" title="Permalink to this headline">¶</a></h3>
<p>The following properties exist on <cite>postgresql.copyman.CopyFail</cite> exceptions:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">CopyFail.manager</span></tt></dt>
<dd>The Manager whose COPY operation failed.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyFail.receiver_faults</span></tt></dt>
<dd>A dictionary mapping a <cite>postgresql.copyman.Receiver</cite> to the exception raised
by that Receiver&#8217;s <tt class="docutils literal"><span class="pre">__exit__</span></tt>. <cite>None</cite> if no exceptions were raised by the
Receivers.</dd>
<dt><tt class="docutils literal"><span class="pre">CopyFail.producer_fault</span></tt></dt>
<dd>The exception Raised by the <cite>postgresql.copyman.Producer</cite>. <cite>None</cite> if none.</dd>
</dl>
</div></blockquote>
</div>
</div>
<div class="section" id="producers">
<h2>Producers<a class="headerlink" href="#producers" title="Permalink to this headline">¶</a></h2>
<p>The following Producers are available:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">postgresql.copyman.StatementProducer(postgresql.api.Statement)</span></tt></dt>
<dd>Given a Statement producing COPY data, construct a Producer.</dd>
<dt><tt class="docutils literal"><span class="pre">postgresql.copyman.IteratorProducer(collections.Iterator)</span></tt></dt>
<dd>Given an Iterator producing <em>chunks</em> of COPY lines, construct a Producer to
manage the data coming from the iterator.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="receivers">
<h2>Receivers<a class="headerlink" href="#receivers" title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">postgresql.copyman.StatementReceiver(postgresql.api.Statement)</span></tt></dt>
<dd>Given a Statement producing COPY data, construct a Producer.</dd>
<dt><tt class="docutils literal"><span class="pre">postgresql.copyman.CallReceiver(callable)</span></tt></dt>
<dd>Given a callable, construct a Receiver that will transmit COPY data in chunks
of lines. That is, the callable will be given a list of COPY lines for each
transfer cycle.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="terminology">
<h2>Terminology<a class="headerlink" href="#terminology" title="Permalink to this headline">¶</a></h2>
<p>The following terms are regularly used to describe the implementation and
processes of the <cite>postgresql.copyman</cite> module:</p>
<blockquote>
<div><dl class="docutils">
<dt>Manager</dt>
<dd>The object used to manage data coming from a Producer and being given to the
Receivers. It also manages the necessary initialization and finalization steps
required by those factors.</dd>
<dt>Producer</dt>
<dd>The object used to produce the COPY data to be given to the Receivers. The
source.</dd>
<dt>Receiver</dt>
<dd>An object that consumes COPY data. A target.</dd>
<dt>Fault</dt>
<dd>Specifically, <cite>postgresql.copyman.Fault</cite> exceptions. A Fault is raised
when a Receiver or a Producer raises an exception during the COPY operation.</dd>
<dt>Reconciliation</dt>
<dd>Generally, the steps performed by the &#8220;reconcile&#8221; method on
<cite>postgresql.copyman.CopyManager</cite> instances. More precisely, the
necessary steps for a Receiver&#8217;s reintroduction into the COPY operation after
a Fault.</dd>
<dt>Failed Copy</dt>
<dd>A failed copy is an aborted COPY operation. This occurs in situations of
untrapped exceptions or an incomplete COPY. Specifically, the COPY will be
noted as failed in cases where the Manager&#8217;s iterator is <em>not</em> ran until
exhaustion.</dd>
<dt>Realignment</dt>
<dd>The process of providing compensating data to the Receivers so that the
connection will be on a message boundary. Occurs when the COPY operation
is aborted.</dd>
</dl>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Copy Management</a><ul>
<li><a class="reference internal" href="#copy-managers">Copy Managers</a><ul>
<li><a class="reference internal" href="#manager-interface-points">Manager Interface Points</a></li>
</ul>
</li>
<li><a class="reference internal" href="#faults">Faults</a><ul>
<li><a class="reference internal" href="#receiver-faults">Receiver Faults</a><ul>
<li><a class="reference internal" href="#receiverfault-properties">ReceiverFault Properties</a></li>
<li><a class="reference internal" href="#reconciliation">Reconciliation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#producer-faults">Producer Faults</a><ul>
<li><a class="reference internal" href="#producerfault-properties">ProducerFault Properties</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#failures">Failures</a><ul>
<li><a class="reference internal" href="#copyfail-properties">CopyFail Properties</a></li>
</ul>
</li>
<li><a class="reference internal" href="#producers">Producers</a></li>
<li><a class="reference internal" href="#receivers">Receivers</a></li>
<li><a class="reference internal" href="#terminology">Terminology</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="driver.html"
title="previous chapter">Driver</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="notifyman.html"
title="next chapter">Notification Management</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/copyman.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="notifyman.html" title="Notification Management"
>next</a> |</li>
<li class="right" >
<a href="driver.html" title="Driver"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="index">Index</h1>
<div class="genindex-jumpbox">
<a href="#A"><strong>A</strong></a>
| <a href="#B"><strong>B</strong></a>
| <a href="#C"><strong>C</strong></a>
| <a href="#D"><strong>D</strong></a>
| <a href="#E"><strong>E</strong></a>
| <a href="#F"><strong>F</strong></a>
| <a href="#H"><strong>H</strong></a>
| <a href="#I"><strong>I</strong></a>
| <a href="#L"><strong>L</strong></a>
| <a href="#M"><strong>M</strong></a>
| <a href="#N"><strong>N</strong></a>
| <a href="#O"><strong>O</strong></a>
| <a href="#P"><strong>P</strong></a>
| <a href="#Q"><strong>Q</strong></a>
| <a href="#R"><strong>R</strong></a>
| <a href="#S"><strong>S</strong></a>
| <a href="#T"><strong>T</strong></a>
| <a href="#U"><strong>U</strong></a>
| <a href="#V"><strong>V</strong></a>
| <a href="#W"><strong>W</strong></a>
| <a href="#X"><strong>X</strong></a>
</div>
<h2 id="A">A</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.alock.ALock">ALock (class in postgresql.alock)</a>
</dt>
<dt><a href="reference.html#postgresql.alock.ALock.acquire">ALock.acquire() (in module postgresql.alock)</a>
</dt>
<dt><a href="reference.html#postgresql.alock.ALock.locked">ALock.locked() (in module postgresql.alock)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.alock.ALock.release">ALock.release() (in module postgresql.alock)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.AuthenticationMethodError">AuthenticationMethodError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="B">B</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Database.backend_id">backend_id (postgresql.api.Database attribute)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="C">C</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.copyman.CallReceiver">CallReceiver (class in postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.CardinalityError">CardinalityError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Category">Category (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.CFError">CFError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.client_address">client_address (postgresql.api.Database attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.client_port">client_port (postgresql.api.Database attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ClientCannotConnectError">ClientCannotConnectError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.closed">closed (postgresql.api.Connection attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster">Cluster (class in postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster">(class in postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.Cluster.address">Cluster.address() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.connect">Cluster.connect() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.connection">Cluster.connection() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.connector">Cluster.connector() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.drop">Cluster.drop() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.drop">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.Cluster.get_pid_from_file">Cluster.get_pid_from_file() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.init">Cluster.init() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.init">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.Cluster.initialized">Cluster.initialized() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.kill">Cluster.kill() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.kill">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.Cluster.ready_for_connections">Cluster.ready_for_connections() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.reload">Cluster.reload() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.restart">Cluster.restart() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.restart">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.Cluster.running">Cluster.running() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.shutdown">Cluster.shutdown() (in module postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.start">Cluster.start() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.start">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.api.Cluster.stop">Cluster.stop() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.stop">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.api.Cluster.wait_until_started">Cluster.wait_until_started() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.wait_until_started">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Cluster.wait_until_stopped">Cluster.wait_until_stopped() (in module postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.wait_until_stopped">(in module postgresql.cluster)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.cluster.ClusterError">ClusterError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.ClusterInitializationError">ClusterInitializationError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.ClusterNotRunningError">ClusterNotRunningError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.ClusterStartupError">ClusterStartupError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.ClusterTimeoutError">ClusterTimeoutError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.ClusterWarning">ClusterWarning (class in postgresql.cluster)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Message.code">code (postgresql.api.Message attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.column_names">column_names (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.column_types">column_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection">Connection (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.clone">Connection.clone() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.close">Connection.close() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.connect">Connection.connect() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ConnectionDoesNotExistError">ConnectionDoesNotExistError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ConnectionFailureError">ConnectionFailureError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connector">Connector (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.connector">connector (postgresql.api.Connection attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ConnectTimeoutError">ConnectTimeoutError</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.CopyFail">CopyFail</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.CopyManager">CopyManager (class in postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.CopyManager.reconcile">CopyManager.reconcile() (in module postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cursor">Cursor (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cursor.clone">Cursor.clone() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cursor.read">Cursor.read() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cursor.seek">Cursor.seek() (in module postgresql.api)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="D">D</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.daemon_path">daemon_path (postgresql.cluster.Cluster attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.data_directory">data_directory (postgresql.api.Cluster attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database">Database (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.cursor_from_id">Database.cursor_from_id() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.do">Database.do() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.execute">Database.execute() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.iternotifies">Database.iternotifies() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.listen">Database.listen() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.listening_channels">Database.listening_channels() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.notify">Database.notify() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.prepare">Database.prepare() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.proc">Database.proc() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.reset">Database.reset() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Database.statement_from_id">Database.statement_from_id() (in module postgresql.api)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Database.unlisten">Database.unlisten() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.installation.default">default() (in module postgresql.installation)</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.default_buffer_size">default_buffer_size (in module postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.sys.default_errformat">default_errformat() (in module postgresql.sys)</a>
</dt>
<dt><a href="reference.html#postgresql.sys.default_msghook">default_msghook() (in module postgresql.sys)</a>
</dt>
<dt><a href="reference.html#postgresql.installation.default_pg_config">default_pg_config() (in module postgresql.installation)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Message.details">details (postgresql.api.Message attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cursor.direction">direction (postgresql.api.Cursor attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.Disconnection">Disconnection</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.DPDSEError">DPDSEError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Driver">Driver (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Driver.connect">Driver.connect() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.DriverError">DriverError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="E">E</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.EREError">EREError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ERIEError">ERIEError</a>
</dt>
<dt><a href="reference.html#postgresql.sys.errformat">errformat() (in module postgresql.sys)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.Error">Error</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.string.escape_ident">escape_ident() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.escape_literal">escape_literal() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.EscapeCharacterError">EscapeCharacterError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.Exception">Exception</a>
</dt>
</dl></td>
</tr></table>
<h2 id="F">F</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.FeatureError">FeatureError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="H">H</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.cluster.Cluster.hba_file">hba_file (postgresql.cluster.Cluster attribute)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="I">I</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.ICVError">ICVError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.IgnoredClientParameterWarning">IgnoredClientParameterWarning (class in postgresql.exceptions)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.InconsistentCursorIsolationError">InconsistentCursorIsolationError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.InFailedTransactionError">InFailedTransactionError</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.InitDBError">InitDBError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.InsecurityError">InsecurityError</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Installation">Installation (class in postgresql.api)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.installation.Installation">(class in postgresql.installation)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.api.Cluster.installation">installation (postgresql.api.Cluster attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.IRError">IRError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction.isolation">isolation (postgresql.api.Transaction attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ITSError">ITSError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="L">L</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.LoadError">LoadError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="M">M</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.map_errors_and_warnings">map_errors_and_warnings() (in module postgresql.exceptions)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Message">Message (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Message.message">message (postgresql.api.Message attribute)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Message.isconsistent">Message.isconsistent() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.alock.ALock.mode">mode (postgresql.alock.ALock attribute)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.api.Transaction.mode">(postgresql.api.Transaction attribute)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.sys.msghook">msghook() (in module postgresql.sys)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="N">N</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.copyman.NullProducer">NullProducer (class in postgresql.copyman)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="O">O</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.OIError">OIError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ONIPSError">ONIPSError</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.open">open() (in module postgresql)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.OperationError">OperationError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="P">P</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Statement.parameter_types">parameter_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.pg_column_types">pg_column_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.installation.pg_config_dictionary">pg_config_dictionary() (in module postgresql.installation)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.pg_parameter_types">pg_parameter_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.temporal.pg_tmp">pg_tmp (in module postgresql.temporal)</a>
</dt>
<dt><a href="reference.html#postgresql.cluster.Cluster.pid">pid (postgresql.cluster.Cluster attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.PLEError">PLEError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.PLPGSQLError">PLPGSQLError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.PLPGSQLRaiseError">PLPGSQLRaiseError</a>
</dt>
<dt><a href="reference.html#module-postgresql">postgresql (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.alock">postgresql.alock (module)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#module-postgresql.api">postgresql.api (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.cluster">postgresql.cluster (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.copyman">postgresql.copyman (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.exceptions">postgresql.exceptions (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.installation">postgresql.installation (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.string">postgresql.string (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.sys">postgresql.sys (module)</a>
</dt>
<dt><a href="reference.html#module-postgresql.temporal">postgresql.temporal (module)</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.ProducerFault">ProducerFault</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.ProtocolProducer">ProtocolProducer (class in postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.ProtocolProducer.recover">ProtocolProducer.recover() (in module postgresql.copyman)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="Q">Q</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.string.qname">qname() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Connection.query">query (postgresql.api.Connection attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.string.quote_ident">quote_ident() (in module postgresql.string)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.string.quote_ident_if_needed">quote_ident_if_needed() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.quote_literal">quote_literal() (in module postgresql.string)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="R">R</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.ReadOnlyTransactionError">ReadOnlyTransactionError</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.ReceiverFault">ReceiverFault</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.sys.reset_errformat">reset_errformat() (in module postgresql.sys)</a>
</dt>
<dt><a href="reference.html#postgresql.sys.reset_msghook">reset_msghook() (in module postgresql.sys)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="S">S</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.exceptions.SavepointError">SavepointError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.SchemaAndDataStatementsError">SchemaAndDataStatementsError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.SEARVError">SEARVError</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.ServerNotReadyError">ServerNotReadyError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings">Settings (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Cluster.settings">settings (postgresql.api.Cluster attribute)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.api.Database.settings">(postgresql.api.Database attribute)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.api.Settings.get">Settings.get() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings.getset">Settings.getset() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings.items">Settings.items() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings.keys">Settings.keys() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings.update">Settings.update() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Settings.values">Settings.values() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.SIOError">SIOError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Message.source">source (postgresql.api.Message attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.string.split">split() (in module postgresql.string)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.string.split_ident">split_ident() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.split_qname">split_qname() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.split_sql">split_sql() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.split_sql_str">split_sql_str() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.string.split_using">split_using() (in module postgresql.string)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.sql_column_types">sql_column_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.sql_parameter_types">sql_parameter_types (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.SREError">SREError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Installation.ssl">ssl (postgresql.api.Installation attribute)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.installation.Installation.ssl">(postgresql.installation.Installation attribute)</a>
</dt>
</dl></dd>
<dt><a href="reference.html#postgresql.api.Statement">Statement (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.clone">Statement.clone() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.close">Statement.close() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.statement_id">statement_id (postgresql.api.Statement attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.StoredProcedure">StoredProcedure (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Statement.string">string (postgresql.api.Statement attribute)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="T">T</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.temporal.Temporal">Temporal (class in postgresql.temporal)</a>
</dt>
<dt><a href="reference.html#postgresql.temporal.Temporal.cluster_dirname">Temporal.cluster_dirname() (in module postgresql.temporal)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction">Transaction (class in postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction.abort">Transaction.abort() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction.begin">Transaction.begin() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction.commit">Transaction.commit() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Transaction.rollback">Transaction.rollback() (in module postgresql.api)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Transaction.start">Transaction.start() (in module postgresql.api)</a>
</dt>
<dt><a href="reference.html#postgresql.copyman.transfer">transfer() (in module postgresql.copyman)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.TRError">TRError</a>
</dt>
<dt><a href="reference.html#postgresql.api.Installation.type">type (postgresql.api.Installation attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.TypeConversionWarning">TypeConversionWarning (class in postgresql.exceptions)</a>
</dt>
<dt><a href="reference.html#postgresql.exceptions.TypeIOError">TypeIOError</a>
</dt>
</dl></td>
</tr></table>
<h2 id="U">U</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.copyman.ulong_pack">ulong_pack() (in module postgresql.copyman)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.string.unsplit">unsplit() (in module postgresql.string)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="V">V</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.version">version (in module postgresql)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.api.Installation.version">(postgresql.api.Installation attribute)</a>
</dt>
</dl></dd>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.version_info">version_info (in module postgresql)</a>
</dt>
<dd><dl>
<dt><a href="reference.html#postgresql.api.Database.version_info">(postgresql.api.Database attribute)</a>
</dt>
<dt><a href="reference.html#postgresql.api.Installation.version_info">(postgresql.api.Installation attribute)</a>
</dt>
</dl></dd>
</dl></td>
</tr></table>
<h2 id="W">W</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.copyman.WireState">WireState (class in postgresql.copyman)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.copyman.WireState.update">WireState.update() (in module postgresql.copyman)</a>
</dt>
</dl></td>
</tr></table>
<h2 id="X">X</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl>
<dt><a href="reference.html#postgresql.api.Database.xact">xact (postgresql.api.Database attribute)</a>
</dt>
</dl></td>
</tr></table>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Gotchas &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Commands" href="bin.html" />
<link rel="prev" title="Client Parameters" href="clientparameters.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="bin.html" title="Commands"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="clientparameters.html" title="Client Parameters"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="gotchas">
<h1>Gotchas<a class="headerlink" href="#gotchas" title="Permalink to this headline">¶</a></h1>
<p>It is recognized that decisions were made that may not always be ideal for a
given user. In order to highlight those potential issues and hopefully bring
some sense into a confusing situation, this document was drawn.</p>
<div class="section" id="non-english-locales">
<h2>Non-English Locales<a class="headerlink" href="#non-english-locales" title="Permalink to this headline">¶</a></h2>
<p>Many non-english locales are not supported due to the localization of the severity field
in messages and errors sent to the client. Internally, py-postgresql uses this to allow
client side filtering of messages and to identify FATAL connection errors that allow the
client to recognize that it should be expecting the connection to terminate.</p>
</div>
<div class="section" id="thread-safety">
<h2>Thread Safety<a class="headerlink" href="#thread-safety" title="Permalink to this headline">¶</a></h2>
<p>py-postgresql connection operations are not thread safe.</p>
</div>
<div class="section" id="client-encoding-setting-should-be-altered-carefully">
<h2><cite>client_encoding</cite> setting should be altered carefully<a class="headerlink" href="#client-encoding-setting-should-be-altered-carefully" title="Permalink to this headline">¶</a></h2>
<p><cite>postgresql.driver</cite>&#8216;s streaming cursor implementation reads a fixed set of rows
when it queries the server for more. In order to optimize some situations, the
driver will send a request for more data, but makes no attempt to wait and
process the data as it is not yet needed. When the user comes back to read more
data from the cursor, it will then look at this new data. The problem being, if
<cite>client_encoding</cite> was switched, it may use the wrong codec to transform the
wire data into higher level Python objects(str).</p>
<p>To avoid this problem from ever happening, set the <cite>client_encoding</cite> early.
Furthermore, it is probably best to never change the <cite>client_encoding</cite> as the
driver automatically makes the necessary transformation to Python strings.</p>
</div>
<div class="section" id="the-user-and-password-is-correct-but-it-does-not-work-when-using-postgresql-driver">
<h2>The user and password is correct, but it does not work when using <cite>postgresql.driver</cite><a class="headerlink" href="#the-user-and-password-is-correct-but-it-does-not-work-when-using-postgresql-driver" title="Permalink to this headline">¶</a></h2>
<p>This issue likely comes from the possibility that the information sent to the
server early in the negotiation phase may not be in an encoding that is
consistent with the server&#8217;s encoding.</p>
<p>One problem is that PostgreSQL does not provide the client with the server
encoding early enough in the negotiation phase, and, therefore, is unable to
process the password data in a way that is consistent with the server&#8217;s
expectations.</p>
<p>Another problem is that PostgreSQL takes much of the data in the startup message
as-is, so a decision about the best way to encode parameters is difficult.</p>
<p>The easy way to avoid <em>most</em> issues with this problem is to initialize the
database in the <cite>utf-8</cite> encoding. The driver defaults the expected server
encoding to <cite>utf-8</cite>. However, this can be overridden by creating the <cite>Connector</cite>
with a <cite>server_encoding</cite> parameter. Setting <cite>server_encoding</cite> to the proper
value of the target server will allow the driver to properly encode <em>some</em> of
the parameters. Also, any GUC parameters passed via the <cite>settings</cite> parameter
should use typed objects when possible to hint that the server encoding should
not be used on that parameter(<cite>bytes</cite>, for instance).</p>
</div>
<div class="section" id="backslash-characters-are-being-treated-literally">
<h2>Backslash characters are being treated literally<a class="headerlink" href="#backslash-characters-are-being-treated-literally" title="Permalink to this headline">¶</a></h2>
<p>The driver enables standard compliant strings. Stop using non-standard features.
;)</p>
<p>If support for non-standard strings was provided it would require to the
driver to provide subjective quote interfaces(eg, db.quote_literal). Doing so is
not desirable as it introduces difficulties for the driver <em>and</em> the user.</p>
</div>
<div class="section" id="types-without-binary-support-in-the-driver-are-unsupported-in-arrays-and-records">
<h2>Types without binary support in the driver are unsupported in arrays and records<a class="headerlink" href="#types-without-binary-support-in-the-driver-are-unsupported-in-arrays-and-records" title="Permalink to this headline">¶</a></h2>
<p>When an array or composite type is identified, <cite>postgresql.protocol.typio</cite>
ultimately chooses the binary format for the transfer of the column or
parameter. When this is done, PostgreSQL will pack or expect <em>all</em> the values
in binary format as well. If that binary format is not supported and the type
is not an string, it will fail to unpack the row or pack the appropriate data for
the element or attribute.</p>
<p>In most cases issues related to this can be avoided with explicit casts to text.</p>
</div>
<div class="section" id="notices-warnings-and-other-messages-are-too-verbose">
<h2>NOTICEs, WARNINGs, and other messages are too verbose<a class="headerlink" href="#notices-warnings-and-other-messages-are-too-verbose" title="Permalink to this headline">¶</a></h2>
<p>For many situations, the information provided with database messages is
far too verbose. However, considering that py-postgresql is a programmer&#8217;s
library, the default of high verbosity is taken with the express purpose of
allowing the programmer to &#8220;adjust the volume&#8221; until appropriate.</p>
<p>By default, py-postgresql adjusts the <tt class="docutils literal"><span class="pre">client_min_messages</span></tt> to only emit
messages at the WARNING level or higher&#8211;ERRORs, FATALs, and PANICs.
This reduces the number of messages generated by most connections dramatically.</p>
<p>If further customization is needed, the <a class="reference internal" href="driver.html#db-messages"><em>Database Messages</em></a> section has
information on overriding the default action taken with database messages.</p>
</div>
<div class="section" id="strange-typeerror-using-load-rows-or-load-chunks">
<h2>Strange TypeError using load_rows() or load_chunks()<a class="headerlink" href="#strange-typeerror-using-load-rows-or-load-chunks" title="Permalink to this headline">¶</a></h2>
<p>When a prepared statement is directly executed using <tt class="docutils literal"><span class="pre">__call__()</span></tt>, it can easily
validate that the appropriate number of parameters are given to the function.
When <tt class="docutils literal"><span class="pre">load_rows()</span></tt> or <tt class="docutils literal"><span class="pre">load_chunks()</span></tt> is used, any tuple in the
the entire sequence can cause this TypeError during the loading process:</p>
<div class="highlight-python"><pre>TypeError: inconsistent items, N processors and M items in row</pre>
</div>
<p>This exception is raised by a generic processing routine whose functionality
is abstract in nature, so the message is abstract as well. It essentially means
that a tuple in the sequence given to the loading method had too many or too few
items.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Gotchas</a><ul>
<li><a class="reference internal" href="#non-english-locales">Non-English Locales</a></li>
<li><a class="reference internal" href="#thread-safety">Thread Safety</a></li>
<li><a class="reference internal" href="#client-encoding-setting-should-be-altered-carefully"><cite>client_encoding</cite> setting should be altered carefully</a></li>
<li><a class="reference internal" href="#the-user-and-password-is-correct-but-it-does-not-work-when-using-postgresql-driver">The user and password is correct, but it does not work when using <cite>postgresql.driver</cite></a></li>
<li><a class="reference internal" href="#backslash-characters-are-being-treated-literally">Backslash characters are being treated literally</a></li>
<li><a class="reference internal" href="#types-without-binary-support-in-the-driver-are-unsupported-in-arrays-and-records">Types without binary support in the driver are unsupported in arrays and records</a></li>
<li><a class="reference internal" href="#notices-warnings-and-other-messages-are-too-verbose">NOTICEs, WARNINGs, and other messages are too verbose</a></li>
<li><a class="reference internal" href="#strange-typeerror-using-load-rows-or-load-chunks">Strange TypeError using load_rows() or load_chunks()</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="clientparameters.html"
title="previous chapter">Client Parameters</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="bin.html"
title="next chapter">Commands</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/gotchas.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="bin.html" title="Commands"
>next</a> |</li>
<li class="right" >
<a href="clientparameters.html" title="Client Parameters"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>py-postgresql &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="#" />
<link rel="next" title="Administration" href="admin.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="admin.html" title="Administration"
accesskey="N">next</a> |</li>
<li><a href="#">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="py-postgresql">
<h1>py-postgresql<a class="headerlink" href="#py-postgresql" title="Permalink to this headline">¶</a></h1>
<p>py-postgresql is a project dedicated to improving the Python client interfaces to PostgreSQL.</p>
<p>At its core, py-postgresql provides a PG-API, <cite>postgresql.api</cite>, and
DB-API 2.0 interface for using a PostgreSQL database.</p>
<div class="section" id="contents">
<h2>Contents<a class="headerlink" href="#contents" title="Permalink to this headline">¶</a></h2>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="admin.html">Administration</a><ul>
<li class="toctree-l2"><a class="reference internal" href="admin.html#installation">Installation</a></li>
<li class="toctree-l2"><a class="reference internal" href="admin.html#environment">Environment</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="driver.html">Driver</a><ul>
<li class="toctree-l2"><a class="reference internal" href="driver.html#establishing-a-connection">Establishing a Connection</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#connections">Connections</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#prepared-statements">Prepared Statements</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#cursors">Cursors</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#rows">Rows</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#queries">Queries</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#stored-procedures">Stored Procedures</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#transactions">Transactions</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#settings">Settings</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#type-support">Type Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="driver.html#database-messages">Database Messages</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="copyman.html">Copy Management</a><ul>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#copy-managers">Copy Managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#faults">Faults</a></li>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#failures">Failures</a></li>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#producers">Producers</a></li>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#receivers">Receivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="copyman.html#terminology">Terminology</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="notifyman.html">Notification Management</a><ul>
<li class="toctree-l2"><a class="reference internal" href="notifyman.html#listening-on-a-single-connection">Listening on a Single Connection</a></li>
<li class="toctree-l2"><a class="reference internal" href="notifyman.html#listening-on-multiple-connections">Listening on Multiple Connections</a></li>
<li class="toctree-l2"><a class="reference internal" href="notifyman.html#notification-managers">Notification Managers</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="alock.html">Advisory Locks</a><ul>
<li class="toctree-l2"><a class="reference internal" href="alock.html#acquiring-alocks">Acquiring ALocks</a></li>
<li class="toctree-l2"><a class="reference internal" href="alock.html#alocks">ALocks</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="cluster.html">Cluster Management</a><ul>
<li class="toctree-l2"><a class="reference internal" href="cluster.html#installations">Installations</a></li>
<li class="toctree-l2"><a class="reference internal" href="cluster.html#clusters">Clusters</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="lib.html">Categories and Libraries</a><ul>
<li class="toctree-l2"><a class="reference internal" href="lib.html#writing-libraries">Writing Libraries</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#using-libraries">Using Libraries</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#symbol-types">Symbol Types</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#symbol-execution-methods">Symbol Execution Methods</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#reference-symbols">Reference Symbols</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#distributing-and-usage">Distributing and Usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#audience-and-motivation">Audience and Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="lib.html#terminology">Terminology</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="clientparameters.html">Client Parameters</a><ul>
<li class="toctree-l2"><a class="reference internal" href="clientparameters.html#collecting-parameters">Collecting Parameters</a></li>
<li class="toctree-l2"><a class="reference internal" href="clientparameters.html#defaults">Defaults</a></li>
<li class="toctree-l2"><a class="reference internal" href="clientparameters.html#postgresql-environment-variables">PostgreSQL Environment Variables</a></li>
<li class="toctree-l2"><a class="reference internal" href="clientparameters.html#postgresql-password-file">PostgreSQL Password File</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="gotchas.html">Gotchas</a><ul>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#non-english-locales">Non-English Locales</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#thread-safety">Thread Safety</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#client-encoding-setting-should-be-altered-carefully"><cite>client_encoding</cite> setting should be altered carefully</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#the-user-and-password-is-correct-but-it-does-not-work-when-using-postgresql-driver">The user and password is correct, but it does not work when using <cite>postgresql.driver</cite></a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#backslash-characters-are-being-treated-literally">Backslash characters are being treated literally</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#types-without-binary-support-in-the-driver-are-unsupported-in-arrays-and-records">Types without binary support in the driver are unsupported in arrays and records</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#notices-warnings-and-other-messages-are-too-verbose">NOTICEs, WARNINGs, and other messages are too verbose</a></li>
<li class="toctree-l2"><a class="reference internal" href="gotchas.html#strange-typeerror-using-load-rows-or-load-chunks">Strange TypeError using load_rows() or load_chunks()</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="reference">
<h2>Reference<a class="headerlink" href="#reference" title="Permalink to this headline">¶</a></h2>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="bin.html">Commands</a><ul>
<li class="toctree-l2"><a class="reference internal" href="bin.html#postgresql-bin-pg-python">postgresql.bin.pg_python</a></li>
<li class="toctree-l2"><a class="reference internal" href="bin.html#postgresql-bin-pg-dotconf">postgresql.bin.pg_dotconf</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="reference.html">Reference</a><ul>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql"><tt class="docutils literal"><span class="pre">postgresql</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.api"><tt class="docutils literal"><span class="pre">postgresql.api</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.sys"><tt class="docutils literal"><span class="pre">postgresql.sys</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.string"><tt class="docutils literal"><span class="pre">postgresql.string</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.exceptions"><tt class="docutils literal"><span class="pre">postgresql.exceptions</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.temporal"><tt class="docutils literal"><span class="pre">postgresql.temporal</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.installation"><tt class="docutils literal"><span class="pre">postgresql.installation</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.cluster"><tt class="docutils literal"><span class="pre">postgresql.cluster</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.copyman"><tt class="docutils literal"><span class="pre">postgresql.copyman</span></tt></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-postgresql.alock"><tt class="docutils literal"><span class="pre">postgresql.alock</span></tt></a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="changes">
<h2>Changes<a class="headerlink" href="#changes" title="Permalink to this headline">¶</a></h2>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="changes-v1.1.html">Changes in v1.1</a></li>
<li class="toctree-l1"><a class="reference internal" href="changes-v1.0.html">Changes in v1.0</a></li>
</ul>
</div>
</div>
<div class="section" id="sample-code">
<h2>Sample Code<a class="headerlink" href="#sample-code" title="Permalink to this headline">¶</a></h2>
<p>Using <cite>postgresql.driver</cite>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">postgresql</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;pq://user:password@host/name_of_database&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TABLE emp (emp_name text PRIMARY KEY, emp_salary numeric)&quot;</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c"># Create the statements.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">make_emp</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;INSERT INTO emp VALUES ($1, $2)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">raise_emp</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;UPDATE emp SET emp_salary = emp_salary + $2 WHERE emp_name = $1&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">get_emp_with_salary_lt</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="s">&quot;SELECT emp_name FROM emp WHERE emp_salay &lt; $1&quot;</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c"># Create some employees, but do it in a transaction--all or nothing.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="n">make_emp</span><span class="p">(</span><span class="s">&quot;John Doe&quot;</span><span class="p">,</span> <span class="s">&quot;150,000&quot;</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">make_emp</span><span class="p">(</span><span class="s">&quot;Jane Doe&quot;</span><span class="p">,</span> <span class="s">&quot;150,000&quot;</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">make_emp</span><span class="p">(</span><span class="s">&quot;Andrew Doe&quot;</span><span class="p">,</span> <span class="s">&quot;55,000&quot;</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">make_emp</span><span class="p">(</span><span class="s">&quot;Susan Doe&quot;</span><span class="p">,</span> <span class="s">&quot;60,000&quot;</span><span class="p">)</span>
<span class="go">&gt;&gt;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c"># Give some raises</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">db</span><span class="o">.</span><span class="n">xact</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">get_emp_with_salary_lt</span><span class="p">(</span><span class="s">&quot;125,000&quot;</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">print</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s">&quot;emp_name&quot;</span><span class="p">])</span>
<span class="gp">... </span> <span class="n">raise_emp</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s">&quot;emp_name&quot;</span><span class="p">],</span> <span class="s">&quot;10,000&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Of course, if DB-API 2.0 is desired, the module is located at
<cite>postgresql.driver.dbapi20</cite>. DB-API extends PG-API, so the features
illustrated above are available on DB-API connections.</p>
<p>See <a class="reference internal" href="driver.html#db-interface"><em>Driver</em></a> for more information.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="#">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">py-postgresql</a><ul>
<li><a class="reference internal" href="#contents">Contents</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#reference">Reference</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#changes">Changes</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#sample-code">Sample Code</a></li>
</ul>
</li>
</ul>
<h4>Next topic</h4>
<p class="topless"><a href="admin.html"
title="next chapter">Administration</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/index.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="admin.html" title="Administration"
>next</a> |</li>
<li><a href="#">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Categories and Libraries &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Client Parameters" href="clientparameters.html" />
<link rel="prev" title="Cluster Management" href="cluster.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="clientparameters.html" title="Client Parameters"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="cluster.html" title="Cluster Management"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="categories-and-libraries">
<h1>Categories and Libraries<a class="headerlink" href="#categories-and-libraries" title="Permalink to this headline">¶</a></h1>
<p>This chapter discusses the usage and implementation of connection categories and
libraries.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">First-time users are encouraged to read the <a class="reference internal" href="#audience-and-motivation">Audience and Motivation</a>
section first.</p>
</div>
<p>Libraries are a collection of SQL statements that can be bound to a
connection. Libraries are <em>normally</em> bound directly to the connection object as
an attribute using a name specified by the library.</p>
<p>Libraries provide a common way for SQL statements to be managed outside of the
code that uses them. When using ILFs, this increases the portability of the SQL
by keeping the statements isolated from the Python code in an accessible format
that can be easily used by other languages or systems &#8212; An ILF parser can be
implemented within a few dozen lines using basic text tools.</p>
<p>SQL statements defined by a Library are identified by their Symbol. These
symbols are named and annotated in order to allow the user to define how a
statement is to be used. The user may state the default execution method of
the statement object, or whether the symbol is to be preloaded at bind
time&#8211;these properties are Symbol Annotations.</p>
<p>The purpose of libraries are to provide a means to manage statements on
disk and at runtime. ILFs provide a means to reference a collection
of statements on disk, and, when loaded, the symbol bindings provides means to
reference a statement already prepared for use on a given connection.</p>
<p>The <cite>postgresql.lib</cite> package-module provides fundamental classes for supporting
categories and libraries.</p>
<div class="section" id="writing-libraries">
<h2>Writing Libraries<a class="headerlink" href="#writing-libraries" title="Permalink to this headline">¶</a></h2>
<p>ILF files are the recommended way to build a library. These files use the
naming convention &#8220;lib{NAME}.sql&#8221;. The prefix and suffix are used describe the
purpose of the file and to provide a hint to editors that SQL highlighting
should be used. The format of an ILF takes the form:</p>
<div class="highlight-python"><pre>&lt;Preface&gt;
[name:type:method]
&lt;statement&gt;
...</pre>
</div>
<p>Where multiple symbols may be defined. The Preface that comes before the first
symbol is an arbitrary block of text that should be used to describe the library.
This block is free-form, and should be considered a good place for some
general documentation.</p>
<p>Symbols are named and described using the contents of section markers:
<tt class="docutils literal"><span class="pre">('['</span> <span class="pre">...</span> <span class="pre">']')</span></tt>. Section markers have three components: the symbol name,
the symbol type and the symbol method. Each of these components are separated
using a single colon, <tt class="docutils literal"><span class="pre">:</span></tt>. All components are optional except the Symbol name.
For example:</p>
<div class="highlight-python"><pre>[get_user_info]
SELECT * FROM user WHERE user_id = $1
[get_user_info_v2::]
SELECT * FROM user WHERE user_id = $1</pre>
</div>
<p>In the above example, <tt class="docutils literal"><span class="pre">get_user_info</span></tt> and <tt class="docutils literal"><span class="pre">get_user_info_v2</span></tt> are identical.
Empty components indicate the default effect.</p>
<p>The second component in the section identifier is the symbol type. All Symbol
types are listed in <a class="reference internal" href="#symbol-types">Symbol Types</a>. This can be
used to specify what the section&#8217;s contents are or when to bind the
symbol:</p>
<div class="highlight-python"><pre>[get_user_info:preload]
SELECT * FROM user WHERE user_id = $1</pre>
</div>
<p>This provides the Binding with the knowledge that the statement should be
prepared when the Library is bound. Therefore, when this Symbol&#8217;s statement
is used for the first time, it will have already been prepared.</p>
<p>Another type is the <tt class="docutils literal"><span class="pre">const</span></tt> Symbol type. This defines a data Symbol whose
<em>statement results</em> will be resolved when the Library is bound:</p>
<div class="highlight-python"><pre>[user_type_ids:const]
SELECT user_type_id, user_type FROM user_types;</pre>
</div>
<p>Constant Symbols cannot take parameters as they are data properties. The
<em>result</em> of the above query is set to the Bindings&#8217; <tt class="docutils literal"><span class="pre">user_type_ids</span></tt>
attribute:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">user_type_ids</span>
<span class="go">&lt;sequence of (user_type_id, user_type)&gt;</span>
</pre></div>
</div>
<p>Where <tt class="docutils literal"><span class="pre">lib</span></tt> in the above is a Binding of the Library containing the
<tt class="docutils literal"><span class="pre">user_type_ids</span></tt> Symbol.</p>
<p>Finally, procedures can be bound as symbols using the <tt class="docutils literal"><span class="pre">proc</span></tt> type:</p>
<div class="highlight-python"><pre>[remove_user:proc]
remove_user(bigint)</pre>
</div>
<p>All procedures symbols are loaded when the Library is bound. Procedure symbols
are special because the execution method is effectively specified by the
procedure itself.</p>
<p>The third component is the symbol <tt class="docutils literal"><span class="pre">method</span></tt>. This defines the execution method
of the statement and ultimately what is returned when the Symbol is called at
runtime. All the execution methods are listed in <a class="reference internal" href="#symbol-execution-methods">Symbol Execution Methods</a>.</p>
<p>The default execution method is the default execution method of
<cite>postgresql.api.PreparedStatement</cite> objects; return the entire result set in a
list object:</p>
<div class="highlight-python"><pre>[get_numbers]
SELECT i FROM generate_series(0, 100-1) AS g(i);</pre>
</div>
<p>When bound:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">get_numbers</span><span class="p">()</span> <span class="o">==</span> <span class="p">[(</span><span class="n">x</span><span class="p">,)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)]</span>
<span class="go">True</span>
</pre></div>
</div>
<p>The transformation of range in the above is necessary as statements
return a sequence of row objects by default.</p>
<p>For large result-sets, fetching all the rows would be taxing on a system&#8217;s
memory. The <tt class="docutils literal"><span class="pre">rows</span></tt> and <tt class="docutils literal"><span class="pre">chunks</span></tt> methods provide an iterator to rows produced
by a statement using a stream:</p>
<div class="highlight-python"><pre>[get_some_rows::rows]
SELECT i FROM generate_series(0, 1000) AS g(i);
[get_some_chunks::chunks]
SELECT i FROM generate_series(0, 1000) AS g(i);</pre>
</div>
<p><tt class="docutils literal"><span class="pre">rows</span></tt> means that the Symbol will return an iterator producing individual rows
of the result, and <tt class="docutils literal"><span class="pre">chunks</span></tt> means that the Symbol will return an iterator
producing sequences of rows of the result.</p>
<p>When bound:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">chain</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">get_some_rows</span><span class="p">())</span> <span class="o">==</span> <span class="nb">list</span><span class="p">(</span><span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">get_some_chunks</span><span class="p">()))</span>
<span class="go">True</span>
</pre></div>
</div>
<p>Other methods include <tt class="docutils literal"><span class="pre">column</span></tt> and <tt class="docutils literal"><span class="pre">first</span></tt>. The column method provides a
means to designate that the symbol should return an iterator of the values in
the first column instead of an iterator to the rows:</p>
<div class="highlight-python"><pre>[another_generate_series_example::column]
SELECT i FROM generate_series(0, $1::int) AS g(i)</pre>
</div>
<p>In use:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">another_generate_series_example</span><span class="p">(</span><span class="mi">100</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">==</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">))</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">another_generate_series_example</span><span class="p">(</span><span class="mi">10</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="go">[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">first</span></tt> method provides direct access to simple results.
Specifically, the first column of the first row when there is only one column.
When there are multiple columns the first row is returned:</p>
<div class="highlight-python"><pre>[get_one::first]
SELECT 1
[get_one_twice::first]
SELECT 1, 1</pre>
</div>
<p>In use:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">get_one</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">get_one_twice</span><span class="p">()</span> <span class="o">==</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last"><tt class="docutils literal"><span class="pre">first</span></tt> should be used with care. When the result returns no rows, <cite>None</cite>
will be returned.</p>
</div>
</div>
<div class="section" id="using-libraries">
<h2>Using Libraries<a class="headerlink" href="#using-libraries" title="Permalink to this headline">¶</a></h2>
<p>After a library is created, it must be loaded before it can be bound using
programmer interfaces. The <cite>postgresql.lib.load</cite> interface provides the
primary entry point for loading libraries.</p>
<p>When <tt class="docutils literal"><span class="pre">load</span></tt> is given a string, it identifies if a directory separator is in
the string, if there is it will treat the string as a <em>path</em> to the ILF to be
loaded. If no separator is found, it will treat the string as the library
name fragment and look for &#8220;lib{NAME}.sql&#8221; in the directories listed in
<cite>postgresql.sys.libpath</cite>.</p>
<p>Once a <cite>postgresql.lib.Library</cite> instance has been acquired, it can then be
bound to a connection for use. <cite>postgresql.lib.Binding</cite> is used to create an
object that provides and manages the Bound Symbols:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql.lib</span> <span class="kn">as</span> <span class="nn">pg_lib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">lib</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">B</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Binding</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">lib</span><span class="p">)</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">B</span></tt> object in the above example provides the Library&#8217;s Symbols as
attributes which can be called to in order to execute the Symbol&#8217;s statement:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">B</span><span class="o">.</span><span class="n">symbol</span><span class="p">(</span><span class="n">param</span><span class="p">)</span>
<span class="gp">...</span>
</pre></div>
</div>
<p>While it is sometimes necessary, manual creation of a Binding is discouraged.
Rather, <cite>postgresql.lib.Category</cite> objects should be used to manage the set of
Libraries to be bound to a connection.</p>
<div class="section" id="categories">
<h3>Categories<a class="headerlink" href="#categories" title="Permalink to this headline">¶</a></h3>
<p>Libraries provide access to a collection of symbols; Bindings provide an
interface to the symbols with respect to a subject database. When a connection
is established, multiple Bindings may need to be created in order to fulfill
the requirements of the programmer. When a Binding is created, it exists in
isolation; this can be an inconvenience when access to both the Binding and
the Connection is necessary. Categories exist to provide a formal method for
defining the interface extensions on a <cite>postgresql.api.Database</cite>
instance(connection).</p>
<p>A Category is essentially a runtime-class for connections. It provides a
formal initialization procedure for connection objects at runtime. However,
the connection resource must be connected prior to category initialization.</p>
<p>Categories are sets of Libraries to be bound to a connection with optional name
substitutions. In order to create one directly, pass the Library instances to
<cite>postgresql.lib.Category</cite>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql.lib</span> <span class="kn">as</span> <span class="nn">pg_lib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">cat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Category</span><span class="p">(</span><span class="n">lib1</span><span class="p">,</span> <span class="n">lib2</span><span class="p">,</span> <span class="n">libN</span><span class="p">)</span>
</pre></div>
</div>
<p>Where <tt class="docutils literal"><span class="pre">lib1</span></tt>, <tt class="docutils literal"><span class="pre">lib2</span></tt>, <tt class="docutils literal"><span class="pre">libN</span></tt> are <cite>postgresql.lib.Library</cite> instances;
usually created by <cite>postgresql.lib.load</cite>. Once created, categories can then
used by passing the <tt class="docutils literal"><span class="pre">category</span></tt> keyword to connection creation interfaces:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">postgresql</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">postgresql</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">category</span> <span class="o">=</span> <span class="n">cat</span><span class="p">)</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">db</span></tt> object will now have Bindings for <tt class="docutils literal"><span class="pre">lib1</span></tt>, <tt class="docutils literal"><span class="pre">lib2</span></tt>, ..., and
<tt class="docutils literal"><span class="pre">libN</span></tt>.</p>
<p>Categories can alter the access point(attribute name) of Bindings. This is done
by instantiating the Category using keyword parameters:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">cat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Category</span><span class="p">(</span><span class="n">lib1</span><span class="p">,</span> <span class="n">lib2</span><span class="p">,</span> <span class="n">libname</span> <span class="o">=</span> <span class="n">libN</span><span class="p">)</span>
</pre></div>
</div>
<p>At this point, when a connection is established as the category <tt class="docutils literal"><span class="pre">cat</span></tt>,
<tt class="docutils literal"><span class="pre">libN</span></tt> will be bound to the connection object on the attribute <tt class="docutils literal"><span class="pre">libname</span></tt>
instead of the name defined by the library.</p>
<p>And a final illustration of Category usage:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">postgresql</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">category</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Category</span><span class="p">(</span><span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">name</span>
<span class="go">&lt;Library&gt;</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="symbol-types">
<h2>Symbol Types<a class="headerlink" href="#symbol-types" title="Permalink to this headline">¶</a></h2>
<p>The symbol type determines how a symbol is going to be treated by the Binding.
For instance, <tt class="docutils literal"><span class="pre">const</span></tt> symbols are resolved when the Library is bound and
the statement object is immediately discarded. Here is a list of symbol types
that can be used in ILF libraries:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">&lt;default&gt;</span></tt> (Empty component)</dt>
<dd>The symbol&#8217;s statement will never change. This allows the Bound Symbol to
hold onto the <cite>postgresql.api.PreparedStatement</cite> object. When the symbol is
used again, it will refer to the existing prepared statement object.</dd>
<dt><tt class="docutils literal"><span class="pre">preload</span></tt></dt>
<dd>Like the default type, the Symbol is a simple statement, but it should be
loaded when the library is bound to the connection.</dd>
<dt><tt class="docutils literal"><span class="pre">const</span></tt></dt>
<dd>The statement takes no parameters and only needs to be executed once. This
will cause the statement to be executed when the library is bound and the
results of the statement will be set to the Binding using the symbol name so
that it may be used as a property by the user.</dd>
<dt><tt class="docutils literal"><span class="pre">proc</span></tt></dt>
<dd>The contents of the section is a procedure identifier. When this type is used
the symbol method <em>should not</em> be specified as the method annotation will be
automatically resolved based on the procedure&#8217;s signature.</dd>
<dt><tt class="docutils literal"><span class="pre">transient</span></tt></dt>
<dd>The Symbol is a statement that should <em>not</em> be retained. Specifically, it is
a statement object that will be discarded when the user discard the referenced
Symbol. Used in cases where the statement is used once or very infrequently.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="symbol-execution-methods">
<h2>Symbol Execution Methods<a class="headerlink" href="#symbol-execution-methods" title="Permalink to this headline">¶</a></h2>
<p>The Symbol Execution Method provides a way to specify how a statement is going
to be used. Specifically, which <cite>postgresql.api.PreparedStatement</cite> method
should be executed when a Bound Symbol is called. The following is a list of
the symbol execution methods and the effect it will have when invoked:</p>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">&lt;default&gt;</span></tt> (Empty component)</dt>
<dd>Returns the entire result set in a single list object. If the statement does
not return rows, a <tt class="docutils literal"><span class="pre">(command,</span> <span class="pre">count)</span></tt> pair will be returned.</dd>
<dt><tt class="docutils literal"><span class="pre">rows</span></tt></dt>
<dd>Returns an iterator producing each row in the result set.</dd>
<dt><tt class="docutils literal"><span class="pre">chunks</span></tt></dt>
<dd>Returns an iterator producing &#8220;chunks&#8221; of rows in the result set.</dd>
<dt><tt class="docutils literal"><span class="pre">first</span></tt></dt>
<dd>Returns the first column of the first row if there is one column in the result
set. If there are multiple columns in the result set, the first row is
returned. If query is non-RETURNING DML&#8211;insert, update, or delete, the row
count is returned.</dd>
<dt><tt class="docutils literal"><span class="pre">column</span></tt></dt>
<dd>Returns an iterator to values in the first column. (Equivalent to
executing a statement as <tt class="docutils literal"><span class="pre">map(operator.itemgetter(0),</span> <span class="pre">ps.rows())</span></tt>.)</dd>
<dt><tt class="docutils literal"><span class="pre">declare</span></tt></dt>
<dd>Returns a scrollable cursor, <cite>postgresql.api.Cursor</cite>, to the result set.</dd>
<dt><tt class="docutils literal"><span class="pre">load_chunks</span></tt></dt>
<dd>Takes an iterable row-chunks to be given to the statement. Returns <cite>None</cite>. If
the statement is a <tt class="docutils literal"><span class="pre">COPY</span> <span class="pre">...</span> <span class="pre">FROM</span> <span class="pre">STDIN</span></tt>, the iterable must produce chunks
of COPY lines.</dd>
<dt><tt class="docutils literal"><span class="pre">load_rows</span></tt></dt>
<dd>Takes an iterable rows to be given as parameters. If the statement is a <tt class="docutils literal"><span class="pre">COPY</span>
<span class="pre">...</span> <span class="pre">FROM</span> <span class="pre">STDIN</span></tt>, the iterable must produce COPY lines.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="reference-symbols">
<h2>Reference Symbols<a class="headerlink" href="#reference-symbols" title="Permalink to this headline">¶</a></h2>
<p>Reference Symbols provide a way to construct a Bound Symbol using the Symbol&#8217;s
query. When invoked, A Reference Symbol&#8217;s query is executed in order to produce
an SQL statement to be used as a Bound Symbol. In ILF files, a reference is
identified by its symbol name being prefixed with an ampersand:</p>
<div class="highlight-python"><pre>[&amp;refsym::first]
SELECT &#x27;SELECT 1::int4&#x27;::text</pre>
</div>
<p>Then executed:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="c"># Runs the &#39;refsym&#39; SQL, and creates a Bound Symbol using the results.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sym</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">refsym</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">sym</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span>
</pre></div>
</div>
<p>The Reference Symbol&#8217;s type and execution method are inherited by the created
Bound Symbol. With one exception, <tt class="docutils literal"><span class="pre">const</span></tt> reference symbols are
special in that they immediately resolved into the target Bound Symbol.</p>
<p>A Reference Symbol&#8217;s source query <em>must</em> produce rows of text columns. Multiple
columns and multiple rows may be produced by the query, but they must be
character types as the results are promptly joined together with whitespace so
that the target statement may be prepared.</p>
<p>Reference Symbols are most likely to be used in dynamic DDL and DML situations,
or, somewhat more specifically, any query whose definition depends on a
generated column list.</p>
</div>
<div class="section" id="distributing-and-usage">
<h2>Distributing and Usage<a class="headerlink" href="#distributing-and-usage" title="Permalink to this headline">¶</a></h2>
<p>For applications, distribution and management can easily be a custom
process. The application designates the library directory; the entry point
adds the path to the <cite>postgresql.sys.libpath</cite> list; a category is built; and, a
connection is made using the category.</p>
<p>For mere Python extensions, however, <tt class="docutils literal"><span class="pre">distutils</span></tt> has a feature that can
aid in ILF distribution. The <tt class="docutils literal"><span class="pre">package_data</span></tt> setup keyword can be used to
include ILF files alongside the Python modules that make up a project. See
<a class="reference external" href="http://docs.python.org/3.1/distutils/setupscript.html#installing-package-data">http://docs.python.org/3.1/distutils/setupscript.html#installing-package-data</a>
for more detailed information on the keyword parameter.</p>
<p>The recommended way to manage libraries for extending projects is to
create a package to contain them. For instance, consider the following layout:</p>
<div class="highlight-python"><pre>project/
setup.py
pkg/
__init__.py
lib/
__init__.py
libthis.sql
libthat.sql</pre>
</div>
<p>The project&#8217;s SQL libraries are organized into a single package directory,
<tt class="docutils literal"><span class="pre">lib</span></tt>, so <tt class="docutils literal"><span class="pre">package_data</span></tt> would be configured:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">package_data</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;pkg.lib&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s">&#39;*.sql&#39;</span><span class="p">]}</span>
</pre></div>
</div>
<p>Subsequently, the <tt class="docutils literal"><span class="pre">lib</span></tt> package initialization script can then be used to
load the libraries, and create any categories(<tt class="docutils literal"><span class="pre">project/pkg/lib/__init__.py</span></tt>):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os.path</span>
<span class="kn">import</span> <span class="nn">postgresql.lib</span> <span class="kn">as</span> <span class="nn">pg_lib</span>
<span class="kn">import</span> <span class="nn">postgresql.sys</span> <span class="kn">as</span> <span class="nn">pg_sys</span>
<span class="n">libdir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)</span>
<span class="n">pg_sys</span><span class="o">.</span><span class="n">libpath</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">libdir</span><span class="p">)</span>
<span class="n">libthis</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s">&#39;this&#39;</span><span class="p">)</span>
<span class="n">libthat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s">&#39;that&#39;</span><span class="p">)</span>
<span class="n">stdcat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Category</span><span class="p">(</span><span class="n">libthis</span><span class="p">,</span> <span class="n">libthat</span><span class="p">)</span>
</pre></div>
</div>
<p>However, it can be undesirable to add the package directory to the global
<cite>postgresql.sys.libpath</cite> search paths. Direct path loading can be used in those
cases:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os.path</span>
<span class="kn">import</span> <span class="nn">postgresql.lib</span> <span class="kn">as</span> <span class="nn">pg_lib</span>
<span class="n">libdir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)</span>
<span class="n">libthis</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">libdir</span><span class="p">,</span> <span class="s">&#39;libthis.sql&#39;</span><span class="p">))</span>
<span class="n">libthat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">libdir</span><span class="p">,</span> <span class="s">&#39;libthat.sql&#39;</span><span class="p">))</span>
<span class="n">stdcat</span> <span class="o">=</span> <span class="n">pg_lib</span><span class="o">.</span><span class="n">Category</span><span class="p">(</span><span class="n">libthis</span><span class="p">,</span> <span class="n">libthat</span><span class="p">)</span>
</pre></div>
</div>
<p>Using the established project context, a connection would then be created as:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">pkg.lib</span> <span class="kn">import</span> <span class="n">stdcat</span>
<span class="kn">import</span> <span class="nn">postgresql</span> <span class="kn">as</span> <span class="nn">pg</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">category</span> <span class="o">=</span> <span class="n">stdcat</span><span class="p">)</span>
<span class="c"># And execute some fictitious symbols.</span>
<span class="n">db</span><span class="o">.</span><span class="n">this</span><span class="o">.</span><span class="n">sym_from_libthis</span><span class="p">()</span>
<span class="n">db</span><span class="o">.</span><span class="n">that</span><span class="o">.</span><span class="n">sym_from_libthat</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="audience-and-motivation">
<h2>Audience and Motivation<a class="headerlink" href="#audience-and-motivation" title="Permalink to this headline">¶</a></h2>
<p>This chapter covers advanced material. It is <strong>not</strong> recommended that categories
and libraries be used for trivial applications or introductory projects.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Libraries and categories are not likely to be of interest to ORM or DB-API users.</p>
</div>
<p>With exception to ORMs or other similar abstractions, the most common pattern
for managing connections and statements is delegation:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyAppDB</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connection</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">connection</span> <span class="o">=</span> <span class="n">connection</span>
<span class="k">def</span> <span class="nf">my_operation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">op_arg1</span><span class="p">,</span> <span class="n">op_arg2</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span>
<span class="s">&quot;SELECT my_operation_proc($1,$2)&quot;</span><span class="p">,</span>
<span class="p">)(</span><span class="n">op_arg1</span><span class="p">,</span> <span class="n">op_arg2</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
<p>The straightforward nature is likeable, but the usage does not take advantage of
prepared statements. In order to do that an extra condition is necessary to see
if the statement has already been prepared:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="o">...</span>
<span class="k">def</span> <span class="nf">my_operation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">op_arg1</span><span class="p">,</span> <span class="n">op_arg2</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;_my_operation&#39;</span><span class="p">):</span>
<span class="n">ps</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_my_operation</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ps</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_my_operation</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span>
<span class="s">&quot;SELECT my_operation_proc($1, $2)&quot;</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">return</span> <span class="n">ps</span><span class="p">(</span><span class="n">op_arg1</span><span class="p">,</span> <span class="n">op_arg2</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
<p>There are many variations that can implement the above. It works and it&#8217;s
simple, but it will be exhausting if repeated and error prone if the
initialization condition is not factored out. Additionally, if access to statement
metadata is needed, the above example is still lacking as it would require
execution of the statement and further protocol expectations to be established.
This is the province of libraries: direct database interface management.</p>
<p>Categories and Libraries are used to factor out and simplify
the above functionality so re-implementation is unnecessary. For example, an
ILF library containing the symbol:</p>
<div class="highlight-python"><pre>[my_operation]
SELECT my_operation_proc($1, $2)
[&lt;other_symbol&gt;]
...</pre>
</div>
<p>Will provide the same functionality as the <tt class="docutils literal"><span class="pre">my_operation</span></tt> method in the
latter Python implementation.</p>
</div>
<div class="section" id="terminology">
<h2>Terminology<a class="headerlink" href="#terminology" title="Permalink to this headline">¶</a></h2>
<p>The following terms are used throughout this chapter:</p>
<blockquote>
<div><dl class="docutils">
<dt>Annotations</dt>
<dd>The information of about a Symbol describing what it is and how it should be
used.</dd>
<dt>Binding</dt>
<dd>An interface to the Symbols provided by a Library for use with a given
connection.</dd>
<dt>Bound Symbol</dt>
<dd>An interface to an individual Symbol ready for execution against the subject
database.</dd>
<dt>Bound Reference</dt>
<dd>An interface to an individual Reference Symbol that will produce a Bound
Symbol when executed.</dd>
<dt>ILF</dt>
<dd>INI-style Library Format. &#8220;lib{NAME}.sql&#8221; files.</dd>
<dt>Library</dt>
<dd>A collection of Symbols&#8211;mapping of names to SQL statements.</dd>
<dt>Local Symbol</dt>
<dd>A relative term used to denote a symbol that exists in the same library as
the subject symbol.</dd>
<dt>Preface</dt>
<dd>The block of text that comes before the first symbol in an ILF file.</dd>
<dt>Symbol</dt>
<dd>An named database operation provided by a Library. Usually, an SQL statement
with Annotations.</dd>
<dt>Reference Symbol</dt>
<dd>A Symbol whose SQL statement <em>produces</em> the source for a Bound Symbol.</dd>
<dt>Category</dt>
<dd>An object supporting a classification for connectors that provides database
initialization facilities for produced connections. For libraries,
<cite>postgresql.lib.Category</cite> objects are a set of Libraries,
<cite>postgresql.lib.Library</cite>.</dd>
</dl>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Categories and Libraries</a><ul>
<li><a class="reference internal" href="#writing-libraries">Writing Libraries</a></li>
<li><a class="reference internal" href="#using-libraries">Using Libraries</a><ul>
<li><a class="reference internal" href="#categories">Categories</a></li>
</ul>
</li>
<li><a class="reference internal" href="#symbol-types">Symbol Types</a></li>
<li><a class="reference internal" href="#symbol-execution-methods">Symbol Execution Methods</a></li>
<li><a class="reference internal" href="#reference-symbols">Reference Symbols</a></li>
<li><a class="reference internal" href="#distributing-and-usage">Distributing and Usage</a></li>
<li><a class="reference internal" href="#audience-and-motivation">Audience and Motivation</a></li>
<li><a class="reference internal" href="#terminology">Terminology</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="cluster.html"
title="previous chapter">Cluster Management</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="clientparameters.html"
title="next chapter">Client Parameters</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/lib.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="clientparameters.html" title="Client Parameters"
>next</a> |</li>
<li class="right" >
<a href="cluster.html" title="Cluster Management"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Notification Management &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="next" title="Advisory Locks" href="alock.html" />
<link rel="prev" title="Copy Management" href="copyman.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="alock.html" title="Advisory Locks"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="copyman.html" title="Copy Management"
accesskey="P">previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="notification-management">
<span id="notifyman"></span><h1>Notification Management<a class="headerlink" href="#notification-management" title="Permalink to this headline">¶</a></h1>
<p>Relevant SQL commands: <a class="reference external" href="http://postgresql.org/docs/current/static/sql-notify.html">NOTIFY</a>,
<a class="reference external" href="http://postgresql.org/docs/current/static/sql-listen.html">LISTEN</a>,
<a class="reference external" href="http://postgresql.org/docs/current/static/sql-unlisten.html">UNLISTEN</a>.</p>
<p>Asynchronous notifications offer a means for PostgreSQL to signal application
code. Often these notifications are used to signal cache invalidation. In 9.0
and greater, notifications may include a &#8220;payload&#8221; in which arbitrary data may
be delivered on a channel being listened to.</p>
<p>By default, received notifications will merely be appended to an internal
list on the connection object. This list will remain empty for the duration
of a connection <em>unless</em> the connection begins listening to a channel that
receives notifications.</p>
<p>The <cite>postgresql.notifyman.NotificationManager</cite> class is used to wait for
messages to come in on a set of connections, pick up the messages, and deliver
the messages to the object&#8217;s user via the <cite>collections.Iterator</cite> protocol.</p>
<div class="section" id="listening-on-a-single-connection">
<h2>Listening on a Single Connection<a class="headerlink" href="#listening-on-a-single-connection" title="Permalink to this headline">¶</a></h2>
<p>The <tt class="docutils literal"><span class="pre">db.iternotifies()</span></tt> method is a simplification of the notification manager. It
returns an iterator to the notifications received on the subject connection.
The iterator yields triples consisting of the <tt class="docutils literal"><span class="pre">channel</span></tt> being
notified, the <tt class="docutils literal"><span class="pre">payload</span></tt> sent with the notification, and the <tt class="docutils literal"><span class="pre">pid</span></tt> of the
backend that caused the notification:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="s">&#39;for_rabbits&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">notify</span><span class="p">(</span><span class="s">&#39;for_rabbits&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">db</span><span class="o">.</span><span class="n">iternotifies</span><span class="p">():</span>
<span class="gp">... </span> <span class="n">channel</span><span class="p">,</span> <span class="n">payload</span><span class="p">,</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">x</span>
<span class="gp">... </span> <span class="k">break</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">channel</span> <span class="o">==</span> <span class="s">&#39;for_rabbits&#39;</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">payload</span> <span class="o">==</span> <span class="s">&#39;&#39;</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">pid</span> <span class="o">==</span> <span class="n">db</span><span class="o">.</span><span class="n">backend_id</span>
<span class="go">True</span>
</pre></div>
</div>
<p>The iterator, by default, will continue listening forever unless the connection
is terminated&#8211;thus the immediate <tt class="docutils literal"><span class="pre">break</span></tt> statement in the above loop. In
cases where some additional activity is necessary, a timeout parameter may be
given to the <tt class="docutils literal"><span class="pre">iternotifies</span></tt> method in order to allow &#8220;idle&#8221; events to occur
at the designated frequency:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">db</span><span class="o">.</span><span class="n">iternotifies</span><span class="p">(</span><span class="mf">0.5</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">break</span>
</pre></div>
</div>
<p>The above example illustrates that idle events are represented using <cite>None</cite>
objects. Idle events are guaranteed to occur <em>approximately</em> at the
specified interval&#8211;the <tt class="docutils literal"><span class="pre">timeout</span></tt> keyword parameter. In addition to
providing a means to do other processing or polling, they also offer a safe
break point for the loop. Internally, the iterator produced by the
<tt class="docutils literal"><span class="pre">iternotifies</span></tt> method <em>is</em> a <cite>NotificationManager</cite>, which will localize the
notifications prior to emitting them via the iterator.
<em>It&#8217;s not safe to break out of the loop, unless an idle event is being handled.</em>
If the loop is broken while a regular event is being processed, some events may
remain in the iterator. In order to consume those events, the iterator <em>must</em>
be accessible.</p>
<p>The iterator will be exhausted when the connection is closed, but if the
connection is closed during the loop, any remaining notifications <em>will</em>
be emitted prior to the loop ending, so it is important to be prepared to
handle exceptions or check for a closed connection.</p>
<p>In situations where multiple connections need to be watched, direct use of the
<cite>NotificationManager</cite> is necessary.</p>
</div>
<div class="section" id="listening-on-multiple-connections">
<h2>Listening on Multiple Connections<a class="headerlink" href="#listening-on-multiple-connections" title="Permalink to this headline">¶</a></h2>
<p>The <cite>postgresql.notifyman.NotificationManager</cite> class is used to manage
<em>connections</em> that are expecting to receive notifications. Instances are
iterators that yield the connection object and notifications received on the
connection or <cite>None</cite> in the case of an idle event. The manager emits events as
a pair; the connection object that received notifications, and <em>all</em> the
notifications picked up on that connection:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">postgresql.notifyman</span> <span class="kn">import</span> <span class="n">NotificationManager</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c"># Using ``nm`` to reference the manager from here on.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nm</span> <span class="o">=</span> <span class="n">NotificationManager</span><span class="p">(</span><span class="n">db1</span><span class="p">,</span> <span class="n">db2</span><span class="p">,</span> <span class="o">...</span><span class="p">,</span> <span class="n">dbN</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nm</span><span class="o">.</span><span class="n">settimeout</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">nm</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="gp">... </span> <span class="c"># idle</span>
<span class="gp">... </span> <span class="k">break</span>
<span class="gp">...</span>
<span class="gp">... </span> <span class="n">db</span><span class="p">,</span> <span class="n">notifies</span> <span class="o">=</span> <span class="n">x</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">channel</span><span class="p">,</span> <span class="n">payload</span><span class="p">,</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">notifies</span><span class="p">:</span>
<span class="gp">... </span> <span class="o">...</span>
</pre></div>
</div>
<p>The manager will continue to wait for and emit events so long as there are
good connections available in the set; it is possible for connections to be
added and removed at any time. Although, in rare circumstances, discarded
connections may still have pending events if it not removed during an idle
event. The <tt class="docutils literal"><span class="pre">connections</span></tt> attribute on <cite>NotificationManager</cite> objects is a
set object that may be used directly in order to add and remove connections
from the manager:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">y</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">nm</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">y</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">nm</span><span class="o">.</span><span class="n">connections</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="gp">... </span> <span class="k">del</span> <span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="gp">...</span>
</pre></div>
</div>
<p>The notification manager is resilient; if a connection dies, it will discard the
connection from the set, and add it to the set of bad connections, the
<tt class="docutils literal"><span class="pre">garbage</span></tt> attribute. In these cases, the idle event <em>should</em> be leveraged to
check for these failures if that&#8217;s a concern. It is the user&#8217;s
responsibility to explicitly handle the failure cases, and remove the bad
connections from the <tt class="docutils literal"><span class="pre">garbage</span></tt> set:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">nm</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">nm</span><span class="o">.</span><span class="n">garbage</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">recovered</span> <span class="o">=</span> <span class="n">take_out_trash</span><span class="p">(</span><span class="n">nm</span><span class="o">.</span><span class="n">garbage</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">nm</span><span class="o">.</span><span class="n">connections</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">recovered</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">nm</span><span class="o">.</span><span class="n">garbage</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">db</span><span class="p">,</span> <span class="n">notifies</span> <span class="o">=</span> <span class="n">x</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">channel</span><span class="p">,</span> <span class="n">payload</span><span class="p">,</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">notifies</span><span class="p">:</span>
<span class="gp">... </span> <span class="o">...</span>
</pre></div>
</div>
<p>Explicitly removing connections from the set can also be a means to gracefully
terminate the event loop:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">nm</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">None</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">done_listening</span> <span class="ow">is</span> <span class="bp">True</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">nm</span><span class="o">.</span><span class="n">connections</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</pre></div>
</div>
<p>However, doing so inside the loop is not a requirement; it is safe to remove a
connection from the set at any point.</p>
</div>
<div class="section" id="notification-managers">
<h2>Notification Managers<a class="headerlink" href="#notification-managers" title="Permalink to this headline">¶</a></h2>
<p>The <cite>postgresql.notifyman.NotificationManager</cite> is an event loop that services
multiple connections. In cases where only one connection needs to be serviced,
the <cite>postgresql.api.Database.iternotifies</cite> method can be used to simplify the
process.</p>
<div class="section" id="notification-manager-constructors">
<h3>Notification Manager Constructors<a class="headerlink" href="#notification-manager-constructors" title="Permalink to this headline">¶</a></h3>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">NotificationManager(*connections,</span> <span class="pre">timeout</span> <span class="pre">=</span> <span class="pre">None)</span></tt></dt>
<dd>Create a NotificationManager instance that manages the notifications coming
from the given set of connections. The <tt class="docutils literal"><span class="pre">timeout</span></tt> keyword is optional and
can be configured using the <tt class="docutils literal"><span class="pre">settimeout</span></tt> method as well.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="notification-manager-interface-points">
<h3>Notification Manager Interface Points<a class="headerlink" href="#notification-manager-interface-points" title="Permalink to this headline">¶</a></h3>
<blockquote>
<div><dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">NotificationManager.__iter__()</span></tt></dt>
<dd>Returns the instance; it is an iterator.</dd>
<dt><tt class="docutils literal"><span class="pre">NotificationManager.__next__()</span></tt></dt>
<dd>Normally, yield the pair, connection and notifications list, when the next
event is received. If a timeout is configured, <cite>None</cite> may be yielded to signal
an idle event. The notifications list is a list of triples:
<tt class="docutils literal"><span class="pre">(channel,</span> <span class="pre">payload,</span> <span class="pre">pid)</span></tt>.</dd>
<dt><tt class="docutils literal"><span class="pre">NotificationManager.settimeout(timeout</span> <span class="pre">:</span> <span class="pre">int)</span></tt></dt>
<dd>Set the amount of time to wait before the manager yields an idle event.
If zero, the manager will never wait and only yield notifications that are
immediately available.
If <cite>None</cite>, the manager will never emit idle events.</dd>
<dt><tt class="docutils literal"><span class="pre">NotificationManager.gettimeout()</span> <span class="pre">-&gt;</span> <span class="pre">[int,</span> <span class="pre">None]</span></tt></dt>
<dd>Get the configured timeout; returns either <cite>None</cite>, or an <cite>int</cite>.</dd>
<dt><tt class="docutils literal"><span class="pre">NotificationManager.connections</span></tt></dt>
<dd>The set of connections that the manager is actively watching for
notifications. Connections may be added or removed from the set at any time.</dd>
<dt><tt class="docutils literal"><span class="pre">NotificationManager.garbage</span></tt></dt>
<dd>The set of connections that failed. Normally empty, but when a connection gets
an exceptional condition or explicitly raises an exception, it is removed from
the <tt class="docutils literal"><span class="pre">connections</span></tt> set, and placed in <tt class="docutils literal"><span class="pre">garbage</span></tt>.</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="zero-timeout">
<h3>Zero Timeout<a class="headerlink" href="#zero-timeout" title="Permalink to this headline">¶</a></h3>
<p>When a timeout of zero, <tt class="docutils literal"><span class="pre">0</span></tt>, is configured, the notification manager will
terminate early. Specifically, each connection will be polled for any pending
notifications, and once all of the collected notifications have been emitted
by the iterator, <cite>StopIteration</cite> will be raised. Notably, <em>no</em> idle events will
occur when the timeout is configured to zero.</p>
<p>Zero timeouts offer a means for the notification &#8220;queue&#8221; to be polled. Often,
this is the appropriate way to collect pending notifications on active
connections where using the connection exclusively for waiting is not
practical:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">notifies</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">iternotifies</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
</pre></div>
</div>
<p>Or with a NotificationManager instance:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">nm</span><span class="o">.</span><span class="n">settimeout</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db_notifies</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">nm</span><span class="p">)</span>
</pre></div>
</div>
<p>In both cases of zero timeout, the iterator may be promptly discarded without
losing any events.</p>
</div>
<div class="section" id="summary-of-characteristics">
<h3>Summary of Characteristics<a class="headerlink" href="#summary-of-characteristics" title="Permalink to this headline">¶</a></h3>
<blockquote>
<div><ul class="simple">
<li>The iterator will continue until the connections die.</li>
<li>Objects yielded by the iterator are either <cite>None</cite>, an &#8220;idle event&#8221;, or an
individual notification triple if using <tt class="docutils literal"><span class="pre">db.iternotifies()</span></tt>, or a
<tt class="docutils literal"><span class="pre">(db,</span> <span class="pre">notifies)</span></tt> pair if using the base <cite>NotificationManager</cite>.</li>
<li>When a connection dies or raises an exception, it will be removed from
the <tt class="docutils literal"><span class="pre">nm.connections</span></tt> set and added to the <tt class="docutils literal"><span class="pre">nm.garbage</span></tt> set.</li>
<li>The NotificationManager instance will <em>not</em> hold any notifications
during an idle event. Idle events offer a break point in which the manager
may be discarded.</li>
<li>A timeout of zero will cause the iterator to only yield the events
that are pending right now, and promptly end. However, the same manager
object may be used again.</li>
<li>A notification triple is a tuple consisting of <tt class="docutils literal"><span class="pre">(channel,</span> <span class="pre">payload,</span> <span class="pre">pid)</span></tt>.</li>
<li>Connections may be added and removed from the <tt class="docutils literal"><span class="pre">nm.connections</span></tt> set at
any time.</li>
</ul>
</div></blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Notification Management</a><ul>
<li><a class="reference internal" href="#listening-on-a-single-connection">Listening on a Single Connection</a></li>
<li><a class="reference internal" href="#listening-on-multiple-connections">Listening on Multiple Connections</a></li>
<li><a class="reference internal" href="#notification-managers">Notification Managers</a><ul>
<li><a class="reference internal" href="#notification-manager-constructors">Notification Manager Constructors</a></li>
<li><a class="reference internal" href="#notification-manager-interface-points">Notification Manager Interface Points</a></li>
<li><a class="reference internal" href="#zero-timeout">Zero Timeout</a></li>
<li><a class="reference internal" href="#summary-of-characteristics">Summary of Characteristics</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="copyman.html"
title="previous chapter">Copy Management</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="alock.html"
title="next chapter">Advisory Locks</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/notifyman.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="alock.html" title="Advisory Locks"
>next</a> |</li>
<li class="right" >
<a href="copyman.html" title="Copy Management"
>previous</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>

Sorry, the diff of this file is not supported yet

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Python Module Index &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="#" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Python Module Index</h1>
<div class="modindex-jumpbox">
<a href="#cap-p"><strong>p</strong></a>
</div>
<table class="indextable modindextable" cellspacing="0" cellpadding="2">
<tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
<tr class="cap" id="cap-p"><td></td><td>
<strong>p</strong></td><td></td></tr>
<tr>
<td><img src="_static/minus.png" class="toggler"
id="toggle-1" style="display: none" alt="-" /></td>
<td>
<a href="reference.html#module-postgresql"><tt class="xref">postgresql</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.alock"><tt class="xref">postgresql.alock</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.api"><tt class="xref">postgresql.api</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.cluster"><tt class="xref">postgresql.cluster</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.copyman"><tt class="xref">postgresql.copyman</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.exceptions"><tt class="xref">postgresql.exceptions</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.installation"><tt class="xref">postgresql.installation</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.string"><tt class="xref">postgresql.string</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.sys"><tt class="xref">postgresql.sys</tt></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="reference.html#module-postgresql.temporal"><tt class="xref">postgresql.temporal</tt></a></td><td>
<em></em></td></tr>
</table>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="#" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>

Sorry, the diff of this file is too big to display

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search &mdash; py-postgresql 1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/searchtools.js"></script>
<link rel="top" title="py-postgresql 1.1.0 documentation" href="index.html" />
<script type="text/javascript">
jQuery(function() { Search.loadIndex("searchindex.js"); });
</script>
<link rel="stylesheet" href="_static/unsuck.css" type="text/css" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="search-documentation">Search</h1>
<div id="fallback" class="admonition warning">
<script type="text/javascript">$('#fallback').hide();</script>
<p>
Please activate JavaScript to enable the search
functionality.
</p>
</div>
<p>
From here you can search these documents. Enter your search
words into the box below and click "search". Note that the search
function will automatically search for all of the words. Pages
containing fewer words won't appear in the result list.
</p>
<form action="" method="get">
<input type="text" name="q" value="" />
<input type="submit" value="search" />
<span id="search-progress" style="padding-left: 10px"></span>
</form>
<div id="search-results">
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">py-postgresql 1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright Python+Postgres.
Last updated on Oct 08, 2012.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
Search.setIndex({filenames:["copyman","alock","bin","notifyman","clientparameters","cluster","reference","driver","index","lib","gotchas","changes-v1.0","changes-v1.1","admin"],titles:["Copy Management","Advisory Locks","Commands","Notification Management","Client Parameters","Cluster Management","Reference","Driver","py-postgresql","Categories and Libraries","Gotchas","Changes in v1.0","Changes in v1.1","Administration"],terms:{"25p02":[7,6],"25p01":6,prior:[9,3,7],cidr:12,gigabyt:0,begin:[7,3,6],cluster_dirnam:6,datamodificationprohibitederror:6,enable_debug:5,deprecationwarn:6,mandir:5,addit:[7,3,4,6],featur:[9,1,8,6,7,5,10],jwp:[11,4,12,2],sensit:6,amount:[0,3,7],diskfullerror:6,"2201x":6,fact:7,timedelta:7,directori:[9,5,4,6,13],binari:[7,8,11,6,10],pass:[9,10,6,7],pg_restor:5,lowerbound:11,datatyp:7,pg_directori:5,operationerror:6,escapesequenceerror:6,backend_id:[7,3,6],prefac:9,lib:[9,5,11],server_encod:[7,10],howev:[0,1,9,3,4,7,5,10,13],t62000:7,benefit:0,what:[9,6,7],replac:[5,6],direct:[0,9,3,6,7,2,11],abil:[7,5,6],gener:[0,9,6,7,11,10],pg_config_dictionari:[5,6],kerberos4_realm:4,numericoid:7,valu:[9,8,2,4,6,7,5,11,10],non:[9,4,8,6,5,10],setof:7,augment:[4,2],now:[9,3,12],clusterwarn:6,sql_column_typ:[7,6],numericrangeerror:6,nomoresetsreturn:6,instruct:[7,4,6],path:[9,2,4,6,7,5,13],latter:[9,7],requir:[0,9,3,6,7,5,2,12,10],reindexdb:5,"final":[7,0,6,9],optpars:4,edit:2,around:[7,12],composit:[7,11,10],recogn:[7,10],sql:[7,9,3,6,2],could:1,dictionari:[0,5,4,6,7],befor:[9,5,3,4,7],zerodivisionerror:6,atabl:7,john:[7,8],necessari:[0,9,3,4,6,7,5,12,10],probabl:10,verbos:[7,8,11,10],current:[5,7,1,4,6],employee_salari:7,allow:[9,1,2,3,4,6,7,5,11,10],rule:[7,6],rolespecificationerror:6,compound:7,shut:5,different_channel:7,each:[0,1,9,3,6,7,5],createlang:5,rel:[9,6,7],server:[7,5,10,6,2],db_notifi:3,explicit:[7,1,4,10],forev:3,layout:[9,5],libthi:9,serial:7,between:[7,5,6],desir:[2,8,6,7,5,11,10],pgsslkei:4,with_libedit_pref:5,multipl:[9,1,8,2,3,6,7,5,11],tzinfo:7,implement:[0,9,6,7,11,12,10],pgsql:[5,6],"0l000":6,need:[0,1,9,3,4,6,7,5,10,13],indexerror:7,simpl:[9,2,4,6,7,12,13],random:7,author:[11,4],suffix:9,payload:[7,3,6],nullvaluenotallow:6,escapecharactererror:6,suffic:4,given:[0,1,2,3,4,6,9,7,5,11,10],ct_that:7,timestamp:[7,11],batch:7,assum:[0,6,7],alreadi:[9,5,6,7],val:[0,1,6,2],dst:[7,6],"case":[0,1,9,3,4,6,7,5,11,10],due:[7,4,10],negat:6,liter:[7,8,4,6,10],readi:[7,0,5,6,9],clusterstartuperror:[5,6],invert:7,applic:[9,1,3,4,6,7],style:9,correl:6,increas:[9,11],dynamicresultsetsreturnedwarn:6,appdata:4,qstr:6,t1968:7,leverag:[7,3],extract:[7,5,4,13],connect:[0,1,8,2,3,4,6,9,7,5,11,12,10],echo:2,abl:7,point:[0,1,9,3,4,6,7,5,13],sequenc:[9,1,6,7,5,10],trivial:[9,4],monetari:6,enable_integer_datetim:5,pgsysconfdir:4,underscor:5,pattern:9,clusternotrunningerror:[5,6],root:[7,4,13],server_set:7,caus:[0,1,9,3,4,6,7,5,11,10],pid:[7,5,3,6],onto:9,collect:[0,8,9,3,4,6,7,5],place:[9,3,4,6,7],unnecessari:[9,7],sharelock:1,maximum:5,oppos:[7,6],other:[9,1,3,4,6,7,8,10,13],microsoft:5,schemaanddatastatementserror:6,recov:[0,3,6],offset:6,normal:[0,9,3,4,6,7,5,13],argument:[7,5,4,6,2],creat:[0,1,8,9,3,6,7,5,11,10],connector:[9,10,6,7],pronam:6,pgkrbsrvname:4,primari:[9,8,4,6,7],loop:[0,3,6,2],configure_opt:5,wrapper:6,reverse_c:7,conveni:[7,11,6],parameter_typ:[7,6],pgdatestyl:4,num_messag:0,descriptor:[7,6],call:[0,9,4,6,7,5],seper:6,producer_fault:[0,6],convent:9,presum:7,look:[9,5,10,6,7],unabl:[6,10],want:4,dimens:7,"0x10d27d830":6,trust:[7,6],hstore:[7,11],index_from_kei:7,immutableruntimeparametererror:6,chapter:[9,13,7,2],duplicatecolumnerror:6,defaultpars:4,api:[0,9,3,6,7,8,2,11],sqlexec:2,cach:[7,5,3],msec:2,join:[9,6],content:[9,5,8,4,6],proc:[7,9,6,2],reconcil:[0,6],side:10,contrast:[7,6],"function":[0,1,9,4,6,7,5,12,10],pg90:5,facilit:[7,6],prompt_password:4,hostnam:[7,4],get_user_info:9,remov:[0,3,4,6,5,11,12],remot:[7,6],script:[9,2,4,5,11,13],publish:[7,6],appropri:[1,3,6,7,5,10],protocol:[9,1,2,3,6,7,11,10],destin:0,hook:[7,6],copyin:7,pg_dotconf:[8,11,2],undefinedparametererror:6,seen:[7,2],form:[0,9,2,4,6,7],unset:7,catalognameerror:6,expect:[9,3,4,6,7,10],channel:[7,3,6],die:3,did:[6,12],python_context:2,hello:7,table1_oid:1,rather:[7,0,5,6,9],cat:[9,2],"2202e":6,exclus:[7,1,3],reconcili:0,debug:[7,5],can:[0,1,9,3,4,6,7,5,11,10],foreignkeycreationerror:6,www:[4,6],exampl:[9,1,3,7,2],"while":[0,9,3,6,7,5,12],ipv4:7,ipv6:7,through:[7,6],producerfault:[0,6],end:[7,3,6],dramat:10,internal_queri:6,less:7,clientparamet:4,union:7,preload:9,xx9301423:7,table_nam:7,unterminatedcstringerror:6,obtain:6,johnson:7,collat:6,pgpassfil:[7,4],give:[7,5,8,6],fine:[7,5],auser:7,pg_controldata:5,instanc:[0,1,9,3,4,6,7,5,10],stringdatalengtherror:6,other_symbol:9,thread:[1,6,7,8,11,10],pgrealm:4,upon:[5,2],differ:[7,4,6],number:[0,1,2,6,7,10],ampersand:9,jane:8,main:7,machin:6,colon:9,releas:[7,1,11,6],yesterdai:7,regprocedur:6,formatt:6,origin:[0,11,6,7],although:3,resolut:[7,4],where:[0,1,8,9,3,6,7,5],strip:7,thrown:6,trap:[0,6,7],python_main:2,better:7,"class":[0,1,9,3,6,7,5,11],total:7,cursor:[9,6,7,8,11,10],practic:3,listen_address:[5,6],transform:[9,10,6,7],connectiondoesnotexisterror:[7,6],lifetim:7,ambiguousaliaserror:6,absolut:[7,5,6],measur:7,transact:[7,8,6,2],irerror:6,unknown_failur:0,sever:[7,6,10],databasedefinitionerror:6,integrityconstraintviolationerror:6,internal_posit:6,emps_by_ag:7,typeconversionwarn:6,another_set:2,lock:[8,1,11,6,12],lost:7,transmiss:[7,2],inappropri:7,writabl:5,extern:6,inclin:7,restricterror:6,max_connect:5,lose:3,header:6,repeat:[9,5,7],parametererror:[7,6],"__enter__":[0,1,7],recycl:6,work:[9,6,7,8,13,10],appendix:6,pg_tmp:6,outsid:[9,7],get:[7,5,3,6],wait_until_start:[5,6],certain:7,infrastructur:7,varchar:[7,6],dropus:5,implicitli:7,name_of_databas:8,potenti:[7,6,10],"default":[9,1,8,3,4,6,7,5,10,11,13],sc_number:7,codec:10,pend:[3,6],suppos:7,realign:0,add:[0,9,3,6,7,11,12],restor:[7,6],strang:[8,10],transfer:[0,10,6,7],gettimeout:3,forego:7,setting_name_to_com:2,right:3,append:[9,3,7,2],authent:[7,6],retain:[9,5],respect:[9,5,6],summari:3,safeti:[8,10],parsed_opt:4,loading_t:0,column:[9,10,12,6,7],sym_from_libthat:9,phase:[12,10],carefulli:[7,8,10],portabl:9,borrow:7,built:[9,5,6,2],invalidsavepointspecificationerror:6,scan:6,stringrighttruncationerror:6,find:6,clustererror:6,redirect:[5,2],format:[9,10,6,7],appear:[6,12],build:[9,5,4,13],transmit:0,qrow:7,column2:6,load:[9,10,6,7],column1:6,special:[9,11,6],were:[0,1,6,7,5,10],receiver_fault:[0,6],english:[8,10],typo:11,scrollabl:[9,7],type:[9,1,6,7,8,11,12,10],environ:[2,4,8,6,7,5,13],floatingpointerror:6,"__class__":5,ilf:9,ddl:9,keyerror:[7,6],parameter:[7,5],filepath:2,tool:[9,5,6],sql_statement_str:7,utf:[5,10],toe:6,attribut:[0,9,3,6,7,5,11,10],escape_liter:6,variat:9,conform:7,too:[0,8,10],"3b001":6,"3b000":6,bound:[9,6,7],"long":[7,5,3],doe:[0,9,8,6,7,5,12,10],aspect:13,core:8,connectionfailureerror:6,statementcompletionunknownerror:6,succ:6,update_r:0,onc:[9,5,3,6,7],asc:7,dou:11,portion:[7,6],listen:[7,8,3,6],updat:[9,8,3,4,6,7,5],intend:[0,11,6],somewhat:9,extens:[9,5,7],get_pid_from_fil:6,triggereddatachangeviol:6,grace:5,asynchron:[7,3],internalerror:6,"__contains__":7,checkerror:6,bpcharoid:7,construct:[7,0,5,6,9],area:6,extend:[9,5,8,6,7],oblig:7,own:11,modifyingsqldatanotpermittederror:6,aren:7,charact:[9,8,10,6,7],escape_id:6,command:[9,8,2,3,4,6,7,5,11],than:[7,5,4],filter:[7,10],init:[5,6],notabl:[7,5,3,4,6],definit:[9,7],default_pg_sysconfdir:4,quantiti:[7,6],hint:[7,9,10,6,2],come:[0,9,3,4,6,7,10],http:[9,4,6],sioerror:6,parent:5,reload:[5,6],privileg:6,opt:13,had:[7,10],languag:[9,6,7],queri:[9,6,7,8,11,12,10],rformat:11,don:[7,4,6,11],synchron:1,via:[10,0,3,6,7],doc:[9,4,6],recvsiz:11,sym:9,entir:[0,9,4,7,5,10],anyth:7,organ:9,refer:[0,9,3,6,7,8,11],signifi:6,dpdseobjecterror:6,pg_data:5,represent:[7,11,12],cio:6,bracket:7,pguser:[7,4],seri:6,descript:[7,4],user_type_id:9,ldap:7,data_directori:[5,6],command_option_map:6,declar:[9,6,7],illustr:[9,8,3,7],python3:[13,11,2],timetzoid:7,ipaddr:12,index:[7,6],infin:11,undefinedobjecterror:6,invalidsqlst:6,pg_config_path:6,correct:[0,8,10,11,7],org:[9,4,6],inet:12,hold:[9,5,3,7],proc_id:6,geqo:4,absenc:7,done:[9,10,7],pqv3:6,much:[1,10],"58p02":6,"58p01":6,statementnameerror:6,mind:7,cardinalityerror:6,unpack:[7,10,11,6,12],awai:6,timezon:[7,4],"0100c":6,purposefulli:[7,4],discourag:[9,7],xml:7,foreignkeyerror:6,interv:[7,3,6],even:[7,5,6],rowset:7,auto:7,asterisk:4,xmldocumenterror:6,unsupport:[8,6,10],featureerror:6,entri:[9,13,4,6,7],overhead:7,unknown:7,reappli:6,sourc:[7,0,4,6,9],locatorerror:6,"abstract":[9,1,10,7],wrap_socket:7,either:[0,3,6,7],"08p01":6,some:[9,1,3,4,7,8,12,10],convers:[7,6],proper:[10,6,12],thei:[9,1,3,4,6,7,5,11],substringerror:6,have:[9,1,3,4,6,7,5,11],iteratorproduc:0,alloc:[0,5],without:[10,7,8,3,2],text_search_config:6,indeterminatetypeerror:6,inherit:[9,4,6,11,7],popen:5,session:[1,6],undesir:[9,4,7],cursornameerror:6,consid:[9,10,6,7],manipul:[7,5],recursionerror:6,noactivetransactionforbrancherror:6,achiev:7,celementtre:7,getpass:[7,4],crashshutdownerror:6,pgport:4,interrupt:[7,11],correspond:[7,6],clear:3,interfac:[0,1,8,9,3,4,6,7,5,11,12,10],usenam:7,encod:[7,5,6,10],format_el:6,split_qnam:6,caller:7,notificationmanag:[3,11],consist:[0,3,4,6,7,5,10],pq_trace:2,enough:[7,10],ctest:7,data:[0,9,3,6,7,5,10],alia:1,save:7,few:[9,5,10,7],minor:[5,6],axel:11,should:[0,8,9,3,4,6,7,5,10,13],pgpass:[7,4],loaderror:[11,6],ultim:[0,5,10,7,9],pranskevichu:11,detail:[9,4,6,7],enter:7,characterist:[7,3],etc:[7,5,4,6,11],integ:[7,6],inform:[0,8,9,4,6,7,5,11,10],transpar:7,factor:[7,0,6,9],all:[9,1,8,2,3,4,6,7,5,10],design:[9,3,6,7],year:7,down:5,immedi:[0,5,3,6,9],advisori:[8,1,11,6],action:[7,6,10],ready_for_connect:[5,6],secur:[7,6],back:[7,10,11,6,2],indic:[9,1,4,6,7,5],indicatorparametervalueerror:6,savepoint:[7,11,6],target:[0,9,2,7,11,10],trace:[7,11,2],reflect:7,"2d000":6,line:[0,9,2,4,6,7],deal:[7,4,6],superus:5,kind:7,reconnect:6,pkglibdir:5,control:[0,5,6,7],channel_and_payload:[7,6],access:[0,1,9,3,6,7,5,11],emp:[7,8],destruct:5,reset_msghook:6,indicatoroverflowerror:6,product:2,modifi:[7,5,12,2],pg_driver:7,enable_cassert:5,print:[7,8,6],triggeredactionerror:6,determin:[9,5,7],primit:1,get_on:9,except:[0,9,3,6,7,8,11,10],would:[9,10,6,7],count:[9,1,11,7],tracer:11,respons:[3,6],timestamptz:[7,11],pgpassword:4,alter:[9,8,6,7,5,11,10],employee_hire_d:7,statementproduc:0,zerolengthstr:6,bug:11,tend:4,payload_data:7,ssl:[7,5,6,2],free:[9,7],chardata:7,"__exit__":[0,1,7],schema:6,channel1:7,section:[9,10,6,7],"42p01":6,substitut:9,panic:[7,10],warning_contain:6,beyond:[0,5],plan:6,"55p02":6,"55p03":6,xmlcontenterror:6,modul:[0,8,9,2,4,6,7,5,11,12],droplang:5,the_real_sekrat:7,likewis:7,col1:7,limit:[7,6],pgtz:4,credenti:[7,6],configur:[9,2,3,6,7,5,13],deleg:9,upperbound:11,driver_set:7,password:[2,4,8,6,7,5,10],step:[0,7],onipserror:6,pair:[9,1,3,6,7,5],jack:7,timestampoid:7,option:[9,2,3,4,6,7,5],suffoc:7,squar:7,text:[9,8,10,6,7],icverror:6,objectdefinitionerror:6,leak:5,goe:[0,5,7],setup:[9,11,13],well:[2,3,6,7,5,12,10],support:[9,1,8,6,7,5,11,12,10],situat:[10,0,3,7,9],iternotifi:[7,3,6],lead:[7,5],great:7,connectionerror:6,condit:[0,3,6,9],specifictypemismatch:6,notif:[7,8,3,6],remain:[7,3],critic:7,program:[6,2],notic:[7,8,11,6,10],another_generate_series_exampl:9,length:7,rlock:[1,6],textoid:7,itself:[9,5,6,7],choos:[1,10],error_contain:6,natur:[0,10,7,9],handl:[0,3,11,6,7],generate_seri:[7,0,6,9],"2b000":6,sslmode:[7,4,2],lookup:4,conjunct:7,devel:5,msg:[7,6],never:[10,9,3,6,7],larg:[9,7],cast:[7,10],pkg:9,pg_src_user:4,element:[7,11,6,10],bandwidth:7,vacuumdb:5,specifi:[9,2,3,4,6,7,5],equal:6,insufficientprivilegeerror:6,powerfunctionargumenterror:6,float8oid:7,object:[0,1,2,3,4,6,9,7,5,10],tabl:[0,1,4,6,7,8],sqlnotyetcompleteerror:6,arguabl:6,exit:[7,0,5,6,2],ipcclean:5,advanc:[9,6,7],chain:9,pg_column_typ:[7,6],from_end:[7,6],getset:[7,5,6],textrepresentationerror:6,my_operation_proc:9,usr:[5,13],just:[7,6,13],categori:[9,8,6,7],isinst:0,fundament:9,string:[9,8,2,4,6,7,5,11,10],dateoid:7,arrai:[7,8,11,10],googl:12,transactioninitiationerror:6,trimerror:6,myappdb:9,effect:[9,4,6,7,5,13],pgdata:[5,4],perform:[0,1,11,6,7],copi:[0,9,6,7,8,11],regularli:[0,7],output:[7,5,6,2],variou:[7,4,6],wrong:[6,10],durat:[3,6],receive_stmt:0,constructor:[7,1,3,6],take_out_trash:3,resourcewarn:11,fastest:7,typio:[11,10],errorlookup:6,insert:[9,8,7],friendli:7,date:[7,11],postmast:[5,6],decor:6,occur:[0,3,4,6,7],also:[0,2,3,4,6,7,5,10],my_oper:9,bind:[9,11,7],librari:[9,6,8,11,12,10],daemon:[5,6],wait_until_stop:[5,6],localedir:5,default_host:4,debra:7,motiv:[9,8],simplif:3,pq_iri:2,pg_config:[5,6,13],pg_cluster:5,duplicatedatabaseerror:6,obviou:6,solitari:7,preliminari:12,approxim:3,straightforward:9,provid:[0,1,8,2,3,4,6,9,7,5,11,10],materi:9,succe:7,avail:[0,1,8,2,3,6,7,5],fulli:6,variant:[5,4],msghook:[7,6],revoc:7,no_default:4,base:[9,3,4,6,7,5],overridden:10,pg_stat_act:[7,6],happen:[6,10],sql_parameter_typ:[7,6],prefix:[9,5,4],unless:[7,3,6],result:[9,5,4,6,7],compens:[0,11],sens:10,standard:[7,5,10,4,2],"42p10":6,guarante:[7,3,6],from:[0,1,8,2,3,4,6,9,7,5,11,10],inspir:2,sent:[7,5,3,6,10],trerror:6,copyout:7,load_chunk:[9,8,10,7],usernam:[7,4,2],dpdseerror:6,els:[0,9],column_typ:[7,6],"return":[0,1,2,3,4,6,9,7,5,11],world:7,assignmenterror:6,ambiguousparametererror:6,finish:0,"0lp01":6,individu:[9,3,6,7],alock:[8,1,11,6],global:9,bin:[2,4,8,5,11,13],precis:0,subclass:[1,6],subject:[0,9,3,4,6,7,10],feedback:11,contrib_hstor:7,information_schema:7,foobar:6,runtimeerror:1,"import":[0,1,8,2,3,4,6,9,7,5],windowerror:6,editor:9,"0x10df38e90":6,concern:3,schemanameerror:6,excess:7,temp:[0,7],otherwis:[7,6],usabl:7,overrid:[7,10,4,6,11],vlad:11,apply_tax:7,src:[7,5,6],"57p02":6,"57p03":6,limitvalueerror:6,"57p01":6,client_encod:[8,4,10],split:6,creator:[6,2],littl:0,notxmlerror:6,search_path:[7,4],guc:[7,10],"__iter__":[0,3],particular:[7,6,13],xmlcommenterror:6,equival:[9,6,7],activetransactionerror:6,extra:[9,7],map_errors_and_warn:6,nonstandarduseofescapecharactererror:6,make:[0,9,2,6,7,5,10],contraint:6,dash:5,messag:[0,2,3,6,7,8,11,10],lot:7,low:6,"39p02":6,"char":7,"39p01":6,strongli:7,isconsist:6,pg_parameter_typ:[7,6],barbara:7,page:7,splitted_it:6,pio:6,ignoredclientparameterwarn:6,held:[1,6],int2oid:7,model:7,thereof:6,network:12,first:[9,1,2,4,6,7,11],time:[9,1,2,3,6,7,5,12],fix:[11,12,10],help:[6,2],pginstal:[4,6,13],shorthand:7,stabil:6,exact:6,rare:[0,3],datestyl:4,hopefulli:10,whenc:[7,6],cover:[9,13],marker:9,statment:6,emp_nam:[8,6],stringdatarighttruncationwarn:6,yet:10,move:[0,7],employe:[7,8],columnreferenceerror:6,written:7,demand:7,care:[9,7],highlight:[9,10],absolu:5,interfer:1,confus:[7,10],str:[7,5,10,6,12],format_messag:6,impli:7,itserror:6,interest:[9,7],pq3:7,delet:9,lastli:1,exist:[0,1,9,6,7,5,12],bodi:[7,6],activ:[7,3],act:[7,2],ideal:[7,10],regardless:[7,1,4],unavail:[7,6],sampl:[7,8],invalid:[7,3,6,2],fill:7,faux:5,send:[7,5,10],fault:[0,8,6],reintroduc:0,file:[9,8,2,4,6,7,5,11,13],emit:[0,3,6,7,11,10],inconveni:9,facil:[9,7],traceback:7,plpgsqlraiseerror:6,implicit:7,denot:9,keyword:[9,3,4,6,7,5],"0f000":6,numer:[7,8,6],latest:7,with_func:6,block:[0,1,9,6,7,5],sysconfdir:[5,4],primarili:[0,5,4,6,7],tax:9,"2f002":6,"__call__":[7,10],default_msghook:6,original_except:0,tag:11,databas:[9,1,8,2,3,4,6,7,5,10],quote_ident_if_need:6,url:7,util:4,thi:[0,1,2,3,4,6,9,7,5,10,13],sslcrtfile:[7,4],appar:7,disconnect:[5,6],"boolean":1,standard_conforming_str:7,prerequisit:6,tupl:[0,3,6,7,5,11,10],relev:3,simpli:[7,4,6],libnam:9,old:7,doubl:7,withcheckoptionerror:6,gracefulli:[3,6],whether:[5,9,1,6,7],thu:3,lack:9,locatorspecificationerror:6,templat:7,"2f004":6,"2f005":6,objectinuseerror:6,"2f003":6,"2f000":6,"public":[7,4],processor:10,createdb:5,mcguffer:7,greater:[7,3],untrap:[0,6],paramet:[9,8,2,3,4,6,7,5,10],unlik:[0,7],memori:[9,5,7],postgersql:7,"0a000":6,sql_statements_str:7,bindir:5,most:[9,10,4,6,7],annot:9,esablish:6,cursordefinitionerror:6,duplicatefileerror:6,wrap:[7,6],nullproduc:6,pg_resetxlog:5,raise_emp:8,"const":9,tcp:6,cost:[0,7],buffer:[7,6],pg_sy:9,functool:7,outcom:7,orm:9,destroi:[7,6],emp_salari:8,noactivetransactionerror:6,read:[9,2,6,7,5,10],ttree:7,faulted_receiv:0,typeerror:[8,10],explicitli:[7,3,6],real:6,must:[0,1,2,3,4,6,9,7,5,12],delai:[5,6],acquisit:[1,6],envkei:6,dynam:9,sc_text:7,rintavarustu:11,behind:6,datetimefieldoverflowerror:6,crl:4,specfici:7,copyfail:[0,6],statement_from_id:[7,6],crt:4,aquir:1,srfcomposit:7,system:[9,5,4,6],sslkeyfil:[7,4],nativ:12,obj:6,compon:[9,6,7],"2bp01":6,simplifi:[9,3,11,7],my_queri:7,titl:4,why:6,provinc:9,cluster:[8,5,11,6,2],hous:6,environ_prefix:4,platform:4,andrew:8,wai:[0,9,3,6,7,5,2,12,10],creation:[9,4,7],offsetvalueerror:6,programm:[9,5,11,6,10],send_stmt:0,errcod:6,pg_lib:9,properli:[7,10,4,11],under:[7,5],third:9,default_port:4,transaction_isol:7,for_rabbit:3,channel_nam:7,duplicateschemaerror:6,pkgincludedir:5,pg_servic:4,pg_execut:5,logargumenterror:6,sleep:5,initi:[0,9,6,7,5,10],request:[7,4,6,10],distinct:[7,6],safe:[0,1,3,6,7,5,10],notifyman:3,deadlockerror:6,undefinedfunctionerror:6,them:[0,9,3,4,6,7,11],fileno:7,libpq:[7,4],sharedir:5,libpath:[9,6],infrequ:9,timestamptzoid:7,pg_catalog:6,"0x10dc0d290":6,resolv:[9,4],receiv:[0,2,3,4,6,7,8,11],ip4:7,still:[9,3,11,6],pgclientencod:4,client:[2,4,8,6,7,5,10],wherea:[7,11,6],libthat:9,ip6:7,context:[0,1,9,2,6,7],continu:[0,5,3],nullvaluenotallowederror:6,earli:[3,10],start:[0,5,6,7],col0:7,consol:2,imped:11,exactli:7,how:[9,1,11,7],"__setitem__":6,plpgsqltoomanyrowserror:6,soon:6,warn:[1,2,4,6,7,8,11,10],recent:7,postgr:[7,5,4,6],view:[7,6],associ:[5,0,1,6,7],issu:[7,6,10],"null":11,pool:6,pgdatabas:4,protocolreceiv:6,libdir:[9,5],srf:[7,6],item:[7,5,6,10],larger:7,xmloid:7,iter:[7,0,3,6,9],statement:[0,9,3,6,7,8,2,11,12,10],tio:6,load_row:[9,8,10,7],defin:[9,1,11,6,7],onli:[0,1,9,3,4,6,7,5,10],insecurityerror:6,describ:[0,1,7,9],usag:[0,9,2,6,7,8,11],cursorstateerror:6,out:[9,3,6,7],pg_python:[11,8,4,2],compliant:10,intervaloid:7,ctype:6,formal:9,clusterinitializationerror:[5,6],depend:[9,4,6,7],alongsid:[9,1],classif:[9,6],reduc:10,contain:[9,5,13,6,7],indexcorruptederror:6,anonym:12,a_statement_id:7,interven:7,servernotreadyerror:6,execut:[0,1,8,2,4,6,9,7,5,10,11,12,13],client_address:[7,6],column_nam:[7,6],syntaxerror:[7,6],pgconnect_timeout:4,select:[0,1,9,2,6,7,8],tempor:[8,11,6],client_min_messag:[7,11,10],func:7,match:4,bring:10,prefer:[7,2],relationship:7,db2:3,introductori:9,when:[0,1,8,2,3,4,6,9,7,5,11,10],idl:[7,3],filesystem:[6,2],sslrootcrlfil:[7,4],directli:[0,1,2,3,6,9,7,5,10],param:[9,4,2],db1:3,insuffici:6,"_my_oper":9,parametervalueerror:6,receiverfault:[0,6],scope:7,assert:[9,5,3,6],finer:7,kill:[5,6],schemadefinitionerror:6,typeio:11,make_emp:8,secret:[7,5,4],initdberror:[5,6],softwar:6,avoid:[0,5,10,7,2],newvalu:2,uniqueerror:[7,6],uncommit:6,altern:[0,6],caught:7,ran:[0,5,6,7],procedure_id:[7,6],subsequ:[9,4,6,7],made:[9,5,10,4,7],rau:11,detect:[7,6],pg_ctl:[5,6],startup:[7,11,6,10],intervalfieldoverflowerror:6,"__main__":2,refsym:9,element3:11,unquot:6,user_typ:9,callabl:[0,6,7],remove_us:9,again:[0,1,9,3,7,5],triggerprotocolerror:6,sslrootcrtfil:[7,4],distribut:[9,8],packet:7,inconsistentcursorisolationerror:6,establish:[9,2,4,6,7,8],"byte":[0,10,6,7],nullvalueeliminatedinsetfunctionwarn:6,involv:0,arbitrari:[0,9,3,6,7,5],bigint:[9,7],setupscript:9,struct:6,assign:7,bad:[3,11],includ:[9,2,3,4,6,7,5,13],displai:[7,4,6],key_or_index:7,fragment:9,twenti:7,note:[0,9,4,6,7,5,12],undefin:[7,6],syntact:7,per:[12,2],touch:6,noth:[8,6,12],initdb:[5,6],take:[0,9,2,6,7,5,10],backend_start:7,signific:[0,7],deliv:3,mk_pack:6,timetz:7,found:[9,6],parse_arg:4,ident:[9,6],compositeerror:6,instead:[9,2,6,7,5,11],produc:[0,9,3,4,6,7,8],tabledefinitionerror:6,"01p01":6,audienc:[9,8],commun:[7,6],datetimeformaterror:6,python:[0,8,9,2,4,6,7,5,10,11,12,13],quotat:6,typemismatcherror:6,fatal:[0,10,6,7],shutdown:[5,6],"try":[0,6,7],adjust:[7,10],a_db_us:4,craft:7,deriv:7,writelin:7,"0b000":6,castcharactervalueerror:6,suitabl:7,hba:[5,6],address:[7,6],anoth:[0,1,9,6,7,10],terminolog:[0,8,9],veri:[9,7,2],"__str__":6,properti:[0,1,9,6,7,5],state:[0,9,4,6,7,5],conflict:[7,1],unfortun:12,pg_instal:5,pwfile:5,daemon_process:5,delimit:7,which:[0,1,9,3,6,7],propag:7,narr:6,develop:11,op_arg2:9,dozen:9,sole:7,futur:7,structur:[7,5],those:[0,1,9,3,4,7,5,10],essenti:[9,10],metadata:[9,7],querycancelederror:6,pghost:4,complex:[0,6],foo:[7,6],decim:7,regist:11,timeout:[0,5,3,6,7],pg_param:4,twitter:11,complet:[7,0,5,6,2],elvi:[11,12],next:[0,3,6,7],cursor_from_id:[7,6],quickli:[0,7],op_arg1:9,susan:8,decis:[6,10],offer:[0,1,3,6,7],total_row:0,best:[0,10,6,2],forward:[7,6,12],abort:[0,6,7],stdout:[7,0,5,6,2],"static":[4,6],dirnam:9,stopiter:[0,3,11,6,7],undefinedtableerror:6,routin:[7,6,10],default_excformat:6,"__context__":0,len:[7,6],duplicatecursorerror:6,sslkei:4,acquir:[9,1,8,6,7],fail:[0,3,6,7,11,10],check:[7,3],plpgsqlnodatafounderror:6,ever:10,t1980:7,whitespac:9,widthbucketfunctionargumenterror:6,from_iter:9,tripl:[7,3,6],about:[0,9,6,7,5,10],undefinedfileerror:6,problem:[0,10,12,7],administr:[8,13],capabl:[5,6],connect_timeout:[7,4],default_statistics_target:7,preparedstat:9,seek:[7,6],prepar:[0,9,3,6,7,8,2,11,10],pg_dump:5,html:[9,4,6],effici:7,wait:[3,6,7,5,11,10],neg:7,clientcannotconnecterror:6,backend:[7,1,3,6],logfil:[5,6],xx400:6,self:[9,6],sighup:5,key_from_index:7,pointer:6,functionexecutednoreturnstatementerror:6,"new":[7,1,10,6,2],cferror:6,unus:6,authenticationspecificationerror:6,recoveri:[5,6],consum:[0,3,7],refresh:6,grantoroperationerror:6,here:[9,3,6,7],forc:7,recv_into:6,channels_and_payload:7,solut:6,project:[9,8,11,12,13],event:[0,3,7],ulong_pack:6,pg_hba:5,resolve_password:4,encourag:9,emploi:12,regularexpressionerror:6,readonlytransactionerror:6,nullvaluenoindicatorparamet:6,follow:[0,9,2,4,6,7],shot:[7,6,12],show:[7,6,2],logic:[11,6],further:[9,4,6,7,11,10],becom:6,version_info:[7,5,6],gid:11,get_numb:9,sub:11,ecpg:5,lambda:7,subprocess:[5,6],order:[0,1,9,3,6,7,5,10],notnullerror:6,yield:[0,3,6,7],manag:[0,1,8,9,3,4,6,7,5,11,12,13],user_id:9,regular:[5,3,6,2],store:[7,1,8,6],gogichashvili:11,clusterdb:5,"40p01":6,maxsplit:6,pick:3,uncaught:7,insid:[0,3,6,7],arrayelementerror:6,both:[0,1,9,3,7,5],branchalreadyactiveerror:6,enabl:[7,5,10],split_sql_str:6,typeioerror:6,builtin:[0,11,6,7],copy_emps_in:7,sreerror:6,share:[7,1,5],intervent:6,elementtre:11,hasattr:9,"0p000":6,connecttimeouterror:6,accommod:[7,6,12],good:[9,3],quote_liter:[6,10],dict:7,notat:7,p0001:6,stdin:[7,0,6,9],smith:7,fictiti:9,snippet:4,"42p20":6,duplicatepreparedstatementerror:6,float4oid:7,client_port:[7,6],"break":[0,3],higher:[7,6,10],bytea:7,get_emp_with_salary_lt:8,ct_thi:7,clustertimeouterror:[5,6],wrongobjecttypeerror:6,term:[0,9],byteaoid:7,unix:[7,11,2],stop:[7,5,6,10],statementprohibitederror:6,throughout:9,singl:[9,1,2,3,4,6,7,8,11],escap:[7,6],broken:[0,3],buffer_s:6,watch:3,coercionerror:6,"catch":6,cours:[7,8,4,6],ters:7,ssearch_path:4,comment:2,varcharoid:7,likeabl:9,internet:7,total_byt:0,name3:7,name2:7,record:[0,6,7,8,11,12,10],last:7,backward:[7,6],quot:[7,11,6,10],protocolproduc:6,certif:7,iri:[7,4,6,2],"transient":[9,6],recover:[0,7],untranslatablecharactererror:6,actual:[0,5,6,7],ipaddress:12,infailedtransactionerror:[7,6],pg_dumpal:5,mani:[0,9,6,7,11,10],identifi:[0,1,9,6,7,5,10],field:[4,6,10],mai:[0,1,9,3,4,6,7,5,10],t1970:7,set_config:7,method:[0,1,8,9,3,6,7,5,11,12,10],name1:7,map:[0,9,4,6,7,5],timeit:2,combin:5,pack:[7,6,10],contribut:7,mode:[7,1,6,2],often:[0,3,11,6,7],"42p04":6,"42p05":6,"42p06":6,"42p07":6,execnam:6,"42p02":6,"42p03":6,usual:[9,5,7],tailor:11,procedur:[9,1,8,6,7],"42p08":6,"42p09":6,distutil:[9,13],nodatawarn:6,temporari:[5,6,2],prompt_titl:[4,6],rais:[0,1,8,3,6,7,5,11,10],exceed:6,runtim:[9,6,7],keep:9,fals:[5,7,1,4,6],error:[7,9,10,6,2],unavailablelockerror:6,pg_:11,ani:[0,1,9,3,4,6,7,5,10],caten:6,toomanyconnectionserror:6,quote_ident_if_necessari:11,getlen:6,basic:[9,5,6],knowledg:[9,7],that_pkei:7,getaddrinfo:7,containingsqlnotpermittederror:6,reason:6,bool:[7,5],stai:6,modif:[11,2],"2200b":6,"2200c":6,custom:[9,10],"2200f":6,dollar:6,"2200d":6,easi:10,absent:7,whose:[0,9,4,7,5,10],run:[0,9,2,6,7,5],"2200n":6,errformat:6,"2200l":6,"2200m":6,deprec:[11,12],mst:7,invok:[9,6,7],"2200t":6,callreceiv:[0,6],similarli:5,t1985:7,package_data:9,authenticationmethoderror:6,version:[2,6,7,5,11,13],invoc:[7,6,2],reach:6,improv:[8,11],copymanag:[0,6],"10kb":6,quit:7,failur:[0,3,4,6,7,8],interact:[7,2],preparedstatementdefinitionerror:6,revers:7,lockfileexistserror:6,document:[9,11,6,10],p0002:6,p0003:6,p0000:6,casenotfounderror:6,with_openssl:5,separ:[9,4,6],exclusivelock:1,undefinedcolumnerror:6,newlin:4,convert:7,psql_path:5,therefor:[9,5,4,10],none:[0,2,3,4,6,9,7,5],sigterm:6,"__ne__":6,violat:6,"__next__":[0,3,11,7],libn:9,appli:[7,5,6,2],posit:[7,4,6],archiv:13,mechan:6,locat:[7,5,4,8,2],odd:6,sometim:[9,6,7],my_prompt:4,level:[0,1,4,6,7,5,11,10],unlisten:[7,3,6],wire:[6,10],aut:6,emp_salai:8,local:[9,8,3,6,7,5,12,10],inhibit:7,search:9,"0x10d27d170":6,compil:6,standardpars:4,doesn:7,privilegenotrevokedwarn:6,num_byt:0,ereerror:6,mere:[9,1,3,7],merg:11,del:3,patch:[5,11,6],leav:4,warninglookup:6,def:[9,7],tone:7,settimeout:3,incur:6,notifi:[7,3,11,6],period:5,syntax:[7,6],includedir_serv:5,chunksiz:11,same:[9,1,3,6,7],transactionerror:6,arg:[7,6],kerberos5_servic:4,xmlprocessinginstructionerror:6,stream:[9,10,6,7],open:[9,4,8,6,7,5,11],split_id:6,xx002:6,xx000:6,xx001:6,plpgsqlerror:6,smallint:7,conf:[5,4,6,2],t72000:7,backslash:[8,10,6,2],everi:6,soft:6,hba_fil:[5,6],statement_id:[7,6],oper:[0,1,9,6,7,10,11,13],interpol:[7,6],methodcal:7,timeoid:7,small:7,longer:[0,6,7],sure:[7,6],someth:7,reset_errformat:6,get_some_row:9,three:[9,5,6,7],functiondefinitionerror:6,duplicatefunctionerror:6,fetch:[9,6,7],comparison:6,boundari:[0,7],datetim:7,optim:10,repres:[1,3,6,7,5,11],cooper:1,default_buffer_s:6,retriev:5,transactionterminationerror:6,rollback:[7,6],garbag:[7,3,6],implicitzerobitpaddingwarn:6,with_libxml:5,prone:9,typ:[0,1,6],strip_and_int:7,xact:[0,2,6,7,8,11],sequenti:7,gotcha:[8,10],abc:6,memoryerror:6,socket:[12,0,11,7,2],privilegenotgrantedwarn:6,columnerror:6,expos:12,"2pc":11,lib2:9,drawn:10,surviv:1,lib1:9,inconsist:[5,10],fitti:7,you:[4,6,13],accord:6,columndefinitionerror:6,express:[7,10,2],safest:12,silent:6,stderr:[5,6],cannot:[9,5,6,7],present:[7,4],easili:[9,10,7],driverwarn:6,over:[0,5,7],dataerror:6,split_sql:6,intnam:7,partial:[7,4],"0f001":6,recommend:[9,7],"3f000":6,transactionresolutionunknownerror:6,reset:6,quote_id:[11,6],server_vers:7,"__init__":9,dbapi20:[7,8],versionstr:6,searvnameerror:6,psql:[5,4,2],adminshutdownerror:6,host:[7,8,4,6,2],port:[7,5,4,6,2],far:[7,10],symbol:[9,8,11],abov:[9,1,3,4,8,7,5],mkemp:7,full:[7,6],protocolerror:6,preced:5,zero:[5,3,11,6],like:[9,1,2,4,6,7,5,10],dedic:8,domain:[7,11],difficult:10,volum:10,get_user_info_v2:9,semant:7,name:[9,2,6,7,5,11],localhost:[7,5,4,6,2],part:[0,5,11,7],pars:[7,4,6],circumst:[7,3],second:[9,5,6,7],serializationerror:6,parser:9,copyman:[0,8,6],more:[0,9,4,6,7,8,10],mix:6,xlogdir:6,report:[7,11,6],aid:9,resili:3,unsplit:6,chunk:[0,11,7,9],pre:7,piec:7,test:[7,5,11],signatur:[9,7],wirest:6,"2201b":6,"2201e":6,"2201g":6,"2201f":6,closest:7,rang:[9,7],cursor_id:[7,6],int4oid:7,pleerror:6,"2201w":6,duplicateobjecterror:6,simul:7,grantorerror:6,formul:7,"float":7,duplicatealiaserror:6,encodingerror:6,empti:[9,3,4,6,7,11],mean:[0,2,3,4,6,9,7,5,10],window:[5,4,12],employee_dob:7,"short":7,disabl:[7,4,2],close:[1,2,3,6,7,5,11],excformat:6,major:[7,5,6],frequenc:3,overflowerror:6,taken:[7,4,10],itemgett:9,process:[0,2,3,4,6,9,7,5,10,13],srfprotocolerror:6,enable_depend:5,sym_from_libthi:9,known:7,chang:[0,9,2,4,8,7,5,10,11,12,13],"42p19":6,"42p18":6,roll:[7,11,6],prompt:[4,6,2],"42p13":6,"42p12":6,"42p11":6,queue:3,"42p17":6,"42p16":6,"42p15":6,"42p14":6,"22p02":6,"22p03":6,sigkil:[5,6],"22p01":6,"22p06":6,includedir:5,"22p04":6,"22p05":6,win32:4,transport:7,earlier:7,getus:[7,4],constant:[9,7],ambiguouscolumnerror:6,grain:[7,5],serializ:[7,6],"__file__":9,intern:[7,5,3,11,10],grief:7,attempt:[4,6,10],treat:[9,8,10,7],groupingerror:6,reservednameerror:6,ambiguousfunctionerror:6,searverror:6,specif:[0,9,3,6,7,2],difficulti:10,discard:[9,3,7],docdir:5,termin:[7,5,3,6,10],simplest:7,driver:[4,6,7,8,11,10],within:[0,1,9,2,7,5],resourc:[9,1,6],dbn:3,two:[5,7,1,6,12],dbm:6,nametoolongerror:6,binaryrepresentationerror:6,default_pg_config:6,ini:9,statu:12,int4:[9,1,7],advantag:[7,9,6,2],promptli:[9,3,7],valid:[6,10],int8:[0,1,7],info:[7,5,6],home:4,stripxx:7,reli:12,fulfil:9,dml:[9,7],despit:5,code:[9,8,2,3,6,7,5],pertain:6,badisolationforbrancherror:6,been:[0,1,2,3,4,6,9,7,5,12],fairli:6,alwai:[1,2,6,7,5,11,10],int8oid:7,pgsslmode:4,discuss:[9,7,2],furthermor:[7,10],cycl:0,"throw":6,commit:[7,6,12],readingdataprohibitederror:6,pggeqo:4,badcopyerror:6,sample_copi:7,qualiti:7,shown:7,usec:2,split_us:6,negoti:10,readingsqldatanotpermittederror:6,signal:[0,5,3,6],f0000:6,f0001:6,user:[9,8,2,3,4,6,7,5,11,10],success:[7,1],"int":[9,5,3,6,7],interrog:[7,4],instal:[9,4,8,6,7,5,13],pg_src_host:4,packag:[9,13,6,7],fit:7,referenc:[0,9,2,4,6,7],"3d000":6,genexpr:7,escapeocteterror:6,addition:[7,0,6,9],purpos:[9,4,6,7,5,10],integr:6,createus:5,possibl:[7,5,3,6,10],ignor:[6,2],togeth:[9,7],itertool:9,daemon_path:[5,6],irrit:11,"2200g":6,"0x10bc67990":6,later:5,poll:[5,3],against:[9,7,2],claus:7,tranact:6,surround:7,interpret:2,strive:6,write:[9,2,8,6,7,5],default_errformat:6,etre:7,facet:7,timezonedisplacementvalueerror:6,unanticip:7,com:[7,11],guard:7,until:[0,1,3,6,7,5,10],postgresql:[0,1,8,2,3,4,6,9,7,5,10,11,12,13],variabl:[7,8,13,4,2],scroll:7,listening_channel:[7,6],kei:[0,4,8,6,7,5],increment:1,done_listen:3,symmetri:7,after:[0,9,2,4,6,7,5,11,13],"0x10dfc94d0":6,dure:[10,0,3,7],get_one_twic:9,badaccessmodeforbrancherror:6,"true":[9,1,3,4,6,7,5],valentin:11,oid:[7,6],unexpect:4,storedprocedur:[7,6],prohibitedsqlstatementerror:6,clone:[7,6],employee_nam:7,product_cod:7,"switch":10,becaus:9,reintroduct:0,strict:6,escapecharacterconflicterror:6,sep:6,relai:7,set:[0,8,2,3,4,6,9,7,5,11,10],duplicatetableerror:6,accept:[7,5,4,6],"0devel":5,substanti:6,get_some_chunk:9,sec:6,table2_oid:1,see:[9,8,4,6,7],drop:[7,5,11,6],erieerror:6,connectionrejectionerror:6,mutabl:7,similar:[9,1,6,7],relat:[6,10],manual:9,row:[0,9,6,7,8,11,10],high:[0,4,6,7,11,10],drivererror:6,exhaust:[0,3,7,9],stdcat:9,servic:[7,3,4,11],oierror:6,speed:11,filter_notic:7,disk:9,datacorruptederror:6,pg_service_fil:4,incomplet:0,introduc:[12,10],lower:5,textual:7,transform_row:7,isol:[9,5,6,7],automat:[9,5,10,7],the_cursor_id:7,instanti:[5,9,1,6,7],list:[0,9,3,4,6,7,5,11],mutablemap:[7,6],common:[9,1,6,7],pg_proc:6,savepointerror:6,wast:7,restart:[5,6],argv:4,statementreceiv:0,qname:6},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","exception","Python exception"],"3":["py","function","Python function"],"4":["py","attribute","Python attribute"],"5":["py","data","Python data"]},objtypes:{"0":"py:module","1":"py:class","2":"py:exception","3":"py:function","4":"py:attribute","5":"py:data"},objects:{"":{postgresql:[6,0,1,""]},"postgresql.api.Connection":{clone:[6,3,1,""],close:[6,3,1,""],connect:[6,3,1,""],closed:[6,4,1,""],query:[6,4,1,""],connector:[6,4,1,""]},"postgresql.api.Installation":{type:[6,4,1,""],version_info:[6,4,1,""],version:[6,4,1,""],ssl:[6,4,1,""]},"postgresql.copyman.WireState":{update:[6,3,1,""]},"postgresql.temporal":{pg_tmp:[6,5,1,""],Temporal:[6,1,1,""]},"postgresql.installation.Installation":{ssl:[6,4,1,""]},"postgresql.installation":{Installation:[6,1,1,""],default_pg_config:[6,3,1,""],pg_config_dictionary:[6,3,1,""],"default":[6,3,1,""]},"postgresql.temporal.Temporal":{cluster_dirname:[6,3,1,""]},postgresql:{copyman:[6,0,1,""],alock:[6,0,1,""],open:[6,3,1,""],exceptions:[6,0,1,""],sys:[6,0,1,""],installation:[6,0,1,""],cluster:[6,0,1,""],api:[6,0,1,""],temporal:[6,0,1,""],string:[6,0,1,""],version_info:[6,5,1,""],version:[6,5,1,""]},"postgresql.api.Message":{source:[6,4,1,""],isconsistent:[6,3,1,""],details:[6,4,1,""],message:[6,4,1,""],code:[6,4,1,""]},"postgresql.copyman":{NullProducer:[6,1,1,""],CopyFail:[6,2,1,""],default_buffer_size:[6,5,1,""],transfer:[6,3,1,""],CopyManager:[6,1,1,""],ProtocolProducer:[6,1,1,""],ProducerFault:[6,2,1,""],ulong_pack:[6,3,1,""],ReceiverFault:[6,2,1,""],WireState:[6,1,1,""],CallReceiver:[6,1,1,""]},"postgresql.api.Settings":{get:[6,3,1,""],keys:[6,3,1,""],getset:[6,3,1,""],values:[6,3,1,""],update:[6,3,1,""],items:[6,3,1,""]},"postgresql.api.Statement":{statement_id:[6,4,1,""],clone:[6,3,1,""],close:[6,3,1,""],sql_column_types:[6,4,1,""],sql_parameter_types:[6,4,1,""],pg_parameter_types:[6,4,1,""],parameter_types:[6,4,1,""],string:[6,4,1,""],column_types:[6,4,1,""],column_names:[6,4,1,""],pg_column_types:[6,4,1,""]},"postgresql.string":{escape_ident:[6,3,1,""],unsplit:[6,3,1,""],split_qname:[6,3,1,""],quote_ident_if_needed:[6,3,1,""],split_using:[6,3,1,""],split_ident:[6,3,1,""],quote_literal:[6,3,1,""],split_sql_str:[6,3,1,""],split:[6,3,1,""],quote_ident:[6,3,1,""],escape_literal:[6,3,1,""],qname:[6,3,1,""],split_sql:[6,3,1,""]},"postgresql.api.Database":{proc:[6,3,1,""],backend_id:[6,4,1,""],iternotifies:[6,3,1,""],client_port:[6,4,1,""],execute:[6,3,1,""],listening_channels:[6,3,1,""],settings:[6,4,1,""],xact:[6,4,1,""],cursor_from_id:[6,3,1,""],unlisten:[6,3,1,""],statement_from_id:[6,3,1,""],client_address:[6,4,1,""],notify:[6,3,1,""],prepare:[6,3,1,""],version_info:[6,4,1,""],"do":[6,3,1,""],listen:[6,3,1,""],reset:[6,3,1,""]},"postgresql.exceptions":{OperationError:[6,2,1,""],Error:[6,2,1,""],SREError:[6,2,1,""],ServerNotReadyError:[6,2,1,""],ClientCannotConnectError:[6,2,1,""],ReadOnlyTransactionError:[6,2,1,""],ConnectionDoesNotExistError:[6,2,1,""],SEARVError:[6,2,1,""],TypeConversionWarning:[6,1,1,""],ICVError:[6,2,1,""],EscapeCharacterError:[6,2,1,""],SIOError:[6,2,1,""],ConnectionFailureError:[6,2,1,""],TypeIOError:[6,2,1,""],map_errors_and_warnings:[6,3,1,""],InconsistentCursorIsolationError:[6,2,1,""],InFailedTransactionError:[6,2,1,""],DriverError:[6,2,1,""],EREError:[6,2,1,""],Disconnection:[6,2,1,""],InsecurityError:[6,2,1,""],LoadError:[6,2,1,""],AuthenticationMethodError:[6,2,1,""],DPDSEError:[6,2,1,""],TRError:[6,2,1,""],ERIEError:[6,2,1,""],ONIPSError:[6,2,1,""],PLPGSQLError:[6,2,1,""],SchemaAndDataStatementsError:[6,2,1,""],CardinalityError:[6,2,1,""],SavepointError:[6,2,1,""],ITSError:[6,2,1,""],IgnoredClientParameterWarning:[6,1,1,""],PLEError:[6,2,1,""],FeatureError:[6,2,1,""],OIError:[6,2,1,""],CFError:[6,2,1,""],IRError:[6,2,1,""],ConnectTimeoutError:[6,2,1,""],Exception:[6,2,1,""],PLPGSQLRaiseError:[6,2,1,""]},"postgresql.alock":{ALock:[6,1,1,""]},"postgresql.copyman.CopyManager":{reconcile:[6,3,1,""]},"postgresql.api.Cursor":{clone:[6,3,1,""],direction:[6,4,1,""],read:[6,3,1,""],seek:[6,3,1,""]},"postgresql.copyman.ProtocolProducer":{recover:[6,3,1,""]},"postgresql.cluster.Cluster":{stop:[6,3,1,""],start:[6,3,1,""],wait_until_stopped:[6,3,1,""],daemon_path:[6,4,1,""],init:[6,3,1,""],shutdown:[6,3,1,""],initialized:[6,3,1,""],get_pid_from_file:[6,3,1,""],hba_file:[6,4,1,""],ready_for_connections:[6,3,1,""],kill:[6,3,1,""],connector:[6,3,1,""],reload:[6,3,1,""],restart:[6,3,1,""],drop:[6,3,1,""],connection:[6,3,1,""],address:[6,3,1,""],pid:[6,4,1,""],connect:[6,3,1,""],running:[6,3,1,""],wait_until_started:[6,3,1,""]},"postgresql.cluster":{ClusterStartupError:[6,2,1,""],Cluster:[6,1,1,""],ClusterInitializationError:[6,2,1,""],ClusterError:[6,2,1,""],ClusterNotRunningError:[6,2,1,""],ClusterWarning:[6,1,1,""],InitDBError:[6,2,1,""],ClusterTimeoutError:[6,2,1,""]},"postgresql.api":{Driver:[6,1,1,""],Message:[6,1,1,""],Settings:[6,1,1,""],Transaction:[6,1,1,""],Installation:[6,1,1,""],Cluster:[6,1,1,""],Statement:[6,1,1,""],Database:[6,1,1,""],Connection:[6,1,1,""],Category:[6,1,1,""],Cursor:[6,1,1,""],StoredProcedure:[6,1,1,""],Connector:[6,1,1,""]},"postgresql.api.Transaction":{rollback:[6,3,1,""],start:[6,3,1,""],commit:[6,3,1,""],begin:[6,3,1,""],abort:[6,3,1,""],mode:[6,4,1,""],isolation:[6,4,1,""]},"postgresql.api.Driver":{connect:[6,3,1,""]},"postgresql.alock.ALock":{mode:[6,4,1,""],release:[6,3,1,""],acquire:[6,3,1,""],locked:[6,3,1,""]},"postgresql.sys":{default_msghook:[6,3,1,""],errformat:[6,3,1,""],default_errformat:[6,3,1,""],reset_errformat:[6,3,1,""],msghook:[6,3,1,""],reset_msghook:[6,3,1,""]},"postgresql.api.Cluster":{kill:[6,3,1,""],installation:[6,4,1,""],start:[6,3,1,""],wait_until_stopped:[6,3,1,""],restart:[6,3,1,""],drop:[6,3,1,""],data_directory:[6,4,1,""],stop:[6,3,1,""],init:[6,3,1,""],settings:[6,4,1,""],wait_until_started:[6,3,1,""]}}})

Sorry, the diff of this file is too big to display