File: changelog_links.py

package info (click to toggle)
sphinx-astropy 1.9.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 300 kB
  • sloc: python: 563; makefile: 5
file content (82 lines) | stat: -rw-r--r-- 2,976 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This sphinx extension makes the issue numbers in the changelog into links to
GitHub issues.
"""

import re
from docutils.nodes import Text, reference

BLOCK_PATTERN = re.compile(r'\[#.+\]', flags=re.DOTALL)
ISSUE_PATTERN = re.compile('#[0-9]+')


def process_changelog_links(app, doctree, docname):
    for rex in app.changelog_links_rexes:
        if rex.match(docname):
            break
    else:
        # if the doc doesn't match any of the changelog regexes, don't process
        return

    from sphinx.util import logging
    info = logging.getLogger(__name__).info

    info('[changelog_links] Adding changelog links to "{0}"'.format(docname))

    for item in doctree.traverse():

        if not isinstance(item, Text) or item.parent is None:
            continue

        # We build a new list of items to replace the current item. If
        # a link is found, we need to use a 'reference' item.
        children = []

        # First cycle through blocks of issues (delimited by []) then
        # iterate inside each one to find the individual issues.
        prev_block_end = 0
        for block in BLOCK_PATTERN.finditer(item):
            block_start, block_end = block.start(), block.end()
            children.append(Text(item[prev_block_end:block_start]))
            block = item[block_start:block_end]
            prev_end = 0
            for m in ISSUE_PATTERN.finditer(block):
                start, end = m.start(), m.end()
                children.append(Text(block[prev_end:start]))
                issue_number = block[start:end]
                refuri = app.config.github_issues_url + issue_number[1:]
                children.append(reference(text=issue_number,
                                          name=issue_number,
                                          refuri=refuri))
                prev_end = end

            prev_block_end = block_end

            # If no issues were found, this adds the whole item,
            # otherwise it adds the remaining text.
            children.append(Text(block[prev_end:block_end]))

        # If no blocks were found, this adds the whole item, otherwise
        # it adds the remaining text.
        children.append(Text(item[prev_block_end:]))

        # Replace item by the new list of items we have generated,
        # which may contain links.
        item.parent.replace(item, children)


def setup_patterns_rexes(app):
    app.changelog_links_rexes = [re.compile(pat) for pat in
                                 app.config.changelog_links_docpattern]


def setup(app):

    app.connect('doctree-resolved', process_changelog_links)
    app.connect('builder-inited', setup_patterns_rexes)
    app.add_config_value('github_issues_url', None, True)
    app.add_config_value('changelog_links_docpattern', ['.*changelog.*', 'whatsnew/.*'], True)

    return {'parallel_read_safe': True,
            'parallel_write_safe': True}