mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x' into master
This commit is contained in:
@@ -1 +1 @@
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
25
tests/roots/test-ext-autodoc/target/annotations.py
Normal file
25
tests/roots/test-ext-autodoc/target/annotations.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from __future__ import annotations
|
||||
from typing import overload
|
||||
|
||||
|
||||
myint = int
|
||||
|
||||
|
||||
def sum(x: myint, y: myint) -> myint:
|
||||
"""docstring"""
|
||||
return x + y
|
||||
|
||||
|
||||
@overload
|
||||
def mult(x: myint, y: myint) -> myint:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def mult(x: float, y: float) -> float:
|
||||
...
|
||||
|
||||
|
||||
def mult(x, y):
|
||||
"""docstring"""
|
||||
return x, y
|
||||
@@ -1,5 +1,5 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C)
|
||||
# Copyright (C)
|
||||
# This file is distributed under the same license as the Sphinx intl <Tests> package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
|
||||
2
tests/roots/test-linkcheck-localserver/conf.py
Normal file
2
tests/roots/test-linkcheck-localserver/conf.py
Normal file
@@ -0,0 +1,2 @@
|
||||
exclude_patterns = ['_build']
|
||||
linkcheck_anchors = True
|
||||
1
tests/roots/test-linkcheck-localserver/index.rst
Normal file
1
tests/roots/test-linkcheck-localserver/index.rst
Normal file
@@ -0,0 +1 @@
|
||||
`local server <http://localhost:7777/#anchor>`_
|
||||
@@ -1 +1 @@
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
recursive-include test_theme *.conf
|
||||
|
||||
recursive-include test_theme *.conf
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
html_theme = 'test-theme'
|
||||
html_theme_path = ['.', 'test_theme']
|
||||
exclude_patterns = ['_build']
|
||||
html_theme = 'test-theme'
|
||||
html_theme_path = ['.', 'test_theme']
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
=======
|
||||
Theming
|
||||
=======
|
||||
|
||||
|
||||
=======
|
||||
Theming
|
||||
=======
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='test-theme',
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
entry_points="""
|
||||
[sphinx_themes]
|
||||
path = test_theme:get_path
|
||||
""",
|
||||
)
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='test-theme',
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
entry_points="""
|
||||
[sphinx_themes]
|
||||
path = test_theme:get_path
|
||||
""",
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
|
||||
|
||||
def get_path():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
import os
|
||||
|
||||
|
||||
def get_path():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import http.server
|
||||
import json
|
||||
import re
|
||||
import threading
|
||||
from unittest import mock
|
||||
import pytest
|
||||
|
||||
@@ -106,6 +108,21 @@ def test_anchors_ignored(app, status, warning):
|
||||
# expect all ok when excluding #top
|
||||
assert not content
|
||||
|
||||
@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True)
|
||||
def test_raises_for_invalid_status(app, status, warning):
|
||||
server_thread = HttpServerThread(InternalServerErrorHandler, daemon=True)
|
||||
server_thread.start()
|
||||
try:
|
||||
app.builder.build_all()
|
||||
finally:
|
||||
server_thread.terminate()
|
||||
content = (app.outdir / 'output.txt').read_text()
|
||||
assert content == (
|
||||
"index.rst:1: [broken] http://localhost:7777/#anchor: "
|
||||
"500 Server Error: Internal Server Error "
|
||||
"for url: http://localhost:7777/\n"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'linkcheck', testroot='linkcheck', freshenv=True,
|
||||
@@ -160,3 +177,22 @@ def test_linkcheck_request_headers(app, status, warning):
|
||||
assert headers["X-Secret"] == "open sesami"
|
||||
else:
|
||||
assert headers["Accept"] == "text/html,application/xhtml+xml;q=0.9,*/*;q=0.8"
|
||||
|
||||
|
||||
class HttpServerThread(threading.Thread):
|
||||
def __init__(self, handler, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.server = http.server.HTTPServer(("localhost", 7777), handler)
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever(poll_interval=0.01)
|
||||
|
||||
def terminate(self):
|
||||
self.server.shutdown()
|
||||
self.server.server_close()
|
||||
self.join()
|
||||
|
||||
|
||||
class InternalServerErrorHandler(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
self.send_error(500, "Internal Server Error")
|
||||
|
||||
@@ -30,6 +30,13 @@ def test_all(app, status, warning):
|
||||
assert 'Footnotes' not in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('man', testroot='basic',
|
||||
confoverrides={'man_make_section_directory': True})
|
||||
def test_man_make_section_directory(app, status, warning):
|
||||
app.build()
|
||||
assert (app.outdir / '1' / 'python.1').exists()
|
||||
|
||||
|
||||
@pytest.mark.sphinx('man', testroot='directive-code')
|
||||
def test_captioned_code_block(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
@@ -642,6 +642,54 @@ def test_autodoc_typehints_description_for_invalid_node(app):
|
||||
restructuredtext.parse(app, text) # raises no error
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
|
||||
@pytest.mark.sphinx('text', testroot='ext-autodoc')
|
||||
def test_autodoc_type_aliases(app):
|
||||
# default
|
||||
options = {"members": None}
|
||||
actual = do_autodoc(app, 'module', 'target.annotations', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.annotations',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: mult(x: int, y: int) -> int',
|
||||
' mult(x: float, y: float) -> float',
|
||||
' :module: target.annotations',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: sum(x: int, y: int) -> int',
|
||||
' :module: target.annotations',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
]
|
||||
|
||||
# define aliases
|
||||
app.config.autodoc_type_aliases = {'myint': 'myint'}
|
||||
actual = do_autodoc(app, 'module', 'target.annotations', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.annotations',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: mult(x: myint, y: myint) -> myint',
|
||||
' mult(x: float, y: float) -> float',
|
||||
' :module: target.annotations',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: sum(x: myint, y: myint) -> myint',
|
||||
' :module: target.annotations',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_default_options(app):
|
||||
# no settings
|
||||
|
||||
@@ -14,8 +14,10 @@ import re
|
||||
|
||||
import pytest
|
||||
from babel.messages import pofile, mofile
|
||||
from babel.messages.catalog import Catalog
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx import locale
|
||||
from sphinx.testing.util import (
|
||||
path, etree_parse, strip_escseq,
|
||||
assert_re_search, assert_not_re_search, assert_startswith, assert_node
|
||||
@@ -1289,3 +1291,30 @@ def test_image_glob_intl_using_figure_language_filename(app):
|
||||
|
||||
def getwarning(warnings):
|
||||
return strip_escseq(warnings.getvalue().replace(os.sep, '/'))
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='basic', confoverrides={'language': 'de'})
|
||||
def test_customize_system_message(make_app, app_params, sphinx_test_tempdir):
|
||||
try:
|
||||
# clear translators cache
|
||||
locale.translators.clear()
|
||||
|
||||
# prepare message catalog (.po)
|
||||
locale_dir = sphinx_test_tempdir / 'basic' / 'locales' / 'de' / 'LC_MESSAGES'
|
||||
locale_dir.makedirs()
|
||||
with (locale_dir / 'sphinx.po').open('wb') as f:
|
||||
catalog = Catalog()
|
||||
catalog.add('Quick search', 'QUICK SEARCH')
|
||||
pofile.write_po(f, catalog)
|
||||
|
||||
# construct application and convert po file to .mo
|
||||
args, kwargs = app_params
|
||||
app = make_app(*args, **kwargs)
|
||||
assert (locale_dir / 'sphinx.mo').exists()
|
||||
assert app.translator.gettext('Quick search') == 'QUICK SEARCH'
|
||||
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert 'QUICK SEARCH' in content
|
||||
finally:
|
||||
locale.translators.clear()
|
||||
|
||||
@@ -26,7 +26,7 @@ def test_ModuleAnalyzer_get_module_source():
|
||||
ModuleAnalyzer.get_module_source('builtins')
|
||||
with pytest.raises(PycodeError):
|
||||
ModuleAnalyzer.get_module_source('itertools')
|
||||
|
||||
|
||||
|
||||
def test_ModuleAnalyzer_for_string():
|
||||
analyzer = ModuleAnalyzer.for_string('print("Hello world")', 'module_name')
|
||||
|
||||
@@ -53,7 +53,7 @@ from sphinx.pycode import ast
|
||||
("+ a", "+ a"), # UAdd
|
||||
("- 1", "- 1"), # UnaryOp
|
||||
("- a", "- a"), # USub
|
||||
("(1, 2, 3)", "1, 2, 3"), # Tuple
|
||||
("(1, 2, 3)", "(1, 2, 3)"), # Tuple
|
||||
("()", "()"), # Tuple (empty)
|
||||
])
|
||||
def test_unparse(source, expected):
|
||||
|
||||
@@ -32,6 +32,10 @@ class MyList(List[T]):
|
||||
pass
|
||||
|
||||
|
||||
class BrokenType:
|
||||
__args__ = int
|
||||
|
||||
|
||||
def test_stringify():
|
||||
assert stringify(int) == "int"
|
||||
assert stringify(str) == "str"
|
||||
@@ -113,3 +117,7 @@ def test_stringify_type_hints_alias():
|
||||
MyTuple = Tuple[str, str]
|
||||
assert stringify(MyStr) == "str"
|
||||
assert stringify(MyTuple) == "Tuple[str, str]" # type: ignore
|
||||
|
||||
|
||||
def test_stringify_broken_type_hints():
|
||||
assert stringify(BrokenType) == 'test_util_typing.BrokenType'
|
||||
|
||||
Reference in New Issue
Block a user