mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 08:19:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			117 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- 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
 | |
|             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,
 | |
|         '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
 | 
