ยปCore Development>Code coverage>Doc/tools/extensions/c_annotations.py

Python code coverage for Doc/tools/extensions/c_annotations.py

#countcontent
1n/a# -*- coding: utf-8 -*-
2n/a"""
3n/a c_annotations.py
4n/a ~~~~~~~~~~~~~~~~
5n/a
6n/a Supports annotations for C API elements:
7n/a
8n/a * reference count annotations for C API functions. Based on
9n/a refcount.py and anno-api.py in the old Python documentation tools.
10n/a
11n/a * stable API annotations
12n/a
13n/a Usage: Set the `refcount_file` config value to the path to the reference
14n/a count data file.
15n/a
16n/a :copyright: Copyright 2007-2014 by Georg Brandl.
17n/a :license: Python license.
18n/a"""
19n/a
20n/afrom os import path
21n/afrom docutils import nodes
22n/afrom docutils.parsers.rst import directives
23n/a
24n/afrom sphinx import addnodes
25n/afrom sphinx.domains.c import CObject
26n/a
27n/a
28n/aclass RCEntry:
29n/a def __init__(self, name):
30n/a self.name = name
31n/a self.args = []
32n/a self.result_type = ''
33n/a self.result_refs = None
34n/a
35n/a
36n/aclass Annotations(dict):
37n/a @classmethod
38n/a def fromfile(cls, filename):
39n/a d = cls()
40n/a fp = open(filename, 'r')
41n/a try:
42n/a for line in fp:
43n/a line = line.strip()
44n/a if line[:1] in ("", "#"):
45n/a # blank lines and comments
46n/a continue
47n/a parts = line.split(":", 4)
48n/a if len(parts) != 5:
49n/a raise ValueError("Wrong field count in %r" % line)
50n/a function, type, arg, refcount, comment = parts
51n/a # Get the entry, creating it if needed:
52n/a try:
53n/a entry = d[function]
54n/a except KeyError:
55n/a entry = d[function] = RCEntry(function)
56n/a if not refcount or refcount == "null":
57n/a refcount = None
58n/a else:
59n/a refcount = int(refcount)
60n/a # Update the entry with the new parameter or the result
61n/a # information.
62n/a if arg:
63n/a entry.args.append((arg, type, refcount))
64n/a else:
65n/a entry.result_type = type
66n/a entry.result_refs = refcount
67n/a finally:
68n/a fp.close()
69n/a return d
70n/a
71n/a def add_annotations(self, app, doctree):
72n/a for node in doctree.traverse(addnodes.desc_content):
73n/a par = node.parent
74n/a if par['domain'] != 'c':
75n/a continue
76n/a if par['stableabi']:
77n/a node.insert(0, nodes.emphasis(' Part of the stable ABI.',
78n/a ' Part of the stable ABI.',
79n/a classes=['stableabi']))
80n/a if par['objtype'] != 'function':
81n/a continue
82n/a if not par[0].has_key('names') or not par[0]['names']:
83n/a continue
84n/a name = par[0]['names'][0]
85n/a if name.startswith("c."):
86n/a name = name[2:]
87n/a entry = self.get(name)
88n/a if not entry:
89n/a continue
90n/a elif entry.result_type not in ("PyObject*", "PyVarObject*"):
91n/a continue
92n/a if entry.result_refs is None:
93n/a rc = 'Return value: Always NULL.'
94n/a elif entry.result_refs:
95n/a rc = 'Return value: New reference.'
96n/a else:
97n/a rc = 'Return value: Borrowed reference.'
98n/a node.insert(0, nodes.emphasis(rc, rc, classes=['refcount']))
99n/a
100n/a
101n/adef init_annotations(app):
102n/a refcounts = Annotations.fromfile(
103n/a path.join(app.srcdir, app.config.refcount_file))
104n/a app.connect('doctree-read', refcounts.add_annotations)
105n/a
106n/a
107n/adef setup(app):
108n/a app.add_config_value('refcount_file', '', True)
109n/a app.connect('builder-inited', init_annotations)
110n/a
111n/a # monkey-patch C object...
112n/a CObject.option_spec = {
113n/a 'noindex': directives.flag,
114n/a 'stableabi': directives.flag,
115n/a }
116n/a old_handle_signature = CObject.handle_signature
117n/a def new_handle_signature(self, sig, signode):
118n/a signode.parent['stableabi'] = 'stableabi' in self.options
119n/a return old_handle_signature(self, sig, signode)
120n/a CObject.handle_signature = new_handle_signature
121n/a return {'version': '1.0', 'parallel_read_safe': True}