mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x'
This commit is contained in:
commit
8bf84167a3
42
.github/workflows/main.yml
vendored
42
.github/workflows/main.yml
vendored
@ -1,9 +1,47 @@
|
|||||||
name: CI on Windows
|
name: CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
ubuntu:
|
||||||
|
runs-on: ubuntu-16.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
name: [py36, py37, py38]
|
||||||
|
include:
|
||||||
|
- name: py36
|
||||||
|
python: 3.6
|
||||||
|
docutils: du13
|
||||||
|
- name: py37
|
||||||
|
python: 3.7
|
||||||
|
docutils: du14
|
||||||
|
- name: py38
|
||||||
|
python: 3.8
|
||||||
|
docutils: du15
|
||||||
|
coverage: "--cov ./ --cov-append --cov-config setup.cfg"
|
||||||
|
env:
|
||||||
|
PYTEST_ADDOPTS: ${{ matrix.coverage }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python ${{ matrix.python }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python }}
|
||||||
|
- name: Check Python version
|
||||||
|
run: python --version
|
||||||
|
- name: Install graphviz
|
||||||
|
run: sudo apt-get install graphviz
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pip install -U tox codecov
|
||||||
|
- name: Run Tox
|
||||||
|
run: tox -e ${{ matrix.docutils }} -- -vv
|
||||||
|
- name: codecov
|
||||||
|
uses: codecov/codecov-action@v1
|
||||||
|
if: matrix.coverage
|
||||||
|
|
||||||
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
21
.github/workflows/nodejs.yml
vendored
Normal file
21
.github/workflows/nodejs.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: CI (node.js)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
node-version: 10.7
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ env.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.node-version }}
|
||||||
|
- run: npm install
|
||||||
|
- name: Run headless test
|
||||||
|
uses: GabrielBB/xvfb-action@v1
|
||||||
|
with:
|
||||||
|
run: npm test
|
43
.travis.yml
43
.travis.yml
@ -1,43 +0,0 @@
|
|||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
language: python
|
|
||||||
cache: pip
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PYTHONFAULTHANDLER=x
|
|
||||||
- SKIP_LATEX_BUILD=1
|
|
||||||
- IS_PYTHON=true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- python: '3.6'
|
|
||||||
env:
|
|
||||||
- TOXENV=du14
|
|
||||||
- python: '3.7'
|
|
||||||
env:
|
|
||||||
- TOXENV=du15
|
|
||||||
- python: '3.8'
|
|
||||||
env:
|
|
||||||
- TOXENV=du16
|
|
||||||
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
|
||||||
- python: '3.9'
|
|
||||||
env:
|
|
||||||
- TOXENV=py39
|
|
||||||
|
|
||||||
- language: node_js
|
|
||||||
node_js: '10.7'
|
|
||||||
env: IS_PYTHON=false
|
|
||||||
services: xvfb
|
|
||||||
|
|
||||||
install:
|
|
||||||
- "sudo apt-get install graphviz"
|
|
||||||
- if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi
|
|
||||||
- if [ $IS_PYTHON = false ]; then npm install; fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [ $IS_PYTHON = true ]; then tox -- -vv; fi
|
|
||||||
- if [ $IS_PYTHON = false ]; then npm test; fi
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- if [[ -e .coverage ]]; then codecov -e $TOXENV; fi
|
|
6
CHANGES
6
CHANGES
@ -64,9 +64,15 @@ Deprecated
|
|||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
* #6914: Add a new event :event:`warn-missing-reference` to custom warning
|
||||||
|
messages when failed to resolve a cross-reference
|
||||||
|
* #6914: Emit a detailed warning when failed to resolve a ``:ref:`` reference
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* #7613: autodoc: autodoc does not respect __signature__ of the class
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -22,9 +22,9 @@ Extensions
|
|||||||
|
|
||||||
To learn how to write your own extension, see :ref:`dev-extensions`.
|
To learn how to write your own extension, see :ref:`dev-extensions`.
|
||||||
|
|
||||||
The `sphinx-contrib <https://bitbucket.org/birkenfeld/sphinx-contrib/>`_
|
The `sphinx-contrib <https://github.com/sphinx-contrib>`_ repository contains many
|
||||||
repository contains many contributed extensions. Some of them have their own
|
contributed extensions. Some of them have their own releases on PyPI, others you
|
||||||
releases on PyPI, others you can install from a checkout.
|
can install from a checkout.
|
||||||
|
|
||||||
This is the current list of contributed extensions in that repository:
|
This is the current list of contributed extensions in that repository:
|
||||||
|
|
||||||
|
@ -186,6 +186,7 @@ type for that event::
|
|||||||
13. apply post-transforms (by priority): docutils.document -> docutils.document
|
13. apply post-transforms (by priority): docutils.document -> docutils.document
|
||||||
14. event.doctree-resolved(app, doctree, docname)
|
14. event.doctree-resolved(app, doctree, docname)
|
||||||
- (for any reference node that fails to resolve) event.missing-reference(env, node, contnode)
|
- (for any reference node that fails to resolve) event.missing-reference(env, node, contnode)
|
||||||
|
- (for any reference node that fails to resolve) event.warn-missing-reference(domain, node)
|
||||||
|
|
||||||
15. Generate output files
|
15. Generate output files
|
||||||
16. event.build-finished(app, exception)
|
16. event.build-finished(app, exception)
|
||||||
@ -284,6 +285,14 @@ Here is a more detailed list of these events.
|
|||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.5
|
||||||
|
|
||||||
|
.. event:: warn-missing-reference (app, domain, node)
|
||||||
|
|
||||||
|
Emitted when a cross-reference to an object cannot be resolved even after
|
||||||
|
:event:`missing-reference`. If the event handler can emit warnings for
|
||||||
|
the missing reference, it should return ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
.. event:: doctree-resolved (app, doctree, docname)
|
.. event:: doctree-resolved (app, doctree, docname)
|
||||||
|
|
||||||
Emitted when a doctree has been "resolved" by the environment, that is, all
|
Emitted when a doctree has been "resolved" by the environment, that is, all
|
||||||
|
@ -595,8 +595,6 @@ class StandardDomain(Domain):
|
|||||||
|
|
||||||
dangling_warnings = {
|
dangling_warnings = {
|
||||||
'term': 'term not in glossary: %(target)s',
|
'term': 'term not in glossary: %(target)s',
|
||||||
'ref': 'undefined label: %(target)s (if the link has no caption '
|
|
||||||
'the label must precede a section header)',
|
|
||||||
'numref': 'undefined label: %(target)s',
|
'numref': 'undefined label: %(target)s',
|
||||||
'keyword': 'unknown keyword: %(target)s',
|
'keyword': 'unknown keyword: %(target)s',
|
||||||
'doc': 'unknown document: %(target)s',
|
'doc': 'unknown document: %(target)s',
|
||||||
@ -1075,8 +1073,23 @@ class StandardDomain(Domain):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def warn_missing_reference(app: "Sphinx", domain: Domain, node: pending_xref) -> bool:
|
||||||
|
if domain.name != 'std' or node['reftype'] != 'ref':
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
target = node['reftarget']
|
||||||
|
if target not in domain.anonlabels: # type: ignore
|
||||||
|
msg = __('undefined label: %s')
|
||||||
|
else:
|
||||||
|
msg = __('Failed to create a cross reference. A title or caption not found: %s')
|
||||||
|
|
||||||
|
logger.warning(msg % target, location=node, type='ref', subtype=node['reftype'])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def setup(app: "Sphinx") -> Dict[str, Any]:
|
def setup(app: "Sphinx") -> Dict[str, Any]:
|
||||||
app.add_domain(StandardDomain)
|
app.add_domain(StandardDomain)
|
||||||
|
app.connect('warn-missing-reference', warn_missing_reference)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
@ -45,6 +45,7 @@ core_events = {
|
|||||||
'doctree-read': 'the doctree before being pickled',
|
'doctree-read': 'the doctree before being pickled',
|
||||||
'env-merge-info': 'env, read docnames, other env instance',
|
'env-merge-info': 'env, read docnames, other env instance',
|
||||||
'missing-reference': 'env, node, contnode',
|
'missing-reference': 'env, node, contnode',
|
||||||
|
'warn-missing-reference': 'domain, node',
|
||||||
'doctree-resolved': 'doctree, docname',
|
'doctree-resolved': 'doctree, docname',
|
||||||
'env-updated': 'env',
|
'env-updated': 'env',
|
||||||
'html-collect-pages': 'builder',
|
'html-collect-pages': 'builder',
|
||||||
|
@ -1376,7 +1376,12 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
|||||||
# This sequence is copied from inspect._signature_from_callable.
|
# This sequence is copied from inspect._signature_from_callable.
|
||||||
# ValueError means that no signature could be found, so we keep going.
|
# ValueError means that no signature could be found, so we keep going.
|
||||||
|
|
||||||
# First, let's see if it has an overloaded __call__ defined
|
# First, we check the obj has a __signature__ attribute
|
||||||
|
if (hasattr(self.object, '__signature__') and
|
||||||
|
isinstance(self.object.__signature__, Signature)):
|
||||||
|
return None, None, self.object.__signature__
|
||||||
|
|
||||||
|
# Next, let's see if it has an overloaded __call__ defined
|
||||||
# in its metaclass
|
# in its metaclass
|
||||||
call = get_user_defined_function_or_method(type(self.object), '__call__')
|
call = get_user_defined_function_or_method(type(self.object), '__call__')
|
||||||
|
|
||||||
|
@ -166,7 +166,10 @@ class ReferencesResolver(SphinxPostTransform):
|
|||||||
warn = False
|
warn = False
|
||||||
if not warn:
|
if not warn:
|
||||||
return
|
return
|
||||||
if domain and typ in domain.dangling_warnings:
|
|
||||||
|
if self.app.emit_firstresult('warn-missing-reference', domain, node):
|
||||||
|
return
|
||||||
|
elif domain and typ in domain.dangling_warnings:
|
||||||
msg = domain.dangling_warnings[typ]
|
msg = domain.dangling_warnings[typ]
|
||||||
elif node.get('refdomain', 'std') not in ('', 'std'):
|
elif node.get('refdomain', 'std') not in ('', 'std'):
|
||||||
msg = (__('%s:%s reference target not found: %%(target)s') %
|
msg = (__('%s:%s reference target not found: %%(target)s') %
|
||||||
|
0
tests/roots/test-domain-py-xref-warning/conf.py
Normal file
0
tests/roots/test-domain-py-xref-warning/conf.py
Normal file
7
tests/roots/test-domain-py-xref-warning/index.rst
Normal file
7
tests/roots/test-domain-py-xref-warning/index.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
test-domain-py-xref-warning
|
||||||
|
===========================
|
||||||
|
|
||||||
|
.. _existing-label:
|
||||||
|
|
||||||
|
:ref:`no-label`
|
||||||
|
:ref:`existing-label`
|
@ -1,3 +1,6 @@
|
|||||||
|
from inspect import Parameter, Signature
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
class Foo:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -10,3 +13,11 @@ class Bar:
|
|||||||
class Baz:
|
class Baz:
|
||||||
def __new__(cls, x, y):
|
def __new__(cls, x, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Qux:
|
||||||
|
__signature__ = Signature(parameters=[Parameter('foo', Parameter.POSITIONAL_OR_KEYWORD),
|
||||||
|
Parameter('bar', Parameter.POSITIONAL_OR_KEYWORD)])
|
||||||
|
|
||||||
|
def __init__(self, x, y):
|
||||||
|
pass
|
||||||
|
@ -876,3 +876,11 @@ def test_noindexentry(app):
|
|||||||
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
|
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[0], addnodes.index, entries=[('single', 'f (built-in class)', 'f', '', None)])
|
||||||
assert_node(doctree[2], addnodes.index, entries=[])
|
assert_node(doctree[2], addnodes.index, entries=[])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('dummy', testroot='domain-py-xref-warning')
|
||||||
|
def test_warn_missing_reference(app, status, warning):
|
||||||
|
app.build()
|
||||||
|
assert 'index.rst:6: WARNING: undefined label: no-label' in warning.getvalue()
|
||||||
|
assert ('index.rst:6: WARNING: Failed to create a cross reference. A title or caption not found: existing-label'
|
||||||
|
in warning.getvalue())
|
||||||
|
@ -1832,19 +1832,26 @@ def test_autodoc_for_egged_code(app):
|
|||||||
def test_singledispatch(app):
|
def test_singledispatch(app):
|
||||||
options = {"members": None}
|
options = {"members": None}
|
||||||
actual = do_autodoc(app, 'module', 'target.singledispatch', options)
|
actual = do_autodoc(app, 'module', 'target.singledispatch', options)
|
||||||
assert list(actual) == [
|
if sys.version_info < (3, 6):
|
||||||
'',
|
# check the result via "in" because the order of singledispatch signatures is
|
||||||
'.. py:module:: target.singledispatch',
|
# usually changed (because dict is not OrderedDict yet!)
|
||||||
'',
|
assert '.. py:function:: func(arg, kwarg=None)' in actual
|
||||||
'',
|
assert ' func(arg: int, kwarg=None)' in actual
|
||||||
'.. py:function:: func(arg, kwarg=None)',
|
assert ' func(arg: str, kwarg=None)' in actual
|
||||||
' func(arg: int, kwarg=None)',
|
else:
|
||||||
' func(arg: str, kwarg=None)',
|
assert list(actual) == [
|
||||||
' :module: target.singledispatch',
|
'',
|
||||||
'',
|
'.. py:module:: target.singledispatch',
|
||||||
' A function for general use.',
|
'',
|
||||||
'',
|
'',
|
||||||
]
|
'.. py:function:: func(arg, kwarg=None)',
|
||||||
|
' func(arg: int, kwarg=None)',
|
||||||
|
' func(arg: str, kwarg=None)',
|
||||||
|
' :module: target.singledispatch',
|
||||||
|
'',
|
||||||
|
' A function for general use.',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(sys.version_info < (3, 8),
|
@pytest.mark.skipif(sys.version_info < (3, 8),
|
||||||
|
50
tests/test_ext_autodoc_autoclass.py
Normal file
50
tests/test_ext_autodoc_autoclass.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
test_ext_autodoc_autoclass
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test the autodoc extension. This tests mainly the Documenters; the auto
|
||||||
|
directives are tested in a test source file translated by test_build.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from test_ext_autodoc import do_autodoc
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_classes(app):
|
||||||
|
actual = do_autodoc(app, 'function', 'target.classes.Foo')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: Foo()',
|
||||||
|
' :module: target.classes',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.classes.Bar')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: Bar(x, y)',
|
||||||
|
' :module: target.classes',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.classes.Baz')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: Baz(x, y)',
|
||||||
|
' :module: target.classes',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.classes.Qux')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: Qux(foo, bar)',
|
||||||
|
' :module: target.classes',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
@ -9,6 +9,8 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from test_ext_autodoc import do_autodoc
|
from test_ext_autodoc import do_autodoc
|
||||||
@ -40,6 +42,14 @@ def test_classes(app):
|
|||||||
'',
|
'',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.classes.Qux')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: Qux(foo, bar)',
|
||||||
|
' :module: target.classes',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_callable(app):
|
def test_callable(app):
|
||||||
@ -108,16 +118,23 @@ def test_decorated(app):
|
|||||||
def test_singledispatch(app):
|
def test_singledispatch(app):
|
||||||
options = {}
|
options = {}
|
||||||
actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
|
actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
|
||||||
assert list(actual) == [
|
if sys.version_info < (3, 6):
|
||||||
'',
|
# check the result via "in" because the order of singledispatch signatures is
|
||||||
'.. py:function:: func(arg, kwarg=None)',
|
# usually changed (because dict is not OrderedDict yet!)
|
||||||
' func(arg: int, kwarg=None)',
|
assert '.. py:function:: func(arg, kwarg=None)' in actual
|
||||||
' func(arg: str, kwarg=None)',
|
assert ' func(arg: int, kwarg=None)' in actual
|
||||||
' :module: target.singledispatch',
|
assert ' func(arg: str, kwarg=None)' in actual
|
||||||
'',
|
else:
|
||||||
' A function for general use.',
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
]
|
'.. py:function:: func(arg, kwarg=None)',
|
||||||
|
' func(arg: int, kwarg=None)',
|
||||||
|
' func(arg: str, kwarg=None)',
|
||||||
|
' :module: target.singledispatch',
|
||||||
|
'',
|
||||||
|
' A function for general use.',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
2
tox.ini
2
tox.ini
@ -24,7 +24,7 @@ extras =
|
|||||||
test
|
test
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils
|
PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils
|
||||||
PYTEST_ADDOPTS = --color yes
|
PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes
|
||||||
commands=
|
commands=
|
||||||
pytest --durations 25 {posargs}
|
pytest --durations 25 {posargs}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user