Merge branch '3.x' into 7005_kbd_for_latex

This commit is contained in:
Takeshi KOMIYA
2020-03-05 23:47:07 +09:00
252 changed files with 5956 additions and 3398 deletions

View File

@@ -1,17 +1,8 @@
import os
import sys
from docutils.parsers import Parser
sys.path.insert(0, os.path.abspath('.'))
class DummyMarkdownParser(Parser):
supported = ('markdown',)
extensions = ['source_parser']
source_suffix = ['.rst', '.md']
source_parsers = {
'.md': DummyMarkdownParser
}
source_suffix = ['.rst']

View File

@@ -0,0 +1,4 @@
.. _bar:
bar
===

View File

View File

@@ -0,0 +1,4 @@
.. _foo_1:
foo/foo_1
=========

View File

@@ -0,0 +1,4 @@
.. _foo_2:
foo/foo_2
=========

View File

@@ -0,0 +1,9 @@
.. _foo:
foo/index
=========
.. toctree::
foo_1
foo_2

View File

@@ -0,0 +1,9 @@
.. _index:
index
=====
.. toctree::
foo/index
bar

View File

@@ -0,0 +1,8 @@
.. default-domain:: cpp
.. namespace:: lookup_key_overload
.. function:: void g(int a)
.. function:: void g(double b)
:var:`b`

View File

@@ -0,0 +1,24 @@
.. default-domain:: cpp
.. namespace:: multi_decl_lookup
.. function:: void f1(int a)
void f1(double b)
- a: :var:`a`
- b: :var:`b`
.. function:: template<typename T> void f2(int a)
template<typename U> void f2(double b)
- T: :type:`T`
- U: :type:`U`
.. class:: template<typename T> A
template<typename U> B
.. function:: void f3()
- T: :type:`T`
- U: :type:`U`

View File

@@ -0,0 +1,170 @@
.. default-domain:: cpp
.. namespace:: RolesTargetsOk
.. class:: Class
:cpp:any:`Class`
:class:`Class`
:struct:`Class`
union
func
member
var
:type:`Class`
concept
enum
enumerator
.. union:: Union
:cpp:any:`Union`
class
struct
:union:`Union`
func
member
var
:type:`Union`
concept
enum
enumerator
.. function:: void Function()
:cpp:any:`Function`
class
struct
union
:func:`Function`
member
var
:type:`Function`
concept
enum
enumerator
.. var:: int Variable
:cpp:any:`Variable`
class
struct
union
function
:member:`Variable`
:var:`Variables`
type
concept
enum
enumerator
.. type:: Type = void
:cpp:any:`Type`
class
struct
union
function
member
var
:type:`Type`
concept
enum
enumerator
.. concept:: template<typename T> Concept
:cpp:any:`Concept`
class
struct
union
function
member
var
type
:concept:`Concept`
enum
enumerator
.. enum-struct:: Enum
:cpp:any:`Enum`
class
struct
union
function
member
var
:type:`Enum`
concept
:enum:`Enum`
enumerator
.. enumerator:: Enumerator
:cpp:any:`Enumerator`
class
struct
union
function
member
var
type
concept
enum
:enumerator:`Enumerator`
.. class:: template<typename TParamType, \
int TParamVar, \
template<typename> typename TParamTemplate \
> ClassTemplate
:cpp:any:`TParamType`
:class:`TParamType`
:struct:`TParamType`
:union:`TParamType`
:func:`TParamType`
:member:`TParamType`
:var:`TParamType`
:type:`TParamType`
:concept:`TParamType`
:enum:`TParamType`
:enumerator:`TParamType`
:cpp:any:`TParamVar`
:class:`TParamVar`
:struct:`TParamVar`
:union:`TParamVar`
:func:`TParamVar`
:member:`TParamVar`
:var:`TParamVar`
:type:`TParamVar`
:concept:`TParamVar`
:enum:`TParamVar`
:enumerator:`TParamVar`
:cpp:any:`TParamTemplate`
:class:`TParamTemplate`
:struct:`TParamTemplate`
:union:`TParamTemplate`
:func:`TParamTemplate`
:member:`TParamTemplate`
:var:`TParamTemplate`
:type:`TParamTemplate`
:concept:`TParamTemplate`
:enum:`TParamTemplate`
:enumerator:`TParamTemplate`
.. function:: void FunctionParams(int FunctionParam)
:cpp:any:`FunctionParam`
class
struct
union
function
:member:`FunctionParam`
:var:`FunctionParam`
type
concept
enum
enumerator

View File

@@ -0,0 +1,158 @@
.. default-domain:: cpp
.. namespace:: RolesTargetsWarn
.. class:: Class
class
struct
:union:`Class`
:func:`Class`
:member:`Class`
:var:`Class`
type
:concept:`Class`
:enum:`Class`
:enumerator:`Class`
.. union:: Union
:class:`Union`
:struct:`Union`
union
:func:`Union`
:member:`Union`
:var:`Union`
type
:concept:`Union`
:enum:`Union`
:enumerator:`Union`
.. function:: void Function()
:class:`Function`
:struct:`Function`
:union:`Function`
func
:member:`Function`
:var:`Function`
type
:concept:`Function`
:enum:`Function`
:enumerator:`Function`
.. var:: int Variable
:class:`Variable`
:struct:`Variable`
:union:`Variable`
:func:`Variable`
member
var
:type:`Variable`
:concept:`Variable`
:enum:`Variable`
:enumerator:`Variable`
.. type:: Type = void
:class:`Type`
:struct:`Type`
:union:`Type`
:func:`Type`
:member:`Type`
:var:`Type`
type
:concept:`Type`
:enum:`Type`
:enumerator:`Type`
.. concept:: template<typename T> Concept
:class:`Concept`
:struct:`Concept`
:union:`Concept`
:func:`Concept`
:member:`Concept`
:var:`Concept`
:type:`Concept`
concept
:enum:`Concept`
:enumerator:`Concept`
.. enum-struct:: Enum
:class:`Enum`
:struct:`Enum`
:union:`Enum`
:func:`Enum`
:member:`Enum`
:var:`Enum`
type
:concept:`Enum`
enum
:enumerator:`Enum`
.. enumerator:: Enumerator
:class:`Enumerator`
:struct:`Enumerator`
:union:`Enumerator`
:func:`Enumerator`
:member:`Enumerator`
:var:`Enumerator`
:type:`Enumerator`
:concept:`Enumerator`
:enum:`Enumerator`
enumerator
.. class:: template<typename TParamType, \
int TParamVar, \
template<typename> typename TParamTemplate \
> ClassTemplate
class
struct
union
func
member
var
type
concept
enum
enumerator
class
struct
union
func
member
var
type
concept
enum
enumerator
class
struct
union
func
member
var
type
concept
enum
enumerator
.. function:: void FunctionParams(int FunctionParam)
:class:`FunctionParam`
:struct:`FunctionParam`
:union:`FunctionParam`
:func:`FunctionParam`
member
var
:type:`FunctionParam`
:concept:`FunctionParam`
:enum:`FunctionParam`
:enumerator:`FunctionParam`

View File

@@ -0,0 +1,11 @@
.. default-domain:: cpp
.. class:: template<typename T> A
.. type:: N1 = T::typeOk
- Not ok, warn: :type:`T::typeWarn`
.. type:: N2 = T::U::typeOk
- Not ok, warn: :type:`T::U::typeWarn`

View File

@@ -18,6 +18,12 @@ module
* Link to :py:meth:`module_a.submodule.ModTopLevel.mod_child_1`
.. py:method:: ModTopLevel.prop
:property:
* Link to :py:attr:`prop attribute <.prop>`
* Link to :py:meth:`prop method <.prop>`
.. py:currentmodule:: None
.. py:class:: ModNoModule

View File

@@ -7,3 +7,5 @@
.. automodule:: autodoc_dummy_bar
:members:
.. autofunction:: target.typehints.incr

View File

@@ -110,6 +110,10 @@ class Outer(object):
factory = dict
class InnerChild(Outer.Inner):
"""InnerChild docstring"""
class DocstringSig(object):
def meth(self):
"""meth(FOO, BAR=1) -> BAZ

View File

@@ -0,0 +1,6 @@
from typing import Annotated
def hello(name: Annotated[str, "attribute"]) -> None:
"""docstring"""
pass

View File

@@ -3,6 +3,16 @@ class AsyncClass:
"""A documented coroutine function"""
attr_coro_result = await _other_coro_func() # NOQA
@classmethod
async def do_coroutine2(cls):
"""A documented coroutine classmethod"""
pass
@staticmethod
async def do_coroutine3():
"""A documented coroutine staticmethod"""
pass
async def _other_coro_func():
return "run"

View File

@@ -0,0 +1 @@
from .partialfunction import func2, func3

View File

@@ -1,11 +1,12 @@
from functools import partial
def func1():
def func1(a, b, c):
"""docstring of func1"""
pass
func2 = partial(func1)
func3 = partial(func1)
func2 = partial(func1, 1)
func3 = partial(func2, 2)
func3.__doc__ = "docstring of func3"
func4 = partial(func3, 3)

View File

@@ -14,5 +14,5 @@ class Cell(object):
#: Make a cell alive.
set_alive = partialmethod(set_state, True)
# a partialmethod with no docstring
set_dead = partialmethod(set_state, False)
"""Make a cell dead."""

View File

@@ -0,0 +1,11 @@
def foo(*, a, b):
pass
def bar(a, b, /, c, d):
pass
def baz(a, /, *, b):
pass
def qux(a, b, /):
pass

View File

@@ -0,0 +1,5 @@
def private_function(name):
"""private_function is a docstring().
:meta private:
"""

View File

@@ -0,0 +1,18 @@
#: attr1
attr1: str = ''
#: attr2
attr2: str
#: attr3
attr3 = '' # type: str
class Class:
attr1: int = 0
attr2: int
attr3 = 0 # type: int
def __init__(self):
self.attr4: int = 0 #: attr4
self.attr5: int #: attr5
self.attr6 = 0 # type: int
"""attr6"""

View File

@@ -2,9 +2,43 @@ def incr(a: int, b: int = 1) -> int:
return a + b
def decr(a, b = 1):
# type: (int, int) -> int
return a - b
class Math:
def __init__(self, s: str, o: object = None) -> None:
pass
def incr(self, a: int, b: int = 1) -> int:
return a + b
def decr(self, a, b = 1):
# type: (int, int) -> int
return a - b
def nothing(self):
# type: () -> None
pass
def horse(self,
a, # type: str
b, # type: int
):
# type: (...) -> None
return
def complex_func(arg1, arg2, arg3=None, *args, **kwargs):
# type: (str, List[int], Tuple[int, Union[str, Unknown]], *str, **str) -> None
pass
def missing_attr(c,
a, # type: str
b=None # type: Optional[str]
):
# type: (...) -> str
return a + (b or "")

View File

@@ -1,17 +1,18 @@
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.ext.mathbase import math, displaymath
extensions = ['sphinx.ext.mathjax']
def my_math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
return [math(latex='E = mc^2')], []
text = 'E = mc^2'
return [nodes.math(text, text)], []
class MyMathDirective(Directive):
def run(self):
return [displaymath(latex='E = mc^2')]
text = 'E = mc^2'
return [nodes.math_block(text, text)]
def setup(app):

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -0,0 +1,11 @@
test-html_scaled_image_link
===========================
.. image:: img.png
.. image:: img.png
:scale: 50%
.. image:: img.png
:scale: 50%
:class: no-scaled-link

View File

@@ -0,0 +1,5 @@
Diagram with Nested Classes
===========================
.. inheritance-diagram::
dummy.test_nested

View File

@@ -0,0 +1,12 @@
"""
Test with nested classes.
"""
class A(object):
class B(object):
pass
class C(A.B):
pass

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -24,7 +24,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -26,7 +26,7 @@ header3
\endhead
\hline
\multicolumn{3}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{3}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -22,7 +22,7 @@ header2
\endhead
\hline
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{Continued on next page}}}\\
\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\
\endfoot
\endlastfoot

View File

@@ -0,0 +1,6 @@
Bare
====
.. productionlist::
A: `A` | somethingA
B: `B` | somethingB

View File

@@ -0,0 +1,5 @@
Dup1
====
.. productionlist::
Dup: `Dup` | somethingDup

View File

@@ -0,0 +1,5 @@
Dup2
====
.. productionlist::
Dup: `Dup` | somethingDup

View File

@@ -0,0 +1,6 @@
LineContinuation
================
.. productionlist:: lineContinuation
A: B C D \
E F G

View File

@@ -0,0 +1,6 @@
P1
==
.. productionlist:: P1
A: `A` | somethingA
B: `B` | somethingB

View File

@@ -0,0 +1,6 @@
P2
==
.. productionlist:: P2
A: `A` | somethingA
B: `B` | somethingB

View File

@@ -0,0 +1 @@
exclude_patterns = ['_build']

View File

@@ -0,0 +1,5 @@
FirstLineRule
=============
.. productionlist:: FirstLine: something
SecondLine: somethingElse

View File

@@ -0,0 +1,27 @@
.. toctree::
P1
P2
Bare
Dup1
Dup2
firstLineRule
LineContinuation
- A: :token:`A`
- B: :token:`B`
- P1:A: :token:`P1:A`
- P1:B: :token:`P1:B`
- P2:A: :token:`P1:A`
- P2:B: :token:`P2:B`
- Explicit title A, plain: :token:`MyTitle <A>`
- Explicit title A, colon: :token:`My:Title <A>`
- Explicit title P1:A, plain: :token:`MyTitle <P1:A>`
- Explicit title P1:A, colon: :token:`My:Title <P1:A>`
- Tilde A: :token:`~A`.
- Tilde P1:A: :token:`~P1:A`.
- Tilde explicit title P1:A: :token:`~MyTitle <P1:A>`
- Tilde, explicit title P1:A: :token:`MyTitle <~P1:A>`
- Dup: :token:`Dup`
- FirstLine: :token:`FirstLine`
- SecondLine: :token:`SecondLine`

View File

@@ -0,0 +1,7 @@
:nosearch:
nosearch
========
zfs
latex

View File

@@ -61,20 +61,13 @@ def test_extension_in_blacklist(app, status, warning):
@pytest.mark.sphinx(testroot='add_source_parser')
@pytest.mark.filterwarnings('ignore:The config variable "source_parsers"')
@pytest.mark.filterwarnings('ignore:app.add_source_parser\\(\\) does not support suffix')
def test_add_source_parser(app, status, warning):
assert set(app.config.source_suffix) == {'.rst', '.md', '.test'}
assert set(app.config.source_suffix) == {'.rst', '.test'}
# .rst; only in :confval:`source_suffix`
assert '.rst' not in app.registry.get_source_parsers()
assert app.registry.source_suffix['.rst'] is None
# .md; configured by :confval:`source_suffix` and :confval:`source_parsers`
assert '.md' in app.registry.get_source_parsers()
assert app.registry.source_suffix['.md'] == '.md'
assert app.registry.get_source_parsers()['.md'].__name__ == 'DummyMarkdownParser'
# .test; configured by API
assert app.registry.source_suffix['.test'] == 'test'
assert 'test' in app.registry.get_source_parsers()

View File

@@ -581,6 +581,30 @@ def test_autodoc_inherited_members(app):
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inherited_members_Base(app):
options = {"members": None,
"inherited-members": "Base",
"special-members": None}
# check methods for object class are shown
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
assert ' .. py:method:: Derived.inheritedmeth()' in actual
assert ' .. py:method:: Derived.inheritedclassmeth' not in actual
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inherited_members_None(app):
options = {"members": None,
"inherited-members": "None",
"special-members": None}
# check methods for object class are shown
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
assert ' .. py:method:: Derived.__init__' in actual
assert ' .. py:method:: Derived.__str__' in actual
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_imported_members(app):
options = {"members": None,
@@ -661,6 +685,7 @@ def test_autodoc_ignore_module_all(app):
assert list(filter(lambda l: 'class::' in l, actual)) == [
'.. py:class:: Class(arg)',
'.. py:class:: CustomDict',
'.. py:class:: InnerChild',
'.. py:class:: InstAttCls()',
'.. py:class:: Outer',
' .. py:class:: Outer.Inner',
@@ -751,6 +776,18 @@ def test_autodoc_inner_class(app):
' ',
]
options['show-inheritance'] = True
actual = do_autodoc(app, 'class', 'target.InnerChild', options)
assert list(actual) == [
'',
'.. py:class:: InnerChild',
' :module: target', '',
' Bases: :class:`target.Outer.Inner`',
'',
' InnerChild docstring',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_classmethod(app):
@@ -906,7 +943,7 @@ def test_autodoc_module_scope(app):
'',
'.. py:attribute:: Class.mdocattr',
' :module: target',
' :annotation: = <_io.StringIO object>',
' :value: <_io.StringIO object>',
'',
' should be documented as well - süß',
' '
@@ -922,7 +959,7 @@ def test_autodoc_class_scope(app):
'',
'.. py:attribute:: Class.mdocattr',
' :module: target',
' :annotation: = <_io.StringIO object>',
' :value: <_io.StringIO object>',
'',
' should be documented as well - süß',
' '
@@ -942,12 +979,12 @@ def test_class_attributes(app):
' ',
' .. py:attribute:: AttCls.a1',
' :module: target',
' :annotation: = hello world',
' :value: hello world',
' ',
' ',
' .. py:attribute:: AttCls.a2',
' :module: target',
' :annotation: = None',
' :value: None',
' '
]
@@ -966,7 +1003,7 @@ def test_instance_attributes(app):
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
" :value: 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
@@ -974,28 +1011,28 @@ def test_instance_attributes(app):
' ',
' .. py:attribute:: InstAttCls.ca2',
' :module: target',
" :annotation: = 'b'",
" :value: 'b'",
' ',
' Doc comment for InstAttCls.ca2. One line only.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca3',
' :module: target',
" :annotation: = 'c'",
" :value: 'c'",
' ',
' Docstring for class attribute InstAttCls.ca3.',
' ',
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' :value: None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' ',
' ',
' .. py:attribute:: InstAttCls.ia2',
' :module: target',
' :annotation: = None',
' :value: None',
' ',
' Docstring for instance attribute InstAttCls.ia2.',
' '
@@ -1014,7 +1051,7 @@ def test_instance_attributes(app):
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
" :value: 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
@@ -1022,7 +1059,7 @@ def test_instance_attributes(app):
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' :value: None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' '
@@ -1090,28 +1127,28 @@ def test_enum_class(app):
' ',
' .. py:attribute:: EnumCls.val1',
' :module: target.enum',
' :annotation: = 12',
' :value: 12',
' ',
' doc for val1',
' ',
' ',
' .. py:attribute:: EnumCls.val2',
' :module: target.enum',
' :annotation: = 23',
' :value: 23',
' ',
' doc for val2',
' ',
' ',
' .. py:attribute:: EnumCls.val3',
' :module: target.enum',
' :annotation: = 34',
' :value: 34',
' ',
' doc for val3',
' ',
' ',
' .. py:attribute:: EnumCls.val4',
' :module: target.enum',
' :annotation: = 34',
' :value: 34',
' '
]
@@ -1121,7 +1158,7 @@ def test_enum_class(app):
'',
'.. py:attribute:: EnumCls.val1',
' :module: target.enum',
' :annotation: = 12',
' :value: 12',
'',
' doc for val1',
' '
@@ -1241,19 +1278,25 @@ def test_partialfunction():
'.. py:module:: target.partialfunction',
'',
'',
'.. py:function:: func1()',
'.. py:function:: func1(a, b, c)',
' :module: target.partialfunction',
'',
' docstring of func1',
' ',
'',
'.. py:function:: func2()',
'.. py:function:: func2(b, c)',
' :module: target.partialfunction',
'',
' docstring of func1',
' ',
'',
'.. py:function:: func3()',
'.. py:function:: func3(c)',
' :module: target.partialfunction',
'',
' docstring of func3',
' ',
'',
'.. py:function:: func4()',
' :module: target.partialfunction',
'',
' docstring of func3',
@@ -1261,6 +1304,17 @@ def test_partialfunction():
]
@pytest.mark.usefixtures('setup_test')
def test_imported_partialfunction_should_not_shown_without_imported_members():
options = {"members": None}
actual = do_autodoc(app, 'module', 'target.imported_members', options)
assert list(actual) == [
'',
'.. py:module:: target.imported_members',
''
]
@pytest.mark.usefixtures('setup_test')
def test_bound_method():
options = {"members": None}
@@ -1302,7 +1356,23 @@ def test_coroutine():
' :async:',
' ',
' A documented coroutine function',
' '
' ',
' ',
' .. py:method:: AsyncClass.do_coroutine2()',
' :module: target.coroutine',
' :async:',
' :classmethod:',
' ',
' A documented coroutine classmethod',
' ',
' ',
' .. py:method:: AsyncClass.do_coroutine3()',
' :module: target.coroutine',
' :async:',
' :staticmethod:',
' ',
' A documented coroutine staticmethod',
' ',
]
@@ -1318,35 +1388,160 @@ def test_partialmethod(app):
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
' ',
' ',
' .. py:method:: Cell.set_alive() -> None',
' .. py:method:: Cell.set_alive()',
' :module: target.partialmethod',
' ',
' Make a cell alive.',
' ',
' ',
' .. py:method:: Cell.set_dead() -> None',
' :module: target.partialmethod',
' ',
' Make a cell dead.',
' ',
' ',
' .. py:method:: Cell.set_state(state)',
' :module: target.partialmethod',
' ',
' Update state of cell to *state*.',
' ',
]
if (sys.version_info < (3, 5, 4) or
(3, 6, 5) <= sys.version_info < (3, 7) or
(3, 7, 0, 'beta', 3) <= sys.version_info):
# TODO: this condition should be updated after 3.7-final release.
expected = '\n'.join(expected).replace(' -> None', '').split('\n')
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
assert list(actual) == expected
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_partialmethod_undoc_members(app):
expected = [
'',
'.. py:class:: Cell',
' :module: target.partialmethod',
'',
' An example for partialmethod.',
' ',
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
' ',
' ',
' .. py:method:: Cell.set_alive()',
' :module: target.partialmethod',
' ',
' Make a cell alive.',
' ',
' ',
' .. py:method:: Cell.set_dead()',
' :module: target.partialmethod',
' ',
' ',
' .. py:method:: Cell.set_state(state)',
' :module: target.partialmethod',
' ',
' Update state of cell to *state*.',
' ',
]
options = {"members": None,
"undoc-members": None}
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
assert list(actual) == expected
@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is available since python3.6.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_typed_instance_variables(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'module', 'target.typed_vars', options)
assert list(actual) == [
'',
'.. py:module:: target.typed_vars',
'',
'',
'.. py:class:: Class()',
' :module: target.typed_vars',
'',
' ',
' .. py:attribute:: Class.attr1',
' :module: target.typed_vars',
' :type: int',
' :value: 0',
' ',
' ',
' .. py:attribute:: Class.attr2',
' :module: target.typed_vars',
' :type: int',
' :value: None',
' ',
' ',
' .. py:attribute:: Class.attr3',
' :module: target.typed_vars',
' :type: int',
' :value: 0',
' ',
' ',
' .. py:attribute:: Class.attr4',
' :module: target.typed_vars',
' :type: int',
' :value: None',
' ',
' attr4',
' ',
' ',
' .. py:attribute:: Class.attr5',
' :module: target.typed_vars',
' :type: int',
' :value: None',
' ',
' attr5',
' ',
' ',
' .. py:attribute:: Class.attr6',
' :module: target.typed_vars',
' :type: int',
' :value: None',
' ',
' attr6',
' ',
'',
'.. py:data:: attr1',
' :module: target.typed_vars',
' :type: str',
" :value: ''",
'',
' attr1',
' ',
'',
'.. py:data:: attr2',
' :module: target.typed_vars',
' :type: str',
' :value: None',
'',
' attr2',
' ',
'',
'.. py:data:: attr3',
' :module: target.typed_vars',
' :type: str',
" :value: ''",
'',
' attr3',
' '
]
@pytest.mark.skipif(sys.version_info < (3, 9), reason='py39+ is required.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_Annotated(app):
options = {"members": None}
actual = do_autodoc(app, 'module', 'target.annotated', options)
assert list(actual) == [
'',
'.. py:module:: target.annotated',
'',
'',
'.. py:function:: hello(name: str) -> None',
' :module: target.annotated',
'',
' docstring',
' '
]
@pytest.mark.sphinx('html', testroot='pycode-egg')
def test_autodoc_for_egged_code(app):
options = {"members": None,
@@ -1359,7 +1554,7 @@ def test_autodoc_for_egged_code(app):
'',
'.. py:data:: CONSTANT',
' :module: sample',
' :annotation: = 1',
' :value: 1',
'',
' constant on sample.py',
' ',

View File

@@ -45,7 +45,7 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
"""))
master_doc = srcdir / 'index.txt'
master_doc.write_text(master_doc.text() + dedent("""
master_doc.write_text(master_doc.read_text() + dedent("""
.. toctree::
%(test_name)s/%(test_name)s

View File

@@ -17,7 +17,7 @@ def test_build(app):
app.build()
# TODO: Use better checking of html content
htmltext = (app.outdir / 'changes.html').text()
htmltext = (app.outdir / 'changes.html').read_text()
assert 'New in version 0.6: Some funny stuff.' in htmltext
assert 'Changed in version 0.6: Even more funny stuff.' in htmltext
assert 'Deprecated since version 0.6: Boring stuff.' in htmltext

View File

@@ -0,0 +1,48 @@
"""
test_build_dirhtml
~~~~~~~~~~~~~~~~~~
Test dirhtml builder.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import posixpath
import pytest
from sphinx.util.inventory import InventoryFile
@pytest.mark.sphinx(buildername='dirhtml', testroot='builder-dirhtml')
def test_dirhtml(app, status, warning):
app.build()
assert (app.outdir / 'index.html').exists()
assert (app.outdir / 'foo/index.html').exists()
assert (app.outdir / 'foo/foo_1/index.html').exists()
assert (app.outdir / 'foo/foo_2/index.html').exists()
assert (app.outdir / 'bar/index.html').exists()
content = (app.outdir / 'index.html').read_text()
assert 'href="foo/"' in content
assert 'href="foo/foo_1/"' in content
assert 'href="foo/foo_2/"' in content
assert 'href="bar/"' in content
# objects.inv (refs: #7095)
with (app.outdir / 'objects.inv').open('rb') as f:
invdata = InventoryFile.load(f, 'path/to', posixpath.join)
assert 'index' in invdata.get('std:doc')
assert ('Python', '', 'path/to/', '-') == invdata['std:doc']['index']
assert 'foo/index' in invdata.get('std:doc')
assert ('Python', '', 'path/to/foo/', '-') == invdata['std:doc']['foo/index']
assert 'index' in invdata.get('std:label')
assert ('Python', '', 'path/to/#index', '-') == invdata['std:label']['index']
assert 'foo' in invdata.get('std:label')
assert ('Python', '', 'path/to/foo/#foo', 'foo/index') == invdata['std:label']['foo']

View File

@@ -67,11 +67,11 @@ class EPUBElementTree:
@pytest.mark.sphinx('epub', testroot='basic')
def test_build_epub(app):
app.build()
assert (app.outdir / 'mimetype').text() == 'application/epub+zip'
assert (app.outdir / 'mimetype').read_text() == 'application/epub+zip'
assert (app.outdir / 'META-INF' / 'container.xml').exists()
# toc.ncx
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').text())
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').read_text())
assert toc.find("./ncx:docTitle/ncx:text").text == 'Python'
# toc.ncx / head
@@ -91,7 +91,7 @@ def test_build_epub(app):
assert navlabel.text == 'The basic Sphinx documentation for testing'
# content.opf
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').text())
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').read_text())
# content.opf / metadata
metadata = opf.find("./idpf:metadata")
@@ -143,7 +143,7 @@ def test_build_epub(app):
assert reference.get('href') == 'index.xhtml'
# nav.xhtml
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').text())
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').read_text())
assert nav.attrib == {'lang': 'en',
'{http://www.w3.org/XML/1998/namespace}lang': 'en'}
assert nav.find("./xhtml:head/xhtml:title").text == 'Table of Contents'
@@ -163,7 +163,7 @@ def test_epub_cover(app):
app.build()
# content.opf / metadata
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').text())
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').read_text())
cover_image = opf.find("./idpf:manifest/idpf:item[@href='%s']" % app.config.epub_cover[0])
cover = opf.find("./idpf:metadata/idpf:meta[@name='cover']")
assert cover
@@ -175,7 +175,7 @@ def test_nested_toc(app):
app.build()
# toc.ncx
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').bytes())
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').read_bytes())
assert toc.find("./ncx:docTitle/ncx:text").text == 'Python'
# toc.ncx / navPoint
@@ -205,7 +205,7 @@ def test_nested_toc(app):
anchor = elem.find("./xhtml:a")
return (anchor.get('href'), anchor.text)
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').bytes())
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').read_bytes())
toc = nav.findall("./xhtml:body/xhtml:nav/xhtml:ol/xhtml:li")
assert len(toc) == 4
assert navinfo(toc[0]) == ('index.xhtml',
@@ -230,7 +230,7 @@ def test_escaped_toc(app):
app.build()
# toc.ncx
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').bytes())
toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').read_bytes())
assert toc.find("./ncx:docTitle/ncx:text").text == 'need <b>"escaped"</b> project'
# toc.ncx / navPoint
@@ -260,7 +260,7 @@ def test_escaped_toc(app):
anchor = elem.find("./xhtml:a")
return (anchor.get('href'), anchor.text)
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').bytes())
nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').read_bytes())
toc = nav.findall("./xhtml:body/xhtml:nav/xhtml:ol/xhtml:li")
assert len(toc) == 4
assert navinfo(toc[0]) == ('index.xhtml',
@@ -286,7 +286,7 @@ def test_epub_writing_mode(app):
app.build()
# horizontal / page-progression-direction
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').text())
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').read_text())
assert opf.find("./idpf:spine").get('page-progression-direction') == 'ltr'
# horizontal / ibooks:scroll-axis
@@ -294,7 +294,7 @@ def test_epub_writing_mode(app):
assert metadata.find("./idpf:meta[@property='ibooks:scroll-axis']").text == 'vertical'
# horizontal / writing-mode (CSS)
css = (app.outdir / '_static' / 'epub.css').text()
css = (app.outdir / '_static' / 'epub.css').read_text()
assert 'writing-mode: horizontal-tb;' in css
# vertical
@@ -303,7 +303,7 @@ def test_epub_writing_mode(app):
app.build()
# vertical / page-progression-direction
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').text())
opf = EPUBElementTree.fromstring((app.outdir / 'content.opf').read_text())
assert opf.find("./idpf:spine").get('page-progression-direction') == 'rtl'
# vertical / ibooks:scroll-axis
@@ -311,7 +311,7 @@ def test_epub_writing_mode(app):
assert metadata.find("./idpf:meta[@property='ibooks:scroll-axis']").text == 'horizontal'
# vertical / writing-mode (CSS)
css = (app.outdir / '_static' / 'epub.css').text()
css = (app.outdir / '_static' / 'epub.css').read_text()
assert 'writing-mode: vertical-rl;' in css
@@ -319,10 +319,14 @@ def test_epub_writing_mode(app):
def test_epub_anchor_id(app):
app.build()
html = (app.outdir / 'index.xhtml').text()
assert '<p id="std-setting-STATICFILES_FINDERS">blah blah blah</p>' in html
assert '<span id="std-setting-STATICFILES_SECTION"></span><h1>blah blah blah</h1>' in html
assert 'see <a class="reference internal" href="#std-setting-STATICFILES_FINDERS">' in html
html = (app.outdir / 'index.xhtml').read_text()
assert ('<p id="std-setting-staticfiles-finders">'
'<span id="std-setting-STATICFILES_FINDERS"></span>'
'blah blah blah</p>' in html)
assert ('<span id="std-setting-staticfiles-section"></span>'
'<span id="std-setting-STATICFILES_SECTION"></span>'
'<h1>blah blah blah</h1>' in html)
assert 'see <a class="reference internal" href="#std-setting-staticfiles-finders">' in html
@pytest.mark.sphinx('epub', testroot='html_assets')
@@ -330,7 +334,7 @@ def test_epub_assets(app):
app.builder.build_all()
# epub_sytlesheets (same as html_css_files)
content = (app.outdir / 'index.xhtml').text()
content = (app.outdir / 'index.xhtml').read_text()
assert ('<link rel="stylesheet" type="text/css" href="_static/css/style.css" />'
in content)
assert ('<link media="print" rel="stylesheet" title="title" type="text/css" '
@@ -343,7 +347,7 @@ def test_epub_css_files(app):
app.builder.build_all()
# epub_css_files
content = (app.outdir / 'index.xhtml').text()
content = (app.outdir / 'index.xhtml').read_text()
assert '<link rel="stylesheet" type="text/css" href="_static/css/epub.css" />' in content
# files in html_css_files are not outputed
@@ -360,7 +364,7 @@ def test_html_download_role(app, status, warning):
app.build()
assert not (app.outdir / '_downloads' / 'dummy.dat').exists()
content = (app.outdir / 'index.xhtml').text()
content = (app.outdir / 'index.xhtml').read_text()
assert ('<li><p><code class="xref download docutils literal notranslate">'
'<span class="pre">dummy.dat</span></code></p></li>' in content)
assert ('<li><p><code class="xref download docutils literal notranslate">'

View File

@@ -31,7 +31,7 @@ def test_build_gettext(app):
assert (app.outdir / 'subdir.pot').isfile()
# regression test for issue #960
catalog = (app.outdir / 'markup.pot').text()
catalog = (app.outdir / 'markup.pot').read_text()
assert 'msgid "something, something else, something more"' in catalog
@@ -84,7 +84,7 @@ def test_gettext_index_entries(app):
return m.groups()[0]
return None
pot = (app.outdir / 'index_entries.pot').text()
pot = (app.outdir / 'index_entries.pot').read_text()
msgids = [_f for _f in map(msgid_getter, pot.splitlines()) if _f]
expected_msgids = [
@@ -133,7 +133,7 @@ def test_gettext_disable_index_entries(app):
return m.groups()[0]
return None
pot = (app.outdir / 'index_entries.pot').text()
pot = (app.outdir / 'index_entries.pot').read_text()
msgids = [_f for _f in map(msgid_getter, pot.splitlines()) if _f]
expected_msgids = [
@@ -156,7 +156,7 @@ def test_gettext_template(app):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()
result = (app.outdir / 'sphinx.pot').text()
result = (app.outdir / 'sphinx.pot').read_text()
assert "Welcome" in result
assert "Sphinx %(version)s" in result
@@ -166,7 +166,7 @@ def test_gettext_template_msgid_order_in_sphinxpot(app):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()
result = (app.outdir / 'sphinx.pot').text()
result = (app.outdir / 'sphinx.pot').read_text()
assert re.search(
('msgid "Template 1".*'
'msgid "This is Template 1\\.".*'

View File

@@ -176,8 +176,8 @@ def test_html4_output(app, status, warning):
r'-| |-'),
],
'autodoc.html': [
(".//dt[@id='autodoc_target.Class']", ''),
(".//dt[@id='autodoc_target.function']/em", r'\*\*kwds'),
(".//dl[@class='py class']/dt[@id='autodoc_target.Class']", ''),
(".//dl[@class='py function']/dt[@id='autodoc_target.function']/em", r'\*\*kwds'),
(".//dd/p", r'Return spam\.'),
],
'extapi.html': [
@@ -218,11 +218,11 @@ def test_html4_output(app, status, warning):
"[@class='rfc reference external']/strong", 'RFC 1'),
(".//a[@href='https://tools.ietf.org/html/rfc1.html']"
"[@class='rfc reference external']/strong", 'Request for Comments #1'),
(".//a[@href='objects.html#envvar-HOME']"
(".//a[@href='objects.html#envvar-home']"
"[@class='reference internal']/code/span[@class='pre']", 'HOME'),
(".//a[@href='#with']"
"[@class='reference internal']/code/span[@class='pre']", '^with$'),
(".//a[@href='#grammar-token-try-stmt']"
(".//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$'),
@@ -254,7 +254,7 @@ def test_html4_output(app, status, warning):
(".//dl/dt[@id='term-boson']", 'boson'),
# a production list
(".//pre/strong", 'try_stmt'),
(".//pre/a[@href='#grammar-token-try1-stmt']/code/span", 'try1_stmt'),
(".//pre/a[@href='#grammar-token-_try1-stmt']/code/span", 'try1_stmt'),
# tests for ``only`` directive
(".//p", 'A global substitution.'),
(".//p", 'In HTML.'),
@@ -279,7 +279,7 @@ def test_html4_output(app, status, warning):
(".//dt/code", r'long\(parameter,\s* list\)'),
(".//dt/code", 'another one'),
(".//a[@href='#mod.Cls'][@class='reference internal']", ''),
(".//dl[@class='userdesc']", ''),
(".//dl[@class='std userdesc']", ''),
(".//dt[@id='userdesc-myobj']", ''),
(".//a[@href='#userdesc-myobj'][@class='reference internal']", ''),
# docfields
@@ -426,7 +426,7 @@ def test_html_download(app):
app.build()
# subdir/includes.html
result = (app.outdir / 'subdir' / 'includes.html').text()
result = (app.outdir / 'subdir' / 'includes.html').read_text()
pattern = ('<a class="reference download internal" download="" '
'href="../(_downloads/.*/img.png)">')
matched = re.search(pattern, result)
@@ -435,7 +435,7 @@ def test_html_download(app):
filename = matched.group(1)
# includes.html
result = (app.outdir / 'includes.html').text()
result = (app.outdir / 'includes.html').read_text()
pattern = ('<a class="reference download internal" download="" '
'href="(_downloads/.*/img.png)">')
matched = re.search(pattern, result)
@@ -454,7 +454,7 @@ def test_html_download_role(app, status, warning):
digest_another = md5(b'another/dummy.dat').hexdigest()
assert (app.outdir / '_downloads' / digest_another / 'dummy.dat').exists()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert (('<li><p><a class="reference download internal" download="" '
'href="_downloads/%s/dummy.dat">'
'<code class="xref download docutils literal notranslate">'
@@ -646,7 +646,7 @@ def test_numfig_disabled(app, cached_etree_parse, fname, expect):
def test_numfig_without_numbered_toctree_warn(app, warning):
app.build()
# remove :numbered: option
index = (app.srcdir / 'index.rst').text()
index = (app.srcdir / 'index.rst').read_text()
index = re.sub(':numbered:.*', '', index)
(app.srcdir / 'index.rst').write_text(index)
app.builder.build_all()
@@ -746,7 +746,7 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
confoverrides={'numfig': True})
def test_numfig_without_numbered_toctree(app, cached_etree_parse, fname, expect):
# remove :numbered: option
index = (app.srcdir / 'index.rst').text()
index = (app.srcdir / 'index.rst').read_text()
index = re.sub(':numbered:.*', '', index)
(app.srcdir / 'index.rst').write_text(index)
@@ -1189,7 +1189,7 @@ def test_html_assets(app):
assert not (app.outdir / '_static' / '.htaccess').exists()
assert not (app.outdir / '_static' / '.htpasswd').exists()
assert (app.outdir / '_static' / 'API.html').exists()
assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4'
assert (app.outdir / '_static' / 'API.html').read_text() == 'Sphinx-1.4.4'
assert (app.outdir / '_static' / 'css' / 'style.css').exists()
assert (app.outdir / '_static' / 'js' / 'custom.js').exists()
assert (app.outdir / '_static' / 'rimg.png').exists()
@@ -1210,7 +1210,7 @@ def test_html_assets(app):
assert not (app.outdir / 'subdir' / '.htpasswd').exists()
# html_css_files
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<link rel="stylesheet" type="text/css" href="_static/css/style.css" />' in content
assert ('<link media="print" rel="stylesheet" title="title" type="text/css" '
'href="https://example.com/custom.css" />' in content)
@@ -1249,7 +1249,7 @@ def test_html_sourcelink_suffix_empty(app):
def test_html_entity(app):
app.builder.build_all()
valid_entities = {'amp', 'lt', 'gt', 'quot', 'apos'}
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
for entity in re.findall(r'&([a-z]+);', content, re.M):
assert entity not in valid_entities
@@ -1261,11 +1261,18 @@ def test_html_inventory(app):
with open(app.outdir / 'objects.inv', 'rb') as f:
invdata = InventoryFile.load(f, 'https://www.google.com', os.path.join)
assert set(invdata.keys()) == {'std:label', 'std:doc'}
assert set(invdata['std:label'].keys()) == {'modindex', 'genindex', 'search'}
assert set(invdata['std:label'].keys()) == {'modindex',
'py-modindex',
'genindex',
'search'}
assert invdata['std:label']['modindex'] == ('Python',
'',
'https://www.google.com/py-modindex.html',
'Module Index')
assert invdata['std:label']['py-modindex'] == ('Python',
'',
'https://www.google.com/py-modindex.html',
'Python Module Index')
assert invdata['std:label']['genindex'] == ('Python',
'',
'https://www.google.com/genindex.html',
@@ -1284,7 +1291,7 @@ def test_html_inventory(app):
@pytest.mark.sphinx('html', testroot='images', confoverrides={'html_sourcelink_suffix': ''})
def test_html_anchor_for_figure(app):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert ('<p class="caption"><span class="caption-text">The caption of pic</span>'
'<a class="headerlink" href="#id1" title="Permalink to this image">¶</a></p>'
in content)
@@ -1293,7 +1300,7 @@ def test_html_anchor_for_figure(app):
@pytest.mark.sphinx('html', testroot='directives-raw')
def test_html_raw_directive(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
# standard case
assert 'standalone raw directive (HTML)' in result
@@ -1337,7 +1344,7 @@ def test_alternate_stylesheets(app, cached_etree_parse, fname, expect):
@pytest.mark.sphinx('html', testroot='html_style')
def test_html_style(app, status, warning):
app.build()
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
assert '<link rel="stylesheet" href="_static/default.css" type="text/css" />' in result
assert ('<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />'
not in result)
@@ -1347,7 +1354,7 @@ def test_html_style(app, status, warning):
def test_html_remote_images(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert ('<img alt="https://www.python.org/static/img/python-logo.png" '
'src="https://www.python.org/static/img/python-logo.png" />' in result)
assert not (app.outdir / 'python-logo.png').exists()
@@ -1359,7 +1366,7 @@ def test_html_sidebar(app, status, warning):
# default for alabaster
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' in result
@@ -1374,7 +1381,7 @@ def test_html_sidebar(app, status, warning):
# only relations.html
app.config.html_sidebars = {'**': ['relations.html']}
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
@@ -1388,7 +1395,7 @@ def test_html_sidebar(app, status, warning):
# no sidebars
app.config.html_sidebars = {'**': []}
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert ('<div class="sphinxsidebar" role="navigation" '
'aria-label="main navigation">' not in result)
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
@@ -1419,10 +1426,10 @@ def test_html_manpage(app, cached_etree_parse, fname, expect):
def test_html_baseurl(app, status, warning):
app.build()
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert '<link rel="canonical" href="https://example.com/index.html" />' in result
result = (app.outdir / 'qux' / 'index.html').text(encoding='utf8')
result = (app.outdir / 'qux' / 'index.html').read_text()
assert '<link rel="canonical" href="https://example.com/qux/index.html" />' in result
@@ -1432,10 +1439,10 @@ def test_html_baseurl(app, status, warning):
def test_html_baseurl_and_html_file_suffix(app, status, warning):
app.build()
result = (app.outdir / 'index.htm').text(encoding='utf8')
result = (app.outdir / 'index.htm').read_text()
assert '<link rel="canonical" href="https://example.com/subdir/index.htm" />' in result
result = (app.outdir / 'qux' / 'index.htm').text(encoding='utf8')
result = (app.outdir / 'qux' / 'index.htm').read_text()
assert '<link rel="canonical" href="https://example.com/subdir/qux/index.htm" />' in result
@@ -1542,3 +1549,22 @@ def test_validate_html_static_path(app):
]
validate_html_static_path(app, app.config)
assert app.config.html_static_path == ['_static']
@pytest.mark.sphinx(testroot='html_scaled_image_link')
def test_html_scaled_image_link(app):
app.build()
context = (app.outdir / 'index.html').read_text()
# no scaled parameters
assert re.search('\n<img alt="_images/img.png" src="_images/img.png" />', context)
# scaled_image_link
assert re.search('\n<a class="reference internal image-reference" href="_images/img.png">'
'<img alt="_images/img.png" src="_images/img.png" style="[^"]+" /></a>',
context)
# no-scaled-link class disables the feature
assert re.search('\n<img alt="_images/img.png" class="no-scaled-link"'
' src="_images/img.png" style="[^"]+" />',
context)

View File

@@ -113,7 +113,7 @@ def test_build_latex_doc(app, status, warning, engine, docclass):
@pytest.mark.sphinx('latex')
def test_writer(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'sphinxtests.tex').text(encoding='utf8')
result = (app.outdir / 'sphinxtests.tex').read_text()
assert ('\\begin{sphinxfigure-in-table}\n\\centering\n\\capstart\n'
'\\noindent\\sphinxincludegraphics{{img}.png}\n'
@@ -156,7 +156,7 @@ def test_latex_warnings(app, status, warning):
@pytest.mark.sphinx('latex', testroot='basic')
def test_latex_basic(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -168,7 +168,7 @@ def test_latex_basic(app, status, warning):
@pytest.mark.sphinx('latex', testroot='basic', confoverrides={'language': 'zh'})
def test_latex_additional_settings_for_language_code(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -178,7 +178,7 @@ def test_latex_additional_settings_for_language_code(app, status, warning):
@pytest.mark.sphinx('latex', testroot='basic', confoverrides={'language': 'el'})
def test_latex_additional_settings_for_greek(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -189,7 +189,7 @@ def test_latex_additional_settings_for_greek(app, status, warning):
@pytest.mark.sphinx('latex', testroot='latex-title')
def test_latex_title_after_admonitions(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -200,7 +200,7 @@ def test_latex_title_after_admonitions(app, status, warning):
confoverrides={'release': '1.0'})
def test_latex_release(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -212,7 +212,7 @@ def test_latex_release(app, status, warning):
confoverrides={'numfig': True})
def test_numref(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -238,7 +238,7 @@ def test_numref(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }}' in result
assert r'\addto\captionsenglish{\renewcommand{\tablename}{Table }}' in result
@@ -254,7 +254,7 @@ def test_numref(app, status, warning):
'section': 'SECTION-%s'}})
def test_numref_with_prefix1(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -286,7 +286,7 @@ def test_numref_with_prefix1(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\addto\captionsenglish{\renewcommand{\figurename}{Figure:}}' in result
assert r'\addto\captionsenglish{\renewcommand{\tablename}{Tab\_}}' in result
@@ -302,7 +302,7 @@ def test_numref_with_prefix1(app, status, warning):
'section': 'SECTION_%s_'}})
def test_numref_with_prefix2(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -328,7 +328,7 @@ def test_numref_with_prefix2(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\addto\captionsenglish{\renewcommand{\figurename}{Figure:}}' in result
assert r'\def\fnum@figure{\figurename\thefigure{}.}' in result
@@ -342,7 +342,7 @@ def test_numref_with_prefix2(app, status, warning):
confoverrides={'numfig': True, 'language': 'ja'})
def test_numref_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -368,7 +368,7 @@ def test_numref_with_language_ja(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert '\\@iden{\\renewcommand{\\figurename}{図 }}' in result
assert '\\@iden{\\renewcommand{\\tablename}{表 }}' in result
@@ -379,10 +379,10 @@ def test_numref_with_language_ja(app, status, warning):
def test_latex_obey_numfig_is_false(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxManual.tex').read_text()
assert '\\usepackage{sphinx}' in result
result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxHowTo.tex').read_text()
assert '\\usepackage{sphinx}' in result
@@ -392,10 +392,10 @@ def test_latex_obey_numfig_is_false(app, status, warning):
def test_latex_obey_numfig_secnum_depth_is_zero(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxManual.tex').read_text()
assert '\\usepackage[,nonumfigreset,mathnumfig]{sphinx}' in result
result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxHowTo.tex').read_text()
assert '\\usepackage[,nonumfigreset,mathnumfig]{sphinx}' in result
@@ -405,10 +405,10 @@ def test_latex_obey_numfig_secnum_depth_is_zero(app, status, warning):
def test_latex_obey_numfig_secnum_depth_is_two(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxManual.tex').read_text()
assert '\\usepackage[,numfigreset=2,mathnumfig]{sphinx}' in result
result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxHowTo.tex').read_text()
assert '\\usepackage[,numfigreset=3,mathnumfig]{sphinx}' in result
@@ -418,10 +418,10 @@ def test_latex_obey_numfig_secnum_depth_is_two(app, status, warning):
def test_latex_obey_numfig_but_math_numfig_false(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxManual.tex').read_text()
assert '\\usepackage[,numfigreset=1]{sphinx}' in result
result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8')
result = (app.outdir / 'SphinxHowTo.tex').read_text()
assert '\\usepackage[,numfigreset=2]{sphinx}' in result
@@ -430,7 +430,7 @@ def test_latex_add_latex_package(app, status, warning):
app.add_latex_package('foo')
app.add_latex_package('bar', 'baz')
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
result = (app.outdir / 'test.tex').read_text()
assert '\\usepackage{foo}' in result
assert '\\usepackage[baz]{bar}' in result
@@ -438,7 +438,7 @@ def test_latex_add_latex_package(app, status, warning):
@pytest.mark.sphinx('latex', testroot='latex-babel')
def test_babel_with_no_language_settings(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -451,7 +451,7 @@ def test_babel_with_no_language_settings(app, status, warning):
assert '\\shorthandoff' not in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{page}' in result
assert r'\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -463,7 +463,7 @@ def test_babel_with_no_language_settings(app, status, warning):
confoverrides={'language': 'de'})
def test_babel_with_language_de(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -476,7 +476,7 @@ def test_babel_with_language_de(app, status, warning):
assert '\\shorthandoff{"}' in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{Seite}' in result
assert r'\addto\captionsngerman{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -488,7 +488,7 @@ def test_babel_with_language_de(app, status, warning):
confoverrides={'language': 'ru'})
def test_babel_with_language_ru(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -501,7 +501,7 @@ def test_babel_with_language_ru(app, status, warning):
assert '\\shorthandoff{"}' in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{страница}' in result
assert r'\addto\captionsrussian{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -513,7 +513,7 @@ def test_babel_with_language_ru(app, status, warning):
confoverrides={'language': 'tr'})
def test_babel_with_language_tr(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -526,7 +526,7 @@ def test_babel_with_language_tr(app, status, warning):
assert '\\shorthandoff{=}' in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{sayfa}' in result
assert r'\addto\captionsturkish{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -538,7 +538,7 @@ def test_babel_with_language_tr(app, status, warning):
confoverrides={'language': 'ja'})
def test_babel_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -550,7 +550,7 @@ def test_babel_with_language_ja(app, status, warning):
assert '\\shorthandoff' not in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{ページ}' in result
assert '\\@iden{\\renewcommand{\\figurename}{Fig.\\@{} }}' in result
@@ -562,7 +562,7 @@ def test_babel_with_language_ja(app, status, warning):
confoverrides={'language': 'unknown'})
def test_babel_with_unknown_language(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -577,7 +577,7 @@ def test_babel_with_unknown_language(app, status, warning):
assert "WARNING: no Babel option known for language 'unknown'" in warning.getvalue()
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{page}' in result
assert r'\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -589,7 +589,7 @@ def test_babel_with_unknown_language(app, status, warning):
confoverrides={'language': 'de', 'latex_engine': 'lualatex'})
def test_polyglossia_with_language_de(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -603,7 +603,7 @@ def test_polyglossia_with_language_de(app, status, warning):
assert '\\shorthandoff' not in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{Seite}' in result
assert r'\addto\captionsgerman{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -615,7 +615,7 @@ def test_polyglossia_with_language_de(app, status, warning):
confoverrides={'language': 'de-1901', 'latex_engine': 'lualatex'})
def test_polyglossia_with_language_de_1901(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -629,7 +629,7 @@ def test_polyglossia_with_language_de_1901(app, status, warning):
assert '\\shorthandoff' not in result
# sphinxmessages.sty
result = (app.outdir / 'sphinxmessages.sty').text(encoding='utf8')
result = (app.outdir / 'sphinxmessages.sty').read_text()
print(result)
assert r'\def\pageautorefname{page}' in result
assert r'\addto\captionsgerman{\renewcommand{\figurename}{Fig.\@{} }}' in result
@@ -639,7 +639,7 @@ def test_polyglossia_with_language_de_1901(app, status, warning):
@pytest.mark.sphinx('latex')
def test_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'sphinxtests.tex').text(encoding='utf8')
result = (app.outdir / 'sphinxtests.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -666,7 +666,7 @@ def test_footnote(app, status, warning):
@pytest.mark.sphinx('latex', testroot='footnotes')
def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -707,7 +707,7 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
confoverrides={'latex_show_urls': 'inline'})
def test_latex_show_urls_is_inline(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -752,7 +752,7 @@ def test_latex_show_urls_is_inline(app, status, warning):
confoverrides={'latex_show_urls': 'footnote'})
def test_latex_show_urls_is_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -806,7 +806,7 @@ def test_latex_show_urls_is_footnote(app, status, warning):
confoverrides={'latex_show_urls': 'no'})
def test_latex_show_urls_is_no(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -856,7 +856,7 @@ def test_latex_show_urls_footnote_and_substitutions(app, status, warning):
@pytest.mark.sphinx('latex', testroot='image-in-section')
def test_image_in_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -882,7 +882,7 @@ def test_latex_logo_if_not_found(app, status, warning):
@pytest.mark.sphinx('latex', testroot='toctree-maxdepth')
def test_toctree_maxdepth_manual(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -899,7 +899,7 @@ def test_toctree_maxdepth_manual(app, status, warning):
]})
def test_toctree_maxdepth_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -913,7 +913,7 @@ def test_toctree_maxdepth_howto(app, status, warning):
confoverrides={'master_doc': 'foo'})
def test_toctree_not_found(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -927,7 +927,7 @@ def test_toctree_not_found(app, status, warning):
confoverrides={'master_doc': 'bar'})
def test_toctree_without_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -940,7 +940,7 @@ def test_toctree_without_maxdepth(app, status, warning):
confoverrides={'master_doc': 'qux'})
def test_toctree_with_deeper_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -953,7 +953,7 @@ def test_toctree_with_deeper_maxdepth(app, status, warning):
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')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -965,7 +965,7 @@ def test_latex_toplevel_sectioning_is_None(app, status, warning):
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')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -983,7 +983,7 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning):
]})
def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -997,7 +997,7 @@ def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning):
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')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -1013,7 +1013,7 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning):
]})
def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -1025,7 +1025,7 @@ def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning):
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')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -1036,7 +1036,7 @@ def test_latex_toplevel_sectioning_is_section(app, status, warning):
@pytest.mark.sphinx('latex', testroot='maxlistdepth')
def test_maxlistdepth_at_ten(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
print(status.getvalue())
print(warning.getvalue())
@@ -1049,14 +1049,14 @@ def test_maxlistdepth_at_ten(app, status, warning):
@pytest.mark.test_params(shared_result='latex-table')
def test_latex_table_tabulars(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
tables = {}
for chap in re.split(r'\\(?:section|chapter){', result)[1:]:
sectname, content = chap.split('}', 1)
tables[sectname] = content.strip()
def get_expected(name):
return (app.srcdir / 'expects' / (name + '.tex')).text().strip()
return (app.srcdir / 'expects' / (name + '.tex')).read_text().strip()
# simple_table
actual = tables['simple table']
@@ -1120,14 +1120,14 @@ def test_latex_table_tabulars(app, status, warning):
@pytest.mark.test_params(shared_result='latex-table')
def test_latex_table_longtable(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
tables = {}
for chap in re.split(r'\\(?:section|chapter){', result)[1:]:
sectname, content = chap.split('}', 1)
tables[sectname] = content.strip()
def get_expected(name):
return (app.srcdir / 'expects' / (name + '.tex')).text().strip()
return (app.srcdir / 'expects' / (name + '.tex')).read_text().strip()
# longtable
actual = tables['longtable']
@@ -1181,14 +1181,14 @@ def test_latex_table_longtable(app, status, warning):
@pytest.mark.test_params(shared_result='latex-table')
def test_latex_table_complex_tables(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
tables = {}
for chap in re.split(r'\\(?:section|renewcommand){', result)[1:]:
sectname, content = chap.split('}', 1)
tables[sectname] = content.strip()
def get_expected(name):
return (app.srcdir / 'expects' / (name + '.tex')).text().strip()
return (app.srcdir / 'expects' / (name + '.tex')).read_text().strip()
# grid table
actual = tables['grid table']
@@ -1205,7 +1205,7 @@ def test_latex_table_complex_tables(app, status, warning):
confoverrides={'templates_path': ['_mytemplates/latex']})
def test_latex_table_custom_template_caseA(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert 'SALUT LES COPAINS' in result
@@ -1213,7 +1213,7 @@ def test_latex_table_custom_template_caseA(app, status, warning):
confoverrides={'templates_path': ['_mytemplates']})
def test_latex_table_custom_template_caseB(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert 'SALUT LES COPAINS' not in result
@@ -1221,14 +1221,14 @@ def test_latex_table_custom_template_caseB(app, status, warning):
@pytest.mark.test_params(shared_result='latex-table')
def test_latex_table_custom_template_caseC(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert 'SALUT LES COPAINS' not in result
@pytest.mark.sphinx('latex', testroot='directives-raw')
def test_latex_raw_directive(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
# standard case
assert 'standalone raw directive (HTML)' not in result
@@ -1244,7 +1244,7 @@ def test_latex_raw_directive(app, status, warning):
def test_latex_images(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
# images are copied
assert '\\sphinxincludegraphics{{python-logo}.png}' in result
@@ -1268,7 +1268,7 @@ def test_latex_images(app, status, warning):
def test_latex_index(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert ('A \\index{famous@\\spxentry{famous}}famous '
'\\index{equation@\\spxentry{equation}}equation:\n' in result)
assert ('\n\\index{Einstein@\\spxentry{Einstein}}'
@@ -1282,8 +1282,8 @@ def test_latex_index(app, status, warning):
def test_latex_equations(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
expected = (app.srcdir / 'expects' / 'latex-equations.tex').text().strip()
result = (app.outdir / 'python.tex').read_text()
expected = (app.srcdir / 'expects' / 'latex-equations.tex').read_text().strip()
assert expected in result
@@ -1292,7 +1292,7 @@ def test_latex_equations(app, status, warning):
def test_latex_image_in_parsed_literal(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert ('{\\sphinxunactivateextrasandspace \\raisebox{-0.5\\height}'
'{\\sphinxincludegraphics[height=2.00000cm]{{pic}.png}}'
'}AFTER') in result
@@ -1302,7 +1302,7 @@ def test_latex_image_in_parsed_literal(app, status, warning):
def test_latex_nested_enumerated_list(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert ('\\sphinxsetlistlabels{\\arabic}{enumi}{enumii}{}{.}%\n'
'\\setcounter{enumi}{4}\n' in result)
assert ('\\sphinxsetlistlabels{\\alph}{enumii}{enumiii}{}{.}%\n'
@@ -1319,7 +1319,7 @@ def test_latex_nested_enumerated_list(app, status, warning):
def test_latex_thebibliography(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(result)
assert ('\\begin{sphinxthebibliography}{AuthorYe}\n'
'\\bibitem[AuthorYear]{index:authoryear}\n'
@@ -1332,7 +1332,7 @@ def test_latex_thebibliography(app, status, warning):
def test_latex_glossary(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert ('\\item[{änhlich\\index{änhlich@\\spxentry{änhlich}|spxpagem}'
r'\phantomsection'
r'\label{\detokenize{index:term-anhlich}}}] \leavevmode' in result)
@@ -1356,7 +1356,7 @@ def test_latex_glossary(app, status, warning):
def test_latex_labels(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
# figures
assert (r'\caption{labeled figure}'
@@ -1403,7 +1403,7 @@ def test_latex_labels(app, status, warning):
@pytest.mark.sphinx('latex', testroot='latex-figure-in-admonition')
def test_latex_figure_in_admonition(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert(r'\begin{figure}[H]' in result)
@@ -1433,7 +1433,7 @@ def test_includegraphics_oversized(app, status, warning):
@pytest.mark.sphinx('latex', testroot='index_on_title')
def test_index_on_title(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
assert ('\\chapter{Test for index in top level title}\n'
'\\label{\\detokenize{contents:test-for-index-in-top-level-title}}'
'\\index{index@\\spxentry{index}}\n'
@@ -1444,7 +1444,7 @@ def test_index_on_title(app, status, warning):
confoverrides={'latex_engine': 'pdflatex'})
def test_texescape_for_non_unicode_supported_engine(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text()
result = (app.outdir / 'python.tex').read_text()
print(result)
assert 'script small e: e' in result
assert 'double struck italic small i: i' in result
@@ -1456,7 +1456,7 @@ def test_texescape_for_non_unicode_supported_engine(app, status, warning):
confoverrides={'latex_engine': 'xelatex'})
def test_texescape_for_unicode_supported_engine(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text()
result = (app.outdir / 'python.tex').read_text()
print(result)
assert 'script small e: e' in result
assert 'double struck italic small i: i' in result
@@ -1468,7 +1468,7 @@ def test_texescape_for_unicode_supported_engine(app, status, warning):
confoverrides={'latex_elements': {'extrapackages': r'\usepackage{foo}'}})
def test_latex_elements_extrapackages(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text()
result = (app.outdir / 'test.tex').read_text()
assert r'\usepackage{foo}' in result

View File

@@ -8,6 +8,8 @@
:license: BSD, see LICENSE for details.
"""
import json
import re
from unittest import mock
import pytest
@@ -17,10 +19,10 @@ def test_defaults(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'output.txt').exists()
content = (app.outdir / 'output.txt').text()
content = (app.outdir / 'output.txt').read_text()
print(content)
# looking for '#top' and 'does-not-exist' not found should fail
# looking for '#top' and '#does-not-exist' not found should fail
assert "Anchor 'top' not found" in content
assert "Anchor 'does-not-exist' not found" in content
# looking for non-existent URL should fail
@@ -31,6 +33,58 @@ def test_defaults(app, status, warning):
assert len(content.splitlines()) == 5
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
def test_defaults_json(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'output.json').exists()
content = (app.outdir / 'output.json').read_text()
print(content)
rows = [json.loads(x) for x in content.splitlines()]
row = rows[0]
for attr in ["filename", "lineno", "status", "code", "uri",
"info"]:
assert attr in row
assert len(content.splitlines()) == 8
assert len(rows) == 8
# the output order of the rows is not stable
# due to possible variance in network latency
rowsby = {row["uri"]:row for row in rows}
assert rowsby["https://www.google.com#!bar"] == {
'filename': 'links.txt',
'lineno': 10,
'status': 'working',
'code': 0,
'uri': 'https://www.google.com#!bar',
'info': ''
}
# looking for non-existent URL should fail
dnerow = rowsby['https://localhost:7777/doesnotexist']
assert dnerow['filename'] == 'links.txt'
assert dnerow['lineno'] == 13
assert dnerow['status'] == 'broken'
assert dnerow['code'] == 0
assert dnerow['uri'] == 'https://localhost:7777/doesnotexist'
assert rowsby['https://www.google.com/image2.png'] == {
'filename': 'links.txt',
'lineno': 16,
'status': 'broken',
'code': 0,
'uri': 'https://www.google.com/image2.png',
'info': '404 Client Error: Not Found for url: https://www.google.com/image2.png'
}
# looking for '#top' and '#does-not-exist' not found should fail
assert "Anchor 'top' not found" == \
rowsby["https://www.google.com/#top"]["info"]
assert "Anchor 'does-not-exist' not found" == \
rowsby["http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist"]["info"]
# images should fail
assert "Not Found for url: https://www.google.com/image.png" in \
rowsby["https://www.google.com/image.png"]["info"]
@pytest.mark.sphinx(
'linkcheck', testroot='linkcheck', freshenv=True,
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"],
@@ -44,7 +98,7 @@ def test_anchors_ignored(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'output.txt').exists()
content = (app.outdir / 'output.txt').text()
content = (app.outdir / 'output.txt').read_text()
# expect all ok when excluding #top
assert not content

View File

@@ -19,7 +19,7 @@ def test_all(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'sphinxtests.1').exists()
content = (app.outdir / 'sphinxtests.1').text()
content = (app.outdir / 'sphinxtests.1').read_text()
assert r'\fBprint \fP\fIi\fP\fB\en\fP' in content
assert r'\fBmanpage\en\fP' in content
@@ -33,7 +33,7 @@ def test_all(app, status, warning):
@pytest.mark.sphinx('man', testroot='directive-code')
def test_captioned_code_block(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.1').text()
content = (app.outdir / 'python.1').read_text()
assert ('.sp\n'
'caption \\fItest\\fP rb\n'
@@ -64,5 +64,5 @@ def test_default_man_pages():
@pytest.mark.sphinx('man', testroot='markup-rubric')
def test_rubric(app, status, warning):
app.build()
content = (app.outdir / 'python.1').text()
content = (app.outdir / 'python.1').read_text()
assert 'This is a rubric\n' in content

View File

@@ -49,7 +49,7 @@ def test_texinfo_warnings(app, status, warning):
def test_texinfo(app, status, warning):
TexinfoTranslator.ignore_missing_images = True
app.builder.build_all()
result = (app.outdir / 'sphinxtests.texi').text(encoding='utf8')
result = (app.outdir / 'sphinxtests.texi').read_text()
assert ('@anchor{markup doc}@anchor{11}'
'@anchor{markup id1}@anchor{12}'
'@anchor{markup testing-various-markup}@anchor{13}' in result)
@@ -70,7 +70,7 @@ def test_texinfo(app, status, warning):
def test_texinfo_rubric(app, status, warning):
app.build()
output = (app.outdir / 'python.texi').text()
output = (app.outdir / 'python.texi').read_text()
assert '@heading This is a rubric' in output
assert '@heading This is a multiline rubric' in output
@@ -79,7 +79,7 @@ def test_texinfo_rubric(app, status, warning):
def test_texinfo_citation(app, status, warning):
app.builder.build_all()
output = (app.outdir / 'python.texi').text()
output = (app.outdir / 'python.texi').read_text()
assert 'This is a citation ref; @ref{1,,[CITE1]} and @ref{2,,[CITE2]}.' in output
assert ('@anchor{index cite1}@anchor{1}@w{(CITE1)} \n'
'This is a citation\n') in output

View File

@@ -26,7 +26,7 @@ def with_text_app(*args, **kw):
@with_text_app()
def test_maxwitdh_with_prefix(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'maxwidth.txt').text()
result = (app.outdir / 'maxwidth.txt').read_text()
lines = result.splitlines()
line_widths = [column_width(line) for line in lines]
@@ -49,7 +49,7 @@ def test_maxwitdh_with_prefix(app, status, warning):
def test_lineblock(app, status, warning):
# regression test for #1109: need empty line after line block
app.builder.build_update()
result = (app.outdir / 'lineblock.txt').text()
result = (app.outdir / 'lineblock.txt').read_text()
expect = (
"* one\n"
"\n"
@@ -64,7 +64,7 @@ def test_lineblock(app, status, warning):
@with_text_app()
def test_nonascii_title_line(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'nonascii_title.txt').text()
result = (app.outdir / 'nonascii_title.txt').read_text()
expect_underline = '*********'
result_underline = result.splitlines()[1].strip()
assert expect_underline == result_underline
@@ -73,7 +73,7 @@ def test_nonascii_title_line(app, status, warning):
@with_text_app()
def test_nonascii_table(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'nonascii_table.txt').text()
result = (app.outdir / 'nonascii_table.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
line_widths = [column_width(line) for line in lines]
assert len(set(line_widths)) == 1 # same widths
@@ -82,7 +82,7 @@ def test_nonascii_table(app, status, warning):
@with_text_app()
def test_nonascii_maxwidth(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'nonascii_maxwidth.txt').text()
result = (app.outdir / 'nonascii_maxwidth.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
line_widths = [column_width(line) for line in lines]
assert max(line_widths) < MAXWIDTH
@@ -126,7 +126,7 @@ def test_table_cell():
@with_text_app()
def test_table_with_empty_cell(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'table.txt').text()
result = (app.outdir / 'table.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert lines[0] == "+-------+-------+"
assert lines[1] == "| XXX | XXX |"
@@ -140,7 +140,7 @@ def test_table_with_empty_cell(app, status, warning):
@with_text_app()
def test_table_with_rowspan(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'table_rowspan.txt').text()
result = (app.outdir / 'table_rowspan.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert lines[0] == "+-------+-------+"
assert lines[1] == "| XXXXXXXXX |"
@@ -154,7 +154,7 @@ def test_table_with_rowspan(app, status, warning):
@with_text_app()
def test_table_with_colspan(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'table_colspan.txt').text()
result = (app.outdir / 'table_colspan.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert lines[0] == "+-------+-------+"
assert lines[1] == "| XXX | XXX |"
@@ -168,7 +168,7 @@ def test_table_with_colspan(app, status, warning):
@with_text_app()
def test_table_with_colspan_left(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'table_colspan_left.txt').text()
result = (app.outdir / 'table_colspan_left.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert lines[0] == "+-------+-------+"
assert lines[1] == "| XXX | XXX |"
@@ -182,7 +182,7 @@ def test_table_with_colspan_left(app, status, warning):
@with_text_app()
def test_table_with_colspan_and_rowspan(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'table_colspan_and_rowspan.txt').text()
result = (app.outdir / 'table_colspan_and_rowspan.txt').read_text()
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert result
assert lines[0] == "+-------+-------+-------+"
@@ -197,7 +197,7 @@ def test_table_with_colspan_and_rowspan(app, status, warning):
@with_text_app()
def test_list_items_in_admonition(app, status, warning):
app.builder.build_update()
result = (app.outdir / 'listitems.txt').text()
result = (app.outdir / 'listitems.txt').read_text()
lines = [line.rstrip() for line in result.splitlines()]
assert lines[0] == "See also:"
assert lines[1] == ""
@@ -209,7 +209,7 @@ def test_list_items_in_admonition(app, status, warning):
@with_text_app()
def test_secnums(app, status, warning):
app.builder.build_all()
index = (app.outdir / 'index.txt').text(encoding='utf8')
index = (app.outdir / 'index.txt').read_text()
lines = index.splitlines()
assert lines[0] == "* 1. Section A"
assert lines[1] == ""
@@ -218,7 +218,7 @@ def test_secnums(app, status, warning):
assert lines[4] == " * 2.1. Sub Ba"
assert lines[5] == ""
assert lines[6] == " * 2.2. Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
doc2 = (app.outdir / 'doc2.txt').read_text()
expect = (
"2. Section B\n"
"************\n"
@@ -235,7 +235,7 @@ def test_secnums(app, status, warning):
app.config.text_secnumber_suffix = " "
app.builder.build_all()
index = (app.outdir / 'index.txt').text(encoding='utf8')
index = (app.outdir / 'index.txt').read_text()
lines = index.splitlines()
assert lines[0] == "* 1 Section A"
assert lines[1] == ""
@@ -244,7 +244,7 @@ def test_secnums(app, status, warning):
assert lines[4] == " * 2.1 Sub Ba"
assert lines[5] == ""
assert lines[6] == " * 2.2 Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
doc2 = (app.outdir / 'doc2.txt').read_text()
expect = (
"2 Section B\n"
"***********\n"
@@ -261,7 +261,7 @@ def test_secnums(app, status, warning):
app.config.text_add_secnumbers = False
app.builder.build_all()
index = (app.outdir / 'index.txt').text(encoding='utf8')
index = (app.outdir / 'index.txt').read_text()
lines = index.splitlines()
assert lines[0] == "* Section A"
assert lines[1] == ""
@@ -270,7 +270,7 @@ def test_secnums(app, status, warning):
assert lines[4] == " * Sub Ba"
assert lines[5] == ""
assert lines[6] == " * Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
doc2 = (app.outdir / 'doc2.txt').read_text()
expect = (
"Section B\n"
"*********\n"

View File

@@ -32,5 +32,5 @@ def expect_date(request, monkeypatch):
@pytest.mark.sphinx('html', testroot='correct-year')
def test_correct_year(expect_date, app):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert expect_date in content

View File

@@ -36,7 +36,7 @@ def test_LiteralIncludeReader(literal_inc_path):
options = {'lineno-match': True}
reader = LiteralIncludeReader(literal_inc_path, options, DUMMY_CONFIG)
content, lines = reader.read()
assert content == literal_inc_path.text()
assert content == literal_inc_path.read_text()
assert lines == 13
assert reader.lineno_start == 1
@@ -46,7 +46,7 @@ def test_LiteralIncludeReader_lineno_start(literal_inc_path):
options = {'lineno-start': 4}
reader = LiteralIncludeReader(literal_inc_path, options, DUMMY_CONFIG)
content, lines = reader.read()
assert content == literal_inc_path.text()
assert content == literal_inc_path.read_text()
assert lines == 13
assert reader.lineno_start == 4
@@ -324,7 +324,7 @@ def test_force_option(app, status, warning):
@pytest.mark.sphinx('html', testroot='directive-code')
def test_code_block_caption_html(app, status, warning):
app.builder.build(['caption'])
html = (app.outdir / 'caption.html').text()
html = (app.outdir / 'caption.html').read_text()
caption = ('<div class="code-block-caption">'
'<span class="caption-number">Listing 1 </span>'
'<span class="caption-text">caption <em>test</em> rb'
@@ -336,7 +336,7 @@ def test_code_block_caption_html(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'python.tex').text()
latex = (app.outdir / 'python.tex').read_text()
caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstyleemphasis{test} rb}'
label = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:id1}}}'
link = '\\hyperref[\\detokenize{caption:name-test-rb}]' \
@@ -349,7 +349,7 @@ def test_code_block_caption_latex(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_namedlink_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'python.tex').text()
latex = (app.outdir / 'python.tex').read_text()
label1 = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:name-test-rb}}}'
link1 = '\\hyperref[\\detokenize{caption:name-test-rb}]'\
'{\\sphinxcrossref{\\DUrole{std,std-ref}{Ruby}}'
@@ -366,7 +366,7 @@ def test_code_block_namedlink_latex(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_emphasize_latex(app, status, warning):
app.builder.build(['emphasize'])
latex = (app.outdir / 'python.tex').text().replace('\r\n', '\n')
latex = (app.outdir / 'python.tex').read_text().replace('\r\n', '\n')
includes = '\\fvset{hllines={, 5, 6, 13, 14, 15, 24, 25, 26,}}%\n'
assert includes in latex
includes = '\\end{sphinxVerbatim}\n\\sphinxresetverbatimhllines\n'
@@ -379,7 +379,7 @@ def test_literal_include(app, status, warning):
et = etree_parse(app.outdir / 'index.xml')
secs = et.findall('./section/section')
literal_include = secs[1].findall('literal_block')
literal_src = (app.srcdir / 'literal.inc').text()
literal_src = (app.srcdir / 'literal.inc').read_text()
assert len(literal_include) > 0
actual = literal_include[0].text
assert actual == literal_src
@@ -412,7 +412,7 @@ def test_literal_include_block_start_with_comment_or_brank(app, status, warning)
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_linenos(app, status, warning):
app.builder.build(['linenos'])
html = (app.outdir / 'linenos.html').text()
html = (app.outdir / 'linenos.html').read_text()
# :linenos:
assert ('<td class="linenos"><div class="linenodiv"><pre>'
@@ -458,7 +458,7 @@ def test_literal_include_linenos(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_file_whole_of_emptyline(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'python.tex').text().replace('\r\n', '\n')
latex = (app.outdir / 'python.tex').read_text().replace('\r\n', '\n')
includes = (
'\\begin{sphinxVerbatim}'
'[commandchars=\\\\\\{\\},numbers=left,firstnumber=1,stepnumber=1]\n'
@@ -472,7 +472,7 @@ def test_literalinclude_file_whole_of_emptyline(app, status, warning):
@pytest.mark.sphinx('html', testroot='directive-code')
def test_literalinclude_caption_html(app, status, warning):
app.builder.build('index')
html = (app.outdir / 'caption.html').text()
html = (app.outdir / 'caption.html').read_text()
caption = ('<div class="code-block-caption">'
'<span class="caption-number">Listing 2 </span>'
'<span class="caption-text">caption <strong>test</strong> py'
@@ -484,7 +484,7 @@ def test_literalinclude_caption_html(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'python.tex').text()
latex = (app.outdir / 'python.tex').read_text()
caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstylestrong{test} py}'
label = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:id2}}}'
link = '\\hyperref[\\detokenize{caption:name-test-py}]' \
@@ -497,7 +497,7 @@ def test_literalinclude_caption_latex(app, status, warning):
@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_namedlink_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'python.tex').text()
latex = (app.outdir / 'python.tex').read_text()
label1 = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:name-test-py}}}'
link1 = '\\hyperref[\\detokenize{caption:name-test-py}]'\
'{\\sphinxcrossref{\\DUrole{std,std-ref}{Python}}'
@@ -584,7 +584,7 @@ def test_code_block_highlighted(app, status, warning):
@pytest.mark.sphinx('html', testroot='directive-code')
def test_linenothreshold(app, status, warning):
app.builder.build(['linenothreshold'])
html = (app.outdir / 'linenothreshold.html').text()
html = (app.outdir / 'linenothreshold.html').read_text()
lineos_head = '<td class="linenos"><div class="linenodiv"><pre>'
lineos_tail = '</pre></div></td>'

View File

@@ -126,6 +126,23 @@ def test_toctree_glob_and_url(app):
includefiles=[])
@pytest.mark.sphinx(testroot='toctree-glob')
def test_reversed_toctree(app):
text = (".. toctree::\n"
" :reversed:\n"
"\n"
" foo\n"
" bar/index\n"
" baz\n")
app.env.find_files(app.config, app.builder)
doctree = restructuredtext.parse(app, text, 'index')
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
assert_node(doctree[0][0],
entries=[(None, 'baz'), (None, 'bar/index'), (None, 'foo')],
includefiles=['baz', 'bar/index', 'foo'])
@pytest.mark.sphinx(testroot='toctree-glob')
def test_toctree_twice(app):
text = (".. toctree::\n"

View File

@@ -786,11 +786,78 @@ def test_xref_parsing():
# raise DefinitionError("")
def filter_warnings(warning, file):
lines = warning.getvalue().split("\n");
res = [l for l in lines if "domain-cpp" in l and "{}.rst".format(file) in l and
"WARNING: document isn't included in any toctree" not in l]
print("Filtered warnings for file '{}':".format(file))
for w in res:
print(w)
return res
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'nitpicky': True})
def test_build_domain_cpp_multi_decl_lookup(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "lookup-key-overload")
assert len(ws) == 0
ws = filter_warnings(warning, "multi-decl-lookup")
assert len(ws) == 0
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'nitpicky': True})
def test_build_domain_cpp_warn_template_param_qualified_name(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "warn-template-param-qualified-name")
assert len(ws) == 2
assert "WARNING: cpp:type reference target not found: T::typeWarn" in ws[0]
assert "WARNING: cpp:type reference target not found: T::U::typeWarn" in ws[1]
@pytest.mark.sphinx(testroot='domain-cpp')
def test_build_domain_cpp_misuse_of_roles(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "roles-targets-ok")
assert len(ws) == 0
# TODO: properly check for the warnings we expect
ws = filter_warnings(warning, "roles-targets-warn")
# the roles that should be able to generate warnings:
allRoles = ['class', 'struct', 'union', 'func', 'member', 'var', 'type', 'concept', 'enum', 'enumerator']
ok = [ # targetType, okRoles
('class', ['class', 'struct', 'type']),
('union', ['union', 'type']),
('func', ['func', 'type']),
('member', ['member', 'var']),
('type', ['type']),
('concept', ['concept']),
('enum', ['type', 'enum']),
('enumerator', ['enumerator']),
('tParam', ['class', 'struct', 'union', 'func', 'member', 'var', 'type', 'concept', 'enum', 'enumerator', 'functionParam']),
('functionParam', ['member', 'var']),
]
warn = []
for targetType, roles in ok:
txtTargetType = "function" if targetType == "func" else targetType
for r in allRoles:
if r not in roles:
warn.append("WARNING: cpp:{} targets a {} (".format(r, txtTargetType))
warn = list(sorted(warn))
for w in ws:
assert "targets a" in w
ws = [w[w.index("WARNING:"):] for w in ws]
ws = list(sorted(ws))
print("Expected warnings:")
for w in warn:
print(w)
print("Actual warnings:")
for w in ws:
print(w)
for i in range(min(len(warn), len(ws))):
assert ws[i].startswith(warn[i])
assert len(ws) == len(warn)
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
@@ -824,14 +891,14 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
]
f = 'roles.html'
t = (app.outdir / f).text()
t = (app.outdir / f).read_text()
for s in rolePatterns:
check(s, t, f)
for s in parenPatterns:
check(s, t, f)
f = 'any-role.html'
t = (app.outdir / f).text()
t = (app.outdir / f).read_text()
for s in parenPatterns:
check(s, t, f)
@@ -867,14 +934,14 @@ def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, wa
]
f = 'roles.html'
t = (app.outdir / f).text()
t = (app.outdir / f).read_text()
for s in rolePatterns:
check(s, t, f)
for s in parenPatterns:
check(s, t, f)
f = 'any-role.html'
t = (app.outdir / f).text()
t = (app.outdir / f).read_text()
for s in parenPatterns:
check(s, t, f)
@@ -884,7 +951,7 @@ def test_xref_consistency(app, status, warning):
app.builder.build_all()
test = 'xref_consistency.html'
output = (app.outdir / test).text()
output = (app.outdir / test).read_text()
def classes(role, tag):
pattern = (r'{role}-role:.*?'

View File

@@ -14,7 +14,12 @@ import pytest
from docutils import nodes
from sphinx import addnodes
from sphinx.addnodes import (
desc, desc_annotation, desc_content, desc_name,
desc_parameter, desc_parameterlist, desc_signature
)
from sphinx.domains.javascript import JavaScriptDomain
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
@@ -86,22 +91,22 @@ def test_domain_js_objects(app, status, warning):
assert 'module_b.submodule' in modules
assert 'module_b.submodule' in objects
assert objects['module_a.submodule.ModTopLevel'] == ('module', 'class')
assert objects['module_a.submodule.ModTopLevel.mod_child_1'] == ('module', 'method')
assert objects['module_a.submodule.ModTopLevel.mod_child_2'] == ('module', 'method')
assert objects['module_b.submodule.ModTopLevel'] == ('module', 'class')
assert objects['module_a.submodule.ModTopLevel'][2] == 'class'
assert objects['module_a.submodule.ModTopLevel.mod_child_1'][2] == 'method'
assert objects['module_a.submodule.ModTopLevel.mod_child_2'][2] == 'method'
assert objects['module_b.submodule.ModTopLevel'][2] == 'class'
assert objects['TopLevel'] == ('roles', 'class')
assert objects['top_level'] == ('roles', 'function')
assert objects['NestedParentA'] == ('roles', 'class')
assert objects['NestedParentA.child_1'] == ('roles', 'function')
assert objects['NestedParentA.any_child'] == ('roles', 'function')
assert objects['NestedParentA.NestedChildA'] == ('roles', 'class')
assert objects['NestedParentA.NestedChildA.subchild_1'] == ('roles', 'function')
assert objects['NestedParentA.NestedChildA.subchild_2'] == ('roles', 'function')
assert objects['NestedParentA.child_2'] == ('roles', 'function')
assert objects['NestedParentB'] == ('roles', 'class')
assert objects['NestedParentB.child_1'] == ('roles', 'function')
assert objects['TopLevel'][2] == 'class'
assert objects['top_level'][2] == 'function'
assert objects['NestedParentA'][2] == 'class'
assert objects['NestedParentA.child_1'][2] == 'function'
assert objects['NestedParentA.any_child'][2] == 'function'
assert objects['NestedParentA.NestedChildA'][2] == 'class'
assert objects['NestedParentA.NestedChildA.subchild_1'][2] == 'function'
assert objects['NestedParentA.NestedChildA.subchild_2'][2] == 'function'
assert objects['NestedParentA.child_2'][2] == 'function'
assert objects['NestedParentB'][2] == 'class'
assert objects['NestedParentB.child_1'][2] == 'function'
@pytest.mark.sphinx('dummy', testroot='domain-js')
@@ -115,21 +120,28 @@ def test_domain_js_find_obj(app, status, warning):
assert (find_obj(None, None, 'NONEXISTANT', 'class') == (None, None))
assert (find_obj(None, None, 'NestedParentA', 'class') ==
('NestedParentA', ('roles', 'class')))
('NestedParentA', ('roles', 'nestedparenta', 'class')))
assert (find_obj(None, None, 'NestedParentA.NestedChildA', 'class') ==
('NestedParentA.NestedChildA', ('roles', 'class')))
('NestedParentA.NestedChildA',
('roles', 'nestedparenta-nestedchilda', 'class')))
assert (find_obj(None, 'NestedParentA', 'NestedChildA', 'class') ==
('NestedParentA.NestedChildA', ('roles', 'class')))
('NestedParentA.NestedChildA',
('roles', 'nestedparenta-nestedchilda', 'class')))
assert (find_obj(None, None, 'NestedParentA.NestedChildA.subchild_1', 'func') ==
('NestedParentA.NestedChildA.subchild_1', ('roles', 'function')))
('NestedParentA.NestedChildA.subchild_1',
('roles', 'nestedparenta-nestedchilda-subchild-1', 'function')))
assert (find_obj(None, 'NestedParentA', 'NestedChildA.subchild_1', 'func') ==
('NestedParentA.NestedChildA.subchild_1', ('roles', 'function')))
('NestedParentA.NestedChildA.subchild_1',
('roles', 'nestedparenta-nestedchilda-subchild-1', 'function')))
assert (find_obj(None, 'NestedParentA.NestedChildA', 'subchild_1', 'func') ==
('NestedParentA.NestedChildA.subchild_1', ('roles', 'function')))
('NestedParentA.NestedChildA.subchild_1',
('roles', 'nestedparenta-nestedchilda-subchild-1', 'function')))
assert (find_obj('module_a.submodule', 'ModTopLevel', 'mod_child_2', 'meth') ==
('module_a.submodule.ModTopLevel.mod_child_2', ('module', 'method')))
('module_a.submodule.ModTopLevel.mod_child_2',
('module', 'module-a-submodule-modtoplevel-mod-child-2', 'method')))
assert (find_obj('module_b.submodule', 'ModTopLevel', 'module_a.submodule', 'mod') ==
('module_a.submodule', ('module', 'module')))
('module_a.submodule',
('module', 'module-module-a-submodule', 'module')))
def test_get_full_qualified_name():
@@ -158,3 +170,51 @@ def test_get_full_qualified_name():
kwargs = {'js:module': 'module1', 'js:object': 'Class'}
node = nodes.reference(reftarget='func', **kwargs)
assert domain.get_full_qualified_name(node) == 'module1.Class.func'
def test_js_module(app):
text = ".. js:module:: sphinx"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (nodes.target,
addnodes.index))
assert_node(doctree[0], nodes.target, ids=["module-sphinx"])
assert_node(doctree[1], addnodes.index,
entries=[("single", "sphinx (module)", "module-sphinx", "", None)])
def test_js_function(app):
text = ".. js:function:: sum(a, b)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, "sum"],
desc_parameterlist)],
[desc_content, ()])]))
assert_node(doctree[1][0][1], [desc_parameterlist, ([desc_parameter, "a"],
[desc_parameter, "b"])])
assert_node(doctree[0], addnodes.index,
entries=[("single", "sum() (built-in function)", "sum", "", None)])
assert_node(doctree[1], addnodes.desc, domain="js", objtype="function", noindex=False)
def test_js_class(app):
text = ".. js:class:: Application"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_annotation, "class "],
[desc_name, "Application"],
[desc_parameterlist, ()])],
[desc_content, ()])]))
assert_node(doctree[0], addnodes.index,
entries=[("single", "Application() (class)", "application", "", None)])
assert_node(doctree[1], addnodes.desc, domain="js", objtype="class", noindex=False)
def test_js_data(app):
text = ".. js:data:: name"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, desc_name, "name"],
[desc_content, ()])]))
assert_node(doctree[0], addnodes.index,
entries=[("single", "name (global variable or constant)", "name", "", None)])
assert_node(doctree[1], addnodes.desc, domain="js", objtype="data", noindex=False)

View File

@@ -8,6 +8,7 @@
:license: BSD, see LICENSE for details.
"""
import sys
from unittest.mock import Mock
import pytest
@@ -105,19 +106,22 @@ def test_domain_py_xrefs(app, status, warning):
'mod_child_2', 'meth')
assert_refnode(refnodes[4], 'module_a.submodule', 'ModTopLevel',
'module_a.submodule.ModTopLevel.mod_child_1', 'meth')
assert_refnode(refnodes[5], 'module_b.submodule', None,
assert_refnode(refnodes[5], 'module_a.submodule', 'ModTopLevel',
'prop', 'attr')
assert_refnode(refnodes[6], 'module_a.submodule', 'ModTopLevel',
'prop', 'meth')
assert_refnode(refnodes[7], 'module_b.submodule', None,
'ModTopLevel', 'class')
assert_refnode(refnodes[6], 'module_b.submodule', 'ModTopLevel',
assert_refnode(refnodes[8], 'module_b.submodule', 'ModTopLevel',
'ModNoModule', 'class')
assert_refnode(refnodes[7], False, False, 'int', 'class')
assert_refnode(refnodes[8], False, False, 'tuple', 'class')
assert_refnode(refnodes[9], False, False, 'str', 'class')
assert_refnode(refnodes[10], False, False, 'float', 'class')
assert_refnode(refnodes[11], False, False, 'list', 'class')
assert_refnode(refnodes[11], False, False, 'list', 'class')
assert_refnode(refnodes[12], False, False, 'ModTopLevel', 'class')
assert_refnode(refnodes[13], False, False, 'index', 'doc', domain='std')
assert len(refnodes) == 14
assert_refnode(refnodes[9], False, False, 'int', 'class')
assert_refnode(refnodes[10], False, False, 'tuple', 'class')
assert_refnode(refnodes[11], False, False, 'str', 'class')
assert_refnode(refnodes[12], False, False, 'float', 'class')
assert_refnode(refnodes[13], False, False, 'list', 'class')
assert_refnode(refnodes[14], False, False, 'ModTopLevel', 'class')
assert_refnode(refnodes[15], False, False, 'index', 'doc', domain='std')
assert len(refnodes) == 16
doctree = app.env.get_doctree('module_option')
refnodes = list(doctree.traverse(addnodes.pending_xref))
@@ -161,6 +165,21 @@ def test_domain_py_objects(app, status, warning):
assert objects['NestedParentB.child_1'] == ('roles', 'method')
@pytest.mark.sphinx('html', testroot='domain-py')
def test_resolve_xref_for_properties(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'module.html').read_text()
assert ('Link to <a class="reference internal" href="#module_a.submodule.ModTopLevel.prop"'
' title="module_a.submodule.ModTopLevel.prop">'
'<code class="xref py py-attr docutils literal notranslate"><span class="pre">'
'prop</span> <span class="pre">attribute</span></code></a>' in content)
assert ('Link to <a class="reference internal" href="#module_a.submodule.ModTopLevel.prop"'
' title="module_a.submodule.ModTopLevel.prop">'
'<code class="xref py py-meth docutils literal notranslate"><span class="pre">'
'prop</span> <span class="pre">method</span></code></a>' in content)
@pytest.mark.sphinx('dummy', testroot='domain-py')
def test_domain_py_find_obj(app, status, warning):
@@ -223,7 +242,73 @@ def test_pyfunction_signature(app):
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="function",
domain="py", objtype="function", noindex=False)
assert_node(doctree[1][0][1], [desc_parameterlist, desc_parameter, "name: str"])
assert_node(doctree[1][0][1],
[desc_parameterlist, desc_parameter, ("name",
": str")])
def test_pyfunction_signature_full(app):
text = (".. py:function:: hello(a: str, b = 1, *args: str, "
"c: bool = True, **kwargs: str) -> str")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, "hello"],
desc_parameterlist,
[desc_returns, "str"])],
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="function",
domain="py", objtype="function", noindex=False)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, ("a",
": str")],
[desc_parameter, ("b",
"=1")],
[desc_parameter, ("*args",
": str")],
[desc_parameter, ("c",
": bool",
" = True")],
[desc_parameter, ("**kwargs",
": str")])])
@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
def test_pyfunction_signature_full_py38(app):
# case: separator at head
text = ".. py:function:: hello(*, a)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "*"],
[desc_parameter, ("a",
"=None")])])
# case: separator in the middle
text = ".. py:function:: hello(a, /, b, *, c)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "a"],
[desc_parameter, "/"],
[desc_parameter, "b"],
[desc_parameter, "*"],
[desc_parameter, ("c",
"=None")])])
# case: separator in the middle (2)
text = ".. py:function:: hello(a, /, *, b)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "a"],
[desc_parameter, "/"],
[desc_parameter, "*"],
[desc_parameter, ("b",
"=None")])])
# case: separator at tail
text = ".. py:function:: hello(a, /)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "a"],
[desc_parameter, "/"])])
def test_optional_pyfunction_signature(app):
@@ -267,6 +352,20 @@ def test_exceptions_module_is_ignored(app):
def test_pydata_signature(app):
text = (".. py:data:: version\n"
" :type: int\n"
" :value: 1\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, "version"],
[desc_annotation, ": int"],
[desc_annotation, " = 1"])],
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="data",
domain="py", objtype="data", noindex=False)
def test_pydata_signature_old(app):
text = (".. py:data:: version\n"
" :annotation: = 1\n")
doctree = restructuredtext.parse(app, text)
@@ -463,7 +562,9 @@ def test_pystaticmethod(app):
def test_pyattribute(app):
text = (".. py:class:: Class\n"
"\n"
" .. py:attribute:: attr\n")
" .. py:attribute:: attr\n"
" :type: str\n"
" :value: ''\n")
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
@@ -473,7 +574,9 @@ def test_pyattribute(app):
desc)])]))
assert_node(doctree[1][1][0], addnodes.index,
entries=[('single', 'attr (Class attribute)', 'Class.attr', '', None)])
assert_node(doctree[1][1][1], ([desc_signature, desc_name, "attr"],
assert_node(doctree[1][1][1], ([desc_signature, ([desc_name, "attr"],
[desc_annotation, ": str"],
[desc_annotation, " = ''"])],
[desc_content, ()]))
assert 'Class.attr' in domain.objects
assert domain.objects['Class.attr'] == ('index', 'attribute')
@@ -523,3 +626,26 @@ def test_module_index_not_collapsed(app):
('s', [IndexEntry('sphinx', 0, 'index', 'module-sphinx', '', '', '')])],
True
)
@pytest.mark.sphinx(freshenv=True, confoverrides={'modindex_common_prefix': ['sphinx.']})
def test_modindex_common_prefix(app):
text = (".. py:module:: docutils\n"
".. py:module:: sphinx\n"
".. py:module:: sphinx.config\n"
".. py:module:: sphinx.builders\n"
".. py:module:: sphinx.builders.html\n"
".. py:module:: sphinx_intl\n")
restructuredtext.parse(app, text)
index = PythonModuleIndex(app.env.get_domain('py'))
assert index.generate() == (
[('b', [IndexEntry('sphinx.builders', 1, 'index', 'module-sphinx.builders', '', '', ''), # NOQA
IndexEntry('sphinx.builders.html', 2, 'index', 'module-sphinx.builders.html', '', '', '')]), # NOQA
('c', [IndexEntry('sphinx.config', 0, 'index', 'module-sphinx.config', '', '', '')]),
('d', [IndexEntry('docutils', 0, 'index', 'module-docutils', '', '', '')]),
('s', [IndexEntry('sphinx', 0, 'index', 'module-sphinx', '', '', ''),
IndexEntry('sphinx_intl', 0, 'index', 'module-sphinx_intl', '', '', '')])],
True
)

View File

@@ -76,7 +76,7 @@ def test_rst_directive_option(app):
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
"directive-option-foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
@@ -90,7 +90,7 @@ def test_rst_directive_option_with_argument(app):
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
"directive-option-foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
@@ -105,7 +105,7 @@ def test_rst_directive_option_type(app):
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
"directive-option-foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
@@ -121,7 +121,7 @@ def test_rst_directive_and_directive_option(app):
desc)])]))
assert_node(doctree[1][1][0],
entries=[("pair", "foo (directive); :bar: (directive option)",
"directive:option-foo-bar", "", "B")])
"directive-option-foo-bar", "", "B")])
assert_node(doctree[1][1][1], ([desc_signature, desc_name, ":bar:"],
[desc_content, ()]))
assert_node(doctree[1][1][1], addnodes.desc, desctype="directive:option",

View File

@@ -8,11 +8,15 @@
:license: BSD, see LICENSE for details.
"""
import pytest
from unittest import mock
from docutils import nodes
from docutils.nodes import definition, definition_list, definition_list_item, term
from html5lib import HTMLParser
from sphinx import addnodes
from sphinx.addnodes import (
desc, desc_addname, desc_content, desc_name, desc_signature, glossary, index
@@ -20,6 +24,7 @@ from sphinx.addnodes import (
from sphinx.domains.std import StandardDomain
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
from sphinx.util import docutils
def test_process_doc_handle_figure_caption():
@@ -172,6 +177,15 @@ def test_glossary_warning(app, status, warning):
assert ("case3.rst:4: WARNING: glossary term must be preceded by empty line"
in warning.getvalue())
# duplicated terms
text = (".. glossary::\n"
"\n"
" term-case4\n"
" term-case4\n")
restructuredtext.parse(app, text, "case4")
assert ("case4.rst:3: WARNING: duplicate term description of term-case4, "
"other instance in case4" in warning.getvalue())
def test_glossary_comment(app):
text = (".. glossary::\n"
@@ -303,3 +317,59 @@ def test_multiple_cmdoptions(app):
assert ('cmd', '--output') in domain.progoptions
assert domain.progoptions[('cmd', '-o')] == ('index', 'cmdoption-cmd-o')
assert domain.progoptions[('cmd', '--output')] == ('index', 'cmdoption-cmd-o')
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
reason='docutils-0.13 or above is required')
@pytest.mark.sphinx(testroot='productionlist')
def test_productionlist(app, status, warning):
app.builder.build_all()
warnings = warning.getvalue().split("\n");
assert len(warnings) == 2
assert warnings[-1] == ''
assert "Dup2.rst:4: WARNING: duplicate token description of Dup, other instance in Dup1" in warnings[0]
with (app.outdir / 'index.html').open('rb') as f:
etree = HTMLParser(namespaceHTMLElements=False).parse(f)
ul = list(etree.iter('ul'))[1]
cases = []
for li in list(ul):
assert len(list(li)) == 1
p = list(li)[0]
assert p.tag == 'p'
text = str(p.text).strip(' :')
assert len(list(p)) == 1
a = list(p)[0]
assert a.tag == 'a'
link = a.get('href')
assert len(list(a)) == 1
code = list(a)[0]
assert code.tag == 'code'
assert len(list(code)) == 1
span = list(code)[0]
assert span.tag == 'span'
linkText = span.text.strip()
cases.append((text, link, linkText))
assert cases == [
('A', 'Bare.html#grammar-token-_a', 'A'),
('B', 'Bare.html#grammar-token-_b', 'B'),
('P1:A', 'P1.html#grammar-token-p1_a', 'P1:A'),
('P1:B', 'P1.html#grammar-token-p1_b', 'P1:B'),
('P2:A', 'P1.html#grammar-token-p1_a', 'P1:A'),
('P2:B', 'P2.html#grammar-token-p2_b', 'P2:B'),
('Explicit title A, plain', 'Bare.html#grammar-token-_a', 'MyTitle'),
('Explicit title A, colon', 'Bare.html#grammar-token-_a', 'My:Title'),
('Explicit title P1:A, plain', 'P1.html#grammar-token-p1_a', 'MyTitle'),
('Explicit title P1:A, colon', 'P1.html#grammar-token-p1_a', 'My:Title'),
('Tilde A', 'Bare.html#grammar-token-_a', 'A'),
('Tilde P1:A', 'P1.html#grammar-token-p1_a', 'A'),
('Tilde explicit title P1:A', 'P1.html#grammar-token-p1_a', '~MyTitle'),
('Tilde, explicit title P1:A', 'P1.html#grammar-token-p1_a', 'MyTitle'),
('Dup', 'Dup2.html#grammar-token-_dup', 'Dup'),
('FirstLine', 'firstLineRule.html#grammar-token-_firstline', 'FirstLine'),
('SecondLine', 'firstLineRule.html#grammar-token-_secondline', 'SecondLine'),
]
text = (app.outdir / 'LineContinuation.html').read_text()
assert "A</strong> ::= B C D E F G" in text

View File

@@ -112,6 +112,43 @@ def test_create_seealso_index(app):
assert index[2] == ('S', [('Sphinx', [[], [('see also documentation tool', [])], None])])
@pytest.mark.sphinx('dummy', freshenv=True)
def test_create_main_index(app):
text = (".. index:: !docutils\n"
".. index:: docutils\n"
".. index:: pip; install\n"
".. index:: !pip; install\n")
restructuredtext.parse(app, text)
index = IndexEntries(app.env).create_index(app.builder)
assert len(index) == 2
assert index[0] == ('D', [('docutils', [[('main', '#index-0'),
('', '#index-1')], [], None])])
assert index[1] == ('P', [('pip', [[], [('install', [('main', '#index-3'),
('', '#index-2')])], None])])
@pytest.mark.sphinx('dummy', freshenv=True)
def test_create_index_with_name(app):
text = (".. index:: single: docutils\n"
" :name: ref1\n"
".. index:: single: Python\n"
" :name: ref2\n"
".. index:: Sphinx\n")
restructuredtext.parse(app, text)
index = IndexEntries(app.env).create_index(app.builder)
# check index is created correctly
assert len(index) == 3
assert index[0] == ('D', [('docutils', [[('', '#ref1')], [], None])])
assert index[1] == ('P', [('Python', [[('', '#ref2')], [], None])])
assert index[2] == ('S', [('Sphinx', [[('', '#index-0')], [], None])])
# check the reference labels are created correctly
std = app.env.get_domain('std')
assert std.anonlabels['ref1'] == ('index', 'ref1')
assert std.anonlabels['ref2'] == ('index', 'ref2')
@pytest.mark.sphinx('dummy', freshenv=True)
def test_create_index_by_key(app):
# At present, only glossary directive is able to create index key

View File

@@ -119,16 +119,14 @@ def test_glob(app):
[bullet_list, addnodes.toctree])]) # [0][1][1][1][0]
assert_node(toctree[0][1][1][1][0], addnodes.toctree, caption=None,
glob=True, hidden=False, titlesonly=False,
maxdepth=-1, numbered=0, includefiles=includefiles,
maxdepth=-1, numbered=0, includefiles=list(reversed(includefiles)),
entries=[(None, 'qux/index'), (None, 'baz'), (None, 'bar/bar_3'),
(None, 'bar/bar_2'), (None, 'bar/bar_1'), (None, 'bar/index'),
(None, 'foo')])
includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
'bar/bar_3', 'baz', 'qux/index']
# other collections
assert app.env.toc_num_entries['index'] == 3
assert app.env.toctree_includes['index'] == includefiles + includefiles
assert app.env.toctree_includes['index'] == includefiles + list(reversed(includefiles))
for file in includefiles:
assert 'index' in app.env.files_to_rebuild[file]
assert 'index' in app.env.glob_toctrees

24
tests/test_events.py Normal file
View File

@@ -0,0 +1,24 @@
"""
test_events
~~~~~~~~~~~
Test the EventManager class.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from sphinx.events import EventManager
def test_event_priority():
result = []
events = EventManager(object()) # pass an dummy object as an app
events.connect('builder-inited', lambda app: result.append(1), priority = 500)
events.connect('builder-inited', lambda app: result.append(2), priority = 500)
events.connect('builder-inited', lambda app: result.append(3), priority = 200) # eariler
events.connect('builder-inited', lambda app: result.append(4), priority = 700) # later
events.connect('builder-inited', lambda app: result.append(5), priority = 500)
events.emit('builder-inited')
assert result == [3, 1, 2, 5, 4]

View File

@@ -275,7 +275,7 @@ def test_multibyte_parameters(make_app, apidoc):
assert (outdir / 'conf.py').isfile()
assert (outdir / 'index.rst').isfile()
conf_py = (outdir / 'conf.py').text()
conf_py = (outdir / 'conf.py').read_text()
assert "project = 'プロジェクト名'" in conf_py
assert "author = '著者名'" in conf_py
assert "version = 'バージョン'" in conf_py
@@ -408,11 +408,13 @@ def test_private(tempdir):
# without --private option
apidoc_main(['-o', tempdir, tempdir])
assert (tempdir / 'hello.rst').exists()
assert ':private-members:' not in (tempdir / 'hello.rst').read_text()
assert not (tempdir / '_world.rst').exists()
# with --private option
apidoc_main(['--private', '-o', tempdir, tempdir])
apidoc_main(['--private', '-f', '-o', tempdir, tempdir])
assert (tempdir / 'hello.rst').exists()
assert ':private-members:' in (tempdir / 'hello.rst').read_text()
assert (tempdir / '_world.rst').exists()
@@ -424,7 +426,7 @@ def test_toc_file(tempdir):
apidoc_main(['-o', tempdir, tempdir])
assert (outdir / 'modules.rst').exists()
content = (outdir / 'modules.rst').text()
content = (outdir / 'modules.rst').read_text()
assert content == ("test_toc_file0\n"
"==============\n"
"\n"
@@ -440,7 +442,7 @@ def test_module_file(tempdir):
apidoc_main(['-o', tempdir, tempdir])
assert (outdir / 'example.rst').exists()
content = (outdir / 'example.rst').text()
content = (outdir / 'example.rst').read_text()
assert content == ("example module\n"
"==============\n"
"\n"
@@ -456,7 +458,7 @@ def test_module_file_noheadings(tempdir):
apidoc_main(['--no-headings', '-o', tempdir, tempdir])
assert (outdir / 'example.rst').exists()
content = (outdir / 'example.rst').text()
content = (outdir / 'example.rst').read_text()
assert content == (".. automodule:: example\n"
" :members:\n"
" :undoc-members:\n"
@@ -475,7 +477,7 @@ def test_package_file(tempdir):
assert (outdir / 'testpkg.rst').exists()
assert (outdir / 'testpkg.subpkg.rst').exists()
content = (outdir / 'testpkg.rst').text()
content = (outdir / 'testpkg.rst').read_text()
assert content == ("testpkg package\n"
"===============\n"
"\n"
@@ -514,7 +516,7 @@ def test_package_file(tempdir):
" :undoc-members:\n"
" :show-inheritance:\n")
content = (outdir / 'testpkg.subpkg.rst').text()
content = (outdir / 'testpkg.subpkg.rst').read_text()
assert content == ("testpkg.subpkg package\n"
"======================\n"
"\n"
@@ -536,7 +538,7 @@ def test_package_file_separate(tempdir):
assert (outdir / 'testpkg.rst').exists()
assert (outdir / 'testpkg.example.rst').exists()
content = (outdir / 'testpkg.rst').text()
content = (outdir / 'testpkg.rst').read_text()
assert content == ("testpkg package\n"
"===============\n"
"\n"
@@ -555,7 +557,7 @@ def test_package_file_separate(tempdir):
" :undoc-members:\n"
" :show-inheritance:\n")
content = (outdir / 'testpkg.example.rst').text()
content = (outdir / 'testpkg.example.rst').read_text()
assert content == ("testpkg.example module\n"
"======================\n"
"\n"
@@ -572,7 +574,7 @@ def test_package_file_module_first(tempdir):
(outdir / 'testpkg' / 'example.py').write_text('')
apidoc_main(['--module-first', '-o', tempdir, tempdir])
content = (outdir / 'testpkg.rst').text()
content = (outdir / 'testpkg.rst').read_text()
assert content == ("testpkg package\n"
"===============\n"
"\n"
@@ -601,7 +603,7 @@ def test_package_file_without_submodules(tempdir):
apidoc_main(['-o', tempdir, tempdir / 'testpkg'])
assert (outdir / 'testpkg.rst').exists()
content = (outdir / 'testpkg.rst').text()
content = (outdir / 'testpkg.rst').read_text()
assert content == ("testpkg package\n"
"===============\n"
"\n"
@@ -621,7 +623,7 @@ def test_namespace_package_file(tempdir):
apidoc_main(['--implicit-namespace', '-o', tempdir, tempdir / 'testpkg'])
assert (outdir / 'testpkg.rst').exists()
content = (outdir / 'testpkg.rst').text()
content = (outdir / 'testpkg.rst').read_text()
assert content == ("testpkg namespace\n"
"=================\n"
"\n"

View File

@@ -12,7 +12,6 @@ import platform
import pytest
from sphinx.ext.autodoc import merge_autodoc_default_flags
from test_autodoc import do_autodoc
IS_PYPY = platform.python_implementation() == 'PyPy'
@@ -479,12 +478,37 @@ def test_autodoc_typehints_signature(app):
' :module: target.typehints',
'',
' ',
' .. py:method:: Math.decr(a: int, b: int = 1) -> int',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.horse(a: str, b: int) -> None',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.incr(a: int, b: int = 1) -> int',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.nothing() -> None',
' :module: target.typehints',
' ',
'',
'.. py:function:: complex_func(arg1: str, arg2: List[int], arg3: Tuple[int, '
'Union[str, Unknown]] = None, *args: str, **kwargs: str) -> None',
' :module: target.typehints',
'',
'',
'.. py:function:: decr(a: int, b: int = 1) -> int',
' :module: target.typehints',
'',
'',
'.. py:function:: incr(a: int, b: int = 1) -> int',
' :module: target.typehints',
'',
'',
'.. py:function:: missing_attr(c, a: str, b: Optional[str] = None) -> str',
' :module: target.typehints',
''
]
@@ -505,35 +529,56 @@ def test_autodoc_typehints_none(app):
' :module: target.typehints',
'',
' ',
' .. py:method:: Math.decr(a, b=1)',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.horse(a, b)',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.incr(a, b=1)',
' :module: target.typehints',
' ',
' ',
' .. py:method:: Math.nothing()',
' :module: target.typehints',
' ',
'',
'.. py:function:: complex_func(arg1, arg2, arg3=None, *args, **kwargs)',
' :module: target.typehints',
'',
'',
'.. py:function:: decr(a, b=1)',
' :module: target.typehints',
'',
'',
'.. py:function:: incr(a, b=1)',
' :module: target.typehints',
'',
'',
'.. py:function:: missing_attr(c, a, b=None)',
' :module: target.typehints',
''
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
def test_merge_autodoc_default_flags1(app):
app.config.autodoc_default_flags = ['members', 'undoc-members']
merge_autodoc_default_flags(app, app.config)
assert app.config.autodoc_default_options == {'members': None,
'undoc-members': None}
@pytest.mark.sphinx('html', testroot='ext-autodoc')
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
def test_merge_autodoc_default_flags2(app):
app.config.autodoc_default_flags = ['members', 'undoc-members']
app.config.autodoc_default_options = {'members': 'this,that,order',
'inherited-members': 'this'}
merge_autodoc_default_flags(app, app.config)
assert app.config.autodoc_default_options == {'members': None,
'undoc-members': None,
'inherited-members': 'this'}
@pytest.mark.sphinx('text', testroot='ext-autodoc',
confoverrides={'extensions': ['sphinx.ext.autodoc.typehints'],
'autodoc_typehints': 'description'})
def test_autodoc_typehints_description(app):
app.build()
context = (app.outdir / 'index.txt').read_text()
assert ('target.typehints.incr(a, b=1)\n'
'\n'
' Parameters:\n'
' * **a** (*int*) --\n'
'\n'
' * **b** (*int*) --\n'
'\n'
' Return type:\n'
' int\n'
in context)
@pytest.mark.sphinx('html', testroot='ext-autodoc')
@@ -545,7 +590,7 @@ def test_autodoc_default_options(app):
actual = do_autodoc(app, 'class', 'target.CustomIter')
assert ' .. py:method:: target.CustomIter' not in actual
actual = do_autodoc(app, 'module', 'target')
assert '.. py:function:: save_traceback(app: Sphinx) -> str' not in actual
assert '.. py:function:: save_traceback(app)' not in actual
# with :members:
app.config.autodoc_default_options = {'members': None}
@@ -609,16 +654,6 @@ def test_autodoc_default_options(app):
assert ' .. py:method:: CustomIter.snafucate()' in actual
assert ' Makes this snafucated.' in actual
# with :imported-members:
app.config.autodoc_default_options = {
'members': None,
'imported-members': None,
'ignore-module-all': None,
}
actual = do_autodoc(app, 'module', 'target')
print('\n'.join(actual))
assert '.. py:function:: save_traceback(app: Sphinx) -> str' in actual
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_options_with_values(app):

View File

@@ -18,7 +18,7 @@ from sphinx.ext.autodoc.mock import _MockModule, _MockObject, mock
def test_MockModule():
mock = _MockModule('mocked_module', None)
mock = _MockModule('mocked_module')
assert isinstance(mock.some_attr, _MockObject)
assert isinstance(mock.some_method, _MockObject)
assert isinstance(mock.attr1.attr2, _MockObject)

View File

@@ -0,0 +1,46 @@
"""
test_ext_autodoc_private_members
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Test the autodoc extension. This tests mainly for private-members option.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import pytest
from test_autodoc import do_autodoc
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_private_field(app):
app.config.autoclass_content = 'class'
options = {"members": None}
actual = do_autodoc(app, 'module', 'target.private', options)
assert list(actual) == [
'',
'.. py:module:: target.private',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_private_field_and_private_members(app):
app.config.autoclass_content = 'class'
options = {"members": None,
"private-members": None}
actual = do_autodoc(app, 'module', 'target.private', options)
assert list(actual) == [
'',
'.. py:module:: target.private',
'',
'',
'.. py:function:: private_function(name)',
' :module: target.private',
'',
' private_function is a docstring().',
' ',
' :meta private:',
' '
]

View File

@@ -21,7 +21,7 @@ from sphinx.util import docutils
def test_autosectionlabel_html(app, status, warning, skipped_labels=False):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = ('<li><p><a class="reference internal" href="#introduce-of-sphinx">'
'<span class=".*?">Introduce of Sphinx</span></a></p></li>')
assert re.search(html, content, re.S)
@@ -69,7 +69,7 @@ def test_autosectionlabel_prefix_document_html(app, status, warning):
def test_autosectionlabel_maxdepth(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
# depth: 1
html = ('<li><p><a class="reference internal" href="#test-ext-autosectionlabel">'

View File

@@ -31,6 +31,7 @@ default_kw = {
'confoverrides': {
'extensions': ['sphinx.ext.autosummary'],
'autosummary_generate': True,
'autosummary_generate_overwrite': False,
'source_suffix': '.rst'
}
}
@@ -209,13 +210,13 @@ def test_autosummary_generate(app, status, warning):
assert doctree[3][0][0][2][2].astext() == 'autosummary_dummy_module.bar(x[, y])\n\n'
assert doctree[3][0][0][2][3].astext() == 'autosummary_importfail\n\n'
module = (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').text()
module = (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').read_text()
assert (' .. autosummary::\n'
' \n'
' Foo\n'
' \n' in module)
Foo = (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').text()
Foo = (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').read_text()
assert '.. automethod:: __init__' in Foo
assert (' .. autosummary::\n'
' \n'
@@ -228,10 +229,40 @@ def test_autosummary_generate(app, status, warning):
' \n' in Foo)
@pytest.mark.sphinx('dummy', testroot='ext-autosummary',
confoverrides={'autosummary_generate_overwrite': False})
def test_autosummary_generate_overwrite1(app_params, make_app):
args, kwargs = app_params
srcdir = kwargs.get('srcdir')
(srcdir / 'generated').makedirs(exist_ok=True)
(srcdir / 'generated' / 'autosummary_dummy_module.rst').write_text('')
app = make_app(*args, **kwargs)
content = (srcdir / 'generated' / 'autosummary_dummy_module.rst').read_text()
assert content == ''
assert 'autosummary_dummy_module.rst' not in app._warning.getvalue()
@pytest.mark.sphinx('dummy', testroot='ext-autosummary',
confoverrides={'autosummary_generate_overwrite': True})
def test_autosummary_generate_overwrite2(app_params, make_app):
args, kwargs = app_params
srcdir = kwargs.get('srcdir')
(srcdir / 'generated').makedirs(exist_ok=True)
(srcdir / 'generated' / 'autosummary_dummy_module.rst').write_text('')
app = make_app(*args, **kwargs)
content = (srcdir / 'generated' / 'autosummary_dummy_module.rst').read_text()
assert content != ''
assert 'autosummary_dummy_module.rst' not in app._warning.getvalue()
@pytest.mark.sphinx('latex', **default_kw)
def test_autosummary_latex_table_colspec(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
result = (app.outdir / 'python.tex').read_text()
print(status.getvalue())
print(warning.getvalue())
assert r'\begin{longtable}[c]{\X{1}{2}\X{1}{2}}' in result
@@ -281,7 +312,7 @@ def test_autosummary_imported_members(app, status, warning):
# generated/foo is generated successfully
assert app.env.get_doctree('generated/autosummary_dummy_package')
module = (app.srcdir / 'generated' / 'autosummary_dummy_package.rst').text()
module = (app.srcdir / 'generated' / 'autosummary_dummy_package.rst').read_text()
assert (' .. autosummary::\n'
' \n'
' Bar\n'
@@ -300,7 +331,7 @@ def test_generate_autosummary_docs_property(app):
mock.return_value = [('target.methods.Base.prop', 'prop', None)]
generate_autosummary_docs([], output_dir=app.srcdir, builder=app.builder, app=app)
content = (app.srcdir / 'target.methods.Base.prop.rst').text()
content = (app.srcdir / 'target.methods.Base.prop.rst').read_text()
assert content == ("target.methods.Base.prop\n"
"========================\n"
"\n"
@@ -313,7 +344,7 @@ def test_generate_autosummary_docs_property(app):
def test_autosummary_skip_member(app):
app.build()
content = (app.srcdir / 'generate' / 'target.Foo.rst').text()
content = (app.srcdir / 'generate' / 'target.Foo.rst').read_text()
assert 'Foo.skipmeth' not in content
assert 'Foo._privatemeth' in content

View File

@@ -17,7 +17,7 @@ import pytest
def test_build(app, status, warning):
app.builder.build_all()
py_undoc = (app.outdir / 'python.txt').text()
py_undoc = (app.outdir / 'python.txt').read_text()
assert py_undoc.startswith('Undocumented Python objects\n'
'===========================\n')
assert 'autodoc_target\n--------------\n' in py_undoc
@@ -28,13 +28,13 @@ def test_build(app, status, warning):
assert ' * mod -- No module named mod' # in the "failed import" section
c_undoc = (app.outdir / 'c.txt').text()
c_undoc = (app.outdir / 'c.txt').read_text()
assert c_undoc.startswith('Undocumented C API elements\n'
'===========================\n')
assert 'api.h' in c_undoc
assert ' * Py_SphinxTest' in c_undoc
undoc_py, undoc_c = pickle.loads((app.outdir / 'undoc.pickle').bytes())
undoc_py, undoc_c = pickle.loads((app.outdir / 'undoc.pickle').read_bytes())
assert len(undoc_c) == 1
# the key is the full path to the header file, which isn't testable
assert list(undoc_c.values())[0] == {('function', 'Py_SphinxTest')}
@@ -50,7 +50,7 @@ def test_build(app, status, warning):
@pytest.mark.sphinx('coverage', testroot='ext-coverage')
def test_coverage_ignore_pyobjects(app, status, warning):
app.builder.build_all()
actual = (app.outdir / 'python.txt').text()
actual = (app.outdir / 'python.txt').read_text()
expected = '''Undocumented Python objects
===========================
coverage_not_ignored

View File

@@ -31,4 +31,4 @@ def test_no_cname_for_github_io_domain(app, status, warning):
def test_cname_for_custom_domain(app, status, warning):
app.builder.build_all()
assert (app.outdir / '.nojekyll').exists()
assert (app.outdir / 'CNAME').text() == 'sphinx-doc.org'
assert (app.outdir / 'CNAME').read_text() == 'sphinx-doc.org'

View File

@@ -20,7 +20,7 @@ from sphinx.ext.graphviz import ClickableMapDefinition
def test_graphviz_png_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class="figure align-default" .*?>\s*'
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
@@ -51,7 +51,7 @@ def test_graphviz_png_html(app, status, warning):
def test_graphviz_svg_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class=\"figure align-default\" .*?>\n'
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
@@ -91,7 +91,7 @@ def test_graphviz_svg_html(app, status, warning):
def test_graphviz_latex(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
macro = ('\\\\begin{figure}\\[htbp\\]\n\\\\centering\n\\\\capstart\n\n'
'\\\\sphinxincludegraphics\\[\\]{graphviz-\\w+.pdf}\n'
'\\\\caption{caption of graph}\\\\label{.*}\\\\end{figure}')
@@ -117,7 +117,7 @@ def test_graphviz_latex(app, status, warning):
def test_graphviz_i18n(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = '<img src=".*?" alt="digraph {\n BAR -&gt; BAZ\n}" class="graphviz" />'
assert re.search(html, content, re.M)

View File

@@ -14,6 +14,6 @@ import pytest
@pytest.mark.sphinx('text', testroot='ext-ifconfig')
def test_ifconfig(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'index.txt').text()
result = (app.outdir / 'index.txt').read_text()
assert 'spam' in result
assert 'ham' not in result

View File

@@ -18,7 +18,7 @@ import pytest
def test_ext_imgconverter(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
assert '\\sphinxincludegraphics{{svgimg}.png}' in content
assert not (app.outdir / 'svgimg.svg').exists()
assert (app.outdir / 'svgimg.png').exists()

View File

@@ -132,13 +132,21 @@ def test_inheritance_diagram(app, status, warning):
('dummy.test.A', 'dummy.test.A', [], None),
]
# inheritance diagram involving a base class nested within another class
for cls in graphs['diagram_w_nested_classes'].class_info:
assert cls in [
('dummy.test_nested.A', 'dummy.test_nested.A', [], None),
('dummy.test_nested.C', 'dummy.test_nested.C', ['dummy.test_nested.A.B'], None),
('dummy.test_nested.A.B', 'dummy.test_nested.A.B', [], None)
]
@pytest.mark.sphinx('html', testroot='ext-inheritance_diagram')
@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram_png_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
pattern = ('<div class="figure align-default" id="id1">\n'
'<div class="graphviz">'
@@ -155,7 +163,7 @@ def test_inheritance_diagram_png_html(app, status, warning):
def test_inheritance_diagram_svg_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
pattern = ('<div class="figure align-default" id="id1">\n'
'<div class="graphviz">'
@@ -173,7 +181,7 @@ def test_inheritance_diagram_svg_html(app, status, warning):
def test_inheritance_diagram_latex(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
pattern = ('\\\\begin{figure}\\[htbp]\n\\\\centering\n\\\\capstart\n\n'
'\\\\sphinxincludegraphics\\[\\]{inheritance-\\w+.pdf}\n'
@@ -195,7 +203,7 @@ def test_inheritance_diagram_latex_alias(app, status, warning):
assert ('test.Bar', 'test.Bar', ['alias.Foo'], None) in aliased_graph
assert ('alias.Foo', 'alias.Foo', [], None) in aliased_graph
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
pattern = ('<div class="figure align-default" id="id1">\n'
'<div class="graphviz">'

View File

@@ -190,6 +190,12 @@ def test_missing_reference_pydomain(tempdir, app, status, warning):
rn = missing_reference(app, app.env, node, contnode)
assert rn.astext() == 'func()'
# py:attr context helps to search objects
kwargs = {'py:module': 'module1'}
node, contnode = fake_node('py', 'attr', 'Foo.bar', 'Foo.bar', **kwargs)
rn = missing_reference(app, app.env, node, contnode)
assert rn.astext() == 'Foo.bar'
def test_missing_reference_stddomain(tempdir, app, status, warning):
inv_file = tempdir / 'inventory'
@@ -236,7 +242,7 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning):
load_mappings(app)
app.build()
html = (app.outdir / 'index.html').text()
html = (app.outdir / 'index.html').read_text()
assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#cpp_foo_bar"'
' title="(in foo v2.0)">'

View File

@@ -39,7 +39,7 @@ def test_imgmath_png(app, status, warning):
if "dvipng command 'dvipng' cannot be run" in warning.getvalue():
raise pytest.skip.Exception('dvipng command "dvipng" is not available')
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.png"'
r'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
@@ -57,7 +57,7 @@ def test_imgmath_svg(app, status, warning):
if "dvisvgm command 'dvisvgm' cannot be run" in warning.getvalue():
raise pytest.skip.Exception('dvisvgm command "dvisvgm" is not available')
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.svg"'
r'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
@@ -69,7 +69,7 @@ def test_imgmath_svg(app, status, warning):
def test_mathjax_options(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert ('<script async="async" integrity="sha384-0123456789" '
'src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?'
'config=TeX-AMS-MML_HTMLorMML"></script>' in content)
@@ -80,7 +80,7 @@ def test_mathjax_options(app, status, warning):
def test_mathjax_align(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class="math notranslate nohighlight">\s*'
r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&amp;= \\pi r\^2\\\\'
r'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
@@ -93,7 +93,7 @@ def test_mathjax_align(app, status, warning):
def test_math_number_all_mathjax(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
html = (r'<div class="math notranslate nohighlight" id="equation-index-0">\s*'
r'<span class="eqno">\(1\)<a .*>\xb6</a></span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
assert re.search(html, content, re.S)
@@ -104,7 +104,7 @@ def test_math_number_all_mathjax(app, status, warning):
def test_math_number_all_latex(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
macro = (r'\\begin{equation\*}\s*'
r'\\begin{split}a\^2\+b\^2=c\^2\\end{split}\s*'
r'\\end{equation\*}')
@@ -134,7 +134,7 @@ def test_math_number_all_latex(app, status, warning):
def test_math_eqref_format_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
content = (app.outdir / 'math.html').read_text()
html = ('<p>Referencing equation <a class="reference internal" '
'href="#equation-foo">Eq.1</a> and <a class="reference internal" '
'href="#equation-foo">Eq.1</a>.</p>')
@@ -147,7 +147,7 @@ def test_math_eqref_format_html(app, status, warning):
def test_math_eqref_format_latex(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
macro = (r'Referencing equation Eq.\\ref{equation:math:foo} and '
r'Eq.\\ref{equation:math:foo}.')
assert re.search(macro, content, re.S)
@@ -160,7 +160,7 @@ def test_math_eqref_format_latex(app, status, warning):
def test_mathjax_numfig_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
content = (app.outdir / 'math.html').read_text()
html = ('<div class="math notranslate nohighlight" id="equation-math-0">\n'
'<span class="eqno">(1.2)')
assert html in content
@@ -178,7 +178,7 @@ def test_mathjax_numfig_html(app, status, warning):
def test_imgmath_numfig_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'page.html').text()
content = (app.outdir / 'page.html').read_text()
html = '<span class="eqno">(3)<a class="headerlink" href="#equation-bar"'
assert html in content
html = ('<p>Referencing equations <a class="reference internal" '
@@ -218,7 +218,7 @@ def test_math_compat(app, status, warning):
def test_mathjax_config(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert ('<script type="text/x-mathjax-config">'
'MathJax.Hub.Config({"extensions": ["tex2jax.js"]})'
'</script>' in content)
@@ -229,5 +229,5 @@ def test_mathjax_config(app, status, warning):
def test_mathjax_is_not_installed_if_no_equations(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert 'MathJax.js' not in content

View File

@@ -479,6 +479,8 @@ Raises:
If the dimensions couldn't be parsed.
`InvalidArgumentsError`
If the arguments are invalid.
:exc:`~ValueError`
If the arguments are wrong.
""", """
Example Function
@@ -488,6 +490,7 @@ Example Function
:raises AttributeError: errors for missing attributes.
:raises ~InvalidDimensionsError: If the dimensions couldn't be parsed.
:raises InvalidArgumentsError: If the arguments are invalid.
:raises ~ValueError: If the arguments are wrong.
"""),
################################
("""

View File

@@ -29,7 +29,7 @@ def test_todo(app, status, warning):
app.builder.build_all()
# check todolist
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert ('<p class="admonition-title">Todo</p>\n'
'<p>todo in foo</p>') in content
@@ -37,7 +37,7 @@ def test_todo(app, status, warning):
'<p>todo in bar</p>') in content
# check todo
content = (app.outdir / 'foo.html').text()
content = (app.outdir / 'foo.html').read_text()
assert ('<p class="admonition-title">Todo</p>\n'
'<p>todo in foo</p>') in content
@@ -67,7 +67,7 @@ def test_todo_not_included(app, status, warning):
app.builder.build_all()
# check todolist
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert ('<p class="admonition-title">Todo</p>\n'
'<p>todo in foo</p>') not in content
@@ -75,7 +75,7 @@ def test_todo_not_included(app, status, warning):
'<p>todo in bar</p>') not in content
# check todo
content = (app.outdir / 'foo.html').text()
content = (app.outdir / 'foo.html').read_text()
assert ('<p class="admonition-title">Todo</p>\n'
'<p>todo in foo</p>') not in content
@@ -102,7 +102,7 @@ def test_todo_valid_link(app, status, warning):
# Ensure the LaTeX output is built.
app.builder.build_all()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
# Look for the link to foo. Note that there are two of them because the
# source document uses todolist twice. We could equally well look for links

View File

@@ -24,7 +24,7 @@ def test_viewcode(app, status, warning):
warnings
)
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
assert result.count('href="_modules/spam/mod1.html#func1"') == 2
assert result.count('href="_modules/spam/mod2.html#func2"') == 2
assert result.count('href="_modules/spam/mod1.html#Class1"') == 2
@@ -37,7 +37,7 @@ def test_viewcode(app, status, warning):
# the next assert fails, until the autodoc bug gets fixed
assert result.count('this is the class attribute class_attr') == 2
result = (app.outdir / '_modules/spam/mod1.html').text()
result = (app.outdir / '_modules/spam/mod1.html').read_text()
result = re.sub('<span class=".*?">', '<span>', result) # filter pygments classes
assert ('<div class="viewcode-block" id="Class1"><a class="viewcode-back" '
'href="../../index.html#spam.Class1">[docs]</a>'
@@ -53,7 +53,7 @@ def test_viewcode(app, status, warning):
def test_linkcode(app, status, warning):
app.builder.build(['objects'])
stuff = (app.outdir / 'objects.html').text()
stuff = (app.outdir / 'objects.html').read_text()
assert 'http://foobar/source/foolib.py' in stuff
assert 'http://foobar/js/' in stuff
@@ -65,7 +65,7 @@ def test_linkcode(app, status, warning):
def test_local_source_files(app, status, warning):
def find_source(app, modname):
if modname == 'not_a_package':
source = (app.srcdir / 'not_a_package/__init__.py').text()
source = (app.srcdir / 'not_a_package/__init__.py').read_text()
tags = {
'func1': ('def', 1, 1),
'Class1': ('class', 1, 1),
@@ -73,7 +73,7 @@ def test_local_source_files(app, status, warning):
'not_a_package.submodule.Class1': ('class', 1, 1),
}
else:
source = (app.srcdir / 'not_a_package/submodule.py').text()
source = (app.srcdir / 'not_a_package/submodule.py').read_text()
tags = {
'not_a_package.submodule.func1': ('def', 11, 15),
'Class1': ('class', 19, 22),
@@ -93,7 +93,7 @@ def test_local_source_files(app, status, warning):
warnings
)
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
assert result.count('href="_modules/not_a_package.html#func1"') == 1
assert result.count('href="_modules/not_a_package.html#not_a_package.submodule.func1"') == 1
assert result.count('href="_modules/not_a_package/submodule.html#Class1"') == 1

View File

@@ -40,7 +40,7 @@ class ComplainOnUnhighlighted(PygmentsBridge):
def test_add_lexer(app, status, warning):
app.add_lexer('test', MyLexer())
app.add_lexer('test', MyLexer)
bridge = PygmentsBridge('html')
ret = bridge.highlight_block('ab', 'test')

View File

@@ -95,7 +95,7 @@ def assert_count(expected_expr, result, count):
@pytest.mark.test_params(shared_result='test_intl_basic')
def test_text_toctree(app):
app.build()
result = (app.outdir / 'index.txt').text()
result = (app.outdir / 'index.txt').read_text()
assert_startswith(result, "CONTENTS\n********\n\nTABLE OF CONTENTS\n")
@@ -117,7 +117,7 @@ def test_text_emit_warnings(app, warning):
def test_text_warning_node(app):
app.build()
# test warnings in translation
result = (app.outdir / 'warnings.txt').text()
result = (app.outdir / 'warnings.txt').read_text()
expect = ("3. I18N WITH REST WARNINGS"
"\n**************************\n"
"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
@@ -131,7 +131,7 @@ def test_text_warning_node(app):
def test_text_title_underline(app):
app.build()
# --- simple translation; check title underlines
result = (app.outdir / 'bom.txt').text()
result = (app.outdir / 'bom.txt').read_text()
expect = ("2. Datei mit UTF-8"
"\n******************\n" # underline matches new translation
"\nThis file has umlauts: äöü.\n")
@@ -144,7 +144,7 @@ def test_text_title_underline(app):
def test_text_subdirs(app):
app.build()
# --- check translation in subdirs
result = (app.outdir / 'subdir' / 'index.txt').text()
result = (app.outdir / 'subdir' / 'index.txt').read_text()
assert_startswith(result, "1. subdir contents\n******************\n")
@@ -154,7 +154,7 @@ def test_text_subdirs(app):
def test_text_inconsistency_warnings(app, warning):
app.build()
# --- check warnings for inconsistency in number of references
result = (app.outdir / 'refs_inconsistency.txt').text()
result = (app.outdir / 'refs_inconsistency.txt').read_text()
expect = ("8. I18N WITH REFS INCONSISTENCY"
"\n*******************************\n"
"\n* FOR CITATION [ref3].\n"
@@ -204,7 +204,7 @@ def test_text_inconsistency_warnings(app, warning):
def test_text_literalblock_warnings(app, warning):
app.build()
# --- check warning for literal block
result = (app.outdir / 'literalblock.txt').text()
result = (app.outdir / 'literalblock.txt').read_text()
expect = ("9. I18N WITH LITERAL BLOCK"
"\n**************************\n"
"\nCORRECT LITERAL BLOCK:\n"
@@ -226,7 +226,7 @@ def test_text_literalblock_warnings(app, warning):
def test_text_definition_terms(app):
app.build()
# --- definition terms: regression test for #975, #2198, #2205
result = (app.outdir / 'definition_terms.txt').text()
result = (app.outdir / 'definition_terms.txt').read_text()
expect = ("13. I18N WITH DEFINITION TERMS"
"\n******************************\n"
"\nSOME TERM"
@@ -246,7 +246,7 @@ def test_text_definition_terms(app):
def test_text_glossary_term(app, warning):
app.build()
# --- glossary terms: regression test for #1090
result = (app.outdir / 'glossary_terms.txt').text()
result = (app.outdir / 'glossary_terms.txt').read_text()
expect = ("18. I18N WITH GLOSSARY TERMS"
"\n****************************\n"
"\nSOME NEW TERM"
@@ -265,7 +265,7 @@ def test_text_glossary_term(app, warning):
def test_text_glossary_term_inconsistencies(app, warning):
app.build()
# --- glossary term inconsistencies: regression test for #1090
result = (app.outdir / 'glossary_terms_inconsistency.txt').text()
result = (app.outdir / 'glossary_terms_inconsistency.txt').read_text()
expect = ("19. I18N WITH GLOSSARY TERMS INCONSISTENCY"
"\n******************************************\n"
"\n1. LINK TO *SOME NEW TERM*.\n")
@@ -298,7 +298,7 @@ def test_gettext_section(app):
def test_text_section(app):
app.build()
# --- section
result = (app.outdir / 'section.txt').text()
result = (app.outdir / 'section.txt').read_text()
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'section.po')
for expect_msg in [m for m in expect if m.id]:
assert expect_msg.string in result
@@ -310,7 +310,7 @@ def test_text_section(app):
def test_text_seealso(app):
app.build()
# --- seealso
result = (app.outdir / 'seealso.txt').text()
result = (app.outdir / 'seealso.txt').read_text()
expect = ("12. I18N WITH SEEALSO"
"\n*********************\n"
"\nSee also: SHORT TEXT 1\n"
@@ -327,7 +327,7 @@ def test_text_seealso(app):
def test_text_figure_captions(app):
app.build()
# --- figure captions: regression test for #940
result = (app.outdir / 'figure.txt').text()
result = (app.outdir / 'figure.txt').read_text()
expect = ("14. I18N WITH FIGURE CAPTION"
"\n****************************\n"
"\n [image]MY CAPTION OF THE FIGURE\n"
@@ -371,7 +371,7 @@ def test_text_figure_captions(app):
def test_text_rubric(app):
app.build()
# --- rubric: regression test for pull request #190
result = (app.outdir / 'rubric.txt').text()
result = (app.outdir / 'rubric.txt').read_text()
expect = ("I18N WITH RUBRIC"
"\n****************\n"
"\n-[ RUBRIC TITLE ]-\n"
@@ -389,7 +389,7 @@ def test_text_rubric(app):
def test_text_docfields(app):
app.build()
# --- docfields
result = (app.outdir / 'docfields.txt').text()
result = (app.outdir / 'docfields.txt').read_text()
expect = ("21. I18N WITH DOCFIELDS"
"\n***********************\n"
"\nclass Cls1\n"
@@ -420,7 +420,7 @@ def test_text_admonitions(app):
# --- admonitions
# #1206: gettext did not translate admonition directive's title
# seealso: http://docutils.sourceforge.net/docs/ref/rst/directives.html#admonitions
result = (app.outdir / 'admonitions.txt').text()
result = (app.outdir / 'admonitions.txt').read_text()
directives = (
"attention", "caution", "danger", "error", "hint",
"important", "note", "tip", "warning", "admonition")
@@ -462,7 +462,7 @@ def test_gettext_table(app):
def test_text_table(app):
app.build()
# --- toctree
result = (app.outdir / 'table.txt').text()
result = (app.outdir / 'table.txt').read_text()
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'table.po')
for expect_msg in [m for m in expect if m.id]:
assert expect_msg.string in result
@@ -486,7 +486,7 @@ def test_gettext_toctree(app):
def test_text_toctree(app):
app.build()
# --- toctree
result = (app.outdir / 'toctree.txt').text()
result = (app.outdir / 'toctree.txt').read_text()
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'toctree.po')
for expect_msg in [m for m in expect if m.id]:
assert expect_msg.string in result
@@ -510,7 +510,7 @@ def test_gettext_topic(app):
def test_text_topic(app):
app.build()
# --- topic
result = (app.outdir / 'topic.txt').text()
result = (app.outdir / 'topic.txt').read_text()
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'topic.po')
for expect_msg in [m for m in expect if m.id]:
assert expect_msg.string in result
@@ -628,7 +628,7 @@ def test_gettext_dont_rebuild_mo(make_app, app_params):
def test_html_meta(app):
app.build()
# --- test for meta
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
expected_expr = '<meta content="TESTDATA FOR I18N" name="description" />'
assert expected_expr in result
expected_expr = '<meta content="I18N, SPHINX, MARKUP" name="keywords" />'
@@ -644,7 +644,7 @@ def test_html_footnotes(app):
app.build()
# --- test for #955 cant-build-html-with-footnotes-when-using
# expect no error by build
(app.outdir / 'footnote.html').text()
(app.outdir / 'footnote.html').read_text()
@sphinx_intl
@@ -653,7 +653,7 @@ def test_html_footnotes(app):
def test_html_undefined_refs(app):
app.build()
# --- links to undefined reference
result = (app.outdir / 'refs_inconsistency.html').text()
result = (app.outdir / 'refs_inconsistency.html').read_text()
expected_expr = ('<a class="reference external" '
'href="http://www.example.com">reference</a>')
@@ -675,7 +675,7 @@ def test_html_undefined_refs(app):
def test_html_index_entries(app):
app.build()
# --- index entries: regression test for #976
result = (app.outdir / 'genindex.html').text()
result = (app.outdir / 'genindex.html').read_text()
def wrap(tag, keyword):
start_tag = "<%s[^>]*>" % tag
@@ -713,7 +713,7 @@ def test_html_index_entries(app):
def test_html_versionchanges(app):
app.build()
# --- versionchanges
result = (app.outdir / 'versionchange.html').text()
result = (app.outdir / 'versionchange.html').read_text()
def get_content(result, name):
matched = re.search(r'<div class="%s">\n*(.*?)</div>' % name,
@@ -750,7 +750,7 @@ def test_html_docfields(app):
app.build()
# --- docfields
# expect no error by build
(app.outdir / 'docfields.html').text()
(app.outdir / 'docfields.html').read_text()
@sphinx_intl
@@ -759,7 +759,7 @@ def test_html_docfields(app):
def test_html_template(app):
app.build()
# --- gettext template
result = (app.outdir / 'contents.html').text()
result = (app.outdir / 'contents.html').read_text()
assert "WELCOME" in result
assert "SPHINX 2013.120" in result
@@ -1056,7 +1056,7 @@ def test_xml_label_targets(app):
def test_additional_targets_should_not_be_translated(app):
app.build()
# [literalblock.txt]
result = (app.outdir / 'literalblock.html').text()
result = (app.outdir / 'literalblock.html').read_text()
# title should be translated
expected_expr = 'CODE-BLOCKS'
@@ -1092,7 +1092,7 @@ def test_additional_targets_should_not_be_translated(app):
# [raw.txt]
result = (app.outdir / 'raw.html').text()
result = (app.outdir / 'raw.html').read_text()
# raw block should not be translated
expected_expr = """<iframe src="http://sphinx-doc.org"></iframe></div>"""
@@ -1100,7 +1100,7 @@ def test_additional_targets_should_not_be_translated(app):
# [figure.txt]
result = (app.outdir / 'figure.html').text()
result = (app.outdir / 'figure.html').read_text()
# alt and src for image block should not be translated
expected_expr = """<img alt="i18n" src="_images/i18n.png" />"""
@@ -1130,7 +1130,7 @@ def test_additional_targets_should_not_be_translated(app):
def test_additional_targets_should_be_translated(app):
app.build()
# [literalblock.txt]
result = (app.outdir / 'literalblock.html').text()
result = (app.outdir / 'literalblock.html').read_text()
# title should be translated
expected_expr = 'CODE-BLOCKS'
@@ -1166,7 +1166,7 @@ def test_additional_targets_should_be_translated(app):
# [raw.txt]
result = (app.outdir / 'raw.html').text()
result = (app.outdir / 'raw.html').read_text()
# raw block should be translated
expected_expr = """<iframe src="HTTP://SPHINX-DOC.ORG"></iframe></div>"""
@@ -1174,7 +1174,7 @@ def test_additional_targets_should_be_translated(app):
# [figure.txt]
result = (app.outdir / 'figure.html').text()
result = (app.outdir / 'figure.html').read_text()
# alt and src for image block should be translated
expected_expr = """<img alt="I18N -&gt; IMG" src="_images/img.png" />"""

50
tests/test_pycode_ast.py Normal file
View File

@@ -0,0 +1,50 @@
"""
test_pycode_ast
~~~~~~~~~~~~~~~
Test pycode.ast
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
import pytest
from sphinx.pycode import ast
@pytest.mark.parametrize('source,expected', [
("os.path", "os.path"), # Attribute
("b'bytes'", "b'bytes'"), # Bytes
("object()", "object()"), # Call
("1234", "1234"), # Constant
("{'key1': 'value1', 'key2': 'value2'}",
"{'key1': 'value1', 'key2': 'value2'}"), # Dict
("...", "..."), # Ellipsis
("Tuple[int, int]", "Tuple[int, int]"), # Index, Subscript
("lambda x, y: x + y",
"lambda x, y: ..."), # Lambda
("[1, 2, 3]", "[1, 2, 3]"), # List
("sys", "sys"), # Name, NameConstant
("1234", "1234"), # Num
("{1, 2, 3}", "{1, 2, 3}"), # Set
("'str'", "'str'"), # Str
("(1, 2, 3)", "1, 2, 3"), # Tuple
])
def test_unparse(source, expected):
module = ast.parse(source)
assert ast.unparse(module.body[0].value) == expected
def test_unparse_None():
assert ast.unparse(None) is None
@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
def test_unparse_py38():
source = "lambda x=0, /, y=1, *args, z, **kwargs: x + y + z"
expected = "lambda x=0, /, y=1, *args, z, **kwargs: ..."
module = ast.parse(source)
assert ast.unparse(module.body[0].value) == expected

View File

@@ -99,12 +99,19 @@ def test_annotated_assignment_py36():
source = ('a: str = "Sphinx" #: comment\n'
'b: int = 1\n'
'"""string on next line"""\n'
'c: int #: comment')
'c: int #: comment\n'
'd = 1 # type: int\n'
'"""string on next line"""\n')
parser = Parser(source)
parser.parse()
assert parser.comments == {('', 'a'): 'comment',
('', 'b'): 'string on next line',
('', 'c'): 'comment'}
('', 'c'): 'comment',
('', 'd'): 'string on next line'}
assert parser.annotations == {('', 'a'): 'str',
('', 'b'): 'int',
('', 'c'): 'int',
('', 'd'): 'int'}
assert parser.definitions == {}

View File

@@ -193,7 +193,7 @@ def test_generated_files_eol(tempdir):
qs.generate(d)
def assert_eol(filename, eol):
content = filename.bytes().decode()
content = filename.read_bytes().decode()
assert all([l[-len(eol):] == eol for l in content.splitlines(True)])
assert_eol(tempdir / 'make.bat', '\r\n')

View File

@@ -41,7 +41,7 @@ def setup_module():
def jsload(path):
searchindex = path.text()
searchindex = path.read_text()
assert searchindex.startswith('Search.setIndex(')
assert searchindex.endswith(')')
@@ -98,7 +98,7 @@ def test_meta_keys_are_handled_for_language_de(app, status, warning):
@pytest.mark.sphinx(testroot='search')
def test_stemmer_does_not_remove_short_words(app, status, warning):
app.builder.build_all()
searchindex = (app.outdir / 'searchindex.js').text()
searchindex = (app.outdir / 'searchindex.js').read_text()
assert 'zfs' in searchindex
@@ -112,11 +112,11 @@ def test_stemmer(app, status, warning):
@pytest.mark.sphinx(testroot='search')
def test_term_in_heading_and_section(app, status, warning):
searchindex = (app.outdir / 'searchindex.js').text()
searchindex = (app.outdir / 'searchindex.js').read_text()
# if search term is in the title of one doc and in the text of another
# both documents should be a hit in the search index as a title,
# respectively text hit
assert 'textinhead:1' in searchindex
assert 'textinhead:2' in searchindex
assert 'textinhead:0' in searchindex
@@ -247,8 +247,18 @@ def test_IndexBuilder_lookup():
def test_search_index_gen_zh(app, status, warning):
app.builder.build_all()
# jsdump fails if search language is 'zh'; hence we just get the text:
searchindex = (app.outdir / 'searchindex.js').text()
searchindex = (app.outdir / 'searchindex.js').read_text()
assert 'chinesetest ' not in searchindex
assert 'chinesetest' in searchindex
assert 'chinesetesttwo' in searchindex
assert 'cas' in searchindex
@pytest.mark.sphinx(testroot='search')
def test_nosearch(app):
app.build()
index = jsload(app.outdir / 'searchindex.js')
assert index['docnames'] == ['index', 'nosearch', 'tocitem']
assert 'latex' not in index['terms']
assert 'zfs' in index['terms']
assert index['terms']['zfs'] == 0 # zfs on nosearch.rst is not registered to index

View File

@@ -94,7 +94,7 @@ def nonascii_srcdir(request, setup_command):
"""))
master_doc = srcdir / 'index.txt'
master_doc.write_bytes((master_doc.text() + dedent("""
master_doc.write_bytes((master_doc.read_text() + dedent("""
.. toctree::
%(mb_name)s/%(mb_name)s

View File

@@ -17,7 +17,7 @@ from sphinx.util import docutils
def test_basic(app, status, warning):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<p> “Sphinx” is a tool that makes it easy …</p>' in content
@@ -25,7 +25,7 @@ def test_basic(app, status, warning):
def test_text_builder(app, status, warning):
app.build()
content = (app.outdir / 'index.txt').text()
content = (app.outdir / 'index.txt').read_text()
assert '-- "Sphinx" is a tool that makes it easy ...' in content
@@ -33,7 +33,7 @@ def test_text_builder(app, status, warning):
def test_man_builder(app, status, warning):
app.build()
content = (app.outdir / 'python.1').text()
content = (app.outdir / 'python.1').read_text()
assert '\\-\\- "Sphinx" is a tool that makes it easy ...' in content
@@ -41,7 +41,7 @@ def test_man_builder(app, status, warning):
def test_latex_builder(app, status, warning):
app.build()
content = (app.outdir / 'python.tex').text()
content = (app.outdir / 'python.tex').read_text()
assert '\\textendash{} “Sphinx” is a tool that makes it easy …' in content
@@ -50,7 +50,7 @@ def test_latex_builder(app, status, warning):
def test_ja_html_builder(app, status, warning):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<p>-- &quot;Sphinx&quot; is a tool that makes it easy ...</p>' in content
@@ -59,7 +59,7 @@ def test_ja_html_builder(app, status, warning):
def test_smartquotes_disabled(app, status, warning):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<p>-- &quot;Sphinx&quot; is a tool that makes it easy ...</p>' in content
@@ -70,7 +70,7 @@ def test_smartquotes_disabled(app, status, warning):
def test_smartquotes_action(app, status, warning):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<p>-- “Sphinx” is a tool that makes it easy ...</p>' in content
@@ -79,7 +79,7 @@ def test_smartquotes_action(app, status, warning):
def test_smartquotes_excludes_language(app, status, warning):
app.build()
content = (app.outdir / 'index.html').text()
content = (app.outdir / 'index.html').read_text()
assert '<p> 「Sphinx」 is a tool that makes it easy …</p>' in content
@@ -88,5 +88,5 @@ def test_smartquotes_excludes_language(app, status, warning):
def test_smartquotes_excludes_builders(app, status, warning):
app.build()
content = (app.outdir / 'python.1').text()
content = (app.outdir / 'python.1').read_text()
assert ' “Sphinx” is a tool that makes it easy …' in content

View File

@@ -20,7 +20,7 @@ def test_layout_overloading(make_app, app_params):
setup_documenters(app)
app.builder.build_update()
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
assert '<!-- layout overloading -->' in result
@@ -31,5 +31,5 @@ def test_autosummary_class_template_overloading(make_app, app_params):
setup_documenters(app)
app.builder.build_update()
result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.html').text()
result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.html').read_text()
assert 'autosummary/class.rst method block overloading' in result

View File

@@ -76,16 +76,16 @@ def test_js_source(app, status, warning):
v = '3.4.1'
msg = 'jquery.js version does not match to {v}'.format(v=v)
jquery_min = (app.outdir / '_static' / 'jquery.js').text()
jquery_min = (app.outdir / '_static' / 'jquery.js').read_text()
assert 'jQuery v{v}'.format(v=v) in jquery_min, msg
jquery_src = (app.outdir / '_static' / 'jquery-{v}.js'.format(v=v)).text()
jquery_src = (app.outdir / '_static' / 'jquery-{v}.js'.format(v=v)).read_text()
assert 'jQuery JavaScript Library v{v}'.format(v=v) in jquery_src, msg
v = '1.3.1'
msg = 'underscore.js version does not match to {v}'.format(v=v)
underscore_min = (app.outdir / '_static' / 'underscore.js').text()
underscore_min = (app.outdir / '_static' / 'underscore.js').read_text()
assert 'Underscore.js {v}'.format(v=v) in underscore_min, msg
underscore_src = (app.outdir / '_static' / 'underscore-{v}.js'.format(v=v)).text()
underscore_src = (app.outdir / '_static' / 'underscore-{v}.js'.format(v=v)).read_text()
assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg
@@ -108,12 +108,12 @@ def test_staticfiles(app, status, warning):
app.build()
assert (app.outdir / '_static' / 'staticimg.png').exists()
assert (app.outdir / '_static' / 'statictmpl.html').exists()
assert (app.outdir / '_static' / 'statictmpl.html').text() == (
assert (app.outdir / '_static' / 'statictmpl.html').read_text() == (
'<!-- testing static templates -->\n'
'<html><project>Python</project></html>'
)
result = (app.outdir / 'index.html').text()
result = (app.outdir / 'index.html').read_text()
assert '<meta name="testopt" content="optdefault" />' in result
@@ -122,7 +122,7 @@ def test_theme_sidebars(app, status, warning):
app.build()
# test-theme specifies globaltoc and searchbox as default sidebars
result = (app.outdir / 'index.html').text(encoding='utf8')
result = (app.outdir / 'index.html').read_text()
assert '<h3><a href="#">Table of Contents</a></h3>' in result
assert '<h3>Related Topics</h3>' not in result
assert '<h3>This Page</h3>' not in result

Some files were not shown because too many files have changed in this diff Show More