diff --git a/CHANGES b/CHANGES index 3c8468c79..805a972cc 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,9 @@ Release 1.4 alpha2 (in development) Incompatible changes -------------------- +* #2327: `latex_use_parts` is deprecated now. Use `latex_toplevel_sectioning` instead. +* #2337: Use ``\url{URL}`` macro instead of ``\href{URL}{URL}`` in LaTeX writer. +* #1498: manpage writer: don't make whole of item in definition list bold if it includes strong node. Features added -------------- @@ -13,9 +16,14 @@ Features added * #2245: Add ``latex_elements["passoptionstopackages"]`` option to call PassOptionsToPackages in early stage of preambles. * #2340: Math extension: support alignment of multiple equations for MathJAX. -* #2338: Define ``\titlereference`` macro to redefine the style of ``title-reference`` roles. +* #2338: Define ``\titleref`` macro to redefine the style of ``title-reference`` roles. * Define ``\menuselection`` and ``\accelerator`` macros to redefine the style of `menuselection` roles. -* Define ``\internalreference`` macro to redefine the style of references +* Define ``\crossref`` macro to redefine the style of references +* #2301: Texts in the classic html theme should be hyphenated. +* #2355: Define ``\termref`` macro to redefine the style of ``term`` roles. +* Add :confval:`suppress_warnings` to suppress arbitrary warning message (experimental) +* #2229: Fix no warning is given for unknown options +* #2327: Add `latex_toplevel_sectioning` to switch the top level sectioning of LaTeX document. Bugs fixed ---------- @@ -28,6 +36,13 @@ Bugs fixed * #2329: Refresh environment forcely if source directory has changed. * #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from xcolor package * Fix the confval type checker emits warnings if unicode is given to confvals which expects string value +* #2360: Fix numref in LaTeX output is broken +* #2361: Fix additional paragraphs inside the "compound" directive are indented +* #2364: Fix KeyError 'rootSymbol' on Sphinx upgrade from older version. +* #2348: Move amsmath and amssymb to before fontpkg on LaTeX writer. +* #2368: Ignore emacs lock files like ``.#foo.rst`` by default. +* #2262: literal_block and its caption has been separated by pagebreak in LaTeX output. +* #2319: Fix table counter is overrided by code-block's in LaTeX. Thanks to jfbu. Documentation ------------- @@ -154,6 +169,11 @@ Release 1.3.7 (in development) Bugs fixed ---------- +* #2358: Fix user-preamble could not override the tocdepth definition. +* #2358: Redece tocdepth if ``part`` or ``chapter`` is used for top_sectionlevel. +* #2351: Fix footnote spacing +* #2363: Fix ``toctree()`` in templates generates broken links in SingleHTMLBuilder. + Release 1.3.6 (released Feb 29, 2016) ===================================== diff --git a/doc/config.rst b/doc/config.rst index 40ee674cd..c87db8dd3 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -212,6 +212,26 @@ General configuration .. versionadded:: 0.5 +.. confval:: suppress_warnings + + A list of warning types to suppress arbitrary warning messages. + + Sphinx supports following warning types: + + * ref.term + * ref.ref + * ref.numref + * ref.keyword + * ref.option + * ref.citation + * ref.doc + + You can choose from these types. + + Now, this option should be considered *experimental*. + + .. versionadded:: 1.4 + .. confval:: needs_sphinx If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will @@ -1459,6 +1479,15 @@ These options influence LaTeX output. configuration directory) that is the logo of the docs. It is placed at the top of the title page. Default: ``None``. +.. confval:: latex_toplevel_sectioning + + This value determines the topmost sectioning unit. It should be chosen from + ``part``, ``chapter`` or ``section``. The default is ``None``; the topmost + sectioning unit is switched by documentclass. ``section`` is used if + documentclass will be ``howto``, otherwise ``chapter`` will be used. + + .. versionadded:: 1.4 + .. confval:: latex_use_parts If true, the topmost sectioning unit is parts, else it is chapters. Default: @@ -1466,6 +1495,9 @@ These options influence LaTeX output. .. versionadded:: 0.3 + .. deprecated:: 1.4 + Use :confval:`latex_toplevel_sectioning`. + .. confval:: latex_appendices A list of document names to append as an appendix to all manuals. diff --git a/doc/markup/toctree.rst b/doc/markup/toctree.rst index 4123ee95d..b4c7105fd 100644 --- a/doc/markup/toctree.rst +++ b/doc/markup/toctree.rst @@ -223,11 +223,8 @@ The special document names (and pages generated for them) are: .. rubric:: Footnotes -.. [#] The ``maxdepth`` option does not apply to the LaTeX writer, where the - whole table of contents will always be presented at the begin of the - document, and its depth is controlled by the ``tocdepth`` counter, which - you can reset in your :confval:`latex_preamble` config value using - e.g. ``\setcounter{tocdepth}{2}``. +.. [#] The LaTeX writer only refers the ``maxdepth`` option of first toctree + directive in the document. .. [#] A note on available globbing syntax: you can use the standard shell constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that diff --git a/sphinx/application.py b/sphinx/application.py index ca9fadb2b..4465113d7 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -41,6 +41,7 @@ from sphinx.util import pycompat # noqa: imported for side-effects from sphinx.util import import_object from sphinx.util.tags import Tags from sphinx.util.osutil import ENOENT +from sphinx.util.logging import is_suppressed_warning from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \ term_width_line @@ -318,7 +319,7 @@ class Sphinx(object): wfile.flush() self.messagelog.append(message) - def warn(self, message, location=None, prefix='WARNING: '): + def warn(self, message, location=None, prefix='WARNING: ', type=None, subtype=None): """Emit a warning. If *location* is given, it should either be a tuple of (docname, lineno) @@ -326,12 +327,17 @@ class Sphinx(object): *prefix* usually should not be changed. + *type* and *subtype* are used to suppress warnings with :confval:`suppress_warnings`. + .. note:: For warnings emitted during parsing, you should use :meth:`.BuildEnvironment.warn` since that will collect all warnings during parsing for later output. """ + if is_suppressed_warning(type, subtype, self.config.suppress_warnings): + return + if isinstance(location, tuple): docname, lineno = location if docname: diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 38e009a8f..8863050ba 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -260,12 +260,12 @@ class Builder(object): # while reading, collect all warnings from docutils warnings = [] - self.env.set_warnfunc(lambda *args: warnings.append(args)) + self.env.set_warnfunc(lambda *args, **kwargs: warnings.append((args, kwargs))) updated_docnames = set(self.env.update(self.config, self.srcdir, self.doctreedir, self.app)) self.env.set_warnfunc(self.warn) - for warning in warnings: - self.warn(*warning) + for warning, kwargs in warnings: + self.warn(*warning, **kwargs) doccount = len(updated_docnames) self.info(bold('looking for now-outdated files... '), nonl=1) @@ -350,7 +350,7 @@ class Builder(object): self.info('done') warnings = [] - self.env.set_warnfunc(lambda *args: warnings.append(args)) + self.env.set_warnfunc(lambda *args, **kwargs: warnings.append((args, kwargs))) if self.parallel_ok: # number of subprocesses is parallel-1 because the main process # is busy loading doctrees and doing write_doc_serialized() @@ -366,13 +366,16 @@ class Builder(object): doctree = self.env.get_and_resolve_doctree(docname, self) self.write_doc_serialized(docname, doctree) self.write_doc(docname, doctree) - for warning in warnings: - self.warn(*warning) + for warning, kwargs in warnings: + self.warn(*warning, **kwargs) def _write_parallel(self, docnames, warnings, nproc): def write_process(docs): local_warnings = [] - self.env.set_warnfunc(lambda *args: local_warnings.append(args)) + + def warnfunc(*args, **kwargs): + local_warnings.append((args, kwargs)) + self.env.set_warnfunc(warnfunc) for docname, doctree in docs: self.write_doc(docname, doctree) return local_warnings @@ -402,8 +405,8 @@ class Builder(object): self.info(bold('waiting for workers...')) tasks.join() - for warning in warnings: - self.warn(*warning) + for warning, kwargs in warnings: + self.warn(*warning, **kwargs) def prepare_writing(self, docnames): """A place where you can add logic before :meth:`write_doc` is run""" diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index b06e9fd6e..367e28b8d 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -947,6 +947,13 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder): if hashindex >= 0: refnode['refuri'] = fname + refuri[hashindex:] + def _get_local_toctree(self, docname, collapse=True, **kwds): + if 'includehidden' not in kwds: + kwds['includehidden'] = False + toctree = self.env.get_toctree_for(docname, self, collapse, **kwds) + self.fix_refuris(toctree) + return self.render_partial(toctree)['fragment'] + def assemble_doctree(self): master = self.config.master_doc tree = self.env.get_doctree(master) diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 56767ab8a..f3e64bcb1 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -11,6 +11,7 @@ import os from os import path +import warnings from six import iteritems from docutils import nodes @@ -43,6 +44,21 @@ class LaTeXBuilder(Builder): self.docnames = [] self.document_data = [] texescape.init() + self.check_options() + + def check_options(self): + if self.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'): + self.warn('invalid latex_toplevel_sectioning, ignored: %s' % + self.config.latex_top_sectionlevel) + self.config.latex_top_sectionlevel = None + + if self.config.latex_use_parts: + warnings.warn('latex_use_parts will be removed at Sphinx-1.5. ' + 'Use latex_toplevel_sectioning instead.', + DeprecationWarning) + + if self.config.latex_toplevel_sectioning: + self.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.') def get_outdated_docs(self): return 'all documents' # for now diff --git a/sphinx/config.py b/sphinx/config.py index ac94c5d03..73f442cf9 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -76,6 +76,7 @@ class Config(object): templates_path = ([], 'html'), template_bridge = (None, 'html', string_classes), keep_warnings = (False, 'env'), + suppress_warnings = ([], 'env'), modindex_common_prefix = ([], 'html'), rst_epilog = (None, 'env', string_classes), rst_prolog = (None, 'env', string_classes), @@ -206,7 +207,9 @@ class Config(object): None), latex_logo = (None, None, string_classes), latex_appendices = ([], None), + # now deprecated - use latex_toplevel_sectioning latex_use_parts = (False, None), + latex_toplevel_sectioning = (None, None, [str]), latex_use_modindex = (True, None), # deprecated latex_domain_indices = (True, None, [list]), latex_show_urls = ('no', None), diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index dc1a283bb..e5f9ab557 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -447,7 +447,7 @@ class StandardDomain(Domain): 'productionlist': ProductionList, } roles = { - 'option': OptionXRefRole(), + 'option': OptionXRefRole(warn_dangling=True), 'envvar': EnvVarXRefRole(), # links to tokens in grammar productions 'token': XRefRole(), @@ -485,6 +485,7 @@ class StandardDomain(Domain): 'the label must precede a section header)', 'numref': 'undefined label: %(target)s', 'keyword': 'unknown keyword: %(target)s', + 'option': 'unknown option: %(target)s', } enumerable_nodes = { # node_class -> (figtype, title_getter) diff --git a/sphinx/environment.py b/sphinx/environment.py index b8b40b8e6..20e878414 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -75,7 +75,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 = 46 + (sys.version_info[0] - 2) +ENV_VERSION = 47 + (sys.version_info[0] - 2) dummy_reporter = Reporter('', 4, 4) @@ -242,7 +242,7 @@ class BuildEnvironment: self.versioning_condition = condition self.versioning_compare = compare - def warn(self, docname, msg, lineno=None): + def warn(self, docname, msg, lineno=None, **kwargs): """Emit a warning. This differs from using ``app.warn()`` in that the warning may not @@ -250,11 +250,11 @@ class BuildEnvironment: the update of the environment. """ # strange argument order is due to backwards compatibility - self._warnfunc(msg, (docname, lineno)) + self._warnfunc(msg, (docname, lineno), **kwargs) - def warn_node(self, msg, node): + def warn_node(self, msg, node, **kwargs): """Like :meth:`warn`, but with source information taken from *node*.""" - self._warnfunc(msg, '%s:%s' % get_source_line(node)) + self._warnfunc(msg, '%s:%s' % get_source_line(node), **kwargs) def clear_doc(self, docname): """Remove all traces of a source file in the inventory.""" @@ -391,7 +391,7 @@ class BuildEnvironment: config.exclude_patterns[:] + config.templates_path + config.html_extra_path + - ['**/_sources', '.#*', '*.lproj/**'] + ['**/_sources', '.#*', '**/.#*', '*.lproj/**'] ) self.found_docs = set(get_matching_docs( self.srcdir, config.source_suffix, exclude_matchers=matchers)) @@ -576,7 +576,7 @@ class BuildEnvironment: def read_process(docs): self.app = app self.warnings = [] - self.set_warnfunc(lambda *args: self.warnings.append(args)) + self.set_warnfunc(lambda *args, **kwargs: self.warnings.append((args, kwargs))) for docname in docs: self.read_doc(docname, app) # allow pickling self to send it back @@ -603,8 +603,8 @@ class BuildEnvironment: app.info(bold('waiting for workers...')) tasks.join() - for warning in warnings: - self._warnfunc(*warning) + for warning, kwargs in warnings: + self._warnfunc(*warning, **kwargs) def check_dependents(self, already): to_rewrite = self.assign_section_numbers() + self.assign_figure_numbers() @@ -1540,7 +1540,7 @@ class BuildEnvironment: (node['refdomain'], typ) else: msg = '%r reference target not found: %%(target)s' % typ - self.warn_node(msg % {'target': target}, node) + self.warn_node(msg % {'target': target}, node, type='ref', subtype=typ) def _resolve_doc_reference(self, builder, node, contnode): # directly reference to document by source name; diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index bd1e75214..b9350e3eb 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -214,11 +214,6 @@ def number_equations(app, doctree, docname): node[0] = nodes.Text(num, num) -def setup_amsfont(app): - # use amsfonts if users do not configure latex_elements['amsfonts'] - app.config.latex_elements.setdefault('amsfonts', r'\usepackage{amsfonts}') - - def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): app.add_config_value('math_number_all', False, 'html') app.add_node(math, override=True, @@ -243,4 +238,3 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): app.add_role('eq', eq_role) app.add_directive('math', MathDirective) app.connect('doctree-resolved', number_equations) - app.connect('builder-inited', setup_amsfont) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 30c48c6ca..1e8f43978 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -14,8 +14,6 @@ \RequirePackage{fancybox} \RequirePackage{titlesec} \RequirePackage{tabulary} -\RequirePackage{amsmath} % for \text -\RequirePackage{amssymb} % for some symbols \RequirePackage{makeidx} \RequirePackage{framed} \RequirePackage{ifthen} @@ -146,10 +144,13 @@ \newcommand{\bfcode}[1]{\code{\bfseries#1}} \newcommand{\email}[1]{\textsf{#1}} \newcommand{\tablecontinued}[1]{\textsf{#1}} -\newcommand{\titlereference}[1]{\emph{#1}} +\newcommand{\titleref}[1]{\emph{#1}} \newcommand{\menuselection}[1]{\emph{#1}} \newcommand{\accelerator}[1]{\underline{#1}} -\newcommand{\internalreference}[1]{\emph{#1}} +\newcommand{\crossref}[1]{\emph{#1}} +\newcommand{\termref}[1]{\emph{#1}} + +\newcommand*{\sphinxAtStartFootnote}{\mbox{ }} % Redefine the Verbatim environment to allow border and background colors. % The original environment is still used for verbatims within tables. @@ -157,22 +158,96 @@ \let\endOriginalVerbatim=\endVerbatim % Play with vspace to be able to keep the indentation. -\newlength\distancetoright -\def\mycolorbox#1{% - \setlength\distancetoright{\linewidth}% - \advance\distancetoright -\@totalleftmargin % +\newlength\Sphinx@scratchlength +\newcommand\Sphinxcolorbox [1]{% + \setlength\Sphinx@scratchlength{\linewidth}% + \advance\Sphinx@scratchlength -\@totalleftmargin % \fcolorbox{VerbatimBorderColor}{VerbatimColor}{% - \begin{minipage}{\distancetoright}% + \begin{minipage}{\Sphinx@scratchlength}% #1 \end{minipage}% }% } -\def\FrameCommand{\mycolorbox} +% used for split frames for continuation on next and final page +\def\MidFrameCommand{\Sphinxcolorbox} +\let\LastFrameCommand\MidFrameCommand + +% We customize \FrameCommand (for non split frames) and \FirstFrameCommand +% (split frames), in order for the framed environment to insert a Title above +% the frame, which can not be separated by a pagebreak. + +% The title is specified from outside as macro \SphinxVerbatimTitle. +% \SphinxVerbatimTitle is reset to empty after each use of Verbatim environment. + +% It is also possible to use directly framed environment (i.e. not indirectly +% via the Verbatim environment next), then it is \SphinxFrameTitle which specifies +% the title. +\newcommand*\SphinxFrameTitle {} +\newcommand*\SphinxVerbatimTitle {} +\newcommand*\SphinxSetupCaptionForVerbatim [2] +{% + \def\SphinxVerbatimTitle{\captionof{#1}{#2}\smallskip }% +} + +% \SphinxCustomFBox is copied from framed.sty's \CustomFBox, but +% #1=title/caption is to be set _above_ the top rule, not _below_ +% #1 must be "vertical material", it may be left empty. + +% The amsmath patches \stepcounter to inhibit stepping under +% \firstchoice@false. We use it because framed.sty typesets multiple +% times its contents. +\newif\ifSphinx@myfirstframedpass + +\long\def\SphinxCustomFBox#1#2#3#4#5#6#7{% + % we set up amsmath (amstext.sty) conditional to inhibit counter stepping + % except in first pass + \ifSphinx@myfirstframedpass\firstchoice@true + \else\firstchoice@false\fi + \leavevmode\begingroup + \setbox\@tempboxa\hbox{% + \color@begingroup + \kern\fboxsep{#7}\kern\fboxsep + \color@endgroup}% + \hbox{% + \lower\dimexpr#4+\fboxsep+\dp\@tempboxa\hbox{% + \vbox{% + #1% TITLE + \hrule\@height#3\relax + \hbox{% + \vrule\@width#5\relax + \vbox{% + \vskip\fboxsep + \copy\@tempboxa + \vskip\fboxsep}% + \vrule\@width#6\relax}% + #2% + \hrule\@height#4\relax}% + }% + }% + \endgroup + \global\Sphinx@myfirstframedpassfalse +} + +% for non split frames: +\def\FrameCommand{% + % this is inspired from framed.sty v 0.96 2011/10/22 lines 185--190 + % \fcolorbox (see \Sphinxcolorbox above) from color.sty uses \fbox. + \def\fbox{\SphinxCustomFBox{\SphinxFrameTitle}{}% + \fboxrule\fboxrule\fboxrule\fboxrule}% + % \fcolorbox from xcolor.sty may use rather \XC@fbox. + \let\XC@fbox\fbox + \Sphinxcolorbox +} +% for first portion of split frames: +\let\FirstFrameCommand\FrameCommand \renewcommand{\Verbatim}[1][1]{% % list starts new par, but we don't want it to be set apart vertically - \bgroup\parskip=0pt% - \smallskip% + \bgroup\parskip\z@skip + \smallskip + % use customized framed environment + \let\SphinxFrameTitle\SphinxVerbatimTitle + \global\Sphinx@myfirstframedpasstrue % The list environement is needed to control perfectly the vertical % space. \list{}{% @@ -183,15 +258,17 @@ \setlength\leftmargin{0pt}% }% \item\MakeFramed {\FrameRestore}% - \small% + \small \OriginalVerbatim[#1]% } \renewcommand{\endVerbatim}{% - \endOriginalVerbatim% - \endMakeFramed% - \endlist% - % close group to restore \parskip - \egroup% + \endOriginalVerbatim + \endMakeFramed + \endlist + % close group to restore \parskip (and \SphinxFrameTitle) + \egroup + % reset to empty \SphinxVerbatimTitle + \global\let\SphinxVerbatimTitle\empty } @@ -448,6 +525,9 @@ % \capstart for figures that actually have a caption.) \RequirePackage{hypcap} +% Set up styles of URL: it should be placed after hyperref +\urlstyle{same} + % From docutils.writers.latex2e % inline markup (custom roles) % \DUrole{#1}{#2} tries \DUrole#1{#2} diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index 1f365c689..f6d988e2c 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -189,6 +189,13 @@ div.genindex-jumpbox { /* -- general body styles --------------------------------------------------- */ +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + a.headerlink { visibility: hidden; } diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py new file mode 100644 index 000000000..ef91b728b --- /dev/null +++ b/sphinx/util/logging.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + sphinx.util.logging + ~~~~~~~~~~~~~~~~~~~ + + Logging utility functions for Sphinx. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + + +def is_suppressed_warning(type, subtype, suppress_warnings): + """Check the warning is suppressed or not.""" + if type is None: + return False + + for warning_type in suppress_warnings: + if '.' in warning_type: + target, subtarget = warning_type.split('.', 1) + else: + target, subtarget = warning_type, None + + if target == type: + if (subtype is None or subtarget is None or + subtarget == subtype or subtarget == '*'): + return True + + return False diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 2baf245af..1986e1b50 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -39,7 +39,7 @@ HEADER = r'''%% Generated by Sphinx. %(utf8extra)s %(cmappkg)s %(fontenc)s -%(amsfonts)s +%(amsmath)s %(babel)s %(fontpkg)s %(fncychap)s @@ -51,6 +51,7 @@ HEADER = r'''%% Generated by Sphinx. %(contentsname)s %(numfig_format)s %(pageautorefname)s +%(tocdepth)s %(preamble)s \title{%(title)s} @@ -59,7 +60,6 @@ HEADER = r'''%% Generated by Sphinx. \author{%(author)s} \newcommand{\sphinxlogo}{%(logo)s} \renewcommand{\releasename}{%(releasename)s} -%(tocdepth)s %(makeindex)s ''' @@ -279,7 +279,7 @@ class LaTeXTranslator(nodes.NodeVisitor): '\\else\\fi'), 'cmappkg': '\\usepackage{cmap}', 'fontenc': '\\usepackage[T1]{fontenc}', - 'amsfonts': '', + 'amsmath': '\\usepackage{amsmath,amssymb}', 'babel': '\\usepackage{babel}', 'fontpkg': '\\usepackage{times}', 'fncychap': '\\usepackage[Bjarne]{fncychap}', @@ -331,6 +331,19 @@ class LaTeXTranslator(nodes.NodeVisitor): self.remember_multirow = {} self.remember_multirowcol = {} + # determine top section level + if builder.config.latex_toplevel_sectioning: + self.top_sectionlevel = \ + self.sectionnames.index(builder.config.latex_toplevel_sectioning) + else: + if document.settings.docclass == 'howto': + self.top_sectionlevel = 2 + else: + if builder.config.latex_use_parts: + self.top_sectionlevel = 0 + else: + self.top_sectionlevel = 1 + # sort out some elements papersize = builder.config.latex_paper_size + 'paper' if papersize == 'paper': # e.g. command line "-D latex_paper_size=" @@ -399,12 +412,14 @@ class LaTeXTranslator(nodes.NodeVisitor): self.elements['classoptions'] += ',' + \ self.elements['extraclassoptions'] if document.get('tocdepth'): - if document.settings.docclass == 'howto': - self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' % - document['tocdepth']) - else: - self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' % - (document['tocdepth'] - 1)) + # redece tocdepth if `part` or `chapter` is used for top_sectionlevel + # tocdepth = -1: show only parts + # tocdepth = 0: show parts and chapters + # tocdepth = 1: show parts, chapters and sections + # tocdepth = 2: show parts, chapters, sections and subsections + # ... + self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' % + (document['tocdepth'] + self.top_sectionlevel - 2)) if getattr(document.settings, 'contentsname', None): self.elements['contentsname'] = \ self.babel_renewcommand('\\contentsname', document.settings.contentsname) @@ -432,13 +447,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.pending_footnotes = [] self.curfilestack = [] self.handled_abbrs = set() - if document.settings.docclass == 'howto': - self.top_sectionlevel = 2 - else: - if builder.config.latex_use_parts: - self.top_sectionlevel = 0 - else: - self.top_sectionlevel = 1 self.next_hyperlink_ids = {} self.next_section_ids = set() @@ -925,9 +933,9 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_collected_footnote(self, node): self.in_footnote += 1 if 'footnotetext' in node: - self.body.append('\\footnotetext[%s]{' % node['number']) + self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote%%' % node['number']) else: - self.body.append('\\footnote[%s]{' % node['number']) + self.body.append('\\footnote[%s]{\sphinxAtStartFootnote%%' % node['number']) def depart_collected_footnote(self, node): self.body.append('}') @@ -1267,7 +1275,14 @@ class LaTeXTranslator(nodes.NodeVisitor): depart_field_body = depart_definition def visit_paragraph(self, node): - self.body.append('\n') + # insert blank line, if the paragraph follows a non-paragraph node in a compound + index = node.parent.index(node) + if (index > 0 and isinstance(node.parent, nodes.compound) and + not isinstance(node.parent[index - 1], nodes.paragraph) and + not isinstance(node.parent[index - 1], nodes.compound)): + self.body.append('\\noindent\n') + else: + self.body.append('\n') def depart_paragraph(self, node): self.body.append('\n') @@ -1419,8 +1434,8 @@ class LaTeXTranslator(nodes.NodeVisitor): self.in_caption += 1 if self.in_container_literal_block: self.body.append('\\needspace{\\literalblockneedspace}') - self.body.append('\\vspace{\\literalblockcaptiontopvspace}') - self.body.append('\\captionof{literal-block}{') + self.body.append('\\vspace{\\literalblockcaptiontopvspace}%') + self.body.append('\n\\SphinxSetupCaptionForVerbatim{literal-block}{') return self.body.append('\\caption{') @@ -1504,8 +1519,8 @@ class LaTeXTranslator(nodes.NodeVisitor): return else: domain = self.builder.env.domains['std'] - figtype = domain.get_figtype(node) - if figtype and domain.get_numfig_title(node): + figtype = domain.get_figtype(next) + if figtype and domain.get_numfig_title(next): ids = set() # labels for figures go in the figure body, not before if node.get('refid'): @@ -1584,8 +1599,12 @@ class LaTeXTranslator(nodes.NodeVisitor): if self.in_title or not uri: self.context.append('') elif uri.startswith(URI_SCHEMES): - self.body.append('\\href{%s}{' % self.encode_uri(uri)) - self.context.append('}') + if len(node) == 1 and uri == node[0]: + self.body.append('\\url{%s}' % self.encode_uri(uri)) + raise nodes.SkipNode + else: + self.body.append('\\href{%s}{' % self.encode_uri(uri)) + self.context.append('}') elif uri.startswith('#'): # references to labels in the same document id = self.curfilestack[-1] + ':' + uri[1:] @@ -1606,12 +1625,14 @@ class LaTeXTranslator(nodes.NodeVisitor): # reference to a label id = uri[1:].replace('#', ':') self.body.append(self.hyperlink(id)) - self.body.append(r'\internalreference{') if len(node) and hasattr(node[0], 'attributes') and \ 'std-term' in node[0].get('classes', []): # don't add a pageref for glossary terms self.context.append('}}}') + # mark up as termreference + self.body.append(r'\termref{') else: + self.body.append(r'\crossref{') if self.builder.config.latex_show_pagerefs and not \ self.in_production_list: self.context.append('}}} (%s)' % self.hyperpageref(id)) @@ -1699,7 +1720,7 @@ class LaTeXTranslator(nodes.NodeVisitor): return self.depart_literal_emphasis(node) def visit_title_reference(self, node): - self.body.append(r'\titlereference{') + self.body.append(r'\titleref{') def depart_title_reference(self, node): self.body.append('}') diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 7454a0f20..2651ec2e4 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -203,6 +203,13 @@ class ManualPageTranslator(BaseTranslator): def depart_versionmodified(self, node): self.depart_paragraph(node) + # overwritten -- don't make whole of term bold if it includes strong node + def visit_term(self, node): + if node.traverse(nodes.strong): + self.body.append('\n') + else: + BaseTranslator.visit_term(self, node) + def visit_termsep(self, node): warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5', DeprecationWarning) diff --git a/tests/path.py b/tests/path.py index f4b2612f6..901c9ce96 100755 --- a/tests/path.py +++ b/tests/path.py @@ -12,7 +12,7 @@ import sys import shutil from io import open -from six import PY2, text_type +from six import PY2, text_type, binary_type FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding() @@ -143,7 +143,9 @@ class path(text_type): Returns the text in the file. """ with open(self, mode='U', encoding=encoding, **kwargs) as f: - return f.read() + text = f.read() + contents = repr_as(text, '<%s contents>' % self.basename()) + return contents def bytes(self): """ @@ -198,3 +200,18 @@ class path(text_type): def __repr__(self): return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self)) + + +# Lives here only to avoid circular references; use it from util.py! +class _repr_text(text_type): + def __repr__(self): + return self._repr +class _repr_bin(binary_type): + def __repr__(self): + return self._repr + +def repr_as(string, repr_): + wrapper = _repr_text if isinstance(string, text_type) else _repr_bin + proxy = wrapper(string) + proxy._repr = repr_ + return proxy diff --git a/tests/root/lists.txt b/tests/root/lists.txt index 99a55dc39..1fa2d11c5 100644 --- a/tests/root/lists.txt +++ b/tests/root/lists.txt @@ -52,3 +52,12 @@ y. y #. z #. { + +definition lists +----------------- + +term1 + description + +term2 (**stronged partially**) + description diff --git a/tests/test_build_html.py b/tests/test_build_html.py index f1e4b8cba..985b57fec 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -40,6 +40,7 @@ HTML_WARNINGS = ENV_WARNINGS + """\ %(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*' %(root)s/markup.txt:271: WARNING: Could not lex literal_block as "c". Highlighting skipped. %(root)s/footnote.txt:60: WARNING: citation not found: missing +%(root)s/markup.txt:160: WARNING: unknown option: &option """ if PY3: diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index ea1468c2e..ebed48f9c 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -24,6 +24,7 @@ from test_build_html import ENV_WARNINGS LATEX_WARNINGS = ENV_WARNINGS + """\ +%(root)s/markup.txt:160: WARNING: unknown option: &option %(root)s/footnote.txt:60: WARNING: citation not found: missing %(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*' %(root)s/markup.txt:271: WARNING: Could not lex literal_block as "c". Highlighting skipped. @@ -394,18 +395,18 @@ def test_footnote(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert '\\footnote[1]{\nnumbered\n}' in result - assert '\\footnote[2]{\nauto numbered\n}' in result - assert '\\footnote[3]{\nnamed\n}' in result - assert '{\\hyperref[footnote:bar]{\\internalreference{{[}bar{]}}}}' in result + assert '\\footnote[1]{\sphinxAtStartFootnote%\nnumbered\n}' in result + assert '\\footnote[2]{\sphinxAtStartFootnote%\nauto numbered\n}' in result + assert '\\footnote[3]{\sphinxAtStartFootnote%\nnamed\n}' in result + assert '{\\hyperref[footnote:bar]{\\crossref{{[}bar{]}}}}' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} ' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite\n}' in result assert '\\capstart\\caption{Table caption \\protect\\footnotemark[4]}' in result assert 'name \\protect\\footnotemark[5]' in result assert ('\\end{threeparttable}\n\n' - '\\footnotetext[4]{\nfootnotes in table caption\n}' - '\\footnotetext[5]{\nfootnotes in table\n}' in result) + '\\footnotetext[4]{\sphinxAtStartFootnote%\nfootnotes in table caption\n}' + '\\footnotetext[5]{\sphinxAtStartFootnote%\nfootnotes in table\n}' in result) @with_app(buildername='latex', testroot='footnotes') @@ -416,22 +417,24 @@ def test_reference_in_caption(app, status, warning): print(status.getvalue()) print(warning.getvalue()) assert ('\\caption{This is the figure caption with a reference to \\label{index:id2}' - '{\\hyperref[index:authoryear]{\\internalreference{{[}AuthorYear{]}}}}.}' - in result) + '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}.}' in result) assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result assert '\\caption{The table title with a reference to {[}AuthorYear{]}}' in result assert '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result assert ('\\chapter{The section with a reference to \\protect\\footnotemark[4]}\n' '\\label{index:the-section-with-a-reference-to}' - '\\footnotetext[4]{\nFootnote in section\n}' in result) + '\\footnotetext[4]{\sphinxAtStartFootnote%\nFootnote in section\n}' in result) assert ('\\caption{This is the figure caption with a footnote to ' '\\protect\\footnotemark[6].}\label{index:id23}\end{figure}\n' - '\\footnotetext[6]{\nFootnote in caption\n}')in result + '\\footnotetext[6]{\sphinxAtStartFootnote%\nFootnote in caption\n}')in result assert ('\\caption{footnote \\protect\\footnotemark[7] ' 'in caption of normal table}') in result - assert '\\end{threeparttable}\n\n\\footnotetext[7]{\nFoot note in table\n}' in result - assert '\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}' in result - assert '\end{longtable}\n\n\\footnotetext[8]{\nFoot note in longtable\n}' in result + assert ('\\end{threeparttable}\n\n\\footnotetext[7]{\sphinxAtStartFootnote%\n' + 'Foot note in table\n}' in result) + assert ('\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}' + in result) + assert ('\end{longtable}\n\n\\footnotetext[8]{\sphinxAtStartFootnote%\n' + 'Foot note in longtable\n}' in result) @with_app(buildername='latex', testroot='footnotes', @@ -442,30 +445,31 @@ def test_latex_show_urls_is_inline(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result - assert 'Auto footnote number \\footnote[1]{\nfootnote in baz\n} in baz.rst' in result + assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n' + 'footnote in bar\n} in bar.rst' in result) + assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n' + 'footnote in baz\n} in baz.rst' in result) assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' - '{\\internalreference{The section with a reference to \\phantomsection' - '\\label{index:id1}{\\hyperref[index:authoryear]{\\internalreference' - '{{[}AuthorYear{]}}}}}}}' in result) + '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}' + '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result) assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to]' - '{\\internalreference{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[2]{\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result + '{\\crossref{The section with a reference to }}}' in result) + assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result + assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result - assert 'Third footnote: \\footnote[3]{\nThird\n}' in result + assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde} ' '(http://sphinx-doc.org/\\textasciitilde{}test/)' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] ' '\\leavevmode\nDescription' in result) assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] ' - '\\leavevmode\\footnotetext[5]{\nFootnote in term\n}\nDescription' in result) + '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n' + 'Footnote in term\n}\nDescription' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} ' '(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result) - assert ('\\href{https://github.com/sphinx-doc/sphinx}' - '{https://github.com/sphinx-doc/sphinx}\n' in result) + assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) assert ('\\href{mailto:sphinx-dev@googlegroups.com}' '{sphinx-dev@googlegroups.com}' in result) @@ -478,32 +482,36 @@ def test_latex_show_urls_is_footnote(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result - assert 'Auto footnote number \\footnote[2]{\nfootnote in baz\n} in baz.rst' in result + assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n' + 'footnote in bar\n} in bar.rst' in result) + assert ('Auto footnote number \\footnote[2]{\sphinxAtStartFootnote%\n' + 'footnote in baz\n} in baz.rst' in result) assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' - '{\\internalreference{The section with a reference to \\phantomsection' - '\\label{index:id1}{\\hyperref[index:authoryear]{\\internalreference' - '{{[}AuthorYear{]}}}}}}}' in result) + '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}' + '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result) assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' - '\\string-with\\string-a\\string-reference\\string-to]{\\internalreference' - '{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[3]{\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result + '\\string-with\\string-a\\string-reference\\string-to]' + '{\\crossref{The section with a reference to }}}' in result) + assert 'First footnote: \\footnote[3]{\sphinxAtStartFootnote%\nFirst\n}' in result + assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result assert ('\\href{http://sphinx-doc.org/}{Sphinx}' - '\\footnote[4]{\nhttp://sphinx-doc.org/\n}' in result) - assert 'Third footnote: \\footnote[6]{\nThird\n}' in result + '\\footnote[4]{\sphinxAtStartFootnote%\nhttp://sphinx-doc.org/\n}' in result) + assert 'Third footnote: \\footnote[6]{\sphinxAtStartFootnote%\nThird\n}' in result assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}' - '\\footnote[5]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result) + '\\footnote[5]{\sphinxAtStartFootnote%\n' + 'http://sphinx-doc.org/\\textasciitilde{}test/\n}' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] ' - '\\leavevmode\\footnotetext[8]{\nhttp://sphinx-doc.org/\n}\nDescription' in result) + '\\leavevmode\\footnotetext[8]{\sphinxAtStartFootnote%\n' + 'http://sphinx-doc.org/\n}\nDescription' in result) assert ('\\item[{Footnote in term \\protect\\footnotemark[10]}] ' - '\\leavevmode\\footnotetext[10]{\nFootnote in term\n}\nDescription' in result) + '\\leavevmode\\footnotetext[10]{\sphinxAtStartFootnote%\n' + 'Footnote in term\n}\nDescription' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect' '\\footnotemark[9]}] ' - '\\leavevmode\\footnotetext[9]{\nhttp://sphinx-doc.org/\n}\nDescription' in result) - assert ('\\href{https://github.com/sphinx-doc/sphinx}' - '{https://github.com/sphinx-doc/sphinx}\n' in result) + '\\leavevmode\\footnotetext[9]{\sphinxAtStartFootnote%\n' + 'http://sphinx-doc.org/\n}\nDescription' in result) + assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) assert ('\\href{mailto:sphinx-dev@googlegroups.com}' '{sphinx-dev@googlegroups.com}\n' in result) @@ -516,29 +524,30 @@ def test_latex_show_urls_is_no(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert 'Same footnote number \\footnote[1]{\nfootnote in bar\n} in bar.rst' in result - assert 'Auto footnote number \\footnote[1]{\nfootnote in baz\n} in baz.rst' in result + assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n' + 'footnote in bar\n} in bar.rst' in result) + assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n' + 'footnote in baz\n} in baz.rst' in result) assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' - '{\\internalreference{The section with a reference to \\phantomsection' - '\\label{index:id1}{\\hyperref[index:authoryear]{\\internalreference' - '{{[}AuthorYear{]}}}}}}}' in result) + '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}' + '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result) assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' - '\\string-with\\string-a\\string-reference\\string-to]{\\internalreference' - '{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[2]{\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result + '\\string-with\\string-a\\string-reference\\string-to]' + '{\\crossref{The section with a reference to }}}' in result) + assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result + assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result - assert 'Third footnote: \\footnote[3]{\nThird\n}' in result + assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] ' '\\leavevmode\nDescription' in result) assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] ' - '\\leavevmode\\footnotetext[5]{\nFootnote in term\n}\nDescription' in result) + '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n' + 'Footnote in term\n}\nDescription' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] ' '\\leavevmode\nDescription' in result) - assert ('\\href{https://github.com/sphinx-doc/sphinx}' - '{https://github.com/sphinx-doc/sphinx}\n' in result) + assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) assert ('\\href{mailto:sphinx-dev@googlegroups.com}' '{sphinx-dev@googlegroups.com}\n' in result) @@ -615,3 +624,47 @@ def test_toctree_without_maxdepth(app, status, warning): print(status.getvalue()) print(warning.getvalue()) assert '\\setcounter{tocdepth}' not in result + + +@with_app(buildername='latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': None}) +def test_latex_toplevel_sectioning_is_None(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\chapter{Foo}' in result + + +@with_app(buildername='latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'part'}) +def test_latex_toplevel_sectioning_is_part(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\part{Foo}' in result + + +@with_app(buildername='latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'chapter'}) +def test_latex_toplevel_sectioning_is_chapter(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\chapter{Foo}' in result + + +@with_app(buildername='latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'section'}) +def test_latex_toplevel_sectioning_is_section(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\section{Foo}' in result diff --git a/tests/test_build_manpage.py b/tests/test_build_manpage.py index 26fa8c494..8da2eaadd 100644 --- a/tests/test_build_manpage.py +++ b/tests/test_build_manpage.py @@ -21,3 +21,7 @@ def test_all(app, status, warning): content = (app.outdir / 'SphinxTests.1').text() assert r'\fBprint \fP\fIi\fP\fB\en\fP' in content assert r'\fBmanpage\en\fP' in content + + # term of definition list including nodes.strong + assert '\n.B term1\n' in content + assert '\nterm2 (\\fBstronged partially\\fP)\n' in content diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index 00f2b2232..1cf2232c4 100644 --- a/tests/test_build_texinfo.py +++ b/tests/test_build_texinfo.py @@ -23,6 +23,7 @@ from test_build_html import ENV_WARNINGS TEXINFO_WARNINGS = ENV_WARNINGS + """\ +%(root)s/markup.txt:160: WARNING: unknown option: &option %(root)s/footnote.txt:60: WARNING: citation not found: missing %(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*' %(root)s/images.txt:29: WARNING: no matching candidate for image URI u'svgimg.\\*' diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index 1393e900f..6f7b749b1 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -64,7 +64,7 @@ def test_code_block_caption_html(app, status, warning): def test_code_block_caption_latex(app, status, warning): app.builder.build_all() latex = (app.outdir / 'Python.tex').text(encoding='utf-8') - caption = '\\captionof{literal-block}{caption \\emph{test} rb}' + caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\emph{test} rb}' assert caption in latex @@ -229,7 +229,7 @@ def test_literalinclude_caption_html(app, status, warning): def test_literalinclude_caption_latex(app, status, warning): app.builder.build('index') latex = (app.outdir / 'Python.tex').text(encoding='utf-8') - caption = '\\captionof{literal-block}{caption \\textbf{test} py}' + caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\textbf{test} py}' assert caption in latex diff --git a/tests/test_intl.py b/tests/test_intl.py index 29d068d65..e82d9f3ed 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -24,7 +24,7 @@ from six import string_types from util import tempdir, rootdir, path, gen_with_app, with_app, SkipTest, \ assert_re_search, assert_not_re_search, assert_in, assert_not_in, \ - assert_startswith, assert_node + assert_startswith, assert_node, repr_as root = tempdir / 'test-intl' @@ -120,7 +120,7 @@ def test_text_builder(app, status, warning): # --- warnings in translation - warnings = warning.getvalue().replace(os.sep, '/') + warnings = getwarning(warning) warning_expr = u'.*/warnings.txt:4: ' \ u'WARNING: Inline literal start-string without end-string.\n' yield assert_re_search, warning_expr, warnings @@ -157,7 +157,7 @@ def test_text_builder(app, status, warning): u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n") yield assert_equal, result, expect - warnings = warning.getvalue().replace(os.sep, '/') + warnings = getwarning(warning) warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \ u'WARNING: inconsistent %s in translated message\n' expected_warning_expr = ( @@ -178,7 +178,7 @@ def test_text_builder(app, status, warning): u"\n') diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py new file mode 100644 index 000000000..d88d3cc6d --- /dev/null +++ b/tests/test_util_logging.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +""" + test_util_logging + ~~~~~~~~~~~~~~~~~ + + Test logging util. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" +from __future__ import print_function + +from sphinx.util.logging import is_suppressed_warning + + +def test_is_suppressed_warning(): + suppress_warnings = ["ref", "files.*", "rest.duplicated_labels"] + + assert is_suppressed_warning(None, None, suppress_warnings) is False + assert is_suppressed_warning("ref", None, suppress_warnings) is True + assert is_suppressed_warning("ref", "numref", suppress_warnings) is True + assert is_suppressed_warning("ref", "option", suppress_warnings) is True + assert is_suppressed_warning("files", "image", suppress_warnings) is True + assert is_suppressed_warning("files", "stylesheet", suppress_warnings) is True + assert is_suppressed_warning("rest", "syntax", suppress_warnings) is False + assert is_suppressed_warning("rest", "duplicated_labels", suppress_warnings) is True diff --git a/tests/util.py b/tests/util.py index 969c4e5c4..454cc0d9c 100644 --- a/tests/util.py +++ b/tests/util.py @@ -26,7 +26,7 @@ from sphinx.theming import Theme from sphinx.ext.autodoc import AutoDirective from sphinx.pycode import ModuleAnalyzer -from path import path +from path import path, repr_as try: # Python >=3.3