Skip to content

Commit

Permalink
FIX: use warning instead of errors for version json tests (#993)
Browse files Browse the repository at this point in the history
* use warning instead of errors

* cleaning

* catch error if the request returns 4xx or 5xx

* add some tests

* add a parameter to prevent json test

* fix tests

* Update src/pydata_sphinx_theme/__init__.py

Co-authored-by: Daniel McCloy <[email protected]>

* Update src/pydata_sphinx_theme/__init__.py

Co-authored-by: Daniel McCloy <[email protected]>

* test: fix default behaviour

* add the error in the logging message

Co-authored-by: Daniel McCloy <[email protected]>
  • Loading branch information
12rambau and drammock authored Nov 8, 2022
1 parent 9bd60cd commit d9f8289
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 26 deletions.
8 changes: 8 additions & 0 deletions docs/user_guide/version-dropdown.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ a few different ways:
}
}
By default the theme is testing the :code:`.json` file provided and outputs warnings in the Sphinx build. If this test breaks the pipeline of your docs, the test can be disabled by configuring the :code:`check_switcher` parameter in :code:`conf.py`:

.. code-block:: python
html_theme_options = {
# ...
"check_switcher": False
}
Configure ``switcher['version_match']``
---------------------------------------
Expand Down
48 changes: 33 additions & 15 deletions src/pydata_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pygments.formatters import HtmlFormatter
from pygments.styles import get_all_styles
import requests
from requests.exceptions import ConnectionError, HTTPError, RetryError

from .bootstrap_html_translator import BootstrapHTML5Translator

Expand Down Expand Up @@ -81,8 +82,10 @@ def update_config(app, env):
" Set version URLs in JSON directly."
)

# check the validity of the theme swithcer file
if isinstance(theme_options.get("switcher"), dict):
# check the validity of the theme switcher file
is_dict = isinstance(theme_options.get("switcher"), dict)
should_test = theme_options.get("check_switcher", True)
if is_dict and should_test:
theme_switcher = theme_options.get("switcher")

# raise an error if one of these compulsory keys is missing
Expand All @@ -91,22 +94,37 @@ def update_config(app, env):

# try to read the json file. If it's a url we use request,
# else we simply read the local file from the source directory
# it will raise an error if the file does not exist
# display a log warning if the file cannot be reached
reading_error = None
if urlparse(json_url).scheme in ["http", "https"]:
content = requests.get(json_url).text
try:
request = requests.get(json_url)
request.raise_for_status()
content = request.text
except (ConnectionError, HTTPError, RetryError) as e:
reading_error = repr(e)
else:
content = Path(env.srcdir, json_url).read_text()

# check that the json file is not illformed
# it will throw an error if there is a an issue
switcher_content = json.loads(content)
missing_url = any(["url" not in e for e in switcher_content])
missing_version = any(["version" not in e for e in switcher_content])
if missing_url or missing_version:
raise AttributeError(
f'The version switcher "{json_url}" file is malformed'
' at least one of the items is missing the "url" or "version" key'
try:
content = Path(env.srcdir, json_url).read_text()
except FileNotFoundError as e:
reading_error = repr(e)

if reading_error is not None:
logger.warning(
f'The version switcher "{json_url}" file cannot be read due to the following error:\n'
f"{reading_error}"
)
else:
# check that the json file is not illformed,
# throw a warning if the file is ill formed and an error if it's not json
switcher_content = json.loads(content)
missing_url = any(["url" not in e for e in switcher_content])
missing_version = any(["version" not in e for e in switcher_content])
if missing_url or missing_version:
logger.warning(
f'The version switcher "{json_url}" file is malformed'
' at least one of the items is missing the "url" or "version" key'
)

# Add an analytics ID to the site if provided
analytics = theme_options.get("analytics", {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ primary_sidebar_end = sidebar-ethical-ads.html
footer_items = copyright.html, theme-version.html, sphinx-version.html
secondary_sidebar_items = page-toc.html, searchbox.html, edit-this-page.html, sourcelink.html
switcher =
check_switcher = True
pygment_light_style = tango
pygment_dark_style = monokai
logo =
Expand Down
14 changes: 14 additions & 0 deletions tests/sites/base/missing_url.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"name": "v0.7.1 (stable)",
"version": "0.7.1",
"url": "https://pydata-sphinx-theme.readthedocs.io/en/v0.7.1/"
},
{
"version": "0.7.0",
"url": "https://pydata-sphinx-theme.readthedocs.io/en/v0.7.0/"
},
{
"version": "0.6.3"
}
]
42 changes: 31 additions & 11 deletions tests/test_build.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
from pathlib import Path
from shutil import copytree

Expand All @@ -11,6 +12,12 @@
path_tests = Path(__file__).parent


def escape_ansi(string):
"""helper function to remove ansi coloring from sphinx warnings"""
ansi_escape = re.compile(r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]")
return ansi_escape.sub("", string)


class SphinxBuild:
def __init__(self, app: SphinxTestApp, src: Path):
self.app = app
Expand Down Expand Up @@ -612,7 +619,12 @@ def test_show_nav_level(sphinx_build_factory):
assert "checked" in checkbox.attrs


def test_version_switcher(sphinx_build_factory, file_regression):
switcher_files = ["switcher.json", "http://a.b/switcher.json", "missing_url.json"]
"the switcher files tested in test_version_switcher, not all of them exist"


@pytest.mark.parametrize("url", switcher_files)
def test_version_switcher(sphinx_build_factory, file_regression, url):
"""Regression test the version switcher dropdown HTML.
Note that a lot of the switcher HTML gets populated by JavaScript,
Expand All @@ -625,20 +637,28 @@ def test_version_switcher(sphinx_build_factory, file_regression):
"html_theme_options": {
"navbar_end": ["version-switcher"],
"switcher": {
"json_url": "switcher.json",
"json_url": url,
"version_match": "0.7.1",
},
}
}
sphinx_build = sphinx_build_factory("base", confoverrides=confoverrides).build()
switcher = sphinx_build.html_tree("index.html").select(
".version-switcher__container"
)[
0
] # noqa
file_regression.check(
switcher.prettify(), basename="navbar_switcher", extension=".html"
)
factory = sphinx_build_factory("base", confoverrides=confoverrides)
sphinx_build = factory.build(no_warning=False)

if url == "switcher.json": # this should work
index = sphinx_build.html_tree("index.html")
switcher = index.select(".version-switcher__container")[0]
file_regression.check(
switcher.prettify(), basename="navbar_switcher", extension=".html"
)

elif url == "http://a.b/switcher.json": # this file doesn't exist"
not_read = 'WARNING: The version switcher "http://a.b/switcher.json" file cannot be read due to the following error:\n' # noqa
assert not_read in escape_ansi(sphinx_build.warnings).strip()

elif url == "missing_url.json": # this file is missing the url key for one version
missing_url = 'WARNING: The version switcher "missing_url.json" file is malformed at least one of the items is missing the "url" or "version" key' # noqa
assert escape_ansi(sphinx_build.warnings).strip() == missing_url


def test_theme_switcher(sphinx_build_factory, file_regression):
Expand Down

0 comments on commit d9f8289

Please sign in to comment.