diff options
| author | Ashesh Vashi <asheshv@users.noreply.github.com> | 2018-05-08 15:17:59 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-05-08 15:17:59 +0530 |
| commit | 1bec2bdc437d89847919889f20825e2ca94c8fa0 (patch) | |
| tree | 9a1152781b41e61a8c15a8182c3e6e9cca96899f /doc/src | |
| parent | 84d405894c4236c1d2bb54c673a71e4a8e78a2ec (diff) | |
| parent | 90b26c3e2369e4aa9cf4a70f8ff1e17b06607de0 (diff) | |
| download | psycopg2-1bec2bdc437d89847919889f20825e2ca94c8fa0.tar.gz | |
Merge branch 'master' into master
Diffstat (limited to 'doc/src')
| -rw-r--r-- | doc/src/advanced.rst | 6 | ||||
| -rw-r--r-- | doc/src/conf.py | 6 | ||||
| -rw-r--r-- | doc/src/connection.rst | 19 | ||||
| -rw-r--r-- | doc/src/cursor.rst | 44 | ||||
| -rw-r--r-- | doc/src/errorcodes.rst | 4 | ||||
| -rw-r--r-- | doc/src/extras.rst | 40 | ||||
| -rw-r--r-- | doc/src/faq.rst | 5 | ||||
| -rw-r--r-- | doc/src/index.rst | 1 | ||||
| -rw-r--r-- | doc/src/install.rst | 185 | ||||
| -rw-r--r-- | doc/src/pool.rst | 10 | ||||
| -rwxr-xr-x | doc/src/tools/lib/dbapi_extension.py | 14 | ||||
| -rw-r--r-- | doc/src/tools/lib/sql_role.py | 5 | ||||
| -rw-r--r-- | doc/src/tools/lib/ticket_role.py | 1 | ||||
| -rwxr-xr-x | doc/src/tools/stitch_text.py | 16 | ||||
| -rw-r--r-- | doc/src/tz.rst | 3 | ||||
| -rw-r--r-- | doc/src/usage.rst | 111 |
16 files changed, 240 insertions, 230 deletions
diff --git a/doc/src/advanced.rst b/doc/src/advanced.rst index 5b5fb35..d1683b8 100644 --- a/doc/src/advanced.rst +++ b/doc/src/advanced.rst @@ -188,7 +188,7 @@ representation into the previously defined `!Point` class: ... return Point(float(m.group(1)), float(m.group(2))) ... else: ... raise InterfaceError("bad point representation: %r" % value) - + In order to create a mapping from a PostgreSQL type (either standard or user-defined), its OID must be known. It can be retrieved either by the second @@ -295,7 +295,9 @@ something to read:: print "Got NOTIFY:", notify.pid, notify.channel, notify.payload Running the script and executing a command such as :sql:`NOTIFY test, 'hello'` -in a separate :program:`psql` shell, the output may look similar to:: +in a separate :program:`psql` shell, the output may look similar to: + +.. code-block:: none Waiting for notifications on channel 'test' Timeout diff --git a/doc/src/conf.py b/doc/src/conf.py index 9e73308..a27d6cf 100644 --- a/doc/src/conf.py +++ b/doc/src/conf.py @@ -57,7 +57,7 @@ try: release = psycopg2.__version__.split()[0] version = '.'.join(release.split('.')[:2]) except ImportError: - print "WARNING: couldn't import psycopg to read version." + print("WARNING: couldn't import psycopg to read version.") release = version intersphinx_mapping = { @@ -101,6 +101,10 @@ default_role = 'obj' # output. They are ignored by default. #show_authors = False +# Using 'python' instead of the default gives warnings if parsing an example +# fails, instead of defaulting to none +highlight_language = 'python' + # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' diff --git a/doc/src/connection.rst b/doc/src/connection.rst index 2d720ee..d656fa1 100644 --- a/doc/src/connection.rst +++ b/doc/src/connection.rst @@ -22,7 +22,7 @@ The ``connection`` class :ref:`thread-safety` for details. .. method:: cursor(name=None, cursor_factory=None, scrollable=None, withhold=False) - + Return a new `cursor` object using the connection. If *name* is specified, the returned cursor will be a :ref:`server @@ -41,11 +41,6 @@ The ``connection`` class previously only valid PostgreSQL identifiers were accepted as cursor name. - .. warning:: - It is unsafe to expose the *name* to an untrusted source, for - instance you shouldn't allow *name* to be read from a HTML form. - Consider it as part of the query, not as a query parameter. - The *cursor_factory* argument can be used to create non-standard cursors. The class returned must be a subclass of `psycopg2.extensions.cursor`. See :ref:`subclassing-cursor` for @@ -274,8 +269,8 @@ The ``connection`` class .. __: http://jdbc.postgresql.org/ - Xids returned by `!tpc_recover()` also have extra attributes - `~psycopg2.extensions.Xid.prepared`, `~psycopg2.extensions.Xid.owner`, + Xids returned by `!tpc_recover()` also have extra attributes + `~psycopg2.extensions.Xid.prepared`, `~psycopg2.extensions.Xid.owner`, `~psycopg2.extensions.Xid.database` populated with the values read from the server. @@ -551,7 +546,7 @@ The ``connection`` class the session. .. doctest:: - :options: NORMALIZE_WHITESPACE + :options: +NORMALIZE_WHITESPACE >>> cur.execute("CREATE TABLE foo (id serial PRIMARY KEY);") >>> pprint(conn.notices) @@ -626,7 +621,7 @@ The ``connection`` class pair: Server; Parameters .. method:: get_parameter_status(parameter) - + Look up a current parameter setting of the server. Potential values for ``parameter`` are: ``server_version``, @@ -735,7 +730,7 @@ The ``connection`` class The number is formed by converting the major, minor, and revision numbers into two-decimal-digit numbers and appending them together. For example, version 8.1.5 will be returned as ``80105``. - + .. seealso:: libpq docs for `PQserverVersion()`__ for details. .. __: http://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION @@ -749,7 +744,7 @@ The ``connection`` class .. attribute:: status A read-only integer representing the status of the connection. - Symbolic constants for the values are defined in the module + Symbolic constants for the values are defined in the module `psycopg2.extensions`: see :ref:`connection-status-constants` for the available values. diff --git a/doc/src/cursor.rst b/doc/src/cursor.rst index 417ab6c..5a6935e 100644 --- a/doc/src/cursor.rst +++ b/doc/src/cursor.rst @@ -34,10 +34,10 @@ The ``cursor`` class many cursors from the same connection and should use each cursor from a single thread. See :ref:`thread-safety` for details. - - .. attribute:: description - This read-only attribute is a sequence of 7-item sequences. + .. attribute:: description + + This read-only attribute is a sequence of 7-item sequences. Each of these sequences is a named tuple (a regular tuple if :func:`collections.namedtuple` is not available) containing information @@ -65,7 +65,7 @@ The ``cursor`` class This attribute will be `!None` for operations that do not return rows or if the cursor has not had an operation invoked via the |execute*|_ methods yet. - + .. |pg_type| replace:: :sql:`pg_type` .. _pg_type: http://www.postgresql.org/docs/current/static/catalog-pg-type.html .. _PQgetlength: http://www.postgresql.org/docs/current/static/libpq-exec.html#LIBPQ-PQGETLENGTH @@ -78,7 +78,7 @@ The ``cursor`` class regular tuples. .. method:: close() - + Close the cursor now (rather than whenever `del` is executed). The cursor will be unusable from this point forward; an `~psycopg2.InterfaceError` will be raised if any operation is @@ -88,7 +88,7 @@ The ``cursor`` class the method is automatically called at the end of the ``with`` block. - + .. attribute:: closed Read-only boolean attribute: specifies if the cursor is closed @@ -235,7 +235,7 @@ The ``cursor`` class The `mogrify()` method is a Psycopg extension to the |DBAPI|. .. method:: setinputsizes(sizes) - + This method is exposed in compliance with the |DBAPI|. It currently does nothing but it is safe to call it. @@ -281,17 +281,17 @@ The ``cursor`` class >>> cur.execute("SELECT * FROM test WHERE id = %s", (3,)) >>> cur.fetchone() (3, 42, 'bar') - + A `~psycopg2.ProgrammingError` is raised if the previous call to |execute*|_ did not produce any result set or no call was issued yet. .. method:: fetchmany([size=cursor.arraysize]) - + Fetch the next set of rows of a query result, returning a list of tuples. An empty list is returned when no more rows are available. - + The number of rows to fetch per call is specified by the parameter. If it is not given, the cursor's `~cursor.arraysize` determines the number of rows to be fetched. The method should try to fetch as @@ -309,7 +309,7 @@ The ``cursor`` class A `~psycopg2.ProgrammingError` is raised if the previous call to |execute*|_ did not produce any result set or no call was issued yet. - + Note there are performance considerations involved with the size parameter. For optimal performance, it is usually best to use the `~cursor.arraysize` attribute. If the size parameter is used, @@ -344,7 +344,7 @@ The ``cursor`` class `~psycopg2.ProgrammingError` is raised and the cursor position is not changed. - .. note:: + .. note:: According to the |DBAPI|_, the exception raised for a cursor out of bound should have been `!IndexError`. The best option is @@ -364,7 +364,7 @@ The ``cursor`` class .. attribute:: arraysize - + This read/write attribute specifies the number of rows to fetch at a time with `~cursor.fetchmany()`. It defaults to 1 meaning to fetch a single row at a time. @@ -378,20 +378,20 @@ The ``cursor`` class default is 2000. .. versionadded:: 2.4 - + .. extension:: The `itersize` attribute is a Psycopg extension to the |DBAPI|. - .. attribute:: rowcount - + .. attribute:: rowcount + This read-only attribute specifies the number of rows that the last |execute*|_ produced (for :abbr:`DQL (Data Query Language)` statements - like :sql:`SELECT`) or affected (for + like :sql:`SELECT`) or affected (for :abbr:`DML (Data Manipulation Language)` statements like :sql:`UPDATE` or :sql:`INSERT`). - + The attribute is -1 in case no |execute*| has been performed on the cursor or the row count of the last operation if it can't be determined by the interface. @@ -400,7 +400,7 @@ The ``cursor`` class The |DBAPI|_ interface reserves to redefine the latter case to have the object return `!None` instead of -1 in future versions of the specification. - + .. attribute:: rownumber @@ -457,7 +457,7 @@ The ``cursor`` class command: >>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar')) - >>> cur.statusmessage + >>> cur.statusmessage 'INSERT 0 1' .. extension:: @@ -490,13 +490,13 @@ The ``cursor`` class .. method:: nextset() - + This method is not supported (PostgreSQL does not have multiple data sets) and will raise a `~psycopg2.NotSupportedError` exception. .. method:: setoutputsize(size [, column]) - + This method is exposed in compliance with the |DBAPI|. It currently does nothing but it is safe to call it. diff --git a/doc/src/errorcodes.rst b/doc/src/errorcodes.rst index ed40b1f..ab49afb 100644 --- a/doc/src/errorcodes.rst +++ b/doc/src/errorcodes.rst @@ -50,7 +50,7 @@ An example of the available constants defined in the module: '42P01' Constants representing all the error values defined by PostgreSQL versions -between 8.1 and 10 beta 1 are included in the module. +between 8.1 and 10 are included in the module. .. autofunction:: lookup(code) @@ -59,7 +59,7 @@ between 8.1 and 10 beta 1 are included in the module. >>> try: ... cur.execute("SELECT ouch FROM aargh;") - ... except Exception, e: + ... except Exception as e: ... pass ... >>> errorcodes.lookup(e.pgcode[:2]) diff --git a/doc/src/extras.rst b/doc/src/extras.rst index 36118e7..15f35e8 100644 --- a/doc/src/extras.rst +++ b/doc/src/extras.rst @@ -99,20 +99,6 @@ Real dictionary cursor .. versionadded:: 2.3 -These objects require :py:func:`collections.namedtuple` to be found, so it is -available out-of-the-box only from Python 2.6. Anyway, the namedtuple -implementation is compatible with previous Python versions, so all you -have to do is to `download it`__ and make it available where we -expect it to be... :: - - from somewhere import namedtuple - import collections - collections.namedtuple = namedtuple - from psycopg.extras import NamedTupleConnection - # ... - -.. __: http://code.activestate.com/recipes/500261-named-tuples/ - .. autoclass:: NamedTupleCursor .. autoclass:: NamedTupleConnection @@ -403,7 +389,7 @@ The individual messages in the replication stream are represented by class LogicalStreamConsumer(object): - ... + # ... def __call__(self, msg): self.process_message(msg.payload) @@ -501,7 +487,7 @@ The individual messages in the replication stream are represented by from datetime import datetime def consume(msg): - ... + # ... keepalive_interval = 10.0 while True: @@ -553,17 +539,13 @@ fields to JSON) you can use the `register_json()` function. .. __: http://people.planetpostgresql.org/andrew/index.php?/archives/255-JSON-for-PG-9.2-...-and-now-for-9.1!.html -The Python library used by default to convert Python objects to JSON and to -parse data from the database depends on the language version: with Python 2.6 -and following the :py:mod:`json` module from the standard library is used; -with previous versions the `simplejson`_ module is used if available. Note -that the last `!simplejson` version supporting Python 2.4 is the 2.0.9. +The Python :py:mod:`json` module is used by default to convert Python objects +to JSON and to parse data from the database. .. _JSON: http://www.json.org/ .. |pgjson| replace:: :sql:`json` .. |jsonb| replace:: :sql:`jsonb` .. _pgjson: http://www.postgresql.org/docs/current/static/datatype-json.html -.. _simplejson: http://pypi.python.org/pypi/simplejson/ In order to pass a Python object to the database as query argument you can use the `Json` adapter:: @@ -1043,20 +1025,6 @@ parameters. By reducing the number of server roundtrips the performance can be .. versionadded:: 2.7 - -.. index:: - single: Time zones; Fractional - -Fractional time zones ---------------------- - -.. autofunction:: register_tstz_w_secs - - .. versionadded:: 2.0.9 - - .. versionchanged:: 2.2.2 - function is no-op: see :ref:`tz-handling`. - .. index:: pair: Example; Coroutine; diff --git a/doc/src/faq.rst b/doc/src/faq.rst index fb7b33d..5824d2b 100644 --- a/doc/src/faq.rst +++ b/doc/src/faq.rst @@ -306,7 +306,9 @@ I can't compile `!psycopg2`: the compiler says *error: libpq-fe.h: No such file API support (*i.e.* the libpq used at compile time was at least 9.3) but at runtime an older libpq dynamic library is found. - You can use:: + You can use: + + .. code-block:: shell $ ldd /path/to/packages/psycopg2/_psycopg.so | grep libpq @@ -332,4 +334,3 @@ Psycopg raises *ImportError: cannot import name tz* on import in mod_wsgi / ASP, .. _egg: http://peak.telecommunity.com/DevCenter/PythonEggs .. __: http://stackoverflow.com/questions/2192323/what-is-the-python-egg-cache-python-egg-cache .. __: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPythonEggs - diff --git a/doc/src/index.rst b/doc/src/index.rst index 30ba8fa..852bbc2 100644 --- a/doc/src/index.rst +++ b/doc/src/index.rst @@ -65,4 +65,3 @@ Psycopg 2 is both Unicode and Python 3 friendly. **To Do items in the documentation** .. todolist:: - diff --git a/doc/src/install.rst b/doc/src/install.rst index 9119753..a858cbe 100644 --- a/doc/src/install.rst +++ b/doc/src/install.rst @@ -12,16 +12,6 @@ to use Psycopg on a different Python implementation (PyPy, Jython, IronPython) there is an experimental `porting of Psycopg for Ctypes`__, but it is not as mature as the C implementation yet. -The current `!psycopg2` implementation supports: - -.. - NOTE: keep consistent with setup.py and the /features/ page. - -- Python 2 versions from 2.6 to 2.7 -- Python 3 versions from 3.2 to 3.6 -- PostgreSQL server versions from 7.4 to 9.6 -- PostgreSQL client library version from 9.1 - .. _PostgreSQL: http://www.postgresql.org/ .. _Python: http://www.python.org/ .. _libpq: http://www.postgresql.org/docs/current/static/libpq.html @@ -32,77 +22,20 @@ The current `!psycopg2` implementation supports: .. index:: - single: Install; from PyPI - -Binary install from PyPI ------------------------- - -`!psycopg2` is `available on PyPI`__ in the form of wheel_ packages for the -most common platform (Linux, OSX, Windows): this should make you able to -install a binary version of the module including all the dependencies simply -using: - -.. code-block:: console - - $ pip install psycopg2 - -Make sure to use an up-to-date version of :program:`pip` (you can upgrade it -using something like ``pip install -U pip``) - -.. __: PyPI_ -.. _PyPI: https://pypi.python.org/pypi/psycopg2/ -.. _wheel: http://pythonwheels.com/ - -.. note:: - - The binary packages come with their own versions of a few C libraries, - among which ``libpq`` and ``libssl``, which will be used regardless of other - libraries available on the client: upgrading the system libraries will not - upgrade the libraries used by `!psycopg2`. Please build `!psycopg2` from - source if you want to maintain binary upgradeability. - -.. warning:: - - Because the `!psycopg` wheel package uses its own ``libssl`` binary, it is - incompatible with other extension modules binding with ``libssl`` as well, - for instance the Python `ssl` module: the result will likely be a - segfault. If you need using both `!psycopg2` and other libraries using - ``libssl`` please :ref:`install psycopg from source - <install-from-source>`. - -If you prefer to use the system libraries available on your client you can use -the :command:`pip` ``--no-binary`` option: - -.. code-block:: console - - $ pip install --no-binary psycopg2 - -which can be specified in your :file:`requirements.txt` files too, e.g. use: - -.. code-block:: none - - psycopg2>=2.7,<2.8 --no-binary :all: - -to use the last bugfix release of the `!psycopg2` 2.7 package, specifying to -always compile it from source. Of course in this case you will have to meet -the :ref:`build prerequisites <build-prerequisites>`. - - - -.. index:: - single: Install; from source + single: Prerequisites -.. _install-from-source: +Prerequisites +------------- -Install from source -------------------- - -.. _source-package: +The current `!psycopg2` implementation supports: -You can download a copy of Psycopg source files from the `Psycopg download -page`__ or from PyPI_. +.. + NOTE: keep consistent with setup.py and the /features/ page. -.. __: http://initd.org/psycopg/download/ +- Python version 2.7 +- Python 3 versions from 3.4 to 3.6 +- PostgreSQL server versions from 7.4 to 10 +- PostgreSQL client library version from 9.1 @@ -111,8 +44,8 @@ page`__ or from PyPI_. Build prerequisites ^^^^^^^^^^^^^^^^^^^ -These notes illustrate how to compile Psycopg on Linux. If you want to compile -Psycopg on other platforms you may have to adjust some details accordingly. +The build prerequisites are to be met in order to install Psycopg from source +code, either from a source distribution package or from PyPI. Psycopg is a C wrapper around the libpq_ PostgreSQL client library. To install it from sources you will need: @@ -146,6 +79,12 @@ Once everything is in place it's just a matter of running the standard: .. code-block:: console + $ pip install psycopg2 + +or, from the directory containing the source code: + +.. code-block:: console + $ python setup.py build $ python setup.py install @@ -181,11 +120,91 @@ which is OS-dependent (for instance setting a suitable .. index:: + single: Install; from PyPI + single: Install; wheel + single: Wheel + +Binary install from PyPI +------------------------ + +`!psycopg2` is also `available on PyPI`__ in the form of wheel_ packages for +the most common platform (Linux, OSX, Windows): this should make you able to +install a binary version of the module, not requiring the above build or +runtime prerequisites, simply using: + +.. code-block:: console + + $ pip install psycopg2-binary + +Make sure to use an up-to-date version of :program:`pip` (you can upgrade it +using something like ``pip install -U pip``) + +.. __: PyPI-binary_ +.. _PyPI-binary: https://pypi.python.org/pypi/psycopg2-binary/ +.. _wheel: http://pythonwheels.com/ + +.. note:: + + The binary packages come with their own versions of a few C libraries, + among which ``libpq`` and ``libssl``, which will be used regardless of other + libraries available on the client: upgrading the system libraries will not + upgrade the libraries used by `!psycopg2`. Please build `!psycopg2` from + source if you want to maintain binary upgradeability. + +.. warning:: + + The `!psycopg2` wheel package comes packaged, among the others, with its + own ``libssl`` binary. This may create conflicts with other extension + modules binding with ``libssl`` as well, for instance with the Python + `ssl` module: in some cases, under concurrency, the interaction between + the two libraries may result in a segfault. In case of doubts you are + advised to use a package built from source. + + + +.. index:: + single: Install; disable wheel + single: Wheel; disable + +.. _disable-wheel: + +Disabling wheel packages for Psycopg 2.7 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In version 2.7.x, `pip install psycopg2` would have tried to install the wheel +binary package of Psycopg. Because of the problems the wheel package have +displayed, `psycopg2-binary` has become a separate package, and from 2.8 it +has become the only way to install the binary package. + +If you are using psycopg 2.7 and you want to disable the use of wheel binary +packages, relying on the system system libraries available on your client, you +can use the :command:`pip` |--no-binary option|__, e.g.: + +.. code-block:: console + + $ pip install --no-binary :all: psycopg2 + +.. |--no-binary option| replace:: ``--no-binary`` option +.. __: https://pip.pypa.io/en/stable/reference/pip_install/#install-no-binary + +which can be specified in your :file:`requirements.txt` files too, e.g. use: + +.. code-block:: none + + psycopg2>=2.7,<2.8 --no-binary psycopg2 + +to use the last bugfix release of the `!psycopg2` 2.7 package, specifying to +always compile it from source. Of course in this case you will have to meet +the :ref:`build prerequisites <build-prerequisites>`. + + + +.. index:: single: setup.py single: setup.cfg Non-standard builds -^^^^^^^^^^^^^^^^^^^ +------------------- If you have less standard requirements such as: @@ -225,7 +244,7 @@ order to create a debug package: - Edit the ``setup.cfg`` file adding the ``PSYCOPG_DEBUG`` flag to the ``define`` option. -- :ref:`Compile and install <source-package>` the package. +- :ref:`Compile and install <build-prerequisites>` the package. - Set the :envvar:`PSYCOPG_DEBUG` environment variable: @@ -250,11 +269,11 @@ Running the test suite ---------------------- Once `!psycopg2` is installed you can run the test suite to verify it is -working correctly. You can run: +working correctly. From the source directory, you can run: .. code-block:: console - $ python -c "from psycopg2 import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose + $ python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose The tests run against a database called ``psycopg2_test`` on UNIX socket and the standard port. You can configure a different database to run the test by diff --git a/doc/src/pool.rst b/doc/src/pool.rst index 32bca54..38cd08f 100644 --- a/doc/src/pool.rst +++ b/doc/src/pool.rst @@ -24,13 +24,18 @@ directly in the client application. .. method:: getconn(key=None) - Get a free connection and assign it to *key* if not `!None`. + Get a free connection from the pool. + + The *key* parameter is optional: if used, the connection will be + associated to the key and calling `!getconn()` with the same key again + will return the same connection. .. method:: putconn(conn, key=None, close=False) Put away a connection. If *close* is `!True`, discard the connection from the pool. + *key* should be used consistently with `getconn()`. .. method:: closeall @@ -57,8 +62,7 @@ be used. .. autoclass:: PersistentConnectionPool - .. note:: + .. note:: This pool class is mostly designed to interact with Zope and probably not useful in generic applications. - diff --git a/doc/src/tools/lib/dbapi_extension.py b/doc/src/tools/lib/dbapi_extension.py index cb3fec4..23d9165 100755 --- a/doc/src/tools/lib/dbapi_extension.py +++ b/doc/src/tools/lib/dbapi_extension.py @@ -12,7 +12,7 @@ from docutils import nodes from sphinx.locale import _ -from sphinx.util.compat import Directive, make_admonition +from docutils.parsers.rst import Directive class extension_node(nodes.Admonition, nodes.Element): pass @@ -29,12 +29,11 @@ class Extension(Directive): option_spec = {} def run(self): - nodes = make_admonition(extension_node, - self.name, [_('DB API extension')], self.options, - self.content, self.lineno, self.content_offset, - self.block_text, self.state, self.state_machine) - nodes[0]['classes'].append('dbapi-extension') - return nodes + node = extension_node('\n'.join(self.content)) + node += nodes.title(_('DB API extension'), _('DB API extension')) + self.state.nested_parse(self.content, self.content_offset, node) + node['classes'].append('dbapi-extension') + return [node] def visit_extension_node(self, node): @@ -50,4 +49,3 @@ def setup(app): text=(visit_extension_node, depart_extension_node)) app.add_directive('extension', Extension) - diff --git a/doc/src/tools/lib/sql_role.py b/doc/src/tools/lib/sql_role.py index 8fb8ab8..43347b4 100644 --- a/doc/src/tools/lib/sql_role.py +++ b/doc/src/tools/lib/sql_role.py @@ -12,10 +12,9 @@ from docutils import nodes, utils from docutils.parsers.rst import roles def sql_role(name, rawtext, text, lineno, inliner, options={}, content=[]): - text = utils.unescape(text) + text = utils.unescape(text) options['classes'] = ['sql'] return [nodes.literal(rawtext, text, **options)], [] - + def setup(app): roles.register_local_role('sql', sql_role) - diff --git a/doc/src/tools/lib/ticket_role.py b/doc/src/tools/lib/ticket_role.py index d8ded22..0ee3d63 100644 --- a/doc/src/tools/lib/ticket_role.py +++ b/doc/src/tools/lib/ticket_role.py @@ -56,4 +56,3 @@ def setup(app): app.add_config_value('ticket_remap_offset', None, 'env') app.add_role('ticket', ticket_role) app.add_role('tickets', ticket_role) - diff --git a/doc/src/tools/stitch_text.py b/doc/src/tools/stitch_text.py index c9ed99a..e026622 100755 --- a/doc/src/tools/stitch_text.py +++ b/doc/src/tools/stitch_text.py @@ -5,6 +5,7 @@ import os import sys + def main(): if len(sys.argv) != 3: sys.stderr.write("usage: %s index.rst text-dir\n") @@ -17,23 +18,20 @@ def main(): return 0 + def iter_file_base(fn): f = open(fn) - if sys.version_info[0] >= 3: - have_line = iter(f).__next__ - else: - have_line = iter(f).next - while not have_line().startswith('.. toctree'): + while not next(f).startswith('.. toctree'): pass - while have_line().strip().startswith(':'): + while next(f).strip().startswith(':'): pass yield os.path.splitext(os.path.basename(fn))[0] n = 0 while True: - line = have_line() + line = next(f) if line.isspace(): continue if line.startswith(".."): @@ -47,6 +45,7 @@ def iter_file_base(fn): # maybe format changed? raise Exception("Not enough files found. Format change in index.rst?") + def emit(basename, txt_dir): f = open(os.path.join(txt_dir, basename + ".txt")) for line in f: @@ -57,7 +56,6 @@ def emit(basename, txt_dir): # some space between sections sys.stdout.write("\n\n") - + if __name__ == '__main__': sys.exit(main()) - diff --git a/doc/src/tz.rst b/doc/src/tz.rst index 6e2e981..06333f8 100644 --- a/doc/src/tz.rst +++ b/doc/src/tz.rst @@ -8,9 +8,8 @@ This module holds two different tzinfo implementations that can be used as the `tzinfo` argument to `~datetime.datetime` constructors, directly passed to Psycopg functions or used to set the `cursor.tzinfo_factory` attribute in -cursors. +cursors. .. autoclass:: psycopg2.tz.FixedOffsetTimezone .. autoclass:: psycopg2.tz.LocalTimezone - diff --git a/doc/src/usage.rst b/doc/src/usage.rst index 660f290..db8674c 100644 --- a/doc/src/usage.rst +++ b/doc/src/usage.rst @@ -48,7 +48,7 @@ The main entry points of Psycopg are: - The class `connection` encapsulates a database session. It allows to: - - create new `cursor`\s using the `~connection.cursor()` method to + - create new `cursor` instances using the `~connection.cursor()` method to execute database commands and queries, - terminate transactions using the methods `~connection.commit()` or @@ -73,70 +73,97 @@ The main entry points of Psycopg are: Passing parameters to SQL queries --------------------------------- -Psycopg casts Python variables to SQL literals by type. Many standard Python types -are already `adapted to the correct SQL representation`__. +Psycopg converts Python variables to SQL values using their types: the Python +type determines the function used to convert the object into a string +representation suitable for PostgreSQL. Many standard Python types are +already `adapted to the correct SQL representation`__. .. __: python-types-adaptation_ -Example: the Python function call:: +Passing parameters to an SQL statement happens in functions such as +`cursor.execute()` by using ``%s`` placeholders in the SQL statement, and +passing a sequence of values as the second argument of the function. For +example the Python function call:: - >>> cur.execute( - ... """INSERT INTO some_table (an_int, a_date, a_string) - ... VALUES (%s, %s, %s);""", + >>> cur.execute(""" + ... INSERT INTO some_table (an_int, a_date, a_string) + ... VALUES (%s, %s, %s); + ... """, ... (10, datetime.date(2005, 11, 18), "O'Reilly")) -is converted into the SQL command:: +is converted into a SQL command similar to: + +.. code-block:: sql INSERT INTO some_table (an_int, a_date, a_string) - VALUES (10, '2005-11-18', 'O''Reilly'); + VALUES (10, '2005-11-18', 'O''Reilly'); -Named arguments are supported too using :samp:`%({name})s` placeholders. -Using named arguments the values can be passed to the query in any order and -many placeholders can use the same values:: +Named arguments are supported too using :samp:`%({name})s` placeholders in the +query and specifying the values into a mapping. Using named arguments allows +to specify the values in any order and to repeat the same value in several +places in the query:: - >>> cur.execute( - ... """INSERT INTO some_table (an_int, a_date, another_date, a_string) - ... VALUES (%(int)s, %(date)s, %(date)s, %(str)s);""", + >>> cur.execute(""" + ... INSERT INTO some_table (an_int, a_date, another_date, a_string) + ... VALUES (%(int)s, %(date)s, %(date)s, %(str)s); + ... """, ... {'int': 10, 'str': "O'Reilly", 'date': datetime.date(2005, 11, 18)}) +Using characters ``%``, ``(``, ``)`` in the argument names is not supported. + When parameters are used, in order to include a literal ``%`` in the query you -can use the ``%%`` string. Using characters ``%``, ``(``, ``)`` in the -argument names is not supported. +can use the ``%%`` string:: + + >>> cur.execute("SELECT (%s % 2) = 0 AS even", (10,)) # WRONG + >>> cur.execute("SELECT (%s %% 2) = 0 AS even", (10,)) # correct While the mechanism resembles regular Python strings manipulation, there are a few subtle differences you should care about when passing parameters to a -query: +query. -- The Python string operator ``%`` is not used: the `~cursor.execute()` +- The Python string operator ``%`` *must not be used*: the `~cursor.execute()` method accepts a tuple or dictionary of values as second parameter. - |sql-warn|__. + |sql-warn|__: .. |sql-warn| replace:: **Never** use ``%`` or ``+`` to merge values into queries .. __: sql-injection_ -- The variables placeholder must *always be a* ``%s``, even if a different - placeholder (such as a ``%d`` for integers or ``%f`` for floats) may look - more appropriate:: - - >>> cur.execute("INSERT INTO numbers VALUES (%d)", (42,)) # WRONG - >>> cur.execute("INSERT INTO numbers VALUES (%s)", (42,)) # correct + >>> cur.execute("INSERT INTO numbers VALUES (%s, %s)" % (10, 20)) # WRONG + >>> cur.execute("INSERT INTO numbers VALUES (%s, %s)", (10, 20)) # correct - For positional variables binding, *the second argument must always be a - sequence*, even if it contains a single variable. And remember that Python - requires a comma to create a single element tuple:: + sequence*, even if it contains a single variable (remember that Python + requires a comma to create a single element tuple):: >>> cur.execute("INSERT INTO foo VALUES (%s)", "bar") # WRONG >>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar")) # WRONG >>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct >>> cur.execute("INSERT INTO foo VALUES (%s)", ["bar"]) # correct +- The placeholder *must not be quoted*. Psycopg will add quotes where needed:: + + >>> cur.execute("INSERT INTO numbers VALUES ('%s')", (10,)) # WRONG + >>> cur.execute("INSERT INTO numbers VALUES (%s)", (10,)) # correct + +- The variables placeholder *must always be a* ``%s``, even if a different + placeholder (such as a ``%d`` for integers or ``%f`` for floats) may look + more appropriate:: + + >>> cur.execute("INSERT INTO numbers VALUES (%d)", (10,)) # WRONG + >>> cur.execute("INSERT INTO numbers VALUES (%s)", (10,)) # correct + - Only query values should be bound via this method: it shouldn't be used to - merge table or field names to the query. If you need to generate dynamically - an SQL query (for instance choosing dynamically a table name) you can use - the facilities provided by the `psycopg2.sql` module. + merge table or field names to the query (Psycopg will try quoting the table + name as a string value, generating invalid SQL). If you need to generate + dynamically SQL queries (for instance choosing dynamically a table name) + you can use the facilities provided by the `psycopg2.sql` module:: + >>> cur.execute("INSERT INTO %s VALUES (%s)", ('numbers', 10)) # WRONG + >>> cur.execute( # correct + ... SQL("INSERT INTO {} VALUES (%s)").format(Identifier('numbers')), + ... (10,)) .. index:: Security, SQL injection @@ -430,14 +457,12 @@ the connection or globally: see the function Binary adaptation ^^^^^^^^^^^^^^^^^ -Python types representing binary objects are converted into -PostgreSQL binary string syntax, suitable for :sql:`bytea` fields. Such -types are `buffer` (only available in Python 2), `memoryview` (available -from Python 2.7), `bytearray` (available from Python 2.6) and `bytes` -(only from Python 3: the name is available from Python 2.6 but it's only an -alias for the type `!str`). Any object implementing the `Revised Buffer -Protocol`__ should be usable as binary type where the protocol is supported -(i.e. from Python 2.6). Received data is returned as `!buffer` (in Python 2) +Python types representing binary objects are converted into PostgreSQL binary +string syntax, suitable for :sql:`bytea` fields. Such types are `buffer` +(only available in Python 2), `memoryview`, `bytearray`, and `bytes` (only in +Python 3: the name is available in Python 2 but it's only an alias for the +type `!str`). Any object implementing the `Revised Buffer Protocol`__ should +be usable as binary type. Received data is returned as `!buffer` (in Python 2) or `!memoryview` (in Python 3). .. __: http://www.python.org/dev/peps/pep-3118/ @@ -535,8 +560,7 @@ rounded to the nearest minute, with an error of up to 30 seconds. .. versionchanged:: 2.2.2 timezones with seconds are supported (with rounding). Previously such - timezones raised an error. In order to deal with them in previous - versions use `psycopg2.extras.register_tstz_w_secs()`. + timezones raised an error. .. index:: @@ -792,7 +816,9 @@ lifetime extends well after `~connection.commit()`, calling It is also possible to use a named cursor to consume a cursor created in some other way than using the |DECLARE| executed by `~cursor.execute()`. For example, you may have a PL/pgSQL function - returning a cursor:: + returning a cursor: + + .. code-block:: postgres CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$ BEGIN @@ -990,4 +1016,3 @@ For further details see the documentation for the above methods. .. __: http://www.opengroup.org/bookstore/catalog/c193.htm .. __: http://jdbc.postgresql.org/ - |
