mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 09:57:32 +00:00 
			
		
		
		
	 83dd4e87a6
			
		
	
	
		83dd4e87a6
		
			
		
	
	
	
	
		
			
			Fixed some errors in refcounts.dat, remove functions removed in Python 3, and add more entries for documented functions. This will add several automatically generated notes about return values.
		
			
				
	
	
		
			121 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
	
		
			4 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-2014 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 not entry.result_type.endswith("Object*"):
 | |
|                 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
 | |
|     return {'version': '1.0', 'parallel_read_safe': True}
 |