Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,7 @@
"show-inheritance": None,
}

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
"sphinx": ("https://www.sphinx-doc.org/en/master/", None),
"pytest": ("https://docs.pytest.org/en/stable/", None),
"trimesh": ("https://trimesh.org/", None),
}
from intersphinx_config import intersphinx_mapping

highlight_language = "scenic"
pygments_style = "scenic.syntax.pygment.ScenicStyle"
Expand Down
22 changes: 22 additions & 0 deletions docs/intersphinx_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Shared Intersphinx configuration for Scenic's documentation.

This module defines ``intersphinx_mapping``, which is imported from
``docs/conf.py`` and reused from ``tests/test_docs.py`` to check
connectivity to all configured external documentation sites.
"""

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
"sphinx": ("https://www.sphinx-doc.org/en/master/", None),
"pytest": ("https://docs.pytest.org/en/stable/", None),
"trimesh": ("https://trimesh.org/", None),
}


def iter_intersphinx_urls():
"""Yield the base URLs from the mapping."""
for base_url, _ in intersphinx_mapping.values():
yield base_url
43 changes: 31 additions & 12 deletions tests/test_docs.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
import os
import socket
import subprocess
from urllib.error import URLError
from urllib.request import Request, urlopen

import pytest

from docs.intersphinx_config import iter_intersphinx_urls

pytest.importorskip("sphinx")


def _check_intersphinx_connectivity(timeout=10.0):
"""Check that Intersphinx sites are reachable before building docs."""
problems = []

for url in iter_intersphinx_urls():
# Some docs hosts don't like the default Python-urllib user-agent.
req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
try:
with urlopen(req, timeout=timeout):
pass
except (URLError, TimeoutError) as e:
# We've seen slow HTTPS responses raise a bare TimeoutError from the
# SSL layer instead of being wrapped in URLError, so catch both here
# to avoid flaky failures when docs hosts are slow or unresponsive.
problems.append(f"{url} ({e})")

if problems:
pytest.skip(
"Some Intersphinx sites are not reachable; skipping docs build:\n"
+ "\n".join(problems)
)


@pytest.mark.slow
def test_build_docs():
"""Test that the documentation builds, and run doctests.
We do this in a subprocess since the Sphinx configuration file activates the veneer
and has other side-effects that aren't reset afterward.
"""
try:
socket.getaddrinfo("docs.python.org", 80)
except OSError:
pytest.skip("cannot connect to python.org for Intersphinx")
"""Test that the documentation builds and doctests pass."""
_check_intersphinx_connectivity()

oldDirectory = os.getcwd()
old_directory = os.getcwd()
try:
os.chdir("docs")
subprocess.run(["make", "clean", "html", "SPHINXOPTS=-W"], check=True)
subprocess.run(["make", "doctest", "SPHINXOPTS=-W"], check=True)
finally:
os.chdir(oldDirectory)
os.chdir(old_directory)
Loading