Merge branch '3.x' into escape-combined-args-kwargs

This commit is contained in:
Keewis
2020-07-25 15:15:06 +02:00
207 changed files with 5734 additions and 611 deletions

View File

@@ -0,0 +1,5 @@
from .foo import bar
class foo:
"""docstring of target.name_conflict::foo."""
pass

View File

@@ -0,0 +1,2 @@
class bar:
"""docstring of target.name_conflict.foo::bar."""

View File

@@ -0,0 +1,11 @@
class Foo:
#: name of Foo
__name = None
__age = None
class Bar(Foo):
__address = None
#: a member having mangled-like name
_Baz__email = None

View File

@@ -7,7 +7,7 @@ def sum(x: int, y: int) -> int:
@overload
def sum(x: float, y: float) -> float:
def sum(x: "float", y: "float") -> "float":
...
@@ -29,7 +29,7 @@ class Math:
...
@overload
def sum(self, x: float, y: float) -> float:
def sum(self, x: "float", y: "float") -> "float":
...
@overload
@@ -49,7 +49,7 @@ class Foo:
...
@overload
def __new__(cls, x: str, y: str) -> "Foo":
def __new__(cls, x: "str", y: "str") -> "Foo":
...
def __new__(cls, x, y):
@@ -64,7 +64,7 @@ class Bar:
...
@overload
def __init__(cls, x: str, y: str) -> None:
def __init__(cls, x: "str", y: "str") -> "None":
...
def __init__(cls, x, y):
@@ -77,7 +77,7 @@ class Meta(type):
...
@overload
def __call__(cls, x: str, y: str) -> Any:
def __call__(cls, x: "str", y: "str") -> "Any":
...
def __call__(cls, x, y):

View File

@@ -1,8 +1,15 @@
# for py32 or above
from contextlib import contextmanager
from functools import lru_cache
from typing import Generator
@lru_cache(maxsize=None)
def slow_function(message, timeout):
"""This function is slow."""
print(message)
@contextmanager
def feeling_good(x: int, y: int) -> Generator:
"""You'll feel better in this context!"""
yield

View File

@@ -0,0 +1,21 @@
from os import path # NOQA
from typing import Union
class Foo:
class Bar:
pass
def __init__(self):
pass
def bar(self):
pass
@property
def baz(self):
pass
def bar(x: Union[int, str], y: int = 1) -> None:
pass

View File

@@ -0,0 +1,11 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.autosummary']
autosummary_generate = True
autosummary_filename_map = {
"autosummary_dummy_module": "module_mangled",
"autosummary_dummy_module.bar": "bar"
}

View File

@@ -0,0 +1,9 @@
.. autosummary::
:toctree: generated
:caption: An autosummary
autosummary_dummy_module
autosummary_dummy_module.Foo
autosummary_dummy_module.Foo.bar
autosummary_dummy_module.bar

View File

@@ -2,7 +2,16 @@ from os import path # NOQA
from typing import Union
#: module variable
CONSTANT1 = None
CONSTANT2 = None
class Foo:
#: class variable
CONSTANT3 = None
CONSTANT4 = None
class Bar:
pass

View File

@@ -14,7 +14,7 @@ same type links
link to :term:`Some term` and :term:`Some other term`.
link to :ref:`i18n-role-xref` and :ref:`same-type-links`.
link to :ref:`i18n-role-xref`, :ref:`same-type-links` and :ref:`label <same-type-links>`.
link to :doc:`index` and :doc:`glossary_terms`.

View File

@@ -28,8 +28,8 @@ msgstr "SAME TYPE LINKS"
msgid "link to :term:`Some term` and :term:`Some other term`."
msgstr "LINK TO :term:`SOME OTHER NEW TERM` AND :term:`SOME NEW TERM`."
msgid "link to :ref:`i18n-role-xref` and :ref:`same-type-links`."
msgstr "LINK TO :ref:`same-type-links` AND :ref:`i18n-role-xref`."
msgid "link to :ref:`i18n-role-xref`, :ref:`same-type-links` and :ref:`label <same-type-links>`."
msgstr "LINK TO :ref:`LABEL <i18n-role-xref>` AND :ref:`same-type-links` AND :ref:`same-type-links`."
msgid "link to :doc:`index` and :doc:`glossary_terms`."
msgstr "LINK TO :doc:`glossary_terms` AND :doc:`index`."

View File

@@ -69,4 +69,4 @@ subsubsection
otherdoc
* Embeded standalone hyperlink reference(refs: #5948): `subsection <section1_>`_.
* Embedded standalone hyperlink reference(refs: #5948): `subsection <section1_>`_.

View File

@@ -11,6 +11,8 @@ Some additional anchors to exercise ignore code
* `Example Bar invalid <https://www.google.com/#top>`_
* `Example anchor invalid <http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist>`_
* `Complete nonsense <https://localhost:7777/doesnotexist>`_
* `Example valid local file <conf.py>`_
* `Example invalid local file <path/to/notfound>`_
.. image:: https://www.google.com/image.png
.. figure:: https://www.google.com/image2.png

View File

View File

@@ -0,0 +1,7 @@
.. code-block::
:linenos:
def hello(name)
print("hello", name)
hello("Sphinx")

View File

@@ -32,14 +32,11 @@ Contents:
Latest reference <http://sphinx-doc.org/latest/>
Python <http://python.org/>
self
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
References
==========

View File

@@ -16,6 +16,7 @@ Contents:
foo
bar
http://sphinx-doc.org/
self
.. only:: html

View File

@@ -391,6 +391,6 @@ def test_run_epubcheck(app):
subprocess.run(['java', '-jar', epubcheck, app.outdir / 'SphinxTests.epub'],
stdout=PIPE, stderr=PIPE, check=True)
except CalledProcessError as exc:
print(exc.stdout)
print(exc.stderr)
print(exc.stdout.decode('utf-8'))
print(exc.stderr.decode('utf-8'))
assert False, 'epubcheck exited with return code %s' % exc.returncode

View File

@@ -357,7 +357,6 @@ def test_html4_output(app, status, warning):
"[@class='reference external']", ''),
(".//li/p/a[@href='genindex.html']/span", 'Index'),
(".//li/p/a[@href='py-modindex.html']/span", 'Module Index'),
(".//li/p/a[@href='search.html']/span", 'Search Page'),
# custom sidebar only for contents
(".//h4", 'Contents sidebar'),
# custom JavaScript
@@ -1575,3 +1574,21 @@ def test_html_scaled_image_link(app):
assert re.search('\n<img alt="_images/img.png" class="no-scaled-link"'
' src="_images/img.png" style="[^"]+" />',
context)
@pytest.mark.sphinx('html', testroot='reST-code-block',
confoverrides={'html_codeblock_linenos_style': 'table'})
def test_html_codeblock_linenos_style_table(app):
app.build()
content = (app.outdir / 'index.html').read_text()
assert '<div class="linenodiv"><pre>1\n2\n3\n4</pre></div>' in content
@pytest.mark.sphinx('html', testroot='reST-code-block',
confoverrides={'html_codeblock_linenos_style': 'inline'})
def test_html_codeblock_linenos_style_inline(app):
app.build()
content = (app.outdir / 'index.html').read_text()
assert '<span class="lineno">1 </span>' in content

View File

@@ -64,8 +64,8 @@ def compile_latex_document(app, filename='python.tex'):
'-output-directory=%s' % app.config.latex_engine,
filename]
subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
except OSError: # most likely the latex executable was not found
raise pytest.skip.Exception
except OSError as exc: # most likely the latex executable was not found
raise pytest.skip.Exception from exc
except CalledProcessError as exc:
print(exc.stdout)
print(exc.stderr)
@@ -1477,7 +1477,7 @@ def test_latex_labels(app, status, warning):
r'\label{\detokenize{otherdoc:otherdoc}}'
r'\label{\detokenize{otherdoc::doc}}' in result)
# Embeded standalone hyperlink reference (refs: #5948)
# Embedded standalone hyperlink reference (refs: #5948)
assert result.count(r'\label{\detokenize{index:section1}}') == 1
@@ -1545,7 +1545,7 @@ def test_texescape_for_unicode_supported_engine(app, status, warning):
assert 'superscript: ⁰, ¹' in result
assert 'subscript: ₀, ₁' in result
@pytest.mark.sphinx('latex', testroot='basic',
confoverrides={'latex_elements': {'extrapackages': r'\usepackage{foo}'}})
def test_latex_elements_extrapackages(app, status, warning):

View File

@@ -30,7 +30,9 @@ def test_defaults(app, status, warning):
# images should fail
assert "Not Found for url: https://www.google.com/image.png" in content
assert "Not Found for url: https://www.google.com/image2.png" in content
assert len(content.splitlines()) == 5
# looking for local file should fail
assert "[broken] path/to/notfound" in content
assert len(content.splitlines()) == 6
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
@@ -47,8 +49,8 @@ def test_defaults_json(app, status, warning):
"info"]:
assert attr in row
assert len(content.splitlines()) == 8
assert len(rows) == 8
assert len(content.splitlines()) == 10
assert len(rows) == 10
# the output order of the rows is not stable
# due to possible variance in network latency
rowsby = {row["uri"]:row for row in rows}
@@ -69,7 +71,7 @@ def test_defaults_json(app, status, warning):
assert dnerow['uri'] == 'https://localhost:7777/doesnotexist'
assert rowsby['https://www.google.com/image2.png'] == {
'filename': 'links.txt',
'lineno': 16,
'lineno': 18,
'status': 'broken',
'code': 0,
'uri': 'https://www.google.com/image2.png',
@@ -92,7 +94,8 @@ def test_defaults_json(app, status, warning):
'https://localhost:7777/doesnotexist',
'http://www.sphinx-doc.org/en/1.7/intro.html#',
'https://www.google.com/image.png',
'https://www.google.com/image2.png']
'https://www.google.com/image2.png',
'path/to/notfound']
})
def test_anchors_ignored(app, status, warning):
app.builder.build_all()

View File

@@ -58,8 +58,8 @@ def test_texinfo(app, status, warning):
try:
args = ['makeinfo', '--no-split', 'sphinxtests.texi']
subprocess.run(args, stdout=PIPE, stderr=PIPE, cwd=app.outdir, check=True)
except OSError:
raise pytest.skip.Exception # most likely makeinfo was not found
except OSError as exc:
raise pytest.skip.Exception from exc # most likely makeinfo was not found
except CalledProcessError as exc:
print(exc.stdout)
print(exc.stderr)

View File

@@ -10,6 +10,7 @@
import pytest
from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.c import DefinitionParser, DefinitionError
from sphinx.domains.c import _max_id, _id_prefix, Symbol
from sphinx.testing import restructuredtext
@@ -469,6 +470,8 @@ def test_attributes():
check('member', '__attribute__(()) int f', {1: 'f'})
check('member', '__attribute__((a)) int f', {1: 'f'})
check('member', '__attribute__((a, b)) int f', {1: 'f'})
check('member', '__attribute__((optimize(3))) int f', {1: 'f'})
check('member', '__attribute__((format(printf, 1, 2))) int f', {1: 'f'})
# style: user-defined id
check('member', 'id_attr int f', {1: 'f'})
# style: user-defined paren
@@ -588,3 +591,13 @@ def test_cvar(app):
domain = app.env.get_domain('c')
entry = domain.objects.get('PyClass_Type')
assert entry == ('index', 'c.PyClass_Type', 'var')
def test_noindexentry(app):
text = (".. c:function:: void f()\n"
".. c:function:: void g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C function)', 'c.f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])

View File

@@ -14,8 +14,11 @@ import pytest
import sphinx.domains.cpp as cppDomain
from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
from sphinx.domains.cpp import Symbol, _max_id, _id_prefix
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
from sphinx.util import docutils
@@ -897,6 +900,8 @@ def test_attributes():
check('member', '__attribute__(()) int f', {1: 'f__i', 2: '1f'})
check('member', '__attribute__((a)) int f', {1: 'f__i', 2: '1f'})
check('member', '__attribute__((a, b)) int f', {1: 'f__i', 2: '1f'})
check('member', '__attribute__((optimize(3))) int f', {1: 'f__i', 2: '1f'})
check('member', '__attribute__((format(printf, 1, 2))) int f', {1: 'f__i', 2: '1f'})
# style: user-defined id
check('member', 'id_attr int f', {1: 'f__i', 2: '1f'})
# style: user-defined paren
@@ -1209,3 +1214,13 @@ not found in `{test}`
assert any_role.classes == cpp_any_role.classes, expect
assert any_role.classes == expr_role.content_classes['a'], expect
assert any_role.classes == texpr_role.content_classes['a'], expect
def test_noindexentry(app):
text = (".. cpp:function:: void f()\n"
".. cpp:function:: void g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C++ function)', '_CPPv41fv', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])

View File

@@ -218,3 +218,13 @@ def test_js_data(app):
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)
def test_noindexentry(app):
text = (".. js:function:: f()\n"
".. js:function:: g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f() (built-in function)', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])

View File

@@ -236,18 +236,18 @@ def test_get_full_qualified_name():
assert domain.get_full_qualified_name(node) == 'module1.Class.func'
def test_parse_annotation():
doctree = _parse_annotation("int")
def test_parse_annotation(app):
doctree = _parse_annotation("int", app.env)
assert_node(doctree, ([pending_xref, "int"],))
assert_node(doctree[0], pending_xref, refdomain="py", reftype="class", reftarget="int")
doctree = _parse_annotation("List[int]")
doctree = _parse_annotation("List[int]", app.env)
assert_node(doctree, ([pending_xref, "List"],
[desc_sig_punctuation, "["],
[pending_xref, "int"],
[desc_sig_punctuation, "]"]))
doctree = _parse_annotation("Tuple[int, int]")
doctree = _parse_annotation("Tuple[int, int]", app.env)
assert_node(doctree, ([pending_xref, "Tuple"],
[desc_sig_punctuation, "["],
[pending_xref, "int"],
@@ -255,14 +255,14 @@ def test_parse_annotation():
[pending_xref, "int"],
[desc_sig_punctuation, "]"]))
doctree = _parse_annotation("Tuple[()]")
doctree = _parse_annotation("Tuple[()]", app.env)
assert_node(doctree, ([pending_xref, "Tuple"],
[desc_sig_punctuation, "["],
[desc_sig_punctuation, "("],
[desc_sig_punctuation, ")"],
[desc_sig_punctuation, "]"]))
doctree = _parse_annotation("Callable[[int, int], int]")
doctree = _parse_annotation("Callable[[int, int], int]", app.env)
assert_node(doctree, ([pending_xref, "Callable"],
[desc_sig_punctuation, "["],
[desc_sig_punctuation, "["],
@@ -275,12 +275,11 @@ def test_parse_annotation():
[desc_sig_punctuation, "]"]))
# None type makes an object-reference (not a class reference)
doctree = _parse_annotation("None")
doctree = _parse_annotation("None", app.env)
assert_node(doctree, ([pending_xref, "None"],))
assert_node(doctree[0], pending_xref, refdomain="py", reftype="obj", reftarget="None")
def test_pyfunction_signature(app):
text = ".. py:function:: hello(name: str) -> str"
doctree = restructuredtext.parse(app, text)
@@ -458,14 +457,22 @@ def test_pyobject_prefix(app):
def test_pydata(app):
text = ".. py:data:: var\n"
text = (".. py:module:: example\n"
".. py:data:: var\n"
" :type: int\n")
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, desc_name, "var"],
assert_node(doctree, (nodes.target,
addnodes.index,
addnodes.index,
[desc, ([desc_signature, ([desc_addname, "example."],
[desc_name, "var"],
[desc_annotation, (": ",
[pending_xref, "int"])])],
[desc_content, ()])]))
assert 'var' in domain.objects
assert domain.objects['var'] == ('index', 'var', 'data')
assert_node(doctree[3][0][2][1], pending_xref, **{"py:module": "example"})
assert 'example.var' in domain.objects
assert domain.objects['example.var'] == ('index', 'example.var', 'data')
def test_pyfunction(app):
@@ -679,7 +686,7 @@ def test_pyattribute(app):
text = (".. py:class:: Class\n"
"\n"
" .. py:attribute:: attr\n"
" :type: str\n"
" :type: Optional[str]\n"
" :value: ''\n")
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
@@ -692,9 +699,14 @@ def test_pyattribute(app):
entries=[('single', 'attr (Class attribute)', 'Class.attr', '', None)])
assert_node(doctree[1][1][1], ([desc_signature, ([desc_name, "attr"],
[desc_annotation, (": ",
[pending_xref, "str"])],
[pending_xref, "Optional"],
[desc_sig_punctuation, "["],
[pending_xref, "str"],
[desc_sig_punctuation, "]"])],
[desc_annotation, " = ''"])],
[desc_content, ()]))
assert_node(doctree[1][1][1][0][1][1], pending_xref, **{"py:class": "Class"})
assert_node(doctree[1][1][1][0][1][3], pending_xref, **{"py:class": "Class"})
assert 'Class.attr' in domain.objects
assert domain.objects['Class.attr'] == ('index', 'Class.attr', 'attribute')
@@ -796,3 +808,19 @@ def test_modindex_common_prefix(app):
)
def test_noindexentry(app):
text = (".. py:function:: f()\n"
".. py:function:: g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('pair', 'built-in function; f()', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])
text = (".. py:class:: f\n"
".. py:class:: g\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (built-in class)', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])

View File

@@ -25,12 +25,14 @@ def test_create_single_index(app):
".. index:: ёлка\n"
".. index:: ‏תירבע‎\n"
".. index:: 9-symbol\n"
".. index:: &-symbol\n")
".. index:: &-symbol\n"
".. index:: £100\n")
restructuredtext.parse(app, text)
index = IndexEntries(app.env).create_index(app.builder)
assert len(index) == 6
assert index[0] == ('Symbols', [('&-symbol', [[('', '#index-9')], [], None]),
('9-symbol', [[('', '#index-8')], [], None])])
('9-symbol', [[('', '#index-8')], [], None]),
('£100', [[('', '#index-10')], [], None])])
assert index[1] == ('D', [('docutils', [[('', '#index-0')], [], None])])
assert index[2] == ('P', [('pip', [[], [('install', [('', '#index-2')]),
('upgrade', [('', '#index-3')])], None]),

View File

@@ -41,7 +41,8 @@ def test_process_doc(app):
assert_node(toctree[0][1][0], addnodes.toctree,
caption="Table of Contents", glob=False, hidden=False,
titlesonly=False, maxdepth=2, numbered=999,
entries=[(None, 'foo'), (None, 'bar'), (None, 'http://sphinx-doc.org/')],
entries=[(None, 'foo'), (None, 'bar'), (None, 'http://sphinx-doc.org/'),
(None, 'self')],
includefiles=['foo', 'bar'])
# only branch
@@ -219,7 +220,9 @@ def test_get_toctree_for(app):
([list_item, ([compact_paragraph, reference, "foo"],
bullet_list)],
[list_item, compact_paragraph, reference, "bar"],
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"],
[list_item, compact_paragraph, reference,
"Welcome to Sphinx Testss documentation!"]))
assert_node(toctree[1][0][1],
([list_item, compact_paragraph, reference, "quux"],
[list_item, compact_paragraph, reference, "foo.1"],
@@ -231,6 +234,7 @@ def test_get_toctree_for(app):
assert_node(toctree[1][0][1][2][0][0], reference, refuri="foo#foo-2", secnumber=[1, 3])
assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=[2])
assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
assert_node(toctree[1][3][0][0], reference, refuri="")
assert_node(toctree[2],
[bullet_list, list_item, compact_paragraph, reference, "baz"])
@@ -255,10 +259,13 @@ def test_get_toctree_for_collapse(app):
assert_node(toctree[1],
([list_item, compact_paragraph, reference, "foo"],
[list_item, compact_paragraph, reference, "bar"],
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"],
[list_item, compact_paragraph, reference,
"Welcome to Sphinx Testss documentation!"]))
assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=[1])
assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=[2])
assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
assert_node(toctree[1][3][0][0], reference, refuri="")
assert_node(toctree[2],
[bullet_list, list_item, compact_paragraph, reference, "baz"])
@@ -285,7 +292,9 @@ def test_get_toctree_for_maxdepth(app):
([list_item, ([compact_paragraph, reference, "foo"],
bullet_list)],
[list_item, compact_paragraph, reference, "bar"],
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"],
[list_item, compact_paragraph, reference,
"Welcome to Sphinx Testss documentation!"]))
assert_node(toctree[1][0][1],
([list_item, compact_paragraph, reference, "quux"],
[list_item, ([compact_paragraph, reference, "foo.1"],
@@ -302,6 +311,7 @@ def test_get_toctree_for_maxdepth(app):
assert_node(toctree[1][0][1][2][0][0], reference, refuri="foo#foo-2", secnumber=[1, 3])
assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=[2])
assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/")
assert_node(toctree[1][3][0][0], reference, refuri="")
assert_node(toctree[2],
[bullet_list, list_item, compact_paragraph, reference, "baz"])
@@ -327,7 +337,9 @@ def test_get_toctree_for_includehidden(app):
([list_item, ([compact_paragraph, reference, "foo"],
bullet_list)],
[list_item, compact_paragraph, reference, "bar"],
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"]))
[list_item, compact_paragraph, reference, "http://sphinx-doc.org/"],
[list_item, compact_paragraph, reference,
"Welcome to Sphinx Testss documentation!"]))
assert_node(toctree[1][0][1],
([list_item, compact_paragraph, reference, "quux"],
[list_item, compact_paragraph, reference, "foo.1"],

View File

@@ -121,7 +121,6 @@ def test_pep_0420_enabled_separate(make_app, apidoc):
with open(outdir / 'a.b.c.rst') as f:
rst = f.read()
assert ".. toctree::\n :maxdepth: 4\n\n a.b.c.d\n" in rst
with open(outdir / 'a.b.e.rst') as f:
@@ -509,7 +508,6 @@ def test_package_file(tempdir):
" :undoc-members:\n"
" :show-inheritance:\n"
"\n"
"\n"
"Module contents\n"
"---------------\n"
"\n"
@@ -595,8 +593,7 @@ def test_package_file_module_first(tempdir):
".. automodule:: testpkg.example\n"
" :members:\n"
" :undoc-members:\n"
" :show-inheritance:\n"
"\n")
" :show-inheritance:\n")
def test_package_file_without_submodules(tempdir):
@@ -639,5 +636,4 @@ def test_namespace_package_file(tempdir):
".. automodule:: testpkg.example\n"
" :members:\n"
" :undoc-members:\n"
" :show-inheritance:\n"
"\n")
" :show-inheritance:\n")

View File

@@ -121,15 +121,16 @@ def test_parse_name(app):
verify('class', 'Base', ('test_ext_autodoc', ['Base'], None, None))
# for members
directive.env.ref_context['py:module'] = 'foo'
verify('method', 'util.SphinxTestApp.cleanup',
('foo', ['util', 'SphinxTestApp', 'cleanup'], None, None))
directive.env.ref_context['py:module'] = 'util'
directive.env.ref_context['py:module'] = 'sphinx.testing.util'
verify('method', 'SphinxTestApp.cleanup',
('sphinx.testing.util', ['SphinxTestApp', 'cleanup'], None, None))
directive.env.ref_context['py:module'] = 'sphinx.testing.util'
directive.env.ref_context['py:class'] = 'Foo'
directive.env.temp_data['autodoc:class'] = 'SphinxTestApp'
verify('method', 'cleanup', ('util', ['SphinxTestApp', 'cleanup'], None, None))
verify('method', 'cleanup',
('sphinx.testing.util', ['SphinxTestApp', 'cleanup'], None, None))
verify('method', 'SphinxTestApp.cleanup',
('util', ['SphinxTestApp', 'cleanup'], None, None))
('sphinx.testing.util', ['SphinxTestApp', 'cleanup'], None, None))
def test_format_signature(app):
@@ -800,14 +801,14 @@ def test_autodoc_inner_class(app):
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
assert list(actual) == [
'',
'.. py:class:: Outer.Inner()',
' :module: target',
'.. py:class:: Inner()',
' :module: target.Outer',
'',
' Foo',
'',
'',
' .. py:method:: Outer.Inner.meth()',
' :module: target',
' .. py:method:: Inner.meth()',
' :module: target.Outer',
'',
' Foo',
'',
@@ -1046,7 +1047,7 @@ def test_class_attributes(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_instance_attributes(app):
def test_autoclass_instance_attributes(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.InstAttCls', options)
assert list(actual) == [
@@ -1119,6 +1120,19 @@ def test_instance_attributes(app):
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autoattribute_instance_attributes(app):
actual = do_autodoc(app, 'attribute', 'target.InstAttCls.ia1')
assert list(actual) == [
'',
'.. py:attribute:: InstAttCls.ia1',
' :module: target',
'',
' Doc comment for instance attribute InstAttCls.ia1',
''
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_slots(app):
options = {"members": None,
@@ -1266,7 +1280,7 @@ def test_automethod_for_decorated(app):
actual = do_autodoc(app, 'method', 'target.decorator.Bar.meth')
assert list(actual) == [
'',
'.. py:method:: Bar.meth()',
'.. py:method:: Bar.meth(name=None, age=None)',
' :module: target.decorator',
'',
]
@@ -1431,7 +1445,7 @@ def test_coroutine(app):
actual = do_autodoc(app, 'function', 'target.coroutine.sync_func')
assert list(actual) == [
'',
'.. py:function:: sync_func(*args, **kwargs)',
'.. py:function:: sync_func()',
' :module: target.coroutine',
'',
]
@@ -1881,6 +1895,43 @@ def test_overload(app):
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_pymodule_for_ModuleLevelDocumenter(app):
app.env.ref_context['py:module'] = 'target.classes'
actual = do_autodoc(app, 'class', 'Foo')
assert list(actual) == [
'',
'.. py:class:: Foo()',
' :module: target.classes',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_pymodule_for_ClassLevelDocumenter(app):
app.env.ref_context['py:module'] = 'target.methods'
actual = do_autodoc(app, 'method', 'Base.meth')
assert list(actual) == [
'',
'.. py:method:: Base.meth()',
' :module: target.methods',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_pyclass_for_ClassLevelDocumenter(app):
app.env.ref_context['py:module'] = 'target.methods'
app.env.ref_context['py:class'] = 'Base'
actual = do_autodoc(app, 'method', 'meth')
assert list(actual) == [
'',
'.. py:method:: Base.meth()',
' :module: target.methods',
'',
]
@pytest.mark.sphinx('dummy', testroot='ext-autodoc')
def test_autodoc(app, status, warning):
app.builder.build_all()
@@ -1899,3 +1950,71 @@ my_name
alias of bug2437.autodoc_dummy_foo.Foo"""
assert warning.getvalue() == ''
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_name_conflict(app):
actual = do_autodoc(app, 'class', 'target.name_conflict.foo')
assert list(actual) == [
'',
'.. py:class:: foo()',
' :module: target.name_conflict',
'',
' docstring of target.name_conflict::foo.',
'',
]
actual = do_autodoc(app, 'class', 'target.name_conflict.foo.bar')
assert list(actual) == [
'',
'.. py:class:: bar()',
' :module: target.name_conflict.foo',
'',
' docstring of target.name_conflict.foo::bar.',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_name_mangling(app):
options = {"members": None,
"undoc-members": None,
"private-members": None}
actual = do_autodoc(app, 'module', 'target.name_mangling', options)
assert list(actual) == [
'',
'.. py:module:: target.name_mangling',
'',
'',
'.. py:class:: Bar()',
' :module: target.name_mangling',
'',
'',
' .. py:attribute:: Bar._Baz__email',
' :module: target.name_mangling',
' :value: None',
'',
' a member having mangled-like name',
'',
'',
' .. py:attribute:: Bar.__address',
' :module: target.name_mangling',
' :value: None',
'',
'',
'.. py:class:: Foo()',
' :module: target.name_mangling',
'',
'',
' .. py:attribute:: Foo.__age',
' :module: target.name_mangling',
' :value: None',
'',
'',
' .. py:attribute:: Foo.__name',
' :module: target.name_mangling',
' :value: None',
'',
' name of Foo',
'',
]

View File

@@ -85,8 +85,8 @@ def test_methoddescriptor(app):
actual = do_autodoc(app, 'function', 'builtins.int.__add__')
assert list(actual) == [
'',
'.. py:function:: int.__add__(self, value, /)',
' :module: builtins',
'.. py:function:: __add__(self, value, /)',
' :module: builtins.int',
'',
' Return self+value.',
'',
@@ -98,7 +98,7 @@ def test_decorated(app):
actual = do_autodoc(app, 'function', 'target.decorator.foo')
assert list(actual) == [
'',
'.. py:function:: foo()',
'.. py:function:: foo(name=None, age=None)',
' :module: target.decorator',
'',
]
@@ -146,3 +146,16 @@ def test_wrapped_function(app):
' This function is slow.',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_wrapped_function_contextmanager(app):
actual = do_autodoc(app, 'function', 'target.wrappedfunction.feeling_good')
assert list(actual) == [
'',
'.. py:function:: feeling_good(x: int, y: int) -> Generator',
' :module: target.wrappedfunction',
'',
" You'll feel better in this context!",
'',
]

View File

@@ -13,6 +13,8 @@ import sys
import pytest
from sphinx.testing import restructuredtext
from test_ext_autodoc import do_autodoc
IS_PYPY = platform.python_implementation() == 'PyPy'
@@ -633,6 +635,12 @@ def test_autodoc_typehints_description(app):
in context)
@pytest.mark.sphinx('text', testroot='ext-autodoc',
confoverrides={'autodoc_typehints': "description"})
def test_autodoc_typehints_description_for_invalid_node(app):
text = ".. py:function:: hello; world"
restructuredtext.parse(app, text) # raises no error
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_options(app):

View File

@@ -11,6 +11,7 @@
import abc
import sys
from importlib import import_module
from typing import TypeVar
import pytest
@@ -39,6 +40,7 @@ def test_MockObject():
assert isinstance(mock.attr1.attr2, _MockObject)
assert isinstance(mock.attr1.attr2.meth(), _MockObject)
# subclassing
class SubClass(mock.SomeClass):
"""docstring of SubClass"""
@@ -51,6 +53,16 @@ def test_MockObject():
assert obj.method() == "string"
assert isinstance(obj.other_method(), SubClass)
# parametrized type
T = TypeVar('T')
class SubClass2(mock.SomeClass[T]):
"""docstring of SubClass"""
obj2 = SubClass2()
assert SubClass2.__doc__ == "docstring of SubClass"
assert isinstance(obj2, SubClass2)
def test_mock():
modname = 'sphinx.unknown'

View File

@@ -97,7 +97,7 @@ def test_extract_summary(capsys):
# abbreviations
doc = ['Blabla, i.e. bla.']
assert extract_summary(doc, document) == 'Blabla, i.e.'
assert extract_summary(doc, document) == ' '.join(doc)
# literal
doc = ['blah blah::']
@@ -108,6 +108,12 @@ def test_extract_summary(capsys):
'=========']
assert extract_summary(doc, document) == 'blah blah'
# hyperlink target
doc = ['Do `this <https://www.sphinx-doc.org/>`_ and that. '
'blah blah blah.']
assert (extract_summary(doc, document) ==
'Do `this <https://www.sphinx-doc.org/>`_ and that.')
_, err = capsys.readouterr()
assert err == ''
@@ -202,17 +208,17 @@ def test_autosummary_generate_content_for_module(app):
assert template.render.call_args[0][0] == 'module'
context = template.render.call_args[0][1]
assert context['members'] == ['Exc', 'Foo', '_Baz', '_Exc', '__builtins__',
'__cached__', '__doc__', '__file__', '__name__',
'__package__', '_quux', 'bar', 'qux']
assert context['members'] == ['CONSTANT1', 'CONSTANT2', 'Exc', 'Foo', '_Baz', '_Exc',
'__builtins__', '__cached__', '__doc__', '__file__',
'__name__', '__package__', '_quux', 'bar', 'qux']
assert context['functions'] == ['bar']
assert context['all_functions'] == ['_quux', 'bar']
assert context['classes'] == ['Foo']
assert context['all_classes'] == ['Foo', '_Baz']
assert context['exceptions'] == ['Exc']
assert context['all_exceptions'] == ['Exc', '_Exc']
assert context['attributes'] == ['qux']
assert context['all_attributes'] == ['qux']
assert context['attributes'] == ['CONSTANT1', 'qux']
assert context['all_attributes'] == ['CONSTANT1', 'qux']
assert context['fullname'] == 'autosummary_dummy_module'
assert context['module'] == 'autosummary_dummy_module'
assert context['objname'] == ''
@@ -233,8 +239,9 @@ def test_autosummary_generate_content_for_module_skipped(app):
generate_autosummary_content('autosummary_dummy_module', autosummary_dummy_module, None,
template, None, False, app, False, {})
context = template.render.call_args[0][1]
assert context['members'] == ['_Baz', '_Exc', '__builtins__', '__cached__', '__doc__',
'__file__', '__name__', '__package__', '_quux', 'qux']
assert context['members'] == ['CONSTANT1', 'CONSTANT2', '_Baz', '_Exc', '__builtins__',
'__cached__', '__doc__', '__file__', '__name__',
'__package__', '_quux', 'qux']
assert context['functions'] == []
assert context['classes'] == []
assert context['exceptions'] == []
@@ -250,18 +257,18 @@ def test_autosummary_generate_content_for_module_imported_members(app):
assert template.render.call_args[0][0] == 'module'
context = template.render.call_args[0][1]
assert context['members'] == ['Exc', 'Foo', 'Union', '_Baz', '_Exc', '__builtins__',
'__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', '_quux',
'bar', 'path', 'qux']
assert context['members'] == ['CONSTANT1', 'CONSTANT2', 'Exc', 'Foo', 'Union', '_Baz',
'_Exc', '__builtins__', '__cached__', '__doc__',
'__file__', '__loader__', '__name__', '__package__',
'__spec__', '_quux', 'bar', 'path', 'qux']
assert context['functions'] == ['bar']
assert context['all_functions'] == ['_quux', 'bar']
assert context['classes'] == ['Foo']
assert context['all_classes'] == ['Foo', '_Baz']
assert context['exceptions'] == ['Exc']
assert context['all_exceptions'] == ['Exc', '_Exc']
assert context['attributes'] == ['qux']
assert context['all_attributes'] == ['qux']
assert context['attributes'] == ['CONSTANT1', 'qux']
assert context['all_attributes'] == ['CONSTANT1', 'qux']
assert context['fullname'] == 'autosummary_dummy_module'
assert context['module'] == 'autosummary_dummy_module'
assert context['objname'] == ''
@@ -301,6 +308,11 @@ def test_autosummary_generate(app, status, warning):
' \n'
' Foo\n'
' \n' in module)
assert (' .. autosummary::\n'
' \n'
' CONSTANT1\n'
' qux\n'
' \n' in module)
Foo = (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').read_text()
assert '.. automethod:: __init__' in Foo
@@ -311,6 +323,8 @@ def test_autosummary_generate(app, status, warning):
' \n' in Foo)
assert (' .. autosummary::\n'
' \n'
' ~Foo.CONSTANT3\n'
' ~Foo.CONSTANT4\n'
' ~Foo.baz\n'
' \n' in Foo)
@@ -380,6 +394,20 @@ def test_autosummary_recursive(app, status, warning):
assert 'package.package.module' in content
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-filename-map')
def test_autosummary_filename_map(app, status, warning):
app.build()
assert (app.srcdir / 'generated' / 'module_mangled.rst').exists()
assert not (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').exists()
assert (app.srcdir / 'generated' / 'bar.rst').exists()
assert not (app.srcdir / 'generated' / 'autosummary_dummy_module.bar.rst').exists()
assert (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').exists()
html_warnings = app._warning.getvalue()
assert html_warnings == ''
@pytest.mark.sphinx('latex', **default_kw)
def test_autosummary_latex_table_colspec(app, status, warning):
app.builder.build_all()

View File

@@ -109,7 +109,7 @@ def test_inheritance_diagram(app, status, warning):
('dummy.test.B', 'dummy.test.B', [], None)
]
# inheritance diagram with 2 top classes and specifiying the entire module
# inheritance diagram with 2 top classes and specifying the entire module
# rendering should be
#
# A

View File

@@ -9,10 +9,12 @@
:license: BSD, see LICENSE for details.
"""
import sys
from collections import namedtuple
from unittest import TestCase, mock
from sphinx.application import Sphinx
from sphinx.testing.util import simple_decorator
from sphinx.ext.napoleon import _process_docstring, _skip_member, Config, setup
@@ -49,6 +51,11 @@ class SampleClass:
def __special_undoc__(self):
pass
@simple_decorator
def __decorated_func__(self):
"""doc"""
pass
class SampleError(Exception):
def _private_doc(self):
@@ -129,16 +136,25 @@ class SkipMemberTest(TestCase):
self.assertEqual(None, _skip_member(app, what, member, obj, skip,
mock.Mock()))
else:
self.assertFalse(_skip_member(app, what, member, obj, skip,
mock.Mock()))
self.assertIs(_skip_member(app, what, member, obj, skip,
mock.Mock()), False)
setattr(app.config, config_name, False)
self.assertEqual(None, _skip_member(app, what, member, obj, skip,
mock.Mock()))
def test_namedtuple(self):
self.assertSkip('class', '_asdict',
SampleNamedTuple._asdict, False,
'napoleon_include_private_with_doc')
if sys.version_info < (3, 7):
self.assertSkip('class', '_asdict',
SampleNamedTuple._asdict, False,
'napoleon_include_private_with_doc')
else:
# Since python 3.7, namedtuple._asdict() has not been documented
# because there is no way to check the method is a member of the
# namedtuple class. This testcase confirms only it does not
# raise an error on building document (refs: #1455)
self.assertSkip('class', '_asdict',
SampleNamedTuple._asdict, True,
'napoleon_include_private_with_doc')
def test_class_private_doc(self):
self.assertSkip('class', '_private_doc',
@@ -160,6 +176,11 @@ class SkipMemberTest(TestCase):
SampleClass.__special_undoc__, True,
'napoleon_include_special_with_doc')
def test_class_decorated_doc(self):
self.assertSkip('class', '__decorated_func__',
SampleClass.__decorated_func__, False,
'napoleon_include_special_with_doc')
def test_exception_private_doc(self):
self.assertSkip('exception', '_private_doc',
SampleError._private_doc, False,

View File

@@ -20,6 +20,12 @@ import pytest
from sphinx.ext.napoleon import Config
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
from sphinx.ext.napoleon.docstring import (
_tokenize_type_spec,
_recombine_set_tokens,
_convert_numpy_type_spec,
_token_type
)
class NamedtupleSubclass(namedtuple('NamedtupleSubclass', ('attr1', 'attr2'))):
@@ -57,19 +63,22 @@ class NamedtupleSubclassTest(BaseDocstringTest):
Sample namedtuple subclass
.. attribute:: attr1
:type: Arbitrary type
Quick description of attr1
:type: Arbitrary type
.. attribute:: attr2
:type: Another arbitrary type
Quick description of attr2
:type: Another arbitrary type
.. attribute:: attr3
:type: Type
Adds a newline after the type
:type: Type
"""
self.assertEqual(expected, actual)
@@ -413,9 +422,10 @@ Attributes:
actual = str(GoogleDocstring(docstring))
expected = """\
.. attribute:: in_attr
:type: :class:`numpy.ndarray`
super-dooper attribute
:type: :class:`numpy.ndarray`
"""
self.assertEqual(expected, actual)
@@ -427,9 +437,10 @@ Attributes:
actual = str(GoogleDocstring(docstring))
expected = """\
.. attribute:: in_attr
:type: numpy.ndarray
super-dooper attribute
:type: numpy.ndarray
"""
self.assertEqual(expected, actual)
@@ -1992,6 +2003,154 @@ definition_after_normal_text : int
actual = str(NumpyDocstring(docstring, config))
self.assertEqual(expected, actual)
def test_token_type(self):
tokens = (
("1", "literal"),
("'string'", "literal"),
('"another_string"', "literal"),
("{1, 2}", "literal"),
("{'va{ue', 'set'}", "literal"),
("optional", "control"),
("default", "control"),
(", ", "delimiter"),
(" of ", "delimiter"),
(" or ", "delimiter"),
(": ", "delimiter"),
("True", "obj"),
("None", "obj"),
("name", "obj"),
(":py:class:`Enum`", "reference"),
)
for token, expected in tokens:
actual = _token_type(token)
self.assertEqual(expected, actual)
def test_tokenize_type_spec(self):
specs = (
"str",
"int or float or None, optional",
'{"F", "C", "N"}',
"{'F', 'C', 'N'}, default: 'F'",
"{'F', 'C', 'N or C'}, default 'F'",
'"ma{icious"',
r"'with \'quotes\''",
)
tokens = (
["str"],
["int", " or ", "float", " or ", "None", ", ", "optional"],
["{", '"F"', ", ", '"C"', ", ", '"N"', "}"],
["{", "'F'", ", ", "'C'", ", ", "'N'", "}", ", ", "default", ": ", "'F'"],
["{", "'F'", ", ", "'C'", ", ", "'N or C'", "}", ", ", "default", " ", "'F'"],
['"ma{icious"'],
[r"'with \'quotes\''"],
)
for spec, expected in zip(specs, tokens):
actual = _tokenize_type_spec(spec)
self.assertEqual(expected, actual)
def test_recombine_set_tokens(self):
tokens = (
["{", "1", ", ", "2", "}"],
["{", '"F"', ", ", '"C"', ", ", '"N"', "}", ", ", "optional"],
["{", "'F'", ", ", "'C'", ", ", "'N'", "}", ", ", "default", ": ", "None"],
)
combined_tokens = (
["{1, 2}"],
['{"F", "C", "N"}', ", ", "optional"],
["{'F', 'C', 'N'}", ", ", "default", ": ", "None"],
)
for tokens_, expected in zip(tokens, combined_tokens):
actual = _recombine_set_tokens(tokens_)
self.assertEqual(expected, actual)
def test_recombine_set_tokens_invalid(self):
tokens = (
["{", "1", ", ", "2"],
['"F"', ", ", '"C"', ", ", '"N"', "}", ", ", "optional"],
["{", "1", ", ", "2", ", ", "default", ": ", "None"],
)
combined_tokens = (
["{1, 2"],
['"F"', ", ", '"C"', ", ", '"N"', "}", ", ", "optional"],
["{1, 2", ", ", "default", ": ", "None"],
)
for tokens_, expected in zip(tokens, combined_tokens):
actual = _recombine_set_tokens(tokens_)
self.assertEqual(expected, actual)
def test_convert_numpy_type_spec(self):
translations = {
"DataFrame": "pandas.DataFrame",
}
specs = (
"",
"optional",
"str, optional",
"int or float or None, default: None",
'{"F", "C", "N"}',
"{'F', 'C', 'N'}, default: 'N'",
"DataFrame, optional",
)
converted = (
"",
"*optional*",
":class:`str`, *optional*",
":class:`int` or :class:`float` or :obj:`None`, *default*: :obj:`None`",
'``{"F", "C", "N"}``',
"``{'F', 'C', 'N'}``, *default*: ``'N'``",
":class:`pandas.DataFrame`, *optional*",
)
for spec, expected in zip(specs, converted):
actual = _convert_numpy_type_spec(spec, translations=translations)
self.assertEqual(expected, actual)
def test_parameter_types(self):
docstring = dedent("""\
Parameters
----------
param1 : DataFrame
the data to work on
param2 : int or float or None
a parameter with different types
param3 : dict-like, optional
a optional mapping
param4 : int or float or None, optional
a optional parameter with different types
param5 : {"F", "C", "N"}, optional
a optional parameter with fixed values
""")
expected = dedent("""\
:param param1: the data to work on
:type param1: DataFrame
:param param2: a parameter with different types
:type param2: :class:`int` or :class:`float` or :obj:`None`
:param param3: a optional mapping
:type param3: :term:`dict-like <mapping>`, *optional*
:param param4: a optional parameter with different types
:type param4: :class:`int` or :class:`float` or :obj:`None`, *optional*
:param param5: a optional parameter with fixed values
:type param5: ``{"F", "C", "N"}``, *optional*
""")
translations = {
"dict-like": ":term:`dict-like <mapping>`",
}
config = Config(
napoleon_use_param=True,
napoleon_use_rtype=True,
napoleon_type_aliases=translations,
)
actual = str(NumpyDocstring(docstring, config))
self.assertEqual(expected, actual)
def test_keywords_with_types(self):
docstring = """\
Do as you please
@@ -2019,9 +2178,31 @@ def warns(warning, match):
warnings = [w for w in raw_warnings.split("\n") if w.strip()]
assert len(warnings) == 1 and all(match_re.match(w) for w in warnings)
warning.truncate(0)
class TestNumpyDocstring:
def test_token_type_invalid(self, warning):
tokens = (
"{1, 2",
"}",
"'abc",
"def'",
'"ghi',
'jkl"',
)
errors = (
r".+: invalid value set \(missing closing brace\):",
r".+: invalid value set \(missing opening brace\):",
r".+: malformed string literal \(missing closing quote\):",
r".+: malformed string literal \(missing opening quote\):",
r".+: malformed string literal \(missing closing quote\):",
r".+: malformed string literal \(missing opening quote\):",
)
for token, error in zip(tokens, errors):
with warns(warning, match=error):
_token_type(token)
@pytest.mark.parametrize(
["spec", "pattern"],
(

View File

@@ -956,9 +956,9 @@ def test_xml_role_xref(app):
'glossary_terms#term-Some-term'])
assert_elem(
para2[1],
['LINK TO', 'SAME TYPE LINKS', 'AND',
"I18N ROCK'N ROLE XREF", '.'],
['same-type-links', 'i18n-role-xref'])
['LINK TO', 'LABEL', 'AND',
'SAME TYPE LINKS', 'AND', 'SAME TYPE LINKS', '.'],
['i18n-role-xref', 'same-type-links', 'same-type-links'])
assert_elem(
para2[2],
['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS', '.'],

View File

@@ -50,7 +50,7 @@ def test_RSTParser_prolog_epilog(RSTStateMachine, app):
(content, _), _ = RSTStateMachine().run.call_args
assert list(content.xitems()) == [('dummy.rst', 0, 'hello Sphinx world'),
('dummy.rst', 1, 'Sphinx is a document generator'),
('<generated>', 0, ''),
('dummy.rst', 2, ''),
('<rst_epilog>', 0, 'this is rst_epilog'),
('<rst_epilog>', 1, 'good-bye reST!')]

View File

@@ -130,7 +130,7 @@ def test_signature_partialmethod():
def test_signature_annotations():
from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10,
f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, Node)
f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, Node)
# Class annotations
sig = inspect.signature(f0)
@@ -214,6 +214,10 @@ def test_signature_annotations():
sig = inspect.signature(f19)
assert stringify_signature(sig) == '(*args: int, **kwargs: str)'
# default value is inspect.Signature.empty
sig = inspect.signature(f21)
assert stringify_signature(sig) == "(arg1='whatever', arg2)"
# type hints by string
sig = inspect.signature(Node.children)
if (3, 5, 0) <= sys.version_info < (3, 5, 3):

View File

@@ -32,7 +32,7 @@ def test_append_epilog(app):
assert list(content.xitems()) == [('dummy.rst', 0, 'hello Sphinx world'),
('dummy.rst', 1, 'Sphinx is a document generator'),
('<generated>', 0, ''),
('dummy.rst', 2, ''),
('<rst_epilog>', 0, 'this is rst_epilog'),
('<rst_epilog>', 1, 'good-bye reST!')]

View File

@@ -10,7 +10,9 @@
import sys
from numbers import Integral
from typing import Any, Dict, List, TypeVar, Union, Callable, Tuple, Optional, Generic
from typing import (
Any, Dict, Generator, List, TypeVar, Union, Callable, Tuple, Optional, Generic
)
import pytest
@@ -48,6 +50,7 @@ def test_stringify_type_hints_containers():
assert stringify(Tuple[str, ...]) == "Tuple[str, ...]"
assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]"
assert stringify(MyList[Tuple[int, int]]) == "test_util_typing.MyList[Tuple[int, int]]"
assert stringify(Generator[None, None, None]) == "Generator[None, None, None]"
@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.')

View File

@@ -1,3 +1,4 @@
from inspect import Signature
from numbers import Integral
from typing import Any, Dict, List, TypeVar, Union, Callable, Tuple, Optional
@@ -100,6 +101,9 @@ def f20() -> Optional[Union[int, str]]:
pass
def f21(arg1='whatever', arg2=Signature.empty):
pass
class Node:
def __init__(self, parent: Optional['Node']) -> None: