mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'stable'
This commit is contained in:
commit
c9296ba467
41
CHANGES
41
CHANGES
@ -27,11 +27,26 @@ Release 1.4.2 (in development)
|
||||
Features added
|
||||
--------------
|
||||
|
||||
* Now :confval:`suppress_warnings` accepts following configurations: ``app.add_node``, ``app.add_directive``, ``app.add_role`` and ``app.add_generic_role`` (ref: #2451)
|
||||
* LaTeX writer allows page breaks in topic contents; and their horizontal
|
||||
extent now fits in the line width (shadow in margin). Warning-type
|
||||
admonitions allow page breaks (if very long) and their vertical spacing
|
||||
has been made more coherent with the one for Hint-type notices.
|
||||
* Now :confval:`suppress_warnings` accepts following configurations (ref: #2451, #2466):
|
||||
|
||||
- ``app.add_node``
|
||||
- ``app.add_directive``
|
||||
- ``app.add_role``
|
||||
- ``app.add_generic_role``
|
||||
- ``app.add_source_parser``
|
||||
- ``image.data_uri``
|
||||
- ``image.nonlocal_uri``
|
||||
|
||||
* #2453: LaTeX writer allows page breaks in topic contents; and their
|
||||
horizontal extent now fits in the line width (with shadow in margin). Also
|
||||
warning-type admonitions allow page breaks and their vertical spacing has
|
||||
been made more coherent with the one for hint-type notices (ref #2446).
|
||||
|
||||
* #2459: the framing of literal code-blocks in LaTeX output (and not only the
|
||||
code lines themselves) obey the indentation in lists or quoted blocks.
|
||||
|
||||
* #2343: the long source lines in code-blocks are wrapped (without modifying
|
||||
the line numbering) in LaTeX output (ref #1534, #2304).
|
||||
* Convert linkcheck builder to requests for better encoding handling
|
||||
|
||||
Bugs fixed
|
||||
@ -45,6 +60,22 @@ Bugs fixed
|
||||
* #2447: VerbatimBorderColor wrongly used also for captions of PDF
|
||||
* #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders).
|
||||
* #2446: latex(pdf) sets local tables of contents (or more generally topic nodes) in unbreakable boxes, causes overflow at bottom
|
||||
* #2476: Omit MathJax markers if :nowrap: is given
|
||||
* #2465: latex builder fails in case no caption option is provided to toctree directive
|
||||
* Sphinx crashes if self referenced toctree found
|
||||
* #2481: spelling mistake for mecab search splitter. Thanks to Naoki Sato.
|
||||
* #2309: Fix could not refer "indirect hyperlink targets" by ref-role
|
||||
* intersphinx fails if mapping URL contains any port
|
||||
* #2088: intersphinx crashes if the mapping URL requires basic auth
|
||||
* #2304: auto line breaks in latexpdf codeblocks
|
||||
* #1534: Word wrap long lines in Latex verbatim blocks
|
||||
* #2460: too much white space on top of captioned literal blocks in PDF output
|
||||
* Show error reason when multiple math extensions are loaded (ref: #2499)
|
||||
* #2483: any figure number was not assigned if figure title contains only non text objects
|
||||
* #2501: Unicode subscript numbers are normalized in LaTeX
|
||||
* #2492: Figure directive with :figwidth: generates incorrect Latex-code
|
||||
* The caption of figure is always put on center even if ``:align:`` was specified
|
||||
* #2526: LaTeX writer crashes if the section having only images
|
||||
|
||||
|
||||
Release 1.4.1 (released Apr 12, 2016)
|
||||
|
@ -222,6 +222,9 @@ General configuration
|
||||
* app.add_directive
|
||||
* app.add_role
|
||||
* app.add_generic_role
|
||||
* app.add_source_parser
|
||||
* image.data_uri
|
||||
* image.nonlocal_uri
|
||||
* ref.term
|
||||
* ref.ref
|
||||
* ref.numref
|
||||
|
@ -33,11 +33,14 @@ There are two kinds of test blocks:
|
||||
* *code-output-style* blocks consist of an ordinary piece of Python code, and
|
||||
optionally, a piece of output for that code.
|
||||
|
||||
The doctest extension provides four directives. The *group* argument is
|
||||
interpreted as follows: if it is empty, the block is assigned to the group named
|
||||
``default``. If it is ``*``, the block is assigned to all groups (including the
|
||||
``default`` group). Otherwise, it must be a comma-separated list of group
|
||||
names.
|
||||
|
||||
Directives
|
||||
----------
|
||||
|
||||
The *group* argument below is interpreted as follows: if it is empty, the block
|
||||
is assigned to the group named ``default``. If it is ``*``, the block is
|
||||
assigned to all groups (including the ``default`` group). Otherwise, it must be
|
||||
a comma-separated list of group names.
|
||||
|
||||
.. rst:directive:: .. testsetup:: [group]
|
||||
|
||||
@ -171,7 +174,10 @@ The following is an example for the usage of the directives. The test via
|
||||
This parrot wouldn't voom if you put 3000 volts through it!
|
||||
|
||||
|
||||
There are also these config values for customizing the doctest extension:
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The doctest extension uses the following configuration values:
|
||||
|
||||
.. confval:: doctest_default_flags
|
||||
|
||||
|
@ -51,7 +51,7 @@ The third form provides your theme path dynamically to Sphinx if the
|
||||
called ``sphinx_themes`` in your setup.py file and write a ``get_path`` function
|
||||
that has to return the directory with themes in it::
|
||||
|
||||
// in your 'setup.py'
|
||||
# 'setup.py'
|
||||
|
||||
setup(
|
||||
...
|
||||
@ -63,7 +63,7 @@ that has to return the directory with themes in it::
|
||||
...
|
||||
)
|
||||
|
||||
// in 'your_package.py'
|
||||
# 'your_package.py'
|
||||
|
||||
from os import path
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
@ -788,6 +788,11 @@ class Sphinx(object):
|
||||
|
||||
def add_source_parser(self, suffix, parser):
|
||||
self.debug('[app] adding search source_parser: %r, %r', (suffix, parser))
|
||||
if suffix in self._additional_source_parsers:
|
||||
self.warn('while setting up extension %s: source_parser for %r is '
|
||||
'already registered, it will be overridden' %
|
||||
(self._setting_up_extension[-1], suffix),
|
||||
type='app', subtype='add_source_parser')
|
||||
self._additional_source_parsers[suffix] = parser
|
||||
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from os import path, walk
|
||||
from os import path, walk, getenv
|
||||
from codecs import open
|
||||
from time import time
|
||||
from datetime import datetime, tzinfo, timedelta
|
||||
@ -130,6 +130,12 @@ class I18nBuilder(Builder):
|
||||
timestamp = time()
|
||||
tzdelta = datetime.fromtimestamp(timestamp) - \
|
||||
datetime.utcfromtimestamp(timestamp)
|
||||
# set timestamp from SOURCE_DATE_EPOCH if set
|
||||
# see https://reproducible-builds.org/specs/source-date-epoch/
|
||||
source_date_epoch = getenv('SOURCE_DATE_EPOCH')
|
||||
if source_date_epoch is not None:
|
||||
timestamp = float(source_date_epoch)
|
||||
tzdelta = 0
|
||||
|
||||
|
||||
class LocalTimeZone(tzinfo):
|
||||
|
@ -137,7 +137,7 @@ class LaTeXBuilder(Builder):
|
||||
tree = self.env.get_doctree(indexfile)
|
||||
contentsname = None
|
||||
for toctree in tree.traverse(addnodes.toctree):
|
||||
if toctree['caption']:
|
||||
if 'caption' in toctree:
|
||||
contentsname = toctree['caption']
|
||||
break
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
"""
|
||||
|
||||
import re
|
||||
from os import path, environ
|
||||
from os import path, environ, getenv
|
||||
import shlex
|
||||
|
||||
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
|
||||
@ -19,8 +19,10 @@ from sphinx.errors import ConfigError
|
||||
from sphinx.locale import l_
|
||||
from sphinx.util.osutil import make_filename, cd
|
||||
from sphinx.util.pycompat import execfile_, NoneType
|
||||
from sphinx.util.i18n import format_date
|
||||
|
||||
nonascii_re = re.compile(br'[\x80-\xff]')
|
||||
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
|
||||
|
||||
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
|
||||
if PY3:
|
||||
@ -298,6 +300,15 @@ class Config(object):
|
||||
self.setup = config.get('setup', None)
|
||||
self.extensions = config.get('extensions', [])
|
||||
|
||||
# correct values of copyright year that are not coherent with
|
||||
# the SOURCE_DATE_EPOCH environment variable (if set)
|
||||
# See https://reproducible-builds.org/specs/source-date-epoch/
|
||||
if getenv('SOURCE_DATE_EPOCH') is not None:
|
||||
for k in ('copyright', 'epub_copyright'):
|
||||
if k in config:
|
||||
config[k] = copyright_year_re.sub('\g<1>%s' % format_date('%Y'),
|
||||
config[k])
|
||||
|
||||
def check_types(self, warn):
|
||||
# check all values for deviation from the default value's type, since
|
||||
# that can result in TypeErrors all over the place
|
||||
|
@ -28,6 +28,10 @@ class Figure(images.Figure):
|
||||
self.options['name'] = name
|
||||
self.add_name(figure_node)
|
||||
|
||||
# fill lineno using image node
|
||||
if figure_node.line is None and len(figure_node) == 2:
|
||||
figure_node.line = figure_node[1].line
|
||||
|
||||
return [figure_node]
|
||||
|
||||
|
||||
|
@ -532,6 +532,9 @@ class StandardDomain(Domain):
|
||||
if labelid is None:
|
||||
continue
|
||||
node = document.ids[labelid]
|
||||
if node.tagname == 'target' and 'refid' in node: # indirect hyperlink targets
|
||||
node = document.ids.get(node['refid'])
|
||||
labelid = node['names'][0]
|
||||
if name.isdigit() or 'refuri' in node or \
|
||||
node.tagname.startswith('desc_'):
|
||||
# ignore footnote labels, labels automatically generated from a
|
||||
@ -545,7 +548,7 @@ class StandardDomain(Domain):
|
||||
sectname = clean_astext(node[0]) # node[0] == title node
|
||||
elif self.is_enumerable_node(node):
|
||||
sectname = self.get_numfig_title(node)
|
||||
if sectname is None:
|
||||
if not sectname:
|
||||
continue
|
||||
elif node.traverse(addnodes.toctree):
|
||||
n = node.traverse(addnodes.toctree)[0]
|
||||
|
@ -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 = 47 + (sys.version_info[0] - 2)
|
||||
ENV_VERSION = 48 + (sys.version_info[0] - 2)
|
||||
|
||||
|
||||
dummy_reporter = Reporter('', 4, 4)
|
||||
@ -908,11 +908,13 @@ class BuildEnvironment:
|
||||
node['candidates'] = candidates = {}
|
||||
imguri = node['uri']
|
||||
if imguri.startswith('data:'):
|
||||
self.warn_node('image data URI found. some builders might not support', node)
|
||||
self.warn_node('image data URI found. some builders might not support', node,
|
||||
type='image', subtype='data_uri')
|
||||
candidates['?'] = imguri
|
||||
continue
|
||||
elif imguri.find('://') != -1:
|
||||
self.warn_node('nonlocal image URI found: %s' % imguri, node)
|
||||
self.warn_node('nonlocal image URI found: %s' % imguri, node,
|
||||
type='image', subtype='nonlocal_uri')
|
||||
candidates['?'] = imguri
|
||||
continue
|
||||
rel_imgpath, full_imgpath = self.relfn2path(imguri, docname)
|
||||
@ -1909,6 +1911,10 @@ class BuildEnvironment:
|
||||
traversed = set()
|
||||
|
||||
def traverse_toctree(parent, docname):
|
||||
if parent == docname:
|
||||
self.warn(docname, 'self referenced toctree found. Ignored.')
|
||||
return
|
||||
|
||||
# traverse toctree by pre-order
|
||||
yield parent, docname
|
||||
traversed.add(docname)
|
||||
|
@ -22,7 +22,7 @@ from six import text_type
|
||||
from docutils import nodes
|
||||
|
||||
import sphinx
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.util.png import read_png_depth, write_png_depth
|
||||
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
||||
from sphinx.util.pycompat import sys_encoding
|
||||
@ -267,7 +267,11 @@ def html_visit_displaymath(self, node):
|
||||
|
||||
|
||||
def setup(app):
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
try:
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
except ExtensionError:
|
||||
raise ExtensionError('sphinx.ext.imgmath: other math package is already loaded')
|
||||
|
||||
app.add_config_value('imgmath_image_format', 'png', 'html')
|
||||
app.add_config_value('imgmath_dvipng', 'dvipng', 'html')
|
||||
app.add_config_value('imgmath_dvisvgm', 'dvisvgm', 'html')
|
||||
|
@ -150,7 +150,10 @@ def _strip_basic_auth(url):
|
||||
password = url_parts.password
|
||||
frags = list(url_parts)
|
||||
# swap out "user[:pass]@hostname" for "hostname"
|
||||
frags[1] = url_parts.hostname
|
||||
if url_parts.port:
|
||||
frags[1] = "%s:%s" % (url_parts.hostname, url_parts.port)
|
||||
else:
|
||||
frags[1] = url_parts.hostname
|
||||
url = parse.urlunsplit(frags)
|
||||
return (url, username, password)
|
||||
|
||||
@ -177,7 +180,7 @@ def _read_from_url(url):
|
||||
password_mgr = request.HTTPPasswordMgrWithDefaultRealm()
|
||||
password_mgr.add_password(None, url, username, password)
|
||||
handler = request.HTTPBasicAuthHandler(password_mgr)
|
||||
opener = request.build_opener(default_handlers + [handler])
|
||||
opener = request.build_opener(*(default_handlers + [handler]))
|
||||
else:
|
||||
opener = default_opener
|
||||
|
||||
|
@ -56,7 +56,11 @@ def builder_inited(app):
|
||||
|
||||
|
||||
def setup(app):
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
try:
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
except ExtensionError:
|
||||
raise ExtensionError('sphinx.ext.jsmath: other math package is already loaded')
|
||||
|
||||
app.add_config_value('jsmath_path', '', False)
|
||||
app.connect('builder-inited', builder_inited)
|
||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||
|
@ -14,7 +14,7 @@
|
||||
from docutils import nodes
|
||||
|
||||
import sphinx
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
||||
|
||||
|
||||
@ -29,9 +29,7 @@ def html_visit_math(self, node):
|
||||
def html_visit_displaymath(self, node):
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||
if node['nowrap']:
|
||||
self.body.append(self.builder.config.mathjax_display[0] +
|
||||
self.encode(node['latex']) +
|
||||
self.builder.config.mathjax_display[1])
|
||||
self.body.append(self.encode(node['latex']))
|
||||
self.body.append('</div>')
|
||||
raise nodes.SkipNode
|
||||
|
||||
@ -65,7 +63,11 @@ def builder_inited(app):
|
||||
|
||||
|
||||
def setup(app):
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
try:
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
except ExtensionError:
|
||||
raise ExtensionError('sphinx.ext.mathjax: other math package is already loaded')
|
||||
|
||||
# more information for mathjax secure url is here:
|
||||
# http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
|
||||
app.add_config_value('mathjax_path',
|
||||
@ -74,4 +76,5 @@ def setup(app):
|
||||
app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
|
||||
app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
|
||||
app.connect('builder-inited', builder_inited)
|
||||
|
||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||
|
@ -23,7 +23,7 @@ from six import text_type
|
||||
from docutils import nodes
|
||||
|
||||
import sphinx
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.util.png import read_png_depth, write_png_depth
|
||||
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
||||
from sphinx.util.pycompat import sys_encoding
|
||||
@ -239,7 +239,11 @@ def html_visit_displaymath(self, node):
|
||||
|
||||
def setup(app):
|
||||
app.warn('sphinx.ext.pngmath has been deprecated. Please use sphinx.ext.imgmath instead.')
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
try:
|
||||
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
|
||||
except ExtensionError:
|
||||
raise ExtensionError('sphinx.ext.pngmath: other math package is already loaded')
|
||||
|
||||
app.add_config_value('pngmath_dvipng', 'dvipng', 'html')
|
||||
app.add_config_value('pngmath_latex', 'latex', 'html')
|
||||
app.add_config_value('pngmath_use_preview', False, 'html')
|
||||
|
@ -533,7 +533,7 @@ class SearchJapanese(SearchLanguage):
|
||||
language_name = 'Japanese'
|
||||
splitters = {
|
||||
'default': 'sphinx.search.ja.DefaultSplitter',
|
||||
'mecab': 'sphinx.sarch.ja.MecabSplitter',
|
||||
'mecab': 'sphinx.search.ja.MecabSplitter',
|
||||
'janome': 'sphinx.search.ja.JanomeSplitter',
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,6 @@
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesPackage{sphinx}[2010/01/15 LaTeX package (Sphinx markup)]
|
||||
|
||||
\ifx\directlua\undefined\else
|
||||
% if compiling with lualatex 0.85 or later load compatibility patch issued by
|
||||
% the LaTeX team for older packages relying on \pdf<name> named primitives.
|
||||
\IfFileExists{luatex85.sty}{\RequirePackage{luatex85}}{}
|
||||
\fi
|
||||
|
||||
\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}}
|
||||
|
||||
\RequirePackage{textcomp}
|
||||
@ -166,12 +160,12 @@
|
||||
|
||||
\newcommand\Sphinx@colorbox [2]{%
|
||||
% #1 will be \fcolorbox or, for first part of frame: \Sphinx@fcolorbox
|
||||
#1{VerbatimBorderColor}{VerbatimColor}{%
|
||||
% adjust width to be able to handle indentation.
|
||||
\begin{minipage}{\dimexpr\linewidth-\@totalleftmargin\relax}%
|
||||
#2%
|
||||
\end{minipage}%
|
||||
}%
|
||||
% let the framing obey the current indentation (adapted from framed.sty's code).
|
||||
\hskip\@totalleftmargin
|
||||
\hskip-\fboxsep\hskip-\fboxrule
|
||||
#1{VerbatimBorderColor}{VerbatimColor}{#2}%
|
||||
\hskip-\fboxsep\hskip-\fboxrule
|
||||
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth
|
||||
}
|
||||
% use of \color@b@x here is compatible with both xcolor.sty and color.sty
|
||||
\def\Sphinx@fcolorbox #1#2%
|
||||
@ -184,9 +178,11 @@
|
||||
\newcommand*\SphinxLiteralBlockLabel {}
|
||||
\newcommand*\SphinxSetupCaptionForVerbatim [2]
|
||||
{%
|
||||
\needspace{\literalblockneedspace}\vspace{\literalblockcaptiontopvspace}%
|
||||
\needspace{\literalblockneedspace}%
|
||||
% insert a \label via \SphinxLiteralBlockLabel
|
||||
% reset to normal the color for the literal block caption
|
||||
% the caption inserts \abovecaptionskip whitespace above itself (usually 10pt)
|
||||
% there is also \belowcaptionskip but it is usually zero, hence the \smallskip
|
||||
\def\SphinxVerbatimTitle
|
||||
{\py@NormalColor\captionof{#1}{\SphinxLiteralBlockLabel #2}\smallskip }%
|
||||
}
|
||||
@ -198,12 +194,22 @@
|
||||
\long\def\Sphinx@VerbatimFBox#1{%
|
||||
\leavevmode
|
||||
\begingroup
|
||||
% framed.sty does some measuring but this macro adds possibly a caption
|
||||
% use amsmath conditional to inhibit the caption counter stepping after
|
||||
% first pass
|
||||
\ifSphinx@myfirstframedpass\else\firstchoice@false\fi
|
||||
\setbox\@tempboxa\hbox{\kern\fboxsep{#1}\kern\fboxsep}%
|
||||
\hbox
|
||||
{\lower\dimexpr\fboxrule+\fboxsep+\dp\@tempboxa
|
||||
\hbox{%
|
||||
\vbox{\ifx\SphinxVerbatimTitle\empty\else{\SphinxVerbatimTitle}\fi
|
||||
\vbox{\ifx\SphinxVerbatimTitle\empty\else
|
||||
% add the caption in a centered way above possibly indented frame
|
||||
% hide its width from framed.sty's measuring step
|
||||
% note that the caption brings \abovecaptionskip top vertical space
|
||||
\moveright\dimexpr\fboxrule+.5\wd\@tempboxa
|
||||
\hb@xt@\z@{\hss\begin{minipage}{\wd\@tempboxa}%
|
||||
\SphinxVerbatimTitle
|
||||
\end{minipage}\hss}\fi
|
||||
\hrule\@height\fboxrule\relax
|
||||
\hbox{\vrule\@width\fboxrule\relax
|
||||
\vbox{\vskip\fboxsep\copy\@tempboxa\vskip\fboxsep}%
|
||||
@ -211,16 +217,70 @@
|
||||
\hrule\@height\fboxrule\relax}%
|
||||
}}%
|
||||
\endgroup
|
||||
% amsmath conditional inhibits counter stepping after first pass.
|
||||
\global\Sphinx@myfirstframedpassfalse
|
||||
}
|
||||
|
||||
% For linebreaks inside Verbatim environment from package fancyvrb.
|
||||
\newbox\Sphinxcontinuationbox
|
||||
\newbox\Sphinxvisiblespacebox
|
||||
% These are user customizable e.g. from latex_elements's preamble key.
|
||||
% Use of \textvisiblespace for compatibility with XeTeX/LuaTeX/fontspec.
|
||||
\newcommand*\Sphinxvisiblespace {\textcolor{red}{\textvisiblespace}}
|
||||
\newcommand*\Sphinxcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}}
|
||||
\newcommand*\Sphinxcontinuationindent {3ex }
|
||||
\newcommand*\Sphinxafterbreak {\kern\Sphinxcontinuationindent\copy\Sphinxcontinuationbox}
|
||||
|
||||
% Take advantage of the already applied Pygments mark-up to insert
|
||||
% potential linebreaks for TeX processing.
|
||||
% {, <, #, %, $, ' and ": go to next line.
|
||||
% _, }, ^, &, >, - and ~: stay at end of broken line.
|
||||
% Use of \textquotesingle for straight quote.
|
||||
\newcommand*\Sphinxbreaksatspecials {%
|
||||
\def\PYGZus{\discretionary{\char`\_}{\Sphinxafterbreak}{\char`\_}}%
|
||||
\def\PYGZob{\discretionary{}{\Sphinxafterbreak\char`\{}{\char`\{}}%
|
||||
\def\PYGZcb{\discretionary{\char`\}}{\Sphinxafterbreak}{\char`\}}}%
|
||||
\def\PYGZca{\discretionary{\char`\^}{\Sphinxafterbreak}{\char`\^}}%
|
||||
\def\PYGZam{\discretionary{\char`\&}{\Sphinxafterbreak}{\char`\&}}%
|
||||
\def\PYGZlt{\discretionary{}{\Sphinxafterbreak\char`\<}{\char`\<}}%
|
||||
\def\PYGZgt{\discretionary{\char`\>}{\Sphinxafterbreak}{\char`\>}}%
|
||||
\def\PYGZsh{\discretionary{}{\Sphinxafterbreak\char`\#}{\char`\#}}%
|
||||
\def\PYGZpc{\discretionary{}{\Sphinxafterbreak\char`\%}{\char`\%}}%
|
||||
\def\PYGZdl{\discretionary{}{\Sphinxafterbreak\char`\$}{\char`\$}}%
|
||||
\def\PYGZhy{\discretionary{\char`\-}{\Sphinxafterbreak}{\char`\-}}%
|
||||
\def\PYGZsq{\discretionary{}{\Sphinxafterbreak\textquotesingle}{\textquotesingle}}%
|
||||
\def\PYGZdq{\discretionary{}{\Sphinxafterbreak\char`\"}{\char`\"}}%
|
||||
\def\PYGZti{\discretionary{\char`\~}{\Sphinxafterbreak}{\char`\~}}%
|
||||
}
|
||||
|
||||
% Some characters . , ; ? ! / are not pygmentized.
|
||||
% This macro makes them "active" and they will insert potential linebreaks
|
||||
\newcommand*\Sphinxbreaksatpunct {%
|
||||
\lccode`\~`\.\lowercase{\def~}{\discretionary{\char`\.}{\Sphinxafterbreak}{\char`\.}}%
|
||||
\lccode`\~`\,\lowercase{\def~}{\discretionary{\char`\,}{\Sphinxafterbreak}{\char`\,}}%
|
||||
\lccode`\~`\;\lowercase{\def~}{\discretionary{\char`\;}{\Sphinxafterbreak}{\char`\;}}%
|
||||
\lccode`\~`\:\lowercase{\def~}{\discretionary{\char`\:}{\Sphinxafterbreak}{\char`\:}}%
|
||||
\lccode`\~`\?\lowercase{\def~}{\discretionary{\char`\?}{\Sphinxafterbreak}{\char`\?}}%
|
||||
\lccode`\~`\!\lowercase{\def~}{\discretionary{\char`\!}{\Sphinxafterbreak}{\char`\!}}%
|
||||
\lccode`\~`\/\lowercase{\def~}{\discretionary{\char`\/}{\Sphinxafterbreak}{\char`\/}}%
|
||||
\catcode`\.\active
|
||||
\catcode`\,\active
|
||||
\catcode`\;\active
|
||||
\catcode`\:\active
|
||||
\catcode`\?\active
|
||||
\catcode`\!\active
|
||||
\catcode`\/\active
|
||||
\lccode`\~`\~
|
||||
}
|
||||
|
||||
\renewcommand{\Verbatim}[1][1]{%
|
||||
% quit horizontal mode if we are still in a paragraph
|
||||
\par
|
||||
% list starts new par, but we don't want it to be set apart vertically
|
||||
\parskip\z@skip
|
||||
\smallskip
|
||||
% first, let's check if there is a caption
|
||||
\ifx\SphinxVerbatimTitle\empty
|
||||
\addvspace\z@% counteract possible previous negative skip (French lists!)
|
||||
\smallskip
|
||||
% there was no caption. Check if nevertheless a label was set.
|
||||
\ifx\SphinxLiteralBlockLabel\empty\else
|
||||
% we require some space to be sure hyperlink target from \phantomsection
|
||||
@ -238,8 +298,36 @@
|
||||
% for mid pages and last page portion of (long) split frame:
|
||||
\def\MidFrameCommand{\Sphinx@colorbox\fcolorbox }%
|
||||
\let\LastFrameCommand\MidFrameCommand
|
||||
% The list environement is needed to control perfectly the vertical
|
||||
% space.
|
||||
% fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes.
|
||||
% This customization wraps each line from the input in a \vtop, thus
|
||||
% allowing it to wrap and display on two or more lines in the latex output.
|
||||
% - The codeline counter will be increased only once.
|
||||
% - The wrapped material will not break across pages, it is impossible
|
||||
% to achieve this without extensive rewrite of fancyvrb.
|
||||
% - The (not used in Sphinx) obeytabs option to Verbatim is
|
||||
% broken by this change (showtabs and tabspace work).
|
||||
\sbox\Sphinxcontinuationbox {\Sphinxcontinuationsymbol}%
|
||||
\sbox\Sphinxvisiblespacebox {\FV@SetupFont\Sphinxvisiblespace}%
|
||||
\def\FancyVerbFormatLine ##1{\hsize\linewidth
|
||||
\vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
|
||||
\doublehyphendemerits\z@\finalhyphendemerits\z@
|
||||
\strut ##1\strut}%
|
||||
}%
|
||||
% If the linebreak is at a space, the latter will be displayed as visible
|
||||
% space at end of first line, and a continuation symbol starts next line.
|
||||
% Stretch/shrink are however usually zero for typewriter font.
|
||||
\def\FV@Space {%
|
||||
\nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font
|
||||
\discretionary{\copy\Sphinxvisiblespacebox}{\Sphinxafterbreak}
|
||||
{\kern\fontdimen2\font}%
|
||||
}%
|
||||
% Allow breaks at special characters using \PYG... macros.
|
||||
\Sphinxbreaksatspecials
|
||||
% The list environment is needed to control perfectly the vertical space.
|
||||
% Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt.
|
||||
% - if caption: vertical space above caption = (\abovecaptionskip + D) with
|
||||
% D = \baselineskip-\FrameHeightAdjust, and then \smallskip above frame.
|
||||
% - if no caption: (\smallskip + D) above frame. By default D=6pt.
|
||||
\list{}{%
|
||||
\setlength\parskip{0pt}%
|
||||
\setlength\itemsep{0ex}%
|
||||
@ -251,13 +339,18 @@
|
||||
\item
|
||||
% use a minipage if we are already inside a framed environment
|
||||
\relax\ifSphinx@inframed\noindent\begin{\minipage}{\linewidth}\fi
|
||||
\MakeFramed {\FrameRestore}%
|
||||
\MakeFramed {% adapted over from framed.sty's snugshade environment
|
||||
\advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize
|
||||
\@setminipage }%
|
||||
\small
|
||||
\OriginalVerbatim[#1]%
|
||||
% For grid placement from \strut's in \FancyVerbFormatLine
|
||||
\lineskip\z@skip
|
||||
% Breaks at punctuation characters . , ; ? ! and / need catcode=\active
|
||||
\OriginalVerbatim[#1,codes*=\Sphinxbreaksatpunct]%
|
||||
}
|
||||
\renewcommand{\endVerbatim}{%
|
||||
\endOriginalVerbatim
|
||||
\endMakeFramed
|
||||
\par\unskip\@minipagefalse\endMakeFramed
|
||||
\ifSphinx@inframed\end{minipage}\fi
|
||||
\endlist
|
||||
% LaTeX environments always revert local changes on exit, here e.g. \parskip
|
||||
@ -344,6 +437,7 @@
|
||||
\endtrivlist
|
||||
}
|
||||
|
||||
|
||||
% \moduleauthor{name}{email}
|
||||
\newcommand{\moduleauthor}[2]{}
|
||||
|
||||
@ -456,8 +550,11 @@
|
||||
{\parskip\z@skip\noindent}%
|
||||
}
|
||||
\newcommand{\py@endlightbox}{%
|
||||
\par\nobreak
|
||||
{\parskip\z@skip\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\par
|
||||
\par
|
||||
% counteract previous possible negative skip (French lists!):
|
||||
% (we can't cancel that any earlier \vskip introduced a potential pagebreak)
|
||||
\ifdim\lastskip<\z@\vskip-\lastskip\fi
|
||||
\nobreak\vbox{\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\allowbreak
|
||||
}
|
||||
|
||||
% Some are quite plain:
|
||||
@ -721,8 +818,6 @@
|
||||
% control caption around literal-block
|
||||
\RequirePackage{capt-of}
|
||||
\RequirePackage{needspace}
|
||||
% if the left page space is less than \literalblockneedsapce, insert page-break
|
||||
% if the left page space is less than \literalblockneedspace, insert page-break
|
||||
\newcommand{\literalblockneedspace}{5\baselineskip}
|
||||
\newcommand{\literalblockwithoutcaptionneedspace}{1.5\baselineskip}
|
||||
% margin before the caption of literal-block
|
||||
\newcommand{\literalblockcaptiontopvspace}{0.5\baselineskip}
|
||||
|
@ -5,6 +5,12 @@
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesClass{sphinxhowto}[2009/06/02 Document class (Sphinx HOWTO)]
|
||||
|
||||
\ifx\directlua\undefined\else
|
||||
% if compiling with lualatex 0.85 or later load compatibility patch issued by
|
||||
% the LaTeX team for older packages relying on \pdf<name> named primitives.
|
||||
\IfFileExists{luatex85.sty}{\RequirePackage{luatex85}}{}
|
||||
\fi
|
||||
|
||||
% 'oneside' option overriding the 'twoside' default
|
||||
\newif\if@oneside
|
||||
\DeclareOption{oneside}{\@onesidetrue}
|
||||
|
@ -5,6 +5,12 @@
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesClass{sphinxmanual}[2009/06/02 Document class (Sphinx manual)]
|
||||
|
||||
\ifx\directlua\undefined\else
|
||||
% if compiling with lualatex 0.85 or later load compatibility patch issued by
|
||||
% the LaTeX team for older packages relying on \pdf<name> named primitives.
|
||||
\IfFileExists{luatex85.sty}{\RequirePackage{luatex85}}{}
|
||||
\fi
|
||||
|
||||
% chapters starting at odd pages (overridden by 'openany' document option)
|
||||
\PassOptionsToClass{openright}{\sphinxdocclass}
|
||||
|
||||
|
@ -103,7 +103,8 @@ class Theme(object):
|
||||
if name not in self.themes:
|
||||
if name == 'sphinx_rtd_theme':
|
||||
raise ThemeError('sphinx_rtd_theme is no longer a hard dependency '
|
||||
'since version 1.4.0. Please install it manually.')
|
||||
'since version 1.4.0. Please install it manually.'
|
||||
'(pip install sphinx_rtd_theme)')
|
||||
else:
|
||||
raise ThemeError('no theme named %r found '
|
||||
'(missing theme.conf?)' % name)
|
||||
|
@ -114,7 +114,7 @@ class AutoNumbering(Transform):
|
||||
domain = self.document.settings.env.domains['std']
|
||||
|
||||
for node in self.document.traverse(nodes.Element):
|
||||
if domain.is_enumerable_node(node) and domain.get_numfig_title(node):
|
||||
if domain.is_enumerable_node(node) and domain.get_numfig_title(node) is not None:
|
||||
self.document.note_implicit_target(node)
|
||||
|
||||
|
||||
|
@ -14,7 +14,6 @@ import os
|
||||
import re
|
||||
import warnings
|
||||
from os import path
|
||||
from time import gmtime
|
||||
from datetime import datetime
|
||||
from collections import namedtuple
|
||||
|
||||
@ -188,7 +187,7 @@ def format_date(format, date=None, language=None, warn=None):
|
||||
# See https://wiki.debian.org/ReproducibleBuilds/TimestampsProposal
|
||||
source_date_epoch = os.getenv('SOURCE_DATE_EPOCH')
|
||||
if source_date_epoch is not None:
|
||||
date = gmtime(float(source_date_epoch))
|
||||
date = datetime.utcfromtimestamp(float(source_date_epoch))
|
||||
else:
|
||||
date = datetime.now()
|
||||
|
||||
|
@ -47,8 +47,26 @@ tex_replacements = [
|
||||
('│', r'\textbar{}'),
|
||||
('ℯ', r'e'),
|
||||
('ⅈ', r'i'),
|
||||
('₁', r'1'),
|
||||
('₂', r'2'),
|
||||
('⁰', r'$^\text{0}$'),
|
||||
('¹', r'$^\text{1}$'),
|
||||
('²', r'$^\text{2}$'),
|
||||
('³', r'$^\text{3}$'),
|
||||
('⁴', r'$^\text{4}$'),
|
||||
('⁵', r'$^\text{5}$'),
|
||||
('⁶', r'$^\text{6}$'),
|
||||
('⁷', r'$^\text{7}$'),
|
||||
('⁸', r'$^\text{8}$'),
|
||||
('⁹', r'$^\text{9}$'),
|
||||
('₀', r'$_\text{0}$'),
|
||||
('₁', r'$_\text{1}$'),
|
||||
('₂', r'$_\text{2}$'),
|
||||
('₃', r'$_\text{3}$'),
|
||||
('₄', r'$_\text{4}$'),
|
||||
('₅', r'$_\text{5}$'),
|
||||
('₆', r'$_\text{6}$'),
|
||||
('₇', r'$_\text{7}$'),
|
||||
('₈', r'$_\text{8}$'),
|
||||
('₉', r'$_\text{9}$'),
|
||||
# map Greek alphabet
|
||||
('α', r'\(\alpha\)'),
|
||||
('β', r'\(\beta\)'),
|
||||
|
@ -278,7 +278,7 @@ class HTMLTranslator(BaseTranslator):
|
||||
figtype = self.builder.env.domains['std'].get_figtype(node)
|
||||
if figtype:
|
||||
if len(node['ids']) == 0:
|
||||
msg = 'Any IDs not assiend for %s node' % node.tagname
|
||||
msg = 'Any IDs not assigned for %s node' % node.tagname
|
||||
self.builder.env.warn_node(msg, node)
|
||||
else:
|
||||
append_fignumber(figtype, node['ids'][0])
|
||||
|
@ -263,6 +263,24 @@ class Table(object):
|
||||
self.longtable = False
|
||||
|
||||
|
||||
def width_to_latex_length(length_str):
|
||||
"""Convert `length_str` with rst length to LaTeX length.
|
||||
|
||||
This function is copied from docutils' latex writer
|
||||
"""
|
||||
match = re.match('(\d*\.?\d*)\s*(\S*)', length_str)
|
||||
if not match:
|
||||
return length_str
|
||||
value, unit = match.groups()[:2]
|
||||
if unit in ('', 'pt'):
|
||||
length_str = '%sbp' % value # convert to 'bp'
|
||||
# percentage: relate to current line width
|
||||
elif unit == '%':
|
||||
length_str = '%.3f\\linewidth' % (float(value)/100.0)
|
||||
|
||||
return length_str
|
||||
|
||||
|
||||
class LaTeXTranslator(nodes.NodeVisitor):
|
||||
sectionnames = ["part", "chapter", "section", "subsection",
|
||||
"subsubsection", "paragraph", "subparagraph"]
|
||||
@ -281,7 +299,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
'\\else\\fi'),
|
||||
'cmappkg': '\\usepackage{cmap}',
|
||||
'fontenc': '\\usepackage[T1]{fontenc}',
|
||||
'amsmath': '\\usepackage{amsmath,amssymb}',
|
||||
'amsmath': '\\usepackage{amsmath,amssymb,amstext}',
|
||||
'babel': '\\usepackage{babel}',
|
||||
'fontpkg': '\\usepackage{times}',
|
||||
'fncychap': '\\usepackage[Bjarne]{fncychap}',
|
||||
@ -764,7 +782,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
elif isinstance(parent, nodes.section):
|
||||
short = ''
|
||||
if node.traverse(nodes.image):
|
||||
short = '[%s]' % ' '.join(clean_astext(node).split()).translate(tex_escape_map)
|
||||
short = ('[%s]' %
|
||||
u' '.join(clean_astext(node).split()).translate(tex_escape_map))
|
||||
|
||||
try:
|
||||
self.body.append(r'\%s%s{' % (self.sectionnames[self.sectionlevel], short))
|
||||
@ -1406,10 +1425,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
isinstance(node.children[0], nodes.image) and
|
||||
node.children[0]['ids']):
|
||||
ids += self.hypertarget(node.children[0]['ids'][0], anchor=False)
|
||||
if 'width' in node and node.get('align', '') in ('left', 'right'):
|
||||
if node.get('align', '') in ('left', 'right'):
|
||||
if 'width' in node:
|
||||
length = width_to_latex_length(node['width'])
|
||||
else:
|
||||
length = '0pt'
|
||||
self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
|
||||
(node['align'] == 'right' and 'r' or 'l',
|
||||
node['width']))
|
||||
(node['align'] == 'right' and 'r' or 'l', length))
|
||||
self.context.append(ids + '\\end{wrapfigure}\n')
|
||||
elif self.in_minipage:
|
||||
if ('align' not in node.attributes or
|
||||
|
@ -62,3 +62,7 @@ Test for issue #1700
|
||||
|
||||
:ref:`mastertoc`
|
||||
|
||||
Test for indirect hyperlink targets
|
||||
===================================
|
||||
|
||||
:ref:`indirect hyperref <other-label>`
|
||||
|
@ -107,6 +107,9 @@ Admonitions
|
||||
.. tip::
|
||||
Tip text.
|
||||
|
||||
Indirect hyperlink targets
|
||||
|
||||
.. _other-label: some-label_
|
||||
|
||||
Inline markup
|
||||
-------------
|
||||
@ -142,6 +145,7 @@ Adding \n to test unescaping.
|
||||
* :token:`try statement <try_stmt>`
|
||||
* :ref:`admonition-section`
|
||||
* :ref:`here <some-label>`
|
||||
* :ref:`there <other-label>`
|
||||
* :ref:`my-figure`
|
||||
* :ref:`my-figure-name`
|
||||
* :ref:`my-table`
|
||||
@ -231,6 +235,16 @@ Figures
|
||||
|
||||
Description paragraph is wraped with legend node.
|
||||
|
||||
.. figure:: rimg.png
|
||||
:align: right
|
||||
|
||||
figure with align option
|
||||
|
||||
.. figure:: rimg.png
|
||||
:align: right
|
||||
:figwidth: 50%
|
||||
|
||||
figure with align & figwidth option
|
||||
|
||||
Version markup
|
||||
--------------
|
||||
|
3
tests/roots/test-correct-year/conf.py
Normal file
3
tests/roots/test-correct-year/conf.py
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
copyright = u'2006-2009, Author'
|
||||
|
4
tests/roots/test-correct-year/contents.rst
Normal file
4
tests/roots/test-correct-year/contents.rst
Normal file
@ -0,0 +1,4 @@
|
||||
=================
|
||||
test-correct-year
|
||||
=================
|
||||
|
@ -16,3 +16,7 @@ another blah
|
||||
Other [blah] |picture| section
|
||||
------------------------------
|
||||
other blah
|
||||
|
||||
|picture|
|
||||
---------
|
||||
blah blah blah
|
||||
|
@ -31,16 +31,16 @@ http://www.python.org/logo.png
|
||||
reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
|
||||
:encoding: option\\n?
|
||||
%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
|
||||
(%(root)s/markup.txt:359: WARNING: invalid single index entry u'')?
|
||||
(%(root)s/markup.txt:373: WARNING: invalid single index entry u'')?
|
||||
(%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
|
||||
with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
|
||||
)?"""
|
||||
|
||||
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/markup.txt:285: 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
|
||||
%(root)s/markup.txt:164: WARNING: unknown option: &option
|
||||
"""
|
||||
|
||||
if PY3:
|
||||
@ -151,6 +151,8 @@ HTML_XPATH = {
|
||||
"[@class='reference internal']/code/span[@class='pre']", '^with$'),
|
||||
(".//a[@href='#grammar-token-try_stmt']"
|
||||
"[@class='reference internal']/code/span", '^statement$'),
|
||||
(".//a[@href='#some-label'][@class='reference internal']/span", '^here$'),
|
||||
(".//a[@href='#some-label'][@class='reference internal']/span", '^there$'),
|
||||
(".//a[@href='subdir/includes.html']"
|
||||
"[@class='reference internal']/span", 'Including in subdir'),
|
||||
(".//a[@href='objects.html#cmdoption-python-c']"
|
||||
@ -274,6 +276,9 @@ HTML_XPATH = {
|
||||
'http://sphinx-doc.org/'),
|
||||
(".//a[@class='reference external'][@href='http://sphinx-doc.org/latest/']",
|
||||
'Latest reference'),
|
||||
# Indirect hyperlink targets across files
|
||||
(".//a[@href='markup.html#some-label'][@class='reference internal']/span",
|
||||
'^indirect hyperref$'),
|
||||
],
|
||||
'bom.html': [
|
||||
(".//title", " File with UTF-8 BOM"),
|
||||
|
@ -24,10 +24,10 @@ from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
LATEX_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/markup.txt:160: WARNING: unknown option: &option
|
||||
%(root)s/markup.txt:164: 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.
|
||||
%(root)s/markup.txt:285: WARNING: Could not lex literal_block as "c". Highlighting skipped.
|
||||
"""
|
||||
|
||||
if PY3:
|
||||
@ -106,6 +106,20 @@ def test_latex(app, status, warning):
|
||||
run_latex(app.outdir)
|
||||
|
||||
|
||||
@with_app(buildername='latex')
|
||||
def test_writer(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
|
||||
|
||||
assert ('\\begin{wrapfigure}{r}{0pt}\n\\centering\n'
|
||||
'\\includegraphics{{rimg}.png}\n\\caption{figure with align option}'
|
||||
'\\label{markup:id7}\\end{wrapfigure}' in result)
|
||||
|
||||
assert ('\\begin{wrapfigure}{r}{0.500\\linewidth}\n\\centering\n'
|
||||
'\\includegraphics{{rimg}.png}\n\\caption{figure with align \\& figwidth option}'
|
||||
'\\label{markup:id8}\\end{wrapfigure}' in result)
|
||||
|
||||
|
||||
@with_app(buildername='latex', freshenv=True, # use freshenv to check warnings
|
||||
confoverrides={'latex_documents': [
|
||||
('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
|
||||
|
@ -23,7 +23,7 @@ from test_build_html import ENV_WARNINGS
|
||||
|
||||
|
||||
TEXINFO_WARNINGS = ENV_WARNINGS + """\
|
||||
%(root)s/markup.txt:160: WARNING: unknown option: &option
|
||||
%(root)s/markup.txt:164: 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.\\*'
|
||||
|
49
tests/test_correct_year.py
Normal file
49
tests/test_correct_year.py
Normal file
@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_correct_year
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test copyright year adjustment
|
||||
|
||||
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import os
|
||||
|
||||
from util import TestApp
|
||||
|
||||
|
||||
def test_correct_year():
|
||||
try:
|
||||
# save current value of SOURCE_DATE_EPOCH
|
||||
sde = os.environ.pop('SOURCE_DATE_EPOCH',None)
|
||||
|
||||
# test with SOURCE_DATE_EPOCH unset: no modification
|
||||
app = TestApp(buildername='html',testroot='correct-year')
|
||||
app.builder.build_all()
|
||||
content = (app.outdir / 'contents.html').text()
|
||||
app.cleanup()
|
||||
assert '2006-2009' in content
|
||||
|
||||
# test with SOURCE_DATE_EPOCH set: copyright year should be
|
||||
# updated
|
||||
os.environ['SOURCE_DATE_EPOCH'] = "1293840000"
|
||||
app = TestApp(buildername='html',testroot='correct-year')
|
||||
app.builder.build_all()
|
||||
content = (app.outdir / 'contents.html').text()
|
||||
app.cleanup()
|
||||
assert '2006-2011' in content
|
||||
|
||||
os.environ['SOURCE_DATE_EPOCH'] = "1293839999"
|
||||
app = TestApp(buildername='html',testroot='correct-year')
|
||||
app.builder.build_all()
|
||||
content = (app.outdir / 'contents.html').text()
|
||||
app.cleanup()
|
||||
assert '2006-2010' in content
|
||||
|
||||
finally:
|
||||
# Restores SOURCE_DATE_EPOCH
|
||||
if sde == None:
|
||||
os.environ.pop('SOURCE_DATE_EPOCH',None)
|
||||
else:
|
||||
os.environ['SOURCE_DATE_EPOCH'] = sde
|
@ -24,7 +24,7 @@ def setup_module():
|
||||
global app, env
|
||||
app = TestApp(srcdir='root-envtest')
|
||||
env = app.env
|
||||
env.set_warnfunc(lambda *args: warnings.append(args))
|
||||
env.set_warnfunc(lambda *args, **kwargs: warnings.append(args))
|
||||
|
||||
|
||||
def teardown_module():
|
||||
|
@ -199,6 +199,16 @@ class TestStripBasicAuth(unittest.TestCase):
|
||||
self.assertEqual(None, actual_username)
|
||||
self.assertEqual(None, actual_password)
|
||||
|
||||
def test_having_port(self):
|
||||
"""basic auth creds correctly stripped from URL containing creds even if URL
|
||||
contains port"""
|
||||
url = 'https://user:12345@domain.com:8080/project/objects.inv'
|
||||
expected = 'https://domain.com:8080/project/objects.inv'
|
||||
actual_url, actual_username, actual_password = _strip_basic_auth(url)
|
||||
self.assertEqual(expected, actual_url)
|
||||
self.assertEqual('user', actual_username)
|
||||
self.assertEqual('12345', actual_password)
|
||||
|
||||
|
||||
@mock.patch('six.moves.urllib.request.HTTPBasicAuthHandler')
|
||||
@mock.patch('six.moves.urllib.request.HTTPPasswordMgrWithDefaultRealm')
|
||||
|
Loading…
Reference in New Issue
Block a user