diff --git a/CHANGES b/CHANGES index 2e1f1d7ff..bcbf75d68 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,9 @@ Dependencies Incompatible changes -------------------- +* #5282: html theme: refer ``pygments_style`` settings of HTML themes + preferentially + Deprecated ---------- @@ -60,6 +63,10 @@ Bugs fixed * #5325: latex: cross references has been broken by multiply labeled objects * C++, fixes for symbol addition and lookup. Lookup should no longer break in partial builds. See also #5337. +* #5348: download reference to remote file is not displayed +* #5282: html theme: ``pygments_style`` of theme was overrided by ``conf.py`` + by default +* #4379: toctree shows confusible warning when document is excluded Testing -------- @@ -313,8 +320,8 @@ Documentation * #5083: Fix wrong make.bat option for internationalization. * #5115: napoleon: add admonitions added by #4613 to the docs. -Release 1.7.9 (in development) -============================== +Release 1.7.10 (in development) +=============================== Dependencies ------------ @@ -334,6 +341,19 @@ Bugs fixed Testing -------- +Release 1.7.9 (released Sep 05, 2018) +===================================== + +Features added +-------------- + +* #5359: Make generated texinfo files reproducible by sorting the anchors + +Bugs fixed +---------- + +* #5361: crashed on incremental build if document uses include directive + Release 1.7.8 (released Aug 29, 2018) ===================================== diff --git a/doc/usage/extensions/autosummary.rst b/doc/usage/extensions/autosummary.rst index 008bc5613..24e0d1855 100644 --- a/doc/usage/extensions/autosummary.rst +++ b/doc/usage/extensions/autosummary.rst @@ -208,6 +208,8 @@ The following variables available in the templates: List containing names of all inherited members of class. Only available for classes. + .. versionadded:: 1.8.0 + .. data:: functions List containing names of "public" functions in the module. Here, "public" diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 2e44feb95..a1e39de77 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -22,7 +22,7 @@ from sphinx.domains.changeset import VersionChange # NOQA # for compatibility from sphinx.locale import _ from sphinx.util import url_re, docname_join from sphinx.util.docutils import SphinxDirective -from sphinx.util.matching import patfilter +from sphinx.util.matching import Matcher, patfilter from sphinx.util.nodes import explicit_title_re, set_source_info, \ process_index_entry @@ -96,6 +96,7 @@ class TocTree(SphinxDirective): all_docnames.remove(self.env.docname) # remove current document ret = [] + excluded = Matcher(self.config.exclude_patterns) for entry in self.content: if not entry: continue @@ -131,9 +132,13 @@ class TocTree(SphinxDirective): if url_re.match(ref) or ref == 'self': toctree['entries'].append((title, ref)) elif docname not in self.env.found_docs: - ret.append(self.state.document.reporter.warning( - 'toctree contains reference to nonexisting ' - 'document %r' % docname, line=self.lineno)) + if excluded(self.env.doc2path(docname, None)): + message = 'toctree contains reference to excluded document %r' + else: + message = 'toctree contains reference to nonexisting document %r' + + ret.append(self.state.document.reporter.warning(message % docname, + line=self.lineno)) self.env.note_reread() else: all_docnames.discard(docname) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 941205e3c..f4f8c4621 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -17,7 +17,7 @@ from copy import copy from os import path from six import BytesIO, next -from six.moves import cPickle as pickle, reduce +from six.moves import cPickle as pickle from sphinx import addnodes from sphinx.deprecation import RemovedInSphinx30Warning @@ -64,7 +64,7 @@ default_settings = { # or changed to properly invalidate pickle files. # # NOTE: increase base version by 2 to have distinct numbers for Py2 and 3 -ENV_VERSION = 53 + (sys.version_info[0] - 2) +ENV_VERSION = 54 + (sys.version_info[0] - 2) # config status CONFIG_OK = 1 @@ -662,7 +662,7 @@ class BuildEnvironment(object): def check_consistency(self): # type: () -> None """Do consistency checks.""" - included = reduce(lambda x, y: x | y, self.included.values(), set()) # type: Set[unicode] # NOQA + included = set().union(*self.included.values()) # type: ignore for docname in sorted(self.all_docs): if docname not in self.files_to_rebuild: if docname == self.config.master_doc: diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index f1261bcdc..565396ec4 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -15,6 +15,7 @@ from six import iteritems from sphinx import addnodes from sphinx.locale import __ from sphinx.util import url_re, logging +from sphinx.util.matching import Matcher from sphinx.util.nodes import clean_astext, process_only_nodes if False: @@ -83,6 +84,7 @@ class TocTree(object): # interactions between marking and pruning the tree (see bug #1046). toctree_ancestors = self.get_toctree_ancestors(docname) + excluded = Matcher(self.env.config.exclude_patterns) def _toctree_add_classes(node, depth): # type: (nodes.Node, int) -> None @@ -172,8 +174,12 @@ class TocTree(object): ref, location=toctreenode) except KeyError: # this is raised if the included file does not exist - logger.warning(__('toctree contains reference to nonexisting document %r'), - ref, location=toctreenode) + if excluded(self.env.doc2path(ref, None)): + message = __('toctree contains reference to excluded document %r') + else: + message = __('toctree contains reference to nonexisting document %r') + + logger.warning(message, ref, location=toctreenode) else: # if titles_only is given, only keep the main title and # sub-toctrees diff --git a/sphinx/environment/collectors/asset.py b/sphinx/environment/collectors/asset.py index 70faf108c..725431dfa 100644 --- a/sphinx/environment/collectors/asset.py +++ b/sphinx/environment/collectors/asset.py @@ -128,13 +128,16 @@ class DownloadFileCollector(EnvironmentCollector): """Process downloadable file paths. """ for node in doctree.traverse(addnodes.download_reference): targetname = node['reftarget'] - rel_filename, filename = app.env.relfn2path(targetname, app.env.docname) - app.env.dependencies[app.env.docname].add(rel_filename) - if not os.access(filename, os.R_OK): - logger.warning(__('download file not readable: %s') % filename, - location=node, type='download', subtype='not_readable') - continue - node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename) + if '://' in targetname: + node['refuri'] = targetname + else: + rel_filename, filename = app.env.relfn2path(targetname, app.env.docname) + app.env.dependencies[app.env.docname].add(rel_filename) + if not os.access(filename, os.R_OK): + logger.warning(__('download file not readable: %s') % filename, + location=node, type='download', subtype='not_readable') + continue + node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename) def setup(app): diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 1ecf344e4..fab5d3039 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -79,6 +79,7 @@ from sphinx.util import import_object, rst, logging from sphinx.util.docutils import ( NullReporter, SphinxDirective, new_document, switch_source_input ) +from sphinx.util.matching import Matcher if False: # For type annotation @@ -249,12 +250,17 @@ class Autosummary(SphinxDirective): tree_prefix = self.options['toctree'].strip() docnames = [] + excluded = Matcher(self.config.exclude_patterns) for name, sig, summary, real_name in items: docname = posixpath.join(tree_prefix, real_name) docname = posixpath.normpath(posixpath.join(dirname, docname)) if docname not in self.env.found_docs: - self.warn('toctree references unknown document %r' - % docname) + if excluded(self.env.doc2path(docname, None)): + self.warn('toctree references excluded document %r' + % docname) + else: + self.warn('toctree references unknown document %r' + % docname) docnames.append(docname) tocnode = addnodes.toctree() diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index 79c78ae93..6128c0235 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -78,7 +78,7 @@ language = {{ language | repr }} exclude_patterns = [{{ exclude_patterns }}] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = None # -- Options for HTML output ------------------------------------------------- diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 797b5828e..e2899e8a4 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -564,10 +564,20 @@ class HTMLTranslator(BaseTranslator): def visit_download_reference(self, node): # type: (nodes.Node) -> None - if self.builder.download_support and node.hasattr('filename'): - self.body.append( - '' % - posixpath.join(self.builder.dlpath, node['filename'])) + atts = {'class': 'reference download', + 'download': ''} + + if not self.builder.download_support: + self.context.append('') + elif 'refuri' in node: + atts['class'] += ' external' + atts['href'] = node['refuri'] + self.body.append(self.starttag(node, 'a', '', **atts)) + self.context.append('') + elif 'filename' in node: + atts['class'] += ' internal' + atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: self.context.append('') diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 74dc827a1..c14775b9c 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -510,10 +510,20 @@ class HTML5Translator(BaseTranslator): def visit_download_reference(self, node): # type: (nodes.Node) -> None - if self.builder.download_support and node.hasattr('filename'): - self.body.append( - '' % - posixpath.join(self.builder.dlpath, node['filename'])) + atts = {'class': 'reference download', + 'download': ''} + + if not self.builder.download_support: + self.context.append('') + elif 'refuri' in node: + atts['class'] += ' external' + atts['href'] = node['refuri'] + self.body.append(self.starttag(node, 'a', '', **atts)) + self.context.append('') + elif 'filename' in node: + atts['class'] += ' internal' + atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: self.context.append('') diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 6b7ec5932..701880a61 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -612,7 +612,7 @@ class TexinfoTranslator(nodes.NodeVisitor): node_name = node['node_name'] pointers = tuple([node_name] + self.rellinks[node_name]) self.body.append('\n@node %s,%s,%s,%s\n' % pointers) # type: ignore - for id in self.next_section_ids: + for id in sorted(self.next_section_ids): self.add_anchor(id, node) self.next_section_ids.clear() diff --git a/tests/roots/test-roles-download/conf.py b/tests/roots/test-roles-download/conf.py new file mode 100644 index 000000000..31e7a6ed4 --- /dev/null +++ b/tests/roots/test-roles-download/conf.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_documents = [ + (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report') +] diff --git a/tests/roots/test-roles-download/dummy.dat b/tests/roots/test-roles-download/dummy.dat new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-roles-download/index.rst b/tests/roots/test-roles-download/index.rst new file mode 100644 index 000000000..41cda621a --- /dev/null +++ b/tests/roots/test-roles-download/index.rst @@ -0,0 +1,6 @@ +test-roles-download +=================== + +* :download:`dummy.dat` +* :download:`not_found.dat` +* :download:`Sphinx logo ` diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py index f8c1457fa..074e40fb6 100644 --- a/tests/test_build_epub.py +++ b/tests/test_build_epub.py @@ -354,6 +354,22 @@ def test_epub_css_files(app): 'href="https://example.com/custom.css" />' not in content) +@pytest.mark.sphinx('epub', testroot='roles-download') +def test_html_download_role(app, status, warning): + app.build() + assert not (app.outdir / '_downloads' / 'dummy.dat').exists() + + content = (app.outdir / 'index.xhtml').text() + assert ('
  • ' + 'dummy.dat

  • ' in content) + assert ('
  • ' + 'not_found.dat

  • ' in content) + assert ('
  • ' + 'Sphinx logo' + ' [http://www.sphinx-doc.org/en/master' + '/_static/sphinxheader.png]

  • ' in content) + + @pytest.mark.sphinx('epub') def test_run_epubcheck(app): app.build() diff --git a/tests/test_build_html.py b/tests/test_build_html.py index b8286edb3..51732435e 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1387,3 +1387,23 @@ def test_html_math_renderer_is_mismatched(make_app, app_params): assert False except ConfigError as exc: assert str(exc) == "Unknown math_renderer 'imgmath' is given." + + +@pytest.mark.sphinx('html', testroot='basic') +def test_html_pygments_style_default(app): + style = app.builder.highlighter.formatter_args.get('style') + assert style.__name__ == 'Alabaster' + + +@pytest.mark.sphinx('html', testroot='basic', + confoverrides={'pygments_style': 'sphinx'}) +def test_html_pygments_style_manually(app): + style = app.builder.highlighter.formatter_args.get('style') + assert style.__name__ == 'SphinxStyle' + + +@pytest.mark.sphinx('html', testroot='basic', + confoverrides={'html_theme': 'classic'}) +def test_html_pygments_for_classic_theme(app): + style = app.builder.highlighter.formatter_args.get('style') + assert style.__name__ == 'SphinxStyle' diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 82050cee1..21da21224 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -321,3 +321,23 @@ def test_html5_output(app, cached_etree_parse, fname, expect): app.build() print(app.outdir / fname) check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect) + + +@pytest.mark.sphinx('html', testroot='roles-download', + confoverrides={'html_experimental_html5_writer': True}) +def test_html_download_role(app, status, warning): + app.build() + assert (app.outdir / '_downloads' / 'dummy.dat').exists() + + content = (app.outdir / 'index.html').text() + assert ('
  • ' + '' + 'dummy.dat

  • ' in content) + assert ('
  • ' + 'not_found.dat

  • ' in content) + assert ('
  • ' + '' + 'Sphinx logo' + '

  • ' in content) diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index 6b6892594..b1fd8c2a9 100644 --- a/tests/test_build_texinfo.py +++ b/tests/test_build_texinfo.py @@ -50,6 +50,10 @@ def test_texinfo_warnings(app, status, warning): def test_texinfo(app, status, warning): TexinfoTranslator.ignore_missing_images = True app.builder.build_all() + result = (app.outdir / 'SphinxTests.texi').text(encoding='utf8') + assert ('@anchor{markup doc}@anchor{12}' + '@anchor{markup id1}@anchor{13}' + '@anchor{markup testing-various-markup}@anchor{14}' in result) # now, try to run makeinfo over it cwd = os.getcwd() os.chdir(app.outdir)