summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2019-12-21 12:21:49 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2019-12-21 12:21:49 +0900
commitd47f38e22db5da29c6b3ccce6b213cdc169f0ecd (patch)
treee6ec96b88a836372f8689efe61ef1baf7769777e
parent26a17eade449bfec74aabc6adc9b056d52aa3cf0 (diff)
parentacdcf81599d49de751811269cd428850605224a1 (diff)
downloadsphinx-git-d47f38e22db5da29c6b3ccce6b213cdc169f0ecd.tar.gz
Merge branch '2.0'
-rw-r--r--CHANGES30
-rw-r--r--doc/_themes/sphinx13/layout.html2
-rw-r--r--doc/extdev/deprecated.rst10
-rw-r--r--doc/faq.rst5
-rw-r--r--doc/usage/extensions/duration.rst11
-rw-r--r--doc/usage/extensions/index.rst1
-rw-r--r--setup.py2
-rw-r--r--sphinx/builders/html.py2
-rw-r--r--sphinx/errors.py5
-rw-r--r--sphinx/ext/duration.py96
-rw-r--r--sphinx/io.py27
-rw-r--r--sphinx/pycode/parser.py2
-rw-r--r--sphinx/themes/basic/domainindex.html2
-rw-r--r--sphinx/themes/basic/layout.html2
-rw-r--r--sphinx/themes/basic/search.html6
-rw-r--r--sphinx/themes/basic/searchbox.html2
-rw-r--r--sphinx/themes/bizstyle/layout.html4
-rw-r--r--sphinx/themes/classic/layout.html2
-rw-r--r--sphinx/themes/scrolls/layout.html2
-rw-r--r--sphinx/transforms/i18n.py5
-rw-r--r--sphinx/util/__init__.py14
-rw-r--r--tests/test_build_html.py4
-rw-r--r--tests/test_ext_duration.py21
-rw-r--r--tests/test_ext_math.py2
-rw-r--r--tox.ini2
25 files changed, 220 insertions, 41 deletions
diff --git a/CHANGES b/CHANGES
index 8fbca5bc9..59cb99f64 100644
--- a/CHANGES
+++ b/CHANGES
@@ -42,6 +42,36 @@ Incompatible changes
Deprecated
----------
+* ``sphinx.io.FiletypeNotFoundError``
+* ``sphinx.io.get_filetype()``
+
+Features added
+--------------
+
+* #6910: inheritance_diagram: Make the background of diagrams transparent
+* #6446: duration: Add ``sphinx.ext.durations`` to inspect which documents slow
+ down the build
+
+Bugs fixed
+----------
+
+* #6925: html: Remove redundant type="text/javascript" from <script> elements
+
+Testing
+--------
+
+Release 2.3.1 (in development)
+==============================
+
+Dependencies
+------------
+
+Incompatible changes
+--------------------
+
+Deprecated
+----------
+
Features added
--------------
diff --git a/doc/_themes/sphinx13/layout.html b/doc/_themes/sphinx13/layout.html
index df0b82bb8..8d1b04a14 100644
--- a/doc/_themes/sphinx13/layout.html
+++ b/doc/_themes/sphinx13/layout.html
@@ -30,7 +30,7 @@
.related { display: none; }
{% endif %}
</style>
- <script type="text/javascript">
+ <script>
// intelligent scrolling of the sidebar content
$(window).scroll(function() {
var sb = $('.sphinxsidebarwrapper');
diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst
index 482cb50bb..9fdaa2f96 100644
--- a/doc/extdev/deprecated.rst
+++ b/doc/extdev/deprecated.rst
@@ -26,6 +26,16 @@ The following is a list of deprecated interfaces.
- (will be) Removed
- Alternatives
+ * - ``sphinx.io.FiletypeNotFoundError``
+ - 2.4
+ - 4.0
+ - ``sphinx.errors.FiletypeNotFoundError``
+
+ * - ``sphinx.io.get_filetype()``
+ - 2.4
+ - 4.0
+ - ``sphinx.util.get_filetype()``
+
* - ``sphinx.builders.gettext.POHEADER``
- 2.3
- 4.0
diff --git a/doc/faq.rst b/doc/faq.rst
index ba16ceb9a..28d14d79e 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -89,7 +89,7 @@ Google Analytics
{%- block extrahead %}
{{ super() }}
- <script type="text/javascript">
+ <script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'XXX account number XXX']);
_gaq.push(['_trackPageview']);
@@ -101,7 +101,7 @@ Google Analytics
<div class="footer">This page uses <a href="https://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
- <script type="text/javascript">
+ <script>
(function() {
var ga = document.createElement('script');
ga.src = ('https:' == document.location.protocol ?
@@ -132,7 +132,6 @@ Google Search
(function() {
var cx = '......';
var gcse = document.createElement('script');
- gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
diff --git a/doc/usage/extensions/duration.rst b/doc/usage/extensions/duration.rst
new file mode 100644
index 000000000..c57549984
--- /dev/null
+++ b/doc/usage/extensions/duration.rst
@@ -0,0 +1,11 @@
+:mod:`sphinx.ext.duration` -- Measure durations of Sphinx processing
+====================================================================
+
+.. module:: sphinx.ext.duration
+ :synopsis: Measure durations of Sphinx processing
+
+.. versionadded:: 2.3
+
+This extension measures durations of Sphinx processing and show its
+result at end of the build. It is useful for inspecting what document
+is slowly built.
diff --git a/doc/usage/extensions/index.rst b/doc/usage/extensions/index.rst
index ae9639ee8..6aab8adb2 100644
--- a/doc/usage/extensions/index.rst
+++ b/doc/usage/extensions/index.rst
@@ -23,6 +23,7 @@ These extensions are built in and can be activated by respective entries in the
autosummary
coverage
doctest
+ duration
extlinks
githubpages
graphviz
diff --git a/setup.py b/setup.py
index df34d4fa8..a5dd04b0a 100644
--- a/setup.py
+++ b/setup.py
@@ -47,7 +47,7 @@ extras_require = {
'html5lib',
'flake8>=3.5.0',
'flake8-import-order',
- 'mypy>=0.750',
+ 'mypy>=0.761',
'docutils-stubs',
],
}
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 50c38cdb2..48b21fa4e 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -117,7 +117,6 @@ class JavaScript(str):
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
- self.attributes.setdefault('type', 'text/javascript')
return self
@@ -1098,7 +1097,6 @@ def setup_js_tag_helper(app: Sphinx, pagename: str, templatexname: str,
attrs.append('src="%s"' % pathto(js.filename, resource=True))
else:
# str value (old styled)
- attrs.append('type="text/javascript"')
attrs.append('src="%s"' % pathto(js, resource=True))
return '<script %s>%s</script>' % (' '.join(attrs), body)
diff --git a/sphinx/errors.py b/sphinx/errors.py
index 7f8b1fbd5..64036721f 100644
--- a/sphinx/errors.py
+++ b/sphinx/errors.py
@@ -126,3 +126,8 @@ class PycodeError(Exception):
class NoUri(Exception):
"""Raised by builder.get_relative_uri() if there is no URI available."""
pass
+
+
+class FiletypeNotFoundError(Exception):
+ "Raised by get_filetype() if a filename matches no source suffix."
+ pass
diff --git a/sphinx/ext/duration.py b/sphinx/ext/duration.py
new file mode 100644
index 000000000..1286e49ec
--- /dev/null
+++ b/sphinx/ext/duration.py
@@ -0,0 +1,96 @@
+"""
+ sphinx.ext.duration
+ ~~~~~~~~~~~~~~~~~~~
+
+ Measure durations of Sphinx processing.
+
+ :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from datetime import datetime, timedelta
+from itertools import islice
+from operator import itemgetter
+from typing import cast
+from typing import Dict, List
+
+from docutils import nodes
+
+from sphinx.application import Sphinx
+from sphinx.domains import Domain
+from sphinx.locale import __
+from sphinx.util import logging
+
+logger = logging.getLogger(__name__)
+
+
+class DurationDomain(Domain):
+ """A domain for durations of Sphinx processing."""
+ name = 'duration'
+
+ @property
+ def reading_durations(self) -> Dict[str, timedelta]:
+ return self.data.setdefault('reading_durations', {})
+
+ def note_reading_duration(self, duration: timedelta):
+ self.reading_durations[self.env.docname] = duration
+
+ def clear(self) -> None:
+ self.reading_durations.clear()
+
+ def clear_doc(self, docname: str) -> None:
+ self.reading_durations.pop(docname, None)
+
+ def merge_domaindata(self, docnames: List[str], otherdata: Dict[str, timedelta]) -> None:
+ for docname, duration in otherdata.items():
+ if docname in docnames:
+ self.reading_durations[docname] = duration
+
+
+def on_builder_inited(app: Sphinx) -> None:
+ """Initialize DurationDomain on bootstrap.
+
+ This clears results of last build.
+ """
+ domain = cast(DurationDomain, app.env.get_domain('duration'))
+ domain.clear()
+
+
+def on_source_read(app: Sphinx, docname: str, content: List[str]) -> None:
+ """Start to measure reading duration."""
+ app.env.temp_data['started_at'] = datetime.now()
+
+
+def on_doctree_read(app: Sphinx, doctree: nodes.document) -> None:
+ """Record a reading duration."""
+ started_at = app.env.temp_data.get('started_at')
+ duration = datetime.now() - started_at
+ domain = cast(DurationDomain, app.env.get_domain('duration'))
+ domain.note_reading_duration(duration)
+
+
+def on_build_finished(app: Sphinx, error):
+ """Display duration ranking on current build."""
+ domain = cast(DurationDomain, app.env.get_domain('duration'))
+ durations = sorted(domain.reading_durations.items(), key=itemgetter(1), reverse=True)
+ if not durations:
+ return
+
+ logger.info('')
+ logger.info(__('====================== slowest reading durations ======================='))
+ for docname, d in islice(durations, 5):
+ logger.info('%d.%03d %s', d.seconds, d.microseconds / 1000, docname)
+
+
+def setup(app):
+ app.add_domain(DurationDomain)
+ app.connect('builder-inited', on_builder_inited)
+ app.connect('source-read', on_source_read)
+ app.connect('doctree-read', on_doctree_read)
+ app.connect('build-finished', on_build_finished)
+
+ return {
+ 'version': 'builtin',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/sphinx/io.py b/sphinx/io.py
index f3e72733e..624a04246 100644
--- a/sphinx/io.py
+++ b/sphinx/io.py
@@ -18,7 +18,8 @@ from docutils.readers import standalone
from docutils.transforms.references import DanglingReferences
from docutils.writers import UnfilteredWriter
-from sphinx.deprecation import RemovedInSphinx40Warning
+from sphinx.errors import FiletypeNotFoundError
+from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.transforms import (
AutoIndexUpgrader, DoctreeReadEvent, FigureAligner, SphinxTransformer
)
@@ -26,7 +27,7 @@ from sphinx.transforms.i18n import (
PreserveTranslatableMessages, Locale, RemoveTranslatableInline,
)
from sphinx.transforms.references import SphinxDomains
-from sphinx.util import logging
+from sphinx.util import logging, get_filetype
from sphinx.util import UnicodeDecodeErrorHandler
from sphinx.util.docutils import LoggingReporter
from sphinx.versioning import UIDTransform
@@ -192,20 +193,6 @@ class SphinxFileInput(FileInput):
super().__init__(*args, **kwargs)
-class FiletypeNotFoundError(Exception):
- pass
-
-
-def get_filetype(source_suffix, filename):
- # type: (Dict[str, str], str) -> str
- for suffix, filetype in source_suffix.items():
- if filename.endswith(suffix):
- # If default filetype (None), considered as restructuredtext.
- return filetype or 'restructuredtext'
- else:
- raise FiletypeNotFoundError
-
-
def read_doc(app, env, filename):
# type: (Sphinx, BuildEnvironment, str) -> nodes.document
"""Parse a document and convert to doctree."""
@@ -249,3 +236,11 @@ def read_doc(app, env, filename):
pub.publish()
return pub.document
+
+
+deprecated_alias('sphinx.io',
+ {
+ 'FiletypeNotFoundError': FiletypeNotFoundError,
+ 'get_filetype': get_filetype,
+ },
+ RemovedInSphinx40Warning)
diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py
index 4233089ff..cbae86c9e 100644
--- a/sphinx/pycode/parser.py
+++ b/sphinx/pycode/parser.py
@@ -129,7 +129,7 @@ class TokenProcessor:
def __init__(self, buffers: List[str]) -> None:
lines = iter(buffers)
self.buffers = buffers
- self.tokens = tokenize.generate_tokens(lambda: next(lines)) # type: ignore
+ self.tokens = tokenize.generate_tokens(lambda: next(lines))
self.current = None # type: Token
self.previous = None # type: Token
diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html
index 35c64ccb5..3cf1bc4e8 100644
--- a/sphinx/themes/basic/domainindex.html
+++ b/sphinx/themes/basic/domainindex.html
@@ -12,7 +12,7 @@
{% block extrahead %}
{{ super() }}
{% if not embedded and collapse_index %}
- <script type="text/javascript">
+ <script>
DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true;
</script>
{% endif %}
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 987aeeb6e..2c9e24930 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -87,7 +87,7 @@
{%- endmacro %}
{%- macro script() %}
- <script type="text/javascript" id="documentation_options" data-url_root="{{ pathto('', 1) }}" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
+ <script id="documentation_options" data-url_root="{{ pathto('', 1) }}" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
{%- for js in script_files %}
{{ js_tag(js) }}
{%- endfor %}
diff --git a/sphinx/themes/basic/search.html b/sphinx/themes/basic/search.html
index a9b9960d2..3cda0feaa 100644
--- a/sphinx/themes/basic/search.html
+++ b/sphinx/themes/basic/search.html
@@ -11,16 +11,16 @@
{% set title = _('Search') %}
{%- block scripts %}
{{ super() }}
- <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+ <script src="{{ pathto('_static/searchtools.js', 1) }}"></script>
{%- endblock %}
{% block extrahead %}
- <script type="text/javascript" src="{{ pathto('searchindex.js', 1) }}" defer></script>
+ <script src="{{ pathto('searchindex.js', 1) }}" defer></script>
{{ super() }}
{% endblock %}
{% block body %}
<h1 id="search-documentation">{{ _('Search') }}</h1>
<div id="fallback" class="admonition warning">
- <script type="text/javascript">$('#fallback').hide();</script>
+ <script>$('#fallback').hide();</script>
<p>
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html
index 6679ca6b5..8658f9759 100644
--- a/sphinx/themes/basic/searchbox.html
+++ b/sphinx/themes/basic/searchbox.html
@@ -17,5 +17,5 @@
</form>
</div>
</div>
-<script type="text/javascript">$('#searchbox').show(0);</script>
+<script>$('#searchbox').show(0);</script>
{%- endif %}
diff --git a/sphinx/themes/bizstyle/layout.html b/sphinx/themes/bizstyle/layout.html
index d1deafde4..126bb59e9 100644
--- a/sphinx/themes/bizstyle/layout.html
+++ b/sphinx/themes/bizstyle/layout.html
@@ -11,7 +11,7 @@
{%- block scripts %}
{{ super() }}
- <script type="text/javascript" src="{{ pathto('_static/bizstyle.js', 1) }}"></script>
+ <script src="{{ pathto('_static/bizstyle.js', 1) }}"></script>
{%- endblock %}
{# put the sidebar before the body #}
@@ -26,6 +26,6 @@
{%- block extrahead %}
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!--[if lt IE 9]>
- <script type="text/javascript" src="_static/css3-mediaqueries.js"></script>
+ <script src="_static/css3-mediaqueries.js"></script>
<![endif]-->
{%- endblock %}
diff --git a/sphinx/themes/classic/layout.html b/sphinx/themes/classic/layout.html
index a67a931c8..9f22787c5 100644
--- a/sphinx/themes/classic/layout.html
+++ b/sphinx/themes/classic/layout.html
@@ -12,6 +12,6 @@
{%- block scripts %}
{{ super() }}
{% if theme_collapsiblesidebar|tobool %}
- <script type="text/javascript" src="{{ pathto('_static/sidebar.js', 1) }}"></script>
+ <script src="{{ pathto('_static/sidebar.js', 1) }}"></script>
{% endif %}
{%- endblock %}
diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html
index 08f8970fc..11c571749 100644
--- a/sphinx/themes/scrolls/layout.html
+++ b/sphinx/themes/scrolls/layout.html
@@ -15,7 +15,7 @@
{%- endblock %}
{%- block scripts %}
{{ super() }}
- <script type="text/javascript" src="{{ pathto('_static/theme_extras.js', 1) }}"></script>
+ <script src="{{ pathto('_static/theme_extras.js', 1) }}"></script>
{%- endblock %}
{# do not display relbars #}
{% block relbar1 %}{% endblock %}
diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py
index 6512fd43d..d1c125a7e 100644
--- a/sphinx/transforms/i18n.py
+++ b/sphinx/transforms/i18n.py
@@ -22,7 +22,7 @@ from sphinx.config import Config
from sphinx.domains.std import make_glossary_term, split_term_classifiers
from sphinx.locale import __, init as init_locale
from sphinx.transforms import SphinxTransform
-from sphinx.util import split_index_msg, logging
+from sphinx.util import split_index_msg, logging, get_filetype
from sphinx.util.i18n import docname_to_domain
from sphinx.util.nodes import (
LITERAL_TYPE_NODES, IMAGE_TYPE_NODES, NodeMatcher,
@@ -61,7 +61,8 @@ def publish_msgstr(app: "Sphinx", source: str, source_path: str, source_line: in
from sphinx.io import SphinxI18nReader
reader = SphinxI18nReader()
reader.setup(app)
- parser = app.registry.create_source_parser(app, 'restructuredtext')
+ filetype = get_filetype(config.source_suffix, source_path)
+ parser = app.registry.create_source_parser(app, filetype)
doc = reader.read(
source=StringInput(source=source,
source_path="%s:%s:<translated>" % (source_path, source_line)),
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index d44290b7b..2032b94ac 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -29,7 +29,9 @@ from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Pattern, S
from urllib.parse import urlsplit, urlunsplit, quote_plus, parse_qsl, urlencode
from sphinx.deprecation import RemovedInSphinx40Warning
-from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError
+from sphinx.errors import (
+ PycodeError, SphinxParallelError, ExtensionError, FiletypeNotFoundError
+)
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import strip_colors, colorize, bold, term_width_line # type: ignore
@@ -117,6 +119,16 @@ def get_matching_docs(dirname: str, suffixes: List[str],
break
+def get_filetype(source_suffix, filename):
+ # type: (Dict[str, str], str) -> str
+ for suffix, filetype in source_suffix.items():
+ if filename.endswith(suffix):
+ # If default filetype (None), considered as restructuredtext.
+ return filetype or 'restructuredtext'
+ else:
+ raise FiletypeNotFoundError
+
+
class FilenameUniqDict(dict):
"""
A dictionary that automatically generates unique names for its keys,
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 66164dd1c..b83bd5637 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -1216,8 +1216,8 @@ def test_html_assets(app):
'href="https://example.com/custom.css" />' in content)
# html_js_files
- assert '<script type="text/javascript" src="_static/js/custom.js"></script>' in content
- assert ('<script async="async" type="text/javascript" src="https://example.com/script.js">'
+ assert '<script src="_static/js/custom.js"></script>' in content
+ assert ('<script async="async" src="https://example.com/script.js">'
'</script>' in content)
diff --git a/tests/test_ext_duration.py b/tests/test_ext_duration.py
new file mode 100644
index 000000000..65ea1eef7
--- /dev/null
+++ b/tests/test_ext_duration.py
@@ -0,0 +1,21 @@
+"""
+ test_ext_duration
+ ~~~~~~~~~~~~~~~~~
+
+ Test sphinx.ext.duration extension.
+
+ :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import pytest
+
+
+@pytest.mark.sphinx('dummy', testroot='basic',
+ confoverrides={'extensions': ['sphinx.ext.duration']})
+def test_githubpages(app, status, warning):
+ app.build()
+
+ assert 'slowest reading durations' in status.getvalue()
+ assert re.search('\\d+\\.\\d{3} index\n', status.getvalue())
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index 7fbfd1477..32a50512a 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -70,7 +70,7 @@ def test_mathjax_options(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
- assert ('<script async="async" integrity="sha384-0123456789" type="text/javascript" '
+ assert ('<script async="async" integrity="sha384-0123456789" '
'src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?'
'config=TeX-AMS-MML_HTMLorMML"></script>' in content)
diff --git a/tox.ini b/tox.ini
index 922432d67..8dd113602 100644
--- a/tox.ini
+++ b/tox.ini
@@ -15,7 +15,7 @@ deps =
du13: docutils==0.13.1
du14: docutils==0.14
du15: docutils==0.15
- du16: docutils==0.16b0.dev0
+ du16: docutils==0.16rc1
extras =
test
setenv =