diff options
Diffstat (limited to 'Doc/tools')
-rw-r--r-- | Doc/tools/extensions/c_annotations.py | 4 | ||||
-rw-r--r-- | Doc/tools/extensions/glossary_search.py | 57 | ||||
-rw-r--r-- | Doc/tools/extensions/pyspecific.py | 7 | ||||
-rwxr-xr-x | Doc/tools/rstlint.py | 76 | ||||
-rw-r--r-- | Doc/tools/static/switchers.js | 156 | ||||
-rw-r--r-- | Doc/tools/templates/dummy.html | 9 | ||||
-rw-r--r-- | Doc/tools/templates/indexsidebar.html | 8 | ||||
-rw-r--r-- | Doc/tools/templates/layout.html | 10 | ||||
-rw-r--r-- | Doc/tools/templates/search.html | 48 |
9 files changed, 201 insertions, 174 deletions
diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index fa8244a8fd..76c9d920cb 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -79,9 +79,9 @@ class Annotations(dict): classes=['stableabi'])) if par['objtype'] != 'function': continue - if not par[0].has_key('names') or not par[0]['names']: + if not par[0].has_key('ids') or not par[0]['ids']: continue - name = par[0]['names'][0] + name = par[0]['ids'][0] if name.startswith("c."): name = name[2:] entry = self.get(name) diff --git a/Doc/tools/extensions/glossary_search.py b/Doc/tools/extensions/glossary_search.py new file mode 100644 index 0000000000..34d227d670 --- /dev/null +++ b/Doc/tools/extensions/glossary_search.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" + glossary_search.py + ~~~~~~~~~~~~~~~~ + + Feature search results for glossary items prominently. + + :license: Python license. +""" +from os import path +from sphinx.addnodes import glossary +from sphinx.util import logging +from docutils.nodes import definition_list_item +import json + + +logger = logging.getLogger(__name__) + + +def process_glossary_nodes(app, doctree, fromdocname): + if app.builder.format != 'html': + return + + terms = {} + + for node in doctree.traverse(glossary): + for glossary_item in node.traverse(definition_list_item): + term = glossary_item[0].astext().lower() + definition = glossary_item[1] + + rendered = app.builder.render_partial(definition) + terms[term] = { + 'title': glossary_item[0].astext(), + 'body': rendered['html_body'] + } + + if hasattr(app.env, 'glossary_terms'): + app.env.glossary_terms.update(terms) + else: + app.env.glossary_terms = terms + +def on_build_finish(app, exc): + if not hasattr(app.env, 'glossary_terms'): + return + if not app.env.glossary_terms: + return + + logger.info('Writing glossary.json', color='green') + with open(path.join(app.outdir, '_static', 'glossary.json'), 'w') as f: + json.dump(app.env.glossary_terms, f) + + +def setup(app): + app.connect('doctree-resolved', process_glossary_nodes) + app.connect('build-finished', on_build_finish) + + return {'version': '0.1', 'parallel_read_safe': True} diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 80fbd96d56..28994399e2 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -394,7 +394,12 @@ class DeprecatedRemoved(Directive): translatable=False) node.append(para) env = self.state.document.settings.env - env.get_domain('changeset').note_changeset(node) + # deprecated pre-Sphinx-2 method + if hasattr(env, 'note_versionchange'): + env.note_versionchange('deprecated', version[0], node, self.lineno) + # new method + else: + env.get_domain('changeset').note_changeset(node) return [node] + messages diff --git a/Doc/tools/rstlint.py b/Doc/tools/rstlint.py index a3024d6734..cbcb8eb801 100755 --- a/Doc/tools/rstlint.py +++ b/Doc/tools/rstlint.py @@ -13,6 +13,7 @@ import os import re import sys import getopt +from string import ascii_letters from os.path import join, splitext, abspath, exists from collections import defaultdict @@ -128,6 +129,81 @@ def check_leaked_markup(fn, lines): yield lno+1, 'possibly leaked markup: %r' % line +def hide_literal_blocks(lines): + """Tool to remove literal blocks from given lines. + + It yields empty lines in place of blocks, so line numbers are + still meaningful. + """ + in_block = False + for line in lines: + if line.endswith("::\n"): + in_block = True + elif in_block: + if line == "\n" or line.startswith(" "): + line = "\n" + else: + in_block = False + yield line + + +def type_of_explicit_markup(line): + if re.match(fr'\.\. {all_directives}::', line): + return 'directive' + if re.match(r'\.\. \[[0-9]+\] ', line): + return 'footnote' + if re.match(r'\.\. \[[^\]]+\] ', line): + return 'citation' + if re.match(r'\.\. _.*[^_]: ', line): + return 'target' + if re.match(r'\.\. \|[^\|]*\| ', line): + return 'substitution_definition' + return 'comment' + + +def hide_comments(lines): + """Tool to remove comments from given lines. + + It yields empty lines in place of comments, so line numbers are + still meaningfull. + """ + in_multiline_comment = False + for line in lines: + if line == "..\n": + in_multiline_comment = True + elif in_multiline_comment: + if line == "\n" or line.startswith(" "): + line = "\n" + else: + in_multiline_comment = False + if line.startswith(".. ") and type_of_explicit_markup(line) == 'comment': + line = "\n" + yield line + + + +@checker(".rst", severity=2) +def check_missing_surrogate_space_on_plural(fn, lines): + r"""Check for missing 'backslash-space' between a code sample a letter. + + Good: ``Point``\ s + Bad: ``Point``s + """ + in_code_sample = False + check_next_one = False + for lno, line in enumerate(hide_comments(hide_literal_blocks(lines))): + tokens = line.split("``") + for token_no, token in enumerate(tokens): + if check_next_one: + if token[0] in ascii_letters: + yield lno + 1, f"Missing backslash-space between code sample and {token!r}." + check_next_one = False + if token_no == len(tokens) - 1: + continue + if in_code_sample: + check_next_one = True + in_code_sample = not in_code_sample + def main(argv): usage = '''\ Usage: %s [-v] [-f] [-s sev] [-i path]* [path] diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js deleted file mode 100644 index 1a1c7d0fa5..0000000000 --- a/Doc/tools/static/switchers.js +++ /dev/null @@ -1,156 +0,0 @@ -(function() { - 'use strict'; - - // Parses versions in URL segments like: - // "3", "dev", "release/2.7" or "3.6rc2" - var version_regexs = [ - '(?:\\d)', - '(?:\\d\\.\\d[\\w\\d\\.]*)', - '(?:dev)', - '(?:release/\\d.\\d[\\x\\d\\.]*)']; - - var all_versions = { - '3.10': 'dev (3.10)', - '3.9': 'pre (3.9)', - '3.8': '3.8', - '3.7': '3.7', - '3.6': '3.6', - '2.7': '2.7', - }; - - var all_languages = { - 'en': 'English', - 'fr': 'French', - 'ja': 'Japanese', - 'ko': 'Korean', - 'pt-br': 'Brazilian Portuguese', - 'zh-cn': 'Simplified Chinese', - }; - - function build_version_select(current_version, current_release) { - var buf = ['<select>']; - - $.each(all_versions, function(version, title) { - buf.push('<option value="' + version + '"'); - if (version == current_version) - buf.push(' selected="selected">' + current_release + '</option>'); - else - buf.push('>' + title + '</option>'); - }); - - buf.push('</select>'); - return buf.join(''); - } - - function build_language_select(current_language) { - var buf = ['<select>']; - - $.each(all_languages, function(language, title) { - if (language == current_language) - buf.push('<option value="' + language + '" selected="selected">' + - all_languages[current_language] + '</option>'); - else - buf.push('<option value="' + language + '">' + title + '</option>'); - }); - if (!(current_language in all_languages)) { - // In case we're browsing a language that is not yet in all_languages. - buf.push('<option value="' + current_language + '" selected="selected">' + - current_language + '</option>'); - all_languages[current_language] = current_language; - } - buf.push('</select>'); - return buf.join(''); - } - - function navigate_to_first_existing(urls) { - // Navigate to the first existing URL in urls. - var url = urls.shift(); - if (urls.length == 0) { - window.location.href = url; - return; - } - $.ajax({ - url: url, - success: function() { - window.location.href = url; - }, - error: function() { - navigate_to_first_existing(urls); - } - }); - } - - function on_version_switch() { - var selected_version = $(this).children('option:selected').attr('value') + '/'; - var url = window.location.href; - var current_language = language_segment_from_url(url); - var current_version = version_segment_in_url(url); - var new_url = url.replace('.org/' + current_language + current_version, - '.org/' + current_language + selected_version); - if (new_url != url) { - navigate_to_first_existing([ - new_url, - url.replace('.org/' + current_language + current_version, - '.org/' + selected_version), - 'https://docs.python.org/' + current_language + selected_version, - 'https://docs.python.org/' + selected_version, - 'https://docs.python.org/' - ]); - } - } - - function on_language_switch() { - var selected_language = $(this).children('option:selected').attr('value') + '/'; - var url = window.location.href; - var current_language = language_segment_from_url(url); - var current_version = version_segment_in_url(url); - if (selected_language == 'en/') // Special 'default' case for english. - selected_language = ''; - var new_url = url.replace('.org/' + current_language + current_version, - '.org/' + selected_language + current_version); - if (new_url != url) { - navigate_to_first_existing([ - new_url, - 'https://docs.python.org/' - ]); - } - } - - // Returns the path segment of the language as a string, like 'fr/' - // or '' if not found. - function language_segment_from_url(url) { - var language_regexp = '\.org/([a-z]{2}(?:-[a-z]{2})?/)'; - var match = url.match(language_regexp); - if (match !== null) - return match[1]; - return ''; - } - - // Returns the path segment of the version as a string, like '3.6/' - // or '' if not found. - function version_segment_in_url(url) { - var language_segment = '(?:[a-z]{2}(?:-[a-z]{2})?/)'; - var version_segment = '(?:(?:' + version_regexs.join('|') + ')/)'; - var version_regexp = '\\.org/' + language_segment + '?(' + version_segment + ')'; - var match = url.match(version_regexp); - if (match !== null) - return match[1]; - return '' - } - - $(document).ready(function() { - var release = DOCUMENTATION_OPTIONS.VERSION; - var language_segment = language_segment_from_url(window.location.href); - var current_language = language_segment.replace(/\/+$/g, '') || 'en'; - var version = release.substr(0, 3); - var version_select = build_version_select(version, release); - - $('.version_switcher_placeholder').html(version_select); - $('.version_switcher_placeholder select').bind('change', on_version_switch); - - var language_select = build_language_select(current_language); - - $('.language_switcher_placeholder').html(language_select); - $('.language_switcher_placeholder select').bind('change', on_language_switch); - }); -})(); diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 68ae3ad148..3438b44377 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -6,3 +6,12 @@ In extensions/pyspecific.py: {% trans %}CPython implementation detail:{% endtrans %} {% trans %}Deprecated since version {deprecated}, will be removed in version {removed}{% endtrans %} {% trans %}Deprecated since version {deprecated}, removed in version {removed}{% endtrans %} + + +In docsbuild-scripts, when rewriting indexsidebar.html with actual versions: + +{% trans %}in development{% endtrans %} +{% trans %}pre-release{% endtrans %} +{% trans %}stable{% endtrans %} +{% trans %}security-fixes{% endtrans %} +{% trans %}EOL{% endtrans %} diff --git a/Doc/tools/templates/indexsidebar.html b/Doc/tools/templates/indexsidebar.html index 1c1cb5484a..f7bf6d8e49 100644 --- a/Doc/tools/templates/indexsidebar.html +++ b/Doc/tools/templates/indexsidebar.html @@ -2,12 +2,8 @@ <p><a href="{{ pathto('download') }}">{% trans %}Download these documents{% endtrans %}</a></p> <h3>{% trans %}Docs by version{% endtrans %}</h3> <ul> - <li><a href="https://docs.python.org/3.10/">{% trans %}Python 3.10 (in development){% endtrans %}</a></li> - <li><a href="https://docs.python.org/3.9/">{% trans %}Python 3.9 (pre-release){% endtrans %}</a></li> - <li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (stable){% endtrans %}</a></li> - <li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li> - <li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li> - <li><a href="https://docs.python.org/2.7/">{% trans %}Python 2.7 (EOL){% endtrans %}</a></li> + <li><a href="https://docs.python.org/">{% trans %}Stable{% endtrans %}</a></li> + <li><a href="https://docs.python.org/dev/">{% trans %}In development{% endtrans %}</a></li> <li><a href="https://www.python.org/doc/versions/">{% trans %}All versions{% endtrans %}</a></li> </ul> diff --git a/Doc/tools/templates/layout.html b/Doc/tools/templates/layout.html index 17592d74a4..98ccf42248 100644 --- a/Doc/tools/templates/layout.html +++ b/Doc/tools/templates/layout.html @@ -12,22 +12,14 @@ {% block rootrellink %} {{ super() }} - <li> - {%- if switchers is defined %} - <span class="language_switcher_placeholder">{{ language or 'en' }}</span> - <span class="version_switcher_placeholder">{{ release }}</span> - <a href="{{ pathto('index') }}">{% trans %}Documentation {% endtrans %}</a>{{ reldelim1 }} - {%- else %} + <li id="cpython-language-and-version"> <a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }} - {%- endif %} </li> {% endblock %} {% block extrahead %} <link rel="canonical" href="https://docs.python.org/3/{{pagename}}.html" /> {% if builder != "htmlhelp" %} - {% if switchers is defined and not embedded %} - <script type="text/javascript" src="{{ pathto('_static/switchers.js', 1) }}"></script>{% endif %} {% if pagename == 'whatsnew/changelog' and not embedded %} <script type="text/javascript" src="{{ pathto('_static/changelog_search.js', 1) }}"></script>{% endif %} {% endif %} diff --git a/Doc/tools/templates/search.html b/Doc/tools/templates/search.html new file mode 100644 index 0000000000..cf20c2e1d4 --- /dev/null +++ b/Doc/tools/templates/search.html @@ -0,0 +1,48 @@ +{% extends "!search.html" %} +{% block extrahead %} + {{ super() }} + <script type="text/javascript"> + var GLOSSARY_PAGE = 'glossary.html'; + + jQuery(function() { + $.getJSON("_static/glossary.json", function(glossary) { + var RESULT_TEMPLATE = '<div style="display: none" class="admonition seealso" id="glossary-result">' + + ' <p class="topic-title">' + + ' <a class="glossary-title" href="#"></a>' + + ' </p>' + + ' <div class="glossary-body"></div>' + + '</div>'; + $("#search-results").prepend(RESULT_TEMPLATE); + + var params = $.getQueryParameters(); + if (params.q) { + var search_param = params.q[0].toLowerCase(); + var glossary_item = glossary[search_param]; + if (glossary_item) { + var resultDiv = $("#glossary-result"); + + // set up the title text with a link to the glossary page + resultDiv.find(".glossary-title").text('Glossary: ' + glossary_item.title); + var link_target = search_param.replace(/ /g, '-'); + resultDiv.find(".glossary-title").attr( + 'href', GLOSSARY_PAGE + '#term-' + link_target + ); + + // rewrite any anchor links (to other glossary terms) + // to have a full reference to the glossary page + var body = $(glossary_item.body).children(); + body.find("a[href^='#']").each(function() { + var current_url = $(this).attr('href'); + $(this).attr('href', GLOSSARY_PAGE + current_url); + }); + resultDiv.find(".glossary-body").html(body); + + resultDiv.show(); + } else { + $("#glossary-result").hide(''); + } + } + }); + }); + </script> +{% endblock %}
\ No newline at end of file |