1 |
commit: 59a72da360e2eff53ef510261c3f6307148b52dc |
2 |
Author: Michał Górny <mgorny <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Feb 22 17:15:51 2020 +0000 |
4 |
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Feb 25 15:15:23 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/policy-guide.git/commit/?id=59a72da3 |
7 |
|
8 |
Generate a Policy Index |
9 |
|
10 |
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> |
11 |
|
12 |
exts/policyident.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--- |
13 |
1 file changed, 75 insertions(+), 3 deletions(-) |
14 |
|
15 |
diff --git a/exts/policyident.py b/exts/policyident.py |
16 |
index 6093c8c..7ecc9f2 100644 |
17 |
--- a/exts/policyident.py |
18 |
+++ b/exts/policyident.py |
19 |
@@ -2,13 +2,44 @@ |
20 |
# (c) 2020 Michał Górny |
21 |
# 2-clause BSD license |
22 |
|
23 |
+import collections |
24 |
+ |
25 |
from docutils import nodes |
26 |
|
27 |
+from sphinx.domains import Index |
28 |
from sphinx.util import logging |
29 |
|
30 |
|
31 |
logger = logging.getLogger(__name__) |
32 |
|
33 |
+Policy = collections.namedtuple('Policy', ('id', 'title', 'docname', |
34 |
+ 'chapter')) |
35 |
+ |
36 |
+ |
37 |
+class PolicyIndex(Index): |
38 |
+ name = 'policy-index' |
39 |
+ localname = 'Policy Index' |
40 |
+ shortname = 'Policy Index' |
41 |
+ |
42 |
+ def generate(self, docnames=None): |
43 |
+ env = self.domain.env |
44 |
+ if not hasattr(env, 'policy_index'): |
45 |
+ env.policy_index = [] |
46 |
+ |
47 |
+ entries = collections.defaultdict(list) |
48 |
+ for p in env.policy_index: |
49 |
+ if docnames is not None and p.docname not in docnames: |
50 |
+ continue |
51 |
+ entries[p.chapter].append(('PG' + p.id, # name |
52 |
+ 0, # subtype |
53 |
+ p.docname, # docname |
54 |
+ 'pg' + p.id, # anchor |
55 |
+ p.title, # extra |
56 |
+ '', # qualifier |
57 |
+ '')) # descr |
58 |
+ |
59 |
+ return ([(k, sorted(v)) for k, v in entries.items()], False) |
60 |
+ |
61 |
|
62 |
def find_pg_id(section): |
63 |
# first child should be title |
64 |
@@ -17,7 +48,7 @@ def find_pg_id(section): |
65 |
# second child should be field list |
66 |
cl = section.children[1] |
67 |
if not isinstance(cl, nodes.field_list): |
68 |
- return None |
69 |
+ return None, title.astext(), None |
70 |
|
71 |
for f in cl.traverse(nodes.field): |
72 |
fn = next(iter(f.traverse(nodes.field_name))) |
73 |
@@ -29,20 +60,61 @@ def find_pg_id(section): |
74 |
if fv.astext() != iv: |
75 |
raise RuntimeError('PG value must be 4 digits, zero-padded ({})' |
76 |
.format(iv)) |
77 |
- return iv |
78 |
+ |
79 |
+ el = section |
80 |
+ titles = [] |
81 |
+ while el.parent is not None: |
82 |
+ title = el.children[0] |
83 |
+ assert isinstance(title, nodes.title) |
84 |
+ titles.append(title.astext()) |
85 |
+ el = el.parent |
86 |
+ # combine all section titles up to but excluding |
87 |
+ # the chapter title |
88 |
+ title = ': '.join(reversed(titles[:-1])) |
89 |
+ |
90 |
+ return iv, title, titles[-1] |
91 |
|
92 |
logger.warning('%s: no PG identifier found', title.astext()) |
93 |
+ return None, title.astext(), None |
94 |
|
95 |
|
96 |
def on_doctree_read(app, doctree): |
97 |
+ env = app.builder.env |
98 |
+ if not hasattr(env, 'policy_index'): |
99 |
+ env.policy_index = [] |
100 |
+ |
101 |
for node in doctree.traverse(nodes.section): |
102 |
- pg_id = find_pg_id(node) |
103 |
+ pg_id, title, chapter = find_pg_id(node) |
104 |
if pg_id is not None: |
105 |
node['ids'].insert(0, 'pg' + pg_id) |
106 |
+ env.policy_index.append(Policy(pg_id, title, env.docname, |
107 |
+ chapter)) |
108 |
+ |
109 |
+ |
110 |
+def on_env_purge_doc(app, env, docname): |
111 |
+ if not hasattr(env, 'policy_index'): |
112 |
+ return |
113 |
+ |
114 |
+ env.policy_index = [p for p in env.policy_index |
115 |
+ if p.docname != docname] |
116 |
+ |
117 |
+ |
118 |
+def on_env_merge_info(app, env, docnames, other): |
119 |
+ if not hasattr(other, 'policy_index'): |
120 |
+ return |
121 |
+ if not hasattr(env, 'policy_index'): |
122 |
+ env.policy_index = [] |
123 |
+ |
124 |
+ env.policy_index.extend(other.policy_index) |
125 |
|
126 |
|
127 |
def setup(app): |
128 |
app.connect('doctree-read', on_doctree_read) |
129 |
+ app.connect('env-purge-doc', on_env_purge_doc) |
130 |
+ app.connect('env-merge-info', on_env_merge_info) |
131 |
+ app.add_index_to_domain('std', PolicyIndex) |
132 |
return { |
133 |
'version': '0', |
134 |
+ 'parallel_read_safe': True, |
135 |
+ 'parallel_write_safe': True, |
136 |
} |