Merge branch 'master' into 5035_qthelp_namespace_allows_dashes

This commit is contained in:
Takeshi KOMIYA 2018-06-20 00:45:34 +09:00 committed by GitHub
commit 2f91a2c22e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 180 additions and 57 deletions

13
CHANGES
View File

@ -34,9 +34,10 @@ Incompatible changes
* #1857: latex: :confval:`latex_show_pagerefs` does not add pagerefs for
citations
* #4648: latex: Now "rubric" elements are rendered as unnumbered section title
* #4983: html: The URL for the productionlist has been changed
* #4983: html: The anchor for productionlist tokens has been changed
* Modifying a template variable ``script_files`` in templates is allowed now.
Please use ``app.add_js_file()`` instead.
* #5072: Save environment object also with only new documents
* #5035: qthelp builder allows dashes in :confval:`qthelp_namespace`
Deprecated
@ -138,6 +139,9 @@ Features added
* html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs:
#4193)
* #5029: autosummary: expose ``inherited_members`` to template
* #3784: mathjax: Add :confval:`mathjax_options` to give options to script tag
for mathjax
* #4362: latex: Don't overwrite .tex file if document not changed
Bugs fixed
----------
@ -156,6 +160,11 @@ Features removed
* ``sphinx.ext.pngmath`` extension
Documentation
-------------
* #5083: Fix wrong make.bat option for internationalization.
Release 1.7.6 (in development)
==============================
@ -187,6 +196,8 @@ Bugs fixed
* #5019: autodoc: crashed by Form Feed Character
* #5032: autodoc: loses the first staticmethod parameter for old styled classes
* #5036: quickstart: Typing Ctrl-U clears the whole of line
* #5066: html: "relations" sidebar is not shown by default
* #5091: latex: curly braces in index entries are not handled correctly
Testing
--------

View File

@ -195,6 +195,7 @@ Documentation using sphinx_rtd_theme
* Julia: https://julia.readthedocs.io/
* Jupyter Notebook: https://jupyter-notebook.readthedocs.io/
* Lasagne: https://lasagne.readthedocs.io/
* latexindent.pl: https://latexindentpl.readthedocs.io/
* Linguistica: https://linguistica-uchicago.github.io/lxa5/
* Linux kernel: https://www.kernel.org/doc/html/latest/index.html
* MathJax: https://docs.mathjax.org/

View File

@ -1,9 +1,10 @@
# Makefile for Sphinx documentation
#
PYTHON ?= python
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python3 ../sphinx/cmd/build.py
SPHINXBUILD = $(PYTHON) ../sphinx/cmd/build.py
SPHINXPROJ = sphinx
SOURCEDIR = .
BUILDDIR = _build

View File

@ -3,19 +3,9 @@
{%trans%}project{%endtrans%}</p>
<h3>Download</h3>
{% if version.endswith('+') %}
<p>{%trans%}This documentation is for version <b><a href="changes.html">{{ version }}</a></b>, which is
not released yet.{%endtrans%}</p>
<p>{%trans%}You can use it from the
<a href="https://github.com/sphinx-doc/sphinx/">Git repo</a> or look for
released versions in the <a href="https://pypi.org/project/Sphinx/">Python
Package Index</a>.{%endtrans%}</p>
{% else %}
<p>{%trans%}Current version: <b><a href="changes.html">{{ version }}</a></b>{%endtrans%}</p>
<p>{%trans%}Get Sphinx from the <a href="https://pypi.org/project/Sphinx/">Python Package
Index</a>, or install it with:{%endtrans%}</p>
<p class="download">{%trans%}Current version: <a href="https://pypi.org/project/Sphinx/" alt="PyPI"><img src="https://img.shields.io/pypi/v/sphinx.svg"></a>{%endtrans%}</p>
<p>{%trans%}Install Sphinx with:{%endtrans%}</p>
<pre>pip install -U Sphinx</pre>
{% endif %}
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>

View File

@ -140,6 +140,10 @@ div.sphinxsidebar .logo img {
vertical-align: middle;
}
div.sphinxsidebar .download a img {
vertical-align: middle;
}
div.subscribeformwrapper {
display: block;
overflow: auto;

View File

@ -260,6 +260,16 @@ Sphinx.
You can also give a full ``https://`` URL different from the CDN URL.
.. confval:: mathjax_options
The options to script tag for mathjax. For example, you can set integrity
option with following setting::
mathjax_options = {
'integrity': 'sha384-......',
}
The default is empty (``{}``).
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript
------------------------------------------------------

View File

@ -123,14 +123,14 @@ This section describe an easy way to translate with sphinx-intl.
.. code-block:: console
> set SPHINXOPTS=-D language='de'
> set SPHINXOPTS=-D language=de
> .\make.bat html
command line (for PowerShell):
.. code-block:: console
> Set-Item env:SPHINXOPTS "-D language='de'"
> Set-Item env:SPHINXOPTS "-D language=de"
> .\make.bat html

View File

@ -3,7 +3,7 @@
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=python ../sphinx-build.py
set SPHINXBUILD=python ../sphinx/cmd/build.py
)
set SOURCEDIR=.
set BUILDDIR=_build

View File

@ -372,14 +372,14 @@ class Builder(object):
else:
logger.info(__('none found'))
if updated_docnames:
# save the environment
from sphinx.application import ENV_PICKLE_FILENAME
logger.info(bold(__('pickling environment... ')), nonl=True)
with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
logger.info(__('done'))
# save the environment
from sphinx.application import ENV_PICKLE_FILENAME
logger.info(bold(__('pickling environment... ')), nonl=True)
with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
logger.info(__('done'))
if updated_docnames:
# global actions
self.app.phase = BuildPhase.CONSISTENCY_CHECK
logger.info(bold(__('checking consistency... ')), nonl=True)

View File

@ -1014,19 +1014,27 @@ class StandaloneHTMLBuilder(Builder):
def has_wildcard(pattern):
# type: (unicode) -> bool
return any(char in pattern for char in '*?[')
sidebars = self.theme.get_config('theme', 'sidebars', None)
sidebars = None
matched = None
customsidebar = None
# default sidebars settings for selected theme
theme_default_sidebars = self.theme.get_config('theme', 'sidebars', None)
if theme_default_sidebars:
sidebars = [name.strip() for name in theme_default_sidebars.split(',')]
elif self.theme.name == 'alabaster':
if self.theme.name == 'alabaster':
# provide default settings for alabaster (for compatibility)
# Note: this will be removed before Sphinx-2.0
sidebars = ['about.html', 'navigation.html', 'relation.html',
'searchbox.html', 'donate.html']
try:
# get default sidebars settings from alabaster (if defined)
theme_default_sidebars = self.theme.config.get('theme', 'sidebars')
if theme_default_sidebars:
sidebars = [name.strip() for name in theme_default_sidebars.split(',')]
except Exception:
# fallback to better default settings
sidebars = ['about.html', 'navigation.html', 'relations.html',
'searchbox.html', 'donate.html']
else:
theme_default_sidebars = self.theme.get_config('theme', 'sidebars', None)
if theme_default_sidebars:
sidebars = [name.strip() for name in theme_default_sidebars.split(',')]
# user sidebar settings
for pattern, patsidebars in iteritems(self.config.html_sidebars):

View File

@ -13,7 +13,6 @@ import os
from os import path
from docutils.frontend import OptionParser
from docutils.io import FileOutput
from six import text_type
from sphinx import package_dir, addnodes, highlighting
@ -31,7 +30,7 @@ from sphinx.locale import _, __
from sphinx.transforms import SphinxTransformer
from sphinx.util import texescape, logging, status_iterator
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.util.docutils import new_document
from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, make_filename
@ -134,9 +133,8 @@ class LaTeXBuilder(Builder):
toctree_only = False
if len(entry) > 5:
toctree_only = entry[5]
destination = FileOutput(
destination_path=path.join(self.outdir, targetname),
encoding='utf-8')
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
encoding='utf-8', overwrite_if_changed=True)
logger.info(__("processing %s..."), targetname, nonl=1)
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
if toctrees:

View File

@ -74,6 +74,8 @@ def builder_inited(app):
'mathjax extension to work')
if app.builder.format == 'html':
options = {'async': 'async'}
if app.config.mathjax_options:
options.update(app.config.mathjax_options)
app.builder.add_js_file(app.config.mathjax_path, **options) # type: ignore
@ -88,7 +90,8 @@ def setup(app):
# https://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
app.add_config_value('mathjax_path',
'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?'
'config=TeX-AMS-MML_HTMLorMML', False)
'config=TeX-AMS-MML_HTMLorMML', 'html')
app.add_config_value('mathjax_options', {}, 'html')
app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
app.connect('builder-inited', builder_inited)

View File

@ -9,10 +9,10 @@
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{%- macro script() %}
{%- block scripts %}
{{ super() }}
<script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
{%- endmacro %}
{%- endblock %}
{% block extrahead %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });

View File

@ -9,10 +9,10 @@
#}
{% extends "basic/layout.html" %}
{%- macro script() %}
{%- block scripts %}
{{ super() }}
<script type="text/javascript" src="{{ pathto('_static/bizstyle.js', 1) }}"></script>
{%- endmacro %}
{%- endblock %}
{# put the sidebar before the body #}
{% block sidebar1 %}{{ sidebar() }}{% endblock %}

View File

@ -10,8 +10,8 @@
{%- extends "basic/layout.html" %}
{% if theme_collapsiblesidebar|tobool %}
{%- macro script() %}
{%- block scripts %}
{{ super() }}
<script type="text/javascript" src="{{ pathto('_static/sidebar.js', 1) }}"></script>
{%- endmacro %}
{%- endblock %}
{% endif %}

View File

@ -13,10 +13,10 @@
{{ super() }}
<link rel="stylesheet" href="_static/print.css" type="text/css" />
{%- endblock %}
{%- macro script() %}
{%- block scripts %}
{{ super() }}
<script type="text/javascript" src="{{ pathto('_static/theme_extras.js', 1) }}"></script>
{%- endmacro %}
{%- endblock %}
{# do not display relbars #}
{% block relbar1 %}{% endblock %}
{% block relbar2 %}{% endblock %}

View File

@ -10,6 +10,7 @@
"""
from __future__ import absolute_import
import codecs
import os
import re
import types
@ -21,6 +22,7 @@ from os import path
import docutils
from docutils import nodes
from docutils.io import FileOutput
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
from docutils.statemachine import StateMachine
from docutils.utils import Reporter
@ -300,6 +302,26 @@ def switch_source_input(state, content):
state.memo.reporter.get_source_and_line = get_source_and_line
class SphinxFileOutput(FileOutput):
"""Better FileOutput class for Sphinx."""
def __init__(self, **kwargs):
# type: (Any) -> None
self.overwrite_if_changed = kwargs.pop('overwrite_if_changed', False)
FileOutput.__init__(self, **kwargs)
def write(self, data):
# type: (unicode) -> unicode
if (self.destination_path and self.autoclose and 'b' not in self.mode and
self.overwrite_if_changed and os.path.exists(self.destination_path)):
with codecs.open(self.destination_path, encoding=self.encoding) as f:
# skip writing: content not changed
if f.read() == data:
return data
return FileOutput.write(self, data)
class SphinxDirective(Directive):
"""A base class for Sphinx directives.

View File

@ -1894,8 +1894,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
# type: (nodes.Node, Pattern) -> None
def escape(value):
value = self.encode(value)
value = value.replace(r'\{', r'\sphinxleftcurlybrace')
value = value.replace(r'\}', r'\sphinxrightcurlybrace')
value = value.replace(r'\{', r'{\sphinxleftcurlybrace}')
value = value.replace(r'\}', r'{\sphinxrightcurlybrace}')
return value
if not node.get('inline', True):

View File

@ -1245,21 +1245,50 @@ def test_html_remote_images(app, status, warning):
@pytest.mark.sphinx('html', testroot='basic')
def test_html_sidebar(app, status, warning):
ctx = {}
# default for alabaster
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
assert '<h3><a href="#">Table Of Contents</a></h3>' in result
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' in result
assert '<h3>Navigation</h3>' in result
assert '<h3>Related Topics</h3>' in result
assert '<h3>This Page</h3>' in result
assert '<h3>Quick search</h3>' in result
app.builder.add_sidebars('index', ctx)
assert ctx['sidebars'] == ['about.html', 'navigation.html', 'relations.html',
'searchbox.html', 'donate.html']
# only relations.html
app.config.html_sidebars = {'**': ['relations.html']}
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
assert '<h3>Navigation</h3>' not in result
assert '<h3>Related Topics</h3>' in result
assert '<h3>Quick search</h3>' not in result
app.builder.add_sidebars('index', ctx)
assert ctx['sidebars'] == ['relations.html']
# no sidebars
app.config.html_sidebars = {'**': []}
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
assert '<h3><a href="#">Table Of Contents</a></h3>' not in result
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' not in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
assert '<h3>Navigation</h3>' not in result
assert '<h3>Related Topics</h3>' not in result
assert '<h3>This Page</h3>' not in result
assert '<h3>Quick search</h3>' not in result
app.builder.add_sidebars('index', ctx)
assert ctx['sidebars'] == []
@pytest.mark.parametrize('fname,expect', flat_dict({
'index.html': [(".//em/a[@href='https://example.com/man.1']", "", True),

View File

@ -1201,7 +1201,7 @@ def test_latex_index(app, status, warning):
result = (app.outdir / 'Python.tex').text(encoding='utf8')
assert 'A \\index{famous}famous \\index{equation}equation:\n' in result
assert '\n\\index{Einstein}\\index{relativity}\\ignorespaces \nand' in result
assert '\n\\index{main \\sphinxleftcurlybrace}\\ignorespaces ' in result
assert '\n\\index{main {\\sphinxleftcurlybrace}}\\ignorespaces ' in result
@pytest.mark.sphinx('latex', testroot='latex-equations')

View File

@ -89,6 +89,18 @@ def test_imgmath_svg(app, status, warning):
assert re.search(html, content, re.S)
@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax'],
'mathjax_options': {'integrity': 'sha384-0123456789'}})
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" '
'src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?'
'config=TeX-AMS-MML_HTMLorMML"></script>' in content)
@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_align(app, status, warning):

View File

@ -11,6 +11,7 @@
import os
import alabaster
import pytest
from sphinx.theming import ThemeError
@ -23,11 +24,14 @@ from sphinx.theming import ThemeError
def test_theme_api(app, status, warning):
cfg = app.config
themes = ['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
'traditional', 'epub', 'nature', 'pyramid', 'bizstyle', 'classic', 'nonav',
'test-theme', 'ziptheme', 'staticfiles', 'parent', 'child']
if alabaster.version.__version_info__ >= (0, 7, 11):
themes.append('alabaster')
# test Theme class API
assert set(app.html_themes.keys()) == \
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
'traditional', 'epub', 'nature', 'pyramid', 'bizstyle', 'classic', 'nonav',
'test-theme', 'ziptheme', 'staticfiles', 'parent', 'child'])
assert set(app.html_themes.keys()) == set(themes)
assert app.html_themes['test-theme'] == app.srcdir / 'test_theme' / 'test-theme'
assert app.html_themes['ziptheme'] == app.srcdir / 'ziptheme.zip'
assert app.html_themes['staticfiles'] == app.srcdir / 'test_theme' / 'staticfiles'

View File

@ -9,9 +9,11 @@
:license: BSD, see LICENSE for details.
"""
import os
from docutils import nodes
from sphinx.util.docutils import docutils_namespace, register_node
from sphinx.util.docutils import SphinxFileOutput, docutils_namespace, register_node
def test_register_node():
@ -32,3 +34,31 @@ def test_register_node():
assert not hasattr(nodes.GenericNodeVisitor, 'depart_custom_node')
assert not hasattr(nodes.SparseNodeVisitor, 'visit_custom_node')
assert not hasattr(nodes.SparseNodeVisitor, 'depart_custom_node')
def test_SphinxFileOutput(tmpdir):
content = 'Hello Sphinx World'
# write test.txt at first
filename = str(tmpdir / 'test.txt')
output = SphinxFileOutput(destination_path=filename)
output.write(content)
os.utime(filename, (0, 0))
# overrite it again
output.write(content)
assert os.stat(filename).st_mtime != 0 # updated
# write test2.txt at first
filename = str(tmpdir / 'test2.txt')
output = SphinxFileOutput(destination_path=filename, overwrite_if_changed=True)
output.write(content)
os.utime(filename, (0, 0))
# overrite it again
output.write(content)
assert os.stat(filename).st_mtime == 0 # not updated
# overrite it again (content changed)
output.write(content + "; content change")
assert os.stat(filename).st_mtime != 0 # updated