[Python-checkins] cpython (merge 3.3 -> default): merge with 3.3

georg.brandl python-checkins at python.org
Sat Oct 12 20:00:26 CEST 2013


http://hg.python.org/cpython/rev/b59bff04aec8
changeset:   86243:b59bff04aec8
parent:      86241:23fe05e85ba3
parent:      86242:a63af1c8e0b1
user:        Georg Brandl <georg at python.org>
date:        Sat Oct 12 20:01:14 2013 +0200
summary:
  merge with 3.3

files:
  Doc/c-api/index.rst                                  |    2 +-
  Doc/c-api/stable.rst                                 |   51 ++--
  Doc/conf.py                                          |    4 +-
  Doc/tools/sphinxext/c_annotations.py                 |  117 ++++++++++
  Doc/tools/sphinxext/pydoctheme/static/pydoctheme.css |    8 +
  5 files changed, 152 insertions(+), 30 deletions(-)


diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst
--- a/Doc/c-api/index.rst
+++ b/Doc/c-api/index.rst
@@ -13,6 +13,7 @@
    :maxdepth: 2
 
    intro.rst
+   stable.rst
    veryhigh.rst
    refcounting.rst
    exceptions.rst
@@ -22,5 +23,4 @@
    init.rst
    memory.rst
    objimpl.rst
-   stable.rst
    apiabiversion.rst
diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst
--- a/Doc/c-api/stable.rst
+++ b/Doc/c-api/stable.rst
@@ -6,36 +6,33 @@
 Stable Application Binary Interface
 ***********************************
 
-Traditionally, the C API of Python will change with every release.
-Most changes will be source-compatible, typically by only adding API,
-rather than changing existing API or removing API (although some
-interfaces do get removed after being deprecated first).
+Traditionally, the C API of Python will change with every release.  Most changes
+will be source-compatible, typically by only adding API, rather than changing
+existing API or removing API (although some interfaces do get removed after
+being deprecated first).
 
-Unfortunately, the API compatibility does not extend to binary
-compatibility (the ABI). The reason is primarily the evolution of
-struct definitions, where addition of a new field, or changing
-the type of a field, might not break the API, but can break the ABI.
-As a consequence, extension modules need to be recompiled for
-every Python release (although an exception is possible on Unix
-when none of the affected interfaces are used). In addition, on
-Windows, extension modules link with a specific pythonXY.dll and
-need to be recompiled to link with a newer one.
+Unfortunately, the API compatibility does not extend to binary compatibility
+(the ABI). The reason is primarily the evolution of struct definitions, where
+addition of a new field, or changing the type of a field, might not break the
+API, but can break the ABI.  As a consequence, extension modules need to be
+recompiled for every Python release (although an exception is possible on Unix
+when none of the affected interfaces are used). In addition, on Windows,
+extension modules link with a specific pythonXY.dll and need to be recompiled to
+link with a newer one.
 
-Since Python 3.2, a subset of the API has been declared to guarantee
-a stable ABI. Extension modules wishing to use this API need to define
-``Py_LIMITED_API``. A number of interpreter details then become hidden
-from the extension module; in return, a module is built that works
-on any 3.x version (x>=2) without recompilation.
+Since Python 3.2, a subset of the API has been declared to guarantee a stable
+ABI. Extension modules wishing to use this API (called "limited API") need to
+define ``Py_LIMITED_API``. A number of interpreter details then become hidden
+from the extension module; in return, a module is built that works on any 3.x
+version (x>=2) without recompilation.
 
 In some cases, the stable ABI needs to be extended with new functions.
-Extension modules wishing to use these new APIs need to set
-``Py_LIMITED_API`` to the ``PY_VERSION_HEX`` value (see
-:ref:`apiabiversion`) of the minimum Python version they want to
-support (e.g. ``0x03030000`` for Python 3.3). Such modules will work
-on all subsequent Python releases, but fail to load (because of
+Extension modules wishing to use these new APIs need to set ``Py_LIMITED_API``
+to the ``PY_VERSION_HEX`` value (see :ref:`apiabiversion`) of the minimum Python
+version they want to support (e.g. ``0x03030000`` for Python 3.3). Such modules
+will work on all subsequent Python releases, but fail to load (because of
 missing symbols) on the older releases.
 
-As of Python 3.2, the set of functions available to the limited API
-is documented in PEP 384.
-
-.. XXX copy exact list here? Into each functions definition?
+As of Python 3.2, the set of functions available to the limited API is
+documented in PEP 384.  In the C API documentation, API elements that are not
+part of the limited API are marked as "Not part of the limited API."
diff --git a/Doc/conf.py b/Doc/conf.py
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -12,8 +12,8 @@
 # General configuration
 # ---------------------
 
-extensions = ['sphinx.ext.refcounting', 'sphinx.ext.coverage',
-              'sphinx.ext.doctest', 'pyspecific']
+extensions = ['sphinx.ext.coverage', 'sphinx.ext.doctest',
+              'pyspecific', 'c_annotations']
 templates_path = ['tools/sphinxext']
 
 # General substitutions.
diff --git a/Doc/tools/sphinxext/c_annotations.py b/Doc/tools/sphinxext/c_annotations.py
new file mode 100644
--- /dev/null
+++ b/Doc/tools/sphinxext/c_annotations.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+"""
+    c_annotations.py
+    ~~~~~~~~~~~~~~~~
+
+    Supports annotations for C API elements:
+
+    * reference count annotations for C API functions.  Based on
+      refcount.py and anno-api.py in the old Python documentation tools.
+
+    * stable API annotations
+
+    Usage: Set the `refcount_file` config value to the path to the reference
+    count data file.
+
+    :copyright: Copyright 2007-2013 by Georg Brandl.
+    :license: Python license.
+"""
+
+from os import path
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx import addnodes
+from sphinx.domains.c import CObject
+
+
+class RCEntry:
+    def __init__(self, name):
+        self.name = name
+        self.args = []
+        self.result_type = ''
+        self.result_refs = None
+
+
+class Annotations(dict):
+    @classmethod
+    def fromfile(cls, filename):
+        d = cls()
+        fp = open(filename, 'r')
+        try:
+            for line in fp:
+                line = line.strip()
+                if line[:1] in ("", "#"):
+                    # blank lines and comments
+                    continue
+                parts = line.split(":", 4)
+                if len(parts) != 5:
+                    raise ValueError("Wrong field count in %r" % line)
+                function, type, arg, refcount, comment = parts
+                # Get the entry, creating it if needed:
+                try:
+                    entry = d[function]
+                except KeyError:
+                    entry = d[function] = RCEntry(function)
+                if not refcount or refcount == "null":
+                    refcount = None
+                else:
+                    refcount = int(refcount)
+                # Update the entry with the new parameter or the result
+                # information.
+                if arg:
+                    entry.args.append((arg, type, refcount))
+                else:
+                    entry.result_type = type
+                    entry.result_refs = refcount
+        finally:
+            fp.close()
+        return d
+
+    def add_annotations(self, app, doctree):
+        for node in doctree.traverse(addnodes.desc_content):
+            par = node.parent
+            if par['domain'] != 'c':
+                continue
+            if par['notlimited']:
+                node.insert(0, nodes.emphasis(' Not part of the stable API.',
+                                              ' Not part of the stable API.',
+                                              classes=['notlimited']))
+            if par['objtype'] != 'function':
+                continue
+            if not par[0].has_key('names') or not par[0]['names']:
+                continue
+            entry = self.get(par[0]['names'][0])
+            if not entry:
+                continue
+            elif entry.result_type not in ("PyObject*", "PyVarObject*"):
+                continue
+            if entry.result_refs is None:
+                rc = 'Return value: Always NULL.'
+            elif entry.result_refs:
+                rc = 'Return value: New reference.'
+            else:
+                rc = 'Return value: Borrowed reference.'
+            node.insert(0, nodes.emphasis(rc, rc, classes=['refcount']))
+
+
+def init_annotations(app):
+    refcounts = Annotations.fromfile(
+        path.join(app.srcdir, app.config.refcount_file))
+    app.connect('doctree-read', refcounts.add_annotations)
+
+
+def setup(app):
+    app.add_config_value('refcount_file', '', True)
+    app.connect('builder-inited', init_annotations)
+
+    # monkey-patch C object...
+    CObject.option_spec = {
+        'noindex': directives.flag,
+        'notlimited': directives.flag,
+    }
+    old_handle_signature = CObject.handle_signature
+    def new_handle_signature(self, sig, signode):
+        signode.parent['notlimited'] = 'notlimited' in self.options
+        return old_handle_signature(self, sig, signode)
+    CObject.handle_signature = new_handle_signature
diff --git a/Doc/tools/sphinxext/pydoctheme/static/pydoctheme.css b/Doc/tools/sphinxext/pydoctheme/static/pydoctheme.css
--- a/Doc/tools/sphinxext/pydoctheme/static/pydoctheme.css
+++ b/Doc/tools/sphinxext/pydoctheme/static/pydoctheme.css
@@ -168,3 +168,11 @@
 div.footer a:hover {
     color: #0095C4;
 }
+
+.refcount {
+    color: #060;
+}
+
+.notlimited {
+    color: #922;
+}

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list