Make sphinx to generate Tobiko API docs based on docstrings

This requires fixing a number of docstring so they are valid rST. We add
the '--keep-going' flag to our Sphinx calls so we don't stop on the very
first failure.

Change-Id: Ia195fbc3be2e840e2afe1429b2bc2654bd1d5385
Co-authored-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Slawek Kaplonski 2023-03-31 12:03:14 +02:00
parent e171599316
commit 9a6c62f479
46 changed files with 593 additions and 92 deletions

View File

@ -1,6 +1,19 @@
[DEFAULT]
[ansible]
#
# From tobiko
#
# Default Ansible inventory files (list value)
#inventory_files = /etc/ansible/hosts
# Default Ansible playbook verbosity (integer value)
#verbosity = <None>
[centos]
#
@ -31,6 +44,10 @@
# Default centos SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>
[centos7]
@ -62,6 +79,10 @@
# Default centos7 SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>
[cirros]
@ -93,6 +114,20 @@
# Default cirros SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>
[common]
#
# From tobiko
#
# Default directory where to look for shelves. (string value)
#shelves_dir = ~/.tobiko/cache/shelves
[fedora]
@ -124,6 +159,10 @@
# Default fedora SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>
[glance]
@ -215,6 +254,9 @@
# Cloud name used pick authentication parameters from clouds.* (string value)
#cloud_name = <None>
# Host login from where to search for clouds file (list value)
#clouds_file_hosts = localhost
# Directories where to look for clouds files (list value)
#clouds_file_dirs = .,~/.config/openstack,/etc/openstack
@ -289,7 +331,10 @@
#
# Default SSH key to login to server instances (string value)
#key_file = ~/.ssh/id_rsa
#key_file = ~/.ssh/id_ecdsa
# Default SSH key type to login to server instances (string value)
#key_type = ecdsa
[octavia]
@ -304,6 +349,9 @@
# Timeout, in seconds, to wait for a status change. (integer value)
#check_timeout = 360
# The user we should use when we SSH the amphora. (string value)
#amphora_user = cloud-user
[ping]
@ -362,6 +410,10 @@
# Default rhel SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>
[shell]
@ -377,6 +429,25 @@
#sudo = sudo
[shiftstack]
#
# From tobiko
#
# local clouds file path (string value)
#local_clouds_file_path = .tobiko/shifstack/clouds.yaml
# remote clouds file path on undercloud-0 host (string value)
#remote_clouds_file_path = ~/clouds.yaml
# Keystone credentials cloud name (string value)
#cloud_name = shiftstack
# Path to the RC file used to populate OS_* environment variables (list value)
#rcfile = ./shiftstackrc
[ssh]
#
@ -398,8 +469,8 @@
# Default user SSH configuration files (list value)
#config_files = ssh_config,.ssh/config
# Default SSH private key file(s) (list value)
#key_file = ~/.ssh/id_rsa,.ssh/id
# Default SSH private key file(s) wildcard (list value)
#key_file = .ssh/id,~/.ssh/id_dsa,~/.ssh/id_rsa,~/.ssh/id_ecdsa,~/.ssh/id_ed25519
# Set to False to disable connecting to the SSH agent (boolean value)
#allow_agent = false
@ -487,16 +558,20 @@
#undercloud_ssh_username = stack
# SSH key filename used to login to Undercloud node (string value)
#undercloud_ssh_key_filename = ~/.ssh/id_rsa
#undercloud_ssh_key_filename = <None>
# Undercloud RC filename (list value)
#undercloud_rcfile = ~/stackrc
# undercloud cloud name to be used for loading credentials from the undercloud clouds
# files (string value)
#undercloud_cloud_name = undercloud
# TCP port of SSH server on overcloud hosts (integer value)
#overcloud_ssh_port = <None>
# Default username used to connect to overcloud nodes (string value)
#overcloud_ssh_username = heat-admin
#overcloud_ssh_username = <None>
# SSH key filename used to login to Overcloud nodes (string value)
#overcloud_ssh_key_filename = ~/.ssh/id_overcloud
@ -504,14 +579,28 @@
# Overcloud RC filenames (list value)
#overcloud_rcfile = ~/overcloudrc,~/qe-Cloud-0rc
# overcloud cloud name to be used for loading credentials from the overcloud clouds
# files (string value)
#overcloud_cloud_name = overcloud
# Default IP address version to be used to connect to overcloud nodes (integer value)
#overcloud_ip_version = <None>
# Name of network used to connect to overcloud nodes (string value)
#overcloud_network_name = <None>
# Dictionary with the node groups corresponding to different hostname prefixes (dict
# value)
#overcloud_groups_dict = cmp:compute,ctrl:controller
# path to where to export tripleo inventory file (string value)
#inventory_file = tripleo-hosts.yaml
#inventory_file = .ansible/inventory/tripleo.yaml
# OSP env was done with an external load balancer (boolean value)
#has_external_load_balancer = false
# whether Ceph RGW is deployed (boolean value)
#ceph_rgw = false
[ubuntu]
@ -543,3 +632,7 @@
# Default ubuntu SSH connection timeout (seconds) (floating point value)
#connection_timeout = <None>
# Allow to disable SSH auth algorithmsin order to SSH to old servers likeCirrOS ones
# (dict value)
#disabled_algorithms = <None>

View File

@ -67,6 +67,7 @@ extensions = [
'sphinx.ext.ifconfig',
'sphinx.ext.graphviz',
'sphinx.ext.todo',
'sphinx.ext.napoleon',
'oslo_config.sphinxext',
'oslo_config.sphinxconfiggen',
]
@ -127,3 +128,13 @@ html_static_path = [f'{TOBIKO_DOC_DIR}/_static']
config_generator_config_file = [
(f'etc/tobiko.conf.gen', f"{TOBIKO_DOC_DIR}/_static/tobiko")
]
def autodoc_skip_member(app, what, name, obj, skip, options):
# NOTE(slaweq): skip all external modules, like fixtures from the autodoc
if "tobiko" not in str(obj):
return True
# for tobiko modules, lets do what autodoc already decided to do
return skip
def setup(app):
app.connect('autodoc-skip-member', autodoc_skip_member)

View File

@ -23,8 +23,22 @@
Tobiko Framework Reference Guide
================================
Tobiko package
--------------
.. toctree::
:maxdepth: 1
:maxdepth: 4
modules/tobiko
modules/actors
modules/docker
modules/http
modules/openstack/index
modules/podman
modules/run
modules/shell/index
modules/shiftstack
modules/tripleo/index
* :ref:`genindex`
* :ref:`search`

View File

@ -0,0 +1,9 @@
tobiko.actors
-------------
.. automodule:: tobiko.actors
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.docker
-------------
.. automodule:: tobiko.docker
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.http
-----------
.. automodule:: tobiko.http
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.designate
--------------------------
.. automodule:: tobiko.openstack.designate
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.glance
-----------------------
.. automodule:: tobiko.openstack.glance
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.heat
---------------------
.. automodule:: tobiko.openstack.heat
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,18 @@
tobiko.openstack
----------------
.. toctree::
:maxdepth: 2
designate
glance
heat
ironic
keystone
metalsmith
neutron
nova
octavia
openstackclient
stacks
topology

View File

@ -0,0 +1,9 @@
tobiko.openstack.ironic
-----------------------
.. automodule:: tobiko.openstack.ironic
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.keystone
-------------------------
.. automodule:: tobiko.openstack.keystone
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.metalsmith
---------------------------
.. automodule:: tobiko.openstack.metalsmith
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.neutron
------------------------
.. automodule:: tobiko.openstack.neutron
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.nova
---------------------
.. automodule:: tobiko.openstack.nova
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.octavia
------------------------
.. automodule:: tobiko.openstack.octavia
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.openstackclient
--------------------------------
.. automodule:: tobiko.openstack.openstackclient
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.stacks
-----------------------
.. automodule:: tobiko.openstack.stacks
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.openstack.topology
-------------------------
.. automodule:: tobiko.openstack.topology
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.podman
-------------
.. automodule:: tobiko.podman
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.run
----------
.. automodule:: tobiko.run
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.ansible
--------------------
.. automodule:: tobiko.shell.ansible
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.curl
-----------------
.. automodule:: tobiko.shell.curl
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.files
------------------
.. automodule:: tobiko.shell.files
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,59 @@
tobiko.shell
------------
.. toctree::
:maxdepth: 2
ansible
curl
files
iperf3
ping
sh
ssh
tcpdump
tobiko.shell.find
^^^^^^^^^^^^^^^^^
.. automodule:: tobiko.shell.find
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
tobiko.shell.grep
^^^^^^^^^^^^^^^^^
.. automodule:: tobiko.shell.grep
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
tobiko.shell.ifconfig
^^^^^^^^^^^^^^^^^^^^^
.. automodule:: tobiko.shell.ifconfig
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
tobiko.shell.ip
^^^^^^^^^^^^^^^
.. automodule:: tobiko.shell.ip
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
tobiko.shell.ss
^^^^^^^^^^^^^^^
.. automodule:: tobiko.shell.ss
:members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.iperf3
-------------------
.. automodule:: tobiko.shell.iperf3
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.ping
-----------------
.. automodule:: tobiko.shell.ping
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.sh
---------------
.. automodule:: tobiko.shell.sh
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.ssh
----------------
.. automodule:: tobiko.shell.ssh
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shell.tcpdump
--------------------
.. automodule:: tobiko.shell.tcpdump
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.shiftstack
-----------------
.. automodule:: tobiko.shiftstack
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko
------
.. automodule:: tobiko
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.tripleo.containers
-------------------------
.. automodule:: tobiko.tripleo.containers
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,20 @@
tobiko.tripleo
--------------
.. toctree::
:maxdepth: 2
containers
nova
pacemaker
processes
services
tobiko.tripleo
^^^^^^^^^^^^^^
.. automodule:: tobiko.tripleo
:members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.tripleo.nova
-------------------
.. automodule:: tobiko.tripleo.nova
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.tripleo.pacemaker
------------------------
.. automodule:: tobiko.tripleo.pacemaker
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.tripleo.processes
------------------------
.. automodule:: tobiko.tripleo.processes
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
tobiko.tripleo.services
-----------------------
.. automodule:: tobiko.tripleo.services
:members:
:imported-members:
:undoc-members:
:inherited-members:
:show-inheritance:

View File

@ -29,10 +29,10 @@ class TobikoException(Exception):
"""Base Tobiko Exception.
To use this class, inherit from it and define attribute 'message' string.
If **properties parameters is given, then it will format message string
If ``properties`` parameters is given, then it will format message string
using properties as key-word arguments.
Example:
Example::
class MyException(TobikoException):
message = "This exception occurred because of {reason}"

View File

@ -60,15 +60,17 @@ class UbuntuImageFixture(UbuntuMinimalImageFixture,
The server has additional installed packages compared to
the minimal one:
- iperf3
- ping
- ncat
- nginx
- vlan
- iperf3
- ping
- ncat
- nginx
- vlan
The image will also have below running services:
- nginx HTTP server listening on TCP port 80
- iperf3 server listening on TCP port 5201
- nginx HTTP server listening on TCP port 80
- iperf3 server listening on TCP port 5201
"""
def __init__(self,
@ -189,8 +191,9 @@ class UbuntuServerStackFixture(UbuntuMinimalServerStackFixture,
"""Ubuntu server running an HTTP server
The server has additional commands compared to the minimal one:
iperf3
ping
- iperf3
- ping
"""
#: Glance image used to create a Nova server instance

View File

@ -71,47 +71,37 @@ def ping_parameters(default=None, count=None, deadline=None,
"""Validate parameters and initialize a new PingParameters instance
:param default: (PingParameters or None) instance from where to take
default values when other value is not provided. If None (that is the
default value) it will copy default parameters from
DEFAULT_PING_PARAMETERS
default values when other value is not provided. If None (that is the
default value) it will copy default parameters from
DEFAULT_PING_PARAMETERS
:param count: (int or None) number of ping ICMP message expecting to be
received before having a success. Default value can be configured using
'count' option in [ping] config section.
received before having a success. Default value can be configured using
'count' option in [ping] config section.
:param host: (str or None) IP address or host name to send ICMP
messages to. It is required to format a valid ping command, therefore
no default value exists for this parameter.
messages to. It is required to format a valid ping command, therefore
no default value exists for this parameter.
:param deadline: (int or None) positive number representing the maximum
number of seconds ping command can send ICMP messages before stop
executing. Default value can be configured using 'deadline' option
in [ping] config section.
number of seconds ping command can send ICMP messages before stop
executing. Default value can be configured using 'deadline' option in
[ping] config section.
:param fragmentation: (bool or None) when False this would tell ping
to forbid ICMP messages fragmentation. Default value can be configured
using 'fragmentation' option in [ping] config section. Fragmentation can't
be disabled when using ping provided by BusyBox (IE with CirrOS images).
to forbid ICMP messages fragmentation. Default value can be configured
using 'fragmentation' option in [ping] config section. Fragmentation
can't be disabled when using ping provided by BusyBox (IE with CirrOS
images).
:param interval: (int or None) interval of time before sending following
ICMP message. Default value can be configured using 'interval' option
in [ping] config section.
ICMP message. Default value can be configured using 'interval' option
in [ping] config section.
:param ip_version: (4, 6 or None) If not None it makes sure it will
use specified IP version for sending ICMP packages.
use specified IP version for sending ICMP packages.
:param packet_size: (int or None) if not None, it specifies the total ICMP
message size (headers + payload).
message size (headers + payload).
:param source: (str or None) IP address or interface name from where
to send ICMP message.
to send ICMP message.
:param timeout: (int or None) time in seconds after which ping operation
would raise PingFailed exception.
would raise PingFailed exception.
:raises TypeError: in case some parameter cannot be converted to right
expected type
expected type
:raises ValueError: in case some parameter has an unexpected value
"""

View File

@ -136,7 +136,7 @@ def ping(host: PingHostType, until=TRANSMITTED, check: bool = True,
"""Send ICMP messages to host address until timeout
:param host: destination host address
:param **ping_params: parameters to be forwarded to get_statistics()
:param ping_params: parameters to be forwarded to :mod:`get_statistics`
function
:returns: PingStatistics
"""
@ -152,7 +152,7 @@ def ping_until_delivered(host, **ping_params):
transmitted without being counted as errors.
:param host: destination host address
:param **ping_params: parameters to be forwarded to get_statistics()
:param ping_params: parameters to be forwarded to :mod:`get_statistics`
function
:returns: PingStatistics
:raises: PingFailed in case timeout expires before delivering all
@ -171,7 +171,7 @@ def ping_until_undelivered(host, **ping_params):
example because of errors into the route to remote address).
:param host: destination host address
:param **ping_params: parameters to be forwarded to get_statistics()
:param ping_params: parameters to be forwarded to :mod:`get_statistics`
function
:returns: PingStatistics
:raises: PingFailed in case timeout expires before failing delivering
@ -189,7 +189,7 @@ def ping_until_received(host, **ping_params):
transmitted without any routing errors and they are received back
:param host: destination host address
:param **ping_params: parameters to be forwarded to get_statistics()
:param ping_params: parameters to be forwarded to :mod:`get_statistics`
function
:returns: PingStatistics
:raises: PingFailed in case timeout expires before receiving all
@ -208,7 +208,7 @@ def ping_until_unreceived(host, **ping_params):
back (for example because of network filtering).
:param host: destination host address
:param **ping_params: parameters to be forwarded to get_statistics()
:param ping_params: parameters to be forwarded to :mod:`get_statistics`
function
:returns: PingStatistics
:raises: PingFailed in case timeout expires before failed receiving

View File

@ -543,14 +543,16 @@ def check_or_start_background_process(bg_function=None,
bg_process_name=None,
check_function=None,
**kwargs):
""" Check if process exists, if so restart the process,
execute some check logic i.e. a check function.
if the process by name isn't running,
start a new separate process i.e a background function
params:
bg_process_name= process name
bg_function: function name
check_function: function name """
"""Start or restart a process.
Check if a process exists, if so restart the process, execute some check
logic i.e. a check function. if the process by name isn't running, start a
new separate process i.e a background function
:param bg_process_name: process name
:param bg_function: function name
:param check_function: function name
"""
procs_running_list = get_bg_procs_pids(bg_process_name)
if procs_running_list:

View File

@ -95,15 +95,16 @@ class SockData(dict):
Output of ss command line tool should be parsed and stored in the dict
with keys are items of the SockHeader object. In most of the cases it
should contain the following keys:
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (IP or filename)
- local_port
- remote_addr (IP or filename)
- remote_port
- process (list of processes names)
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (IP or filename)
- local_port
- remote_addr (IP or filename)
- remote_port
- process (list of processes names)
"""
@ -240,15 +241,16 @@ def tcp_listening(address: str = '',
Information can be filtered by local address and port and will be returned
as a list of SockData object where the following keys should exist:
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (netaddr.IPAddress object)
- local_port
- remote_addr (netaddr.IPAddress object)
- remote_port
- process (list of processes names)
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (netaddr.IPAddress object)
- local_port
- remote_addr (netaddr.IPAddress object)
- remote_port
- process (list of processes names)
"""
params = '-t state listening'
ss_fields = SockHeader('Recv-Q Send-Q Local Address:Port'
@ -291,15 +293,16 @@ def unix_listening(file_name: str = '',
Information can be filtered by file name and will be returned as a list of
SockData object where the following keys should exist:
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (filename string)
- local_port (should be *)
- remote_addr (filename string - should be *)
- remote_port (should be *)
- process (list of processes names)
- protocol (optional)
- state (optional)
- recv_q
- send_q
- local_addr (filename string)
- local_port (should be ``*``)
- remote_addr (filename string - should be ``*``)
- remote_port (should be ``*``)
- process (list of processes names)
"""
params = '-x state listening'
ss_fields = SockHeader('Netid Recv-Q Send-Q Local Address:Port'

View File

@ -100,7 +100,7 @@ class OvercloudProcessesStatus(object):
checks that all of these are running in the overcloud:
'ovsdb-server','pcsd', 'corosync', 'beam.smp', 'mysqld', 'redis-server',
'haproxy', 'nova-conductor', 'nova-scheduler', 'neutron-server',
'nova-compute', 'glance-api'
'nova-compute', 'glance-api'
"""
def __init__(self):
self.processes_to_check = ['ovsdb-server', 'pcsd', 'corosync',

View File

@ -387,7 +387,7 @@ envdir = {[docs]envdir}
deps = {[docs]deps}
commands =
{[docs]commands}
sh -c 'cd {toxinidir}/doc/source && sphinx-build -W -b linkcheck . ../build/linkcheck'
sh -c 'cd {toxinidir}/doc/source && sphinx-build -W --keep-going -b linkcheck . ../build/linkcheck'
usedevelop = true
skipsdist = true
skip_install = true
@ -401,7 +401,7 @@ deps = {[docs]deps}
changedir = doc/source
commands =
{[testenv:linkcheck]commands}
sphinx-build -W -b html . ../build/html
sphinx-build -W --keep-going -b html . ../build/html
usedevelop = true
skipsdist = true
skip_install = true