[Python-checkins] cpython (2.7): backport our own copy of the ref-counting extension

benjamin.peterson python-checkins at python.org
Fri Sep 5 16:03:40 CEST 2014


http://hg.python.org/cpython/rev/9d41ceea3b8b
changeset:   92350:9d41ceea3b8b
branch:      2.7
user:        Benjamin Peterson <benjamin at python.org>
date:        Fri Sep 05 10:03:26 2014 -0400
summary:
  backport our own copy of the ref-counting extension

files:
  Doc/conf.py                          |    4 +-
  Doc/tools/sphinxext/c_annotations.py |  120 +++++++++++++++
  2 files changed, 122 insertions(+), 2 deletions(-)


diff --git a/Doc/conf.py b/Doc/conf.py
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -13,8 +13,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,120 @@
+# -*- 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['stableabi']:
+                node.insert(0, nodes.emphasis(' Part of the stable ABI.',
+                                              ' Part of the stable ABI.',
+                                              classes=['stableabi']))
+            if par['objtype'] != 'function':
+                continue
+            if not par[0].has_key('names') or not par[0]['names']:
+                continue
+            name = par[0]['names'][0]
+            if name.startswith("c."):
+                name = name[2:]
+            entry = self.get(name)
+            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,
+        'stableabi': directives.flag,
+    }
+    old_handle_signature = CObject.handle_signature
+    def new_handle_signature(self, sig, signode):
+        signode.parent['stableabi'] = 'stableabi' in self.options
+        return old_handle_signature(self, sig, signode)
+    CObject.handle_signature = new_handle_signature

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


More information about the Python-checkins mailing list