From 8c97fef6563b5aaafb5fde111c51d154d7a4fa99 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Sat, 20 Jul 2024 12:57:04 +0100
Subject: [PATCH 01/14] Fix tests for Sphinx 7.4 (#20)
---
CHANGES | 5 +++++
sphinxcontrib/htmlhelp/__init__.py | 2 +-
tests/roots/test-basic/conf.py | 1 +
tests/roots/test-hhc/conf.py | 1 +
4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/CHANGES b/CHANGES
index f2e1585..30caf3e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Release 2.0.6 (unreleased)
+==========================
+
+* Fix tests for Sphinx 7.4 and later.
+
Release 2.0.5 (2024-01-13)
==========================
diff --git a/sphinxcontrib/htmlhelp/__init__.py b/sphinxcontrib/htmlhelp/__init__.py
index dd27da2..36e80b3 100644
--- a/sphinxcontrib/htmlhelp/__init__.py
+++ b/sphinxcontrib/htmlhelp/__init__.py
@@ -286,7 +286,7 @@ def write_param(name: str, value: str) -> None:
f.write('')
for (key, group) in index:
for title, (refs, subitems, key_) in group:
- write_index(title, refs, subitems)
+ write_index(title, refs, subitems) # type: ignore[arg-type]
f.write('\n')
diff --git a/tests/roots/test-basic/conf.py b/tests/roots/test-basic/conf.py
index e69de29..329280d 100644
--- a/tests/roots/test-basic/conf.py
+++ b/tests/roots/test-basic/conf.py
@@ -0,0 +1 @@
+project = 'Python'
diff --git a/tests/roots/test-hhc/conf.py b/tests/roots/test-hhc/conf.py
index 20447e0..7825564 100644
--- a/tests/roots/test-hhc/conf.py
+++ b/tests/roots/test-hhc/conf.py
@@ -1 +1,2 @@
+project = 'Python'
html_short_title = "Sphinx's documentation"
From 49998fdc1e911048e35fbf6fe0f135a47d338214 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 20 Jul 2024 12:58:00 +0100
Subject: [PATCH 02/14] Bump to 2.0.6 final
---
CHANGES | 2 +-
sphinxcontrib/htmlhelp/__init__.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/CHANGES b/CHANGES
index 30caf3e..c4ebd56 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-Release 2.0.6 (unreleased)
+Release 2.0.6 (2024-07-20)
==========================
* Fix tests for Sphinx 7.4 and later.
diff --git a/sphinxcontrib/htmlhelp/__init__.py b/sphinxcontrib/htmlhelp/__init__.py
index 36e80b3..8ac975e 100644
--- a/sphinxcontrib/htmlhelp/__init__.py
+++ b/sphinxcontrib/htmlhelp/__init__.py
@@ -28,8 +28,8 @@
else:
from sphinx.util import progress_message # type: ignore[attr-defined,no-redef]
-__version__ = '2.0.5'
-__version_info__ = (2, 0, 5)
+__version__ = '2.0.6'
+__version_info__ = (2, 0, 6)
logger = logging.getLogger(__name__)
__ = get_translation(__name__, 'console')
From c5ec8d7d7ca8520b9f6eac2bfb71f37ddc6eef65 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 27 Jul 2024 18:38:40 +0100
Subject: [PATCH 03/14] Update .gitignore
---
.gitignore | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index fe75ce5..10cef94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,17 @@
*.pyc
-*.egg
-*.so
-*.swp
.DS_Store
+idea/
+.vscode/
+
.mypy_cache/
+.pytest_cache/
+.ruff_cache/
.tags
.tox/
+.venv/
+venv/
+
build/
dist/
-sphinxcontrib_htmlhelp.egg-info/
From a21bb3dc83b14ee2518dc548229f9902ea7aadcc Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 05:02:28 +0100
Subject: [PATCH 04/14] Adopt Ruff and use stricter MyPy settings
---
.flake8 | 4 --
.github/workflows/test.yml | 4 +-
.ruff.toml | 53 +++++++++++++++
Makefile | 2 +-
pyproject.toml | 36 +++++++++-
sphinxcontrib/htmlhelp/__init__.py | 105 ++++++++++++++++-------------
sphinxcontrib/htmlhelp/py.typed | 0
tests/conftest.py | 15 ++---
tests/roots/test-basic/conf.py | 2 +
tests/roots/test-chm/conf.py | 2 +
tests/roots/test-hhc/conf.py | 2 +
tests/test_htmlhelp.py | 42 +++++++-----
tox.ini | 6 +-
13 files changed, 188 insertions(+), 85 deletions(-)
delete mode 100644 .flake8
create mode 100644 .ruff.toml
create mode 100644 sphinxcontrib/htmlhelp/py.typed
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 5af0a95..0000000
--- a/.flake8
+++ /dev/null
@@ -1,4 +0,0 @@
-[flake8]
-max-line-length = 95
-ignore = E116,E241,E251
-exclude = .git,.tox,.venv
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 8cd7db1..856df5b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -71,7 +71,9 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- env: [flake8, mypy]
+ env:
+ - ruff
+ - mypy
steps:
- uses: actions/checkout@v3
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 0000000..4b7dd2a
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,53 @@
+target-version = "py39" # Pin Ruff to Python 3.9
+output-format = "full"
+line-length = 95
+
+[lint]
+preview = true
+select = [
+# "ANN", # flake8-annotations
+ "C4", # flake8-comprehensions
+ "COM", # flake8-commas
+ "B", # flake8-bugbear
+ "DTZ", # flake8-datetimez
+ "E", # pycodestyle
+ "EM", # flake8-errmsg
+ "EXE", # flake8-executable
+ "F", # pyflakes
+ "FA", # flake8-future-annotations
+ "FLY", # flynt
+ "FURB", # refurb
+ "G", # flake8-logging-format
+ "I", # isort
+ "ICN", # flake8-import-conventions
+ "INT", # flake8-gettext
+ "LOG", # flake8-logging
+ "PERF", # perflint
+ "PGH", # pygrep-hooks
+ "PIE", # flake8-pie
+ "PT", # flake8-pytest-style
+ "SIM", # flake8-simplify
+ "SLOT", # flake8-slots
+ "TCH", # flake8-type-checking
+ "UP", # pyupgrade
+ "W", # pycodestyle
+ "YTT", # flake8-2020
+]
+ignore = [
+ "E116",
+ "E241",
+ "E251",
+]
+
+[lint.per-file-ignores]
+"tests/*" = [
+ "ANN", # tests don't need annotations
+]
+
+[lint.isort]
+forced-separate = [
+ "tests",
+]
+required-imports = [
+ "from __future__ import annotations",
+]
diff --git a/Makefile b/Makefile
index 26f411a..438ee54 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ clean-mypyfiles:
.PHONY: style-check
style-check:
- @flake8
+ @ruff check
.PHONY: type-check
type-check:
diff --git a/pyproject.toml b/pyproject.toml
index fb933af..5db9843 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -48,9 +48,9 @@ test = [
"html5lib",
]
lint = [
- "flake8",
+ "ruff==0.5.5",
"mypy",
- "docutils-stubs",
+ "types-docutils",
]
standalone = [
"Sphinx>=5",
@@ -73,4 +73,34 @@ include = [
]
[tool.mypy]
-ignore_missing_imports = true
+python_version = "3.9"
+packages = [
+ "sphinxcontrib",
+ "tests",
+]
+exclude = [
+ "tests/roots",
+]
+check_untyped_defs = true
+disallow_any_generics = true
+disallow_incomplete_defs = true
+disallow_subclassing_any = true
+disallow_untyped_calls = true
+disallow_untyped_decorators = true
+disallow_untyped_defs = true
+#explicit_package_bases = true
+extra_checks = true
+no_implicit_reexport = true
+show_column_numbers = true
+show_error_context = true
+strict_optional = true
+warn_redundant_casts = true
+warn_unused_configs = true
+warn_unused_ignores = true
+enable_error_code = [
+ "type-arg",
+ "redundant-self",
+ "truthy-iterable",
+ "ignore-without-code",
+ "unused-awaitable",
+]
diff --git a/sphinxcontrib/htmlhelp/__init__.py b/sphinxcontrib/htmlhelp/__init__.py
index 8ac975e..90c61bb 100644
--- a/sphinxcontrib/htmlhelp/__init__.py
+++ b/sphinxcontrib/htmlhelp/__init__.py
@@ -5,16 +5,13 @@
import html
import os
from os import path
-from typing import Any
-
-from docutils import nodes
-from docutils.nodes import Element, Node, document
+from pathlib import Path
+from typing import TYPE_CHECKING, Any
import sphinx
+from docutils import nodes
from sphinx import addnodes
-from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.config import Config
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.locale import get_translation
from sphinx.util import logging
@@ -23,10 +20,15 @@
from sphinx.util.osutil import make_filename_from_project, relpath
from sphinx.util.template import SphinxRenderer
+if TYPE_CHECKING:
+ from docutils.nodes import Element, Node, document
+ from sphinx.application import Sphinx
+ from sphinx.config import Config
+
if sphinx.version_info[:2] >= (6, 1):
from sphinx.util.display import progress_message
else:
- from sphinx.util import progress_message # type: ignore[attr-defined,no-redef]
+ from sphinx.util import progress_message # type: ignore[no-redef]
__version__ = '2.0.6'
__version_info__ = (2, 0, 6)
@@ -126,8 +128,8 @@ def depart_list_item(self, node: Element) -> None:
def visit_reference(self, node: Element) -> None:
title = chm_htmlescape(node.astext(), True)
- self.append(' ' % title)
- self.append(' ' % node['refuri'])
+ self.append(f' ')
+ self.append(f' ')
self.append('')
raise nodes.SkipNode
@@ -170,7 +172,13 @@ def prepare_writing(self, docnames: set[str]) -> None:
super().prepare_writing(docnames)
self.globalcontext['html5_doctype'] = False
- def update_page_context(self, pagename: str, templatename: str, ctx: dict, event_arg: str) -> None: # NOQA
+ def update_page_context(
+ self,
+ pagename: str,
+ templatename: str,
+ ctx: dict[str, Any],
+ event_arg: str,
+ ) -> None:
ctx['encoding'] = self.encoding
def handle_finish(self) -> None:
@@ -180,14 +188,14 @@ def handle_finish(self) -> None:
self.build_hhx(self.outdir, self.config.htmlhelp_basename)
def write_doc(self, docname: str, doctree: document) -> None:
- for node in doctree.traverse(nodes.reference):
+ for node in doctree.findall(nodes.reference):
# add ``target=_blank`` attributes to external links
if node.get('internal') is None and 'refuri' in node:
node['target'] = '_blank'
super().write_doc(docname, doctree)
- def render(self, name: str, context: dict) -> str:
+ def render(self, name: str, context: dict[str, Any]) -> str:
template = SphinxRenderer(template_dir)
return template.render(name, context)
@@ -220,40 +228,39 @@ def build_project_file(self) -> None:
fn = relpath(path.join(root, fn), self.outdir)
project_files.append(fn.replace(os.sep, '\\'))
- filename = path.join(self.outdir, self.config.htmlhelp_basename + '.hhp')
- with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
- context = {
- 'outname': self.config.htmlhelp_basename,
- 'title': self.config.html_title,
- 'version': self.config.version,
- 'project': self.config.project,
- 'lcid': self.lcid,
- 'master_doc': self.config.master_doc + self.out_suffix,
- 'files': project_files,
- }
- body = self.render('project.hhp', context)
- f.write(body)
+ context = {
+ 'outname': self.config.htmlhelp_basename,
+ 'title': self.config.html_title,
+ 'version': self.config.version,
+ 'project': self.config.project,
+ 'lcid': self.lcid,
+ 'master_doc': self.config.master_doc + self.out_suffix,
+ 'files': project_files,
+ }
+ body = self.render('project.hhp', context)
+ filename = Path(self.outdir, f'{self.config.htmlhelp_basename}.hhp')
+ filename.write_text(body, encoding=self.encoding, errors='xmlcharrefreplace')
@progress_message(__('writing TOC file'))
def build_toc_file(self) -> None:
"""Create a ToC file (.hhp) on outdir."""
- filename = path.join(self.outdir, self.config.htmlhelp_basename + '.hhc')
- with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
- toctree = self.env.get_and_resolve_doctree(self.config.master_doc, self,
- prune_toctrees=False)
- visitor = ToCTreeVisitor(toctree)
- matcher = NodeMatcher(addnodes.compact_paragraph, toctree=True)
- for node in toctree.traverse(matcher): # type: addnodes.compact_paragraph
- node.walkabout(visitor)
-
- context = {
- 'body': visitor.astext(),
- 'suffix': self.out_suffix,
- 'short_title': self.config.html_short_title,
- 'master_doc': self.config.master_doc,
- 'domain_indices': self.domain_indices,
- }
- f.write(self.render('project.hhc', context))
+ toctree = self.env.get_and_resolve_doctree(self.config.master_doc, self,
+ prune_toctrees=False)
+ visitor = ToCTreeVisitor(toctree)
+ matcher = NodeMatcher(addnodes.compact_paragraph, toctree=True)
+ for node in toctree.findall(matcher):
+ node.walkabout(visitor)
+
+ context = {
+ 'body': visitor.astext(),
+ 'suffix': self.out_suffix,
+ 'short_title': self.config.html_short_title,
+ 'master_doc': self.config.master_doc,
+ 'domain_indices': self.domain_indices,
+ }
+ body = self.render('project.hhc', context)
+ filename = Path(self.outdir, f'{self.config.htmlhelp_basename}.hhc')
+ filename.write_text(body, encoding=self.encoding, errors='xmlcharrefreplace')
def build_hhx(self, outdir: str | os.PathLike[str], outname: str) -> None:
logger.info(__('writing index file...'))
@@ -262,9 +269,13 @@ def build_hhx(self, outdir: str | os.PathLike[str], outname: str) -> None:
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
f.write('
\n')
- def write_index(title: str, refs: list[tuple[str, str]], subitems: list[tuple[str, list[tuple[str, str]]]]) -> None: # NOQA
+ def write_index(
+ title: str,
+ refs: list[tuple[str, str]],
+ subitems: list[tuple[str, list[tuple[str, str]]]],
+ ) -> None:
def write_param(name: str, value: str) -> None:
- item = ' \n' % (name, value)
+ item = f' \n'
f.write(item)
title = chm_htmlescape(title, True)
f.write('-
')
- for (key, group) in index:
- for title, (refs, subitems, key_) in group:
- write_index(title, refs, subitems) # type: ignore[arg-type]
+ for (_group_key, group) in index:
+ for title, (refs, subitems, _category_key) in group:
+ write_index(title, refs, subitems)
f.write('\n')
diff --git a/sphinxcontrib/htmlhelp/py.typed b/sphinxcontrib/htmlhelp/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/tests/conftest.py b/tests/conftest.py
index d4b08e5..3934d3f 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,17 +1,14 @@
+from __future__ import annotations
+
from pathlib import Path
import pytest
-import sphinx
-
-pytest_plugins = 'sphinx.testing.fixtures'
+pytest_plugins = (
+ 'sphinx.testing.fixtures',
+)
@pytest.fixture(scope='session')
-def rootdir():
- if sphinx.version_info[:2] < (7, 2):
- from sphinx.testing.path import path
-
- return path(__file__).parent.abspath() / 'roots'
-
+def rootdir() -> Path:
return Path(__file__).resolve().parent / 'roots'
diff --git a/tests/roots/test-basic/conf.py b/tests/roots/test-basic/conf.py
index 329280d..4817a0c 100644
--- a/tests/roots/test-basic/conf.py
+++ b/tests/roots/test-basic/conf.py
@@ -1 +1,3 @@
+from __future__ import annotations
+
project = 'Python'
diff --git a/tests/roots/test-chm/conf.py b/tests/roots/test-chm/conf.py
index 9b6a554..ba72759 100644
--- a/tests/roots/test-chm/conf.py
+++ b/tests/roots/test-chm/conf.py
@@ -1 +1,3 @@
+from __future__ import annotations
+
project = 'test'
diff --git a/tests/roots/test-hhc/conf.py b/tests/roots/test-hhc/conf.py
index 7825564..0374d15 100644
--- a/tests/roots/test-hhc/conf.py
+++ b/tests/roots/test-hhc/conf.py
@@ -1,2 +1,4 @@
+from __future__ import annotations
+
project = 'Python'
html_short_title = "Sphinx's documentation"
diff --git a/tests/test_htmlhelp.py b/tests/test_htmlhelp.py
index f0d74b6..191304a 100644
--- a/tests/test_htmlhelp.py
+++ b/tests/test_htmlhelp.py
@@ -1,20 +1,28 @@
"""Test the HTML Help builder and check output against XPath."""
+from __future__ import annotations
+
import re
from pathlib import Path
+from typing import TYPE_CHECKING
import pytest
from html5lib import HTMLParser
+from sphinx.config import Config
from sphinxcontrib.htmlhelp import chm_htmlescape, default_htmlhelp_basename
-from sphinx.config import Config
+
+if TYPE_CHECKING:
+ from xml.etree.ElementTree import Element
+
+ from sphinx.application import Sphinx
@pytest.mark.sphinx('htmlhelp', testroot='basic')
-def test_build_htmlhelp(app, status, warning):
+def test_build_htmlhelp(app: Sphinx) -> None:
app.build()
- hhp = (app.outdir / 'pythondoc.hhp').read_text()
+ hhp = (app.outdir / 'pythondoc.hhp').read_text(encoding='utf-8')
assert 'Compiled file=pythondoc.chm' in hhp
assert 'Contents file=pythondoc.hhc' in hhp
assert 'Default Window=pythondoc' in hhp
@@ -28,30 +36,30 @@ def test_build_htmlhelp(app, status, warning):
'0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0' in hhp)
files = ['genindex.html', 'index.html', '_static\\alabaster.css', '_static\\basic.css',
- '_static\\custom.css', '_static\\file.png', '_static\\minus.png',
- '_static\\plus.png', '_static\\pygments.css']
- assert '[FILES]\n%s' % '\n'.join(files) in hhp
+ '_static\\custom.css', '_static\\file.png', '_static\\github-banner.svg',
+ '_static\\minus.png', '_static\\plus.png', '_static\\pygments.css']
+ assert '[FILES]\n' + '\n'.join(files) in hhp
@pytest.mark.sphinx('htmlhelp', testroot='basic')
-def test_default_htmlhelp_file_suffix(app, warning):
- assert app.builder.out_suffix == '.html'
+def test_default_htmlhelp_file_suffix(app: Sphinx) -> None:
+ assert app.builder.out_suffix == '.html' # type: ignore[attr-defined]
@pytest.mark.sphinx('htmlhelp', testroot='basic',
confoverrides={'htmlhelp_file_suffix': '.htm'})
-def test_htmlhelp_file_suffix(app, warning):
- assert app.builder.out_suffix == '.htm'
+def test_htmlhelp_file_suffix(app: Sphinx) -> None:
+ assert app.builder.out_suffix == '.htm' # type: ignore[attr-defined]
-def test_default_htmlhelp_basename():
+def test_default_htmlhelp_basename() -> None:
config = Config({'project': 'Sphinx Documentation'})
config.init_values()
assert default_htmlhelp_basename(config) == 'sphinxdoc'
@pytest.mark.sphinx('htmlhelp', testroot='chm')
-def test_chm(app):
+def test_chm(app: Sphinx) -> None:
app.build()
# check .hhk file
@@ -63,10 +71,10 @@ def test_chm(app):
@pytest.mark.sphinx('htmlhelp', testroot='hhc')
-def test_htmlhelp_hhc(app):
+def test_htmlhelp_hhc(app: Sphinx) -> None:
app.build()
- def assert_sitemap(node, name, filename):
+ def assert_sitemap(node: Element, name: str, filename: str) -> None:
assert node.tag == 'object'
assert len(node) == 2
assert node[0].tag == 'param'
@@ -75,7 +83,7 @@ def assert_sitemap(node, name, filename):
assert node[1].attrib == {'name': 'Local', 'value': filename}
# .hhc file
- hhc = (app.outdir / 'pythondoc.hhc').read_text()
+ hhc = (app.outdir / 'pythondoc.hhc').read_text(encoding='utf-8')
tree = HTMLParser(namespaceHTMLElements=False).parse(hhc)
items = tree.find('.//body/ul')
assert len(items) == 4
@@ -108,9 +116,9 @@ def assert_sitemap(node, name, filename):
assert "Sphinx's documentation" in hhc
-def test_chm_htmlescape():
+def test_chm_htmlescape() -> None:
assert chm_htmlescape('Hello world') == 'Hello world'
- assert chm_htmlescape(u'Unicode 文字') == u'Unicode 文字'
+ assert chm_htmlescape('Unicode 文字') == 'Unicode 文字'
assert chm_htmlescape('E') == 'E'
assert chm_htmlescape(' "world"') == '<Hello> "world"'
diff --git a/tox.ini b/tox.ini
index 52e72d9..47cc760 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,7 +2,7 @@
minversion = 2.4.0
envlist =
py{39,310,311,312,313},
- flake8,
+ ruff,
mypy
isolated_build = True
@@ -28,13 +28,13 @@ setenv =
commands=
python -X dev -X warn_default_encoding -m pytest --durations 25 {posargs}
-[testenv:flake8]
+[testenv:ruff]
description =
Run style checks.
extras =
lint
commands=
- flake8
+ ruff check
[testenv:mypy]
description =
From eea902567ebeb1f91a18a7a9d3397e3393889ee0 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 05:04:35 +0100
Subject: [PATCH 05/14] Enable GitHub's dependabot package update service
---
.github/dependabot.yml | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..47a31bc
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ - package-ecosystem: "pip"
+ directory: "/"
+ schedule:
+ interval: "daily"
From d335658968b6e4e83852e6813778994bdf29dd4a Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 05:13:53 +0100
Subject: [PATCH 06/14] Use the latest GitHub actions versions
---
.github/workflows/create-release.yml | 12 ++++++------
.github/workflows/test.yml | 14 +++++++-------
.github/workflows/transifex.yml | 10 +++++-----
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml
index 8387d74..78e6b0e 100644
--- a/.github/workflows/create-release.yml
+++ b/.github/workflows/create-release.yml
@@ -17,9 +17,9 @@ jobs:
permissions:
id-token: write # for PyPI trusted publishing
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3
cache: pip
@@ -35,7 +35,7 @@ jobs:
- name: Mint PyPI API token
id: mint-token
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
with:
# language=JavaScript
script: |
@@ -75,15 +75,15 @@ jobs:
permissions:
contents: write # for softprops/action-gh-release to create GitHub release
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Get release version
id: get_version
- uses: actions/github-script@v6
+ uses: actions/github-script@v7
with:
script: core.setOutput('version', context.ref.replace("refs/tags/", ""))
- name: Create GitHub release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
name: "sphinxcontrib-htmlhelp ${{ steps.get_version.outputs.version }}"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 856df5b..4586b92 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -30,14 +30,14 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
if: "!endsWith(matrix.python, '-dev')"
with:
python-version: ${{ matrix.python }}
- name: Set up Python ${{ matrix.python }} (deadsnakes)
- uses: deadsnakes/action@v2.1.1
+ uses: deadsnakes/action@v3.1.0
if: "endsWith(matrix.python, '-dev')"
with:
python-version: ${{ matrix.python }}
@@ -53,9 +53,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: "3"
- name: Install dependencies
@@ -76,9 +76,9 @@ jobs:
- mypy
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Setup python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: "3"
diff --git a/.github/workflows/transifex.yml b/.github/workflows/transifex.yml
index 1f3bab3..71633f2 100644
--- a/.github/workflows/transifex.yml
+++ b/.github/workflows/transifex.yml
@@ -15,9 +15,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3
- name: Install transifex client
@@ -44,9 +44,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3
- name: Install transifex client
@@ -67,7 +67,7 @@ jobs:
- name: Compile message catalogs
run: python utils/babel_runner.py compile
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v4
+ uses: peter-evans/create-pull-request@v6
with:
commit-message: "[internationalisation] Update translations"
branch: bot/pull-translations
From 6d10d43e07a1ff6833bf6e2ccb58ead944cc1779 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 18:24:08 +0100
Subject: [PATCH 07/14] Fix test_htmlhelp; use the basic theme
---
tests/roots/test-basic/conf.py | 1 +
tests/test_htmlhelp.py | 9 ++++++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/tests/roots/test-basic/conf.py b/tests/roots/test-basic/conf.py
index 4817a0c..f05c8a2 100644
--- a/tests/roots/test-basic/conf.py
+++ b/tests/roots/test-basic/conf.py
@@ -1,3 +1,4 @@
from __future__ import annotations
project = 'Python'
+html_theme = 'basic'
diff --git a/tests/test_htmlhelp.py b/tests/test_htmlhelp.py
index 191304a..8f32fc4 100644
--- a/tests/test_htmlhelp.py
+++ b/tests/test_htmlhelp.py
@@ -35,9 +35,12 @@ def test_build_htmlhelp(app: Sphinx) -> None:
'"pythondoc.hhk","index.html","index.html",,,,,'
'0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0' in hhp)
- files = ['genindex.html', 'index.html', '_static\\alabaster.css', '_static\\basic.css',
- '_static\\custom.css', '_static\\file.png', '_static\\github-banner.svg',
- '_static\\minus.png', '_static\\plus.png', '_static\\pygments.css']
+ files = (
+ 'genindex.html', 'index.html',
+ '_static\\basic.css',
+ '_static\\file.png', '_static\\minus.png', '_static\\plus.png',
+ '_static\\pygments.css',
+ )
assert '[FILES]\n' + '\n'.join(files) in hhp
From b97d63d52d6fe2b507f77caceafa54a2cacdb69a Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 18:31:10 +0100
Subject: [PATCH 08/14] Run mypy without command-line options
---
tox.ini | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tox.ini b/tox.ini
index 47cc760..63459cd 100644
--- a/tox.ini
+++ b/tox.ini
@@ -42,4 +42,4 @@ description =
extras =
lint
commands=
- mypy sphinxcontrib/ --explicit-package-bases
+ mypy
From 54d27bc3930b0c250c327957764fe3bde1c449e0 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 18:38:17 +0100
Subject: [PATCH 09/14] Run CI with Python 3.12 releases
---
.github/workflows/test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4586b92..e337f0f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -25,7 +25,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
- - "3.12-dev"
+ - "3.12"
- "3.13-dev"
fail-fast: false
@@ -44,7 +44,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install .[test,standalone]
+ python -m pip install .[standalone,test]
- name: Test with pytest
run: python -m pytest -vv --durations 25
From b1133fa932ec75ebfb72c41ca7b5191c58eb64bc Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 18:48:22 +0100
Subject: [PATCH 10/14] Rename CHANGES to CHANGES.rst
---
CHANGES => CHANGES.rst | 0
pyproject.toml | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
rename CHANGES => CHANGES.rst (100%)
diff --git a/CHANGES b/CHANGES.rst
similarity index 100%
rename from CHANGES
rename to CHANGES.rst
diff --git a/pyproject.toml b/pyproject.toml
index 5db9843..406980d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -65,7 +65,7 @@ name = "sphinxcontrib.htmlhelp"
[tool.flit.sdist]
include = [
- "CHANGES",
+ "CHANGES.rst",
"LICENSE",
# Tests
"tests/",
From ba51300a7ba6169291be8fdce6839c1f1531cf54 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 19:00:42 +0100
Subject: [PATCH 11/14] Rename LICENSE to LICENCE.rst
---
LICENSE => LICENCE.rst | 0
pyproject.toml | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
rename LICENSE => LICENCE.rst (100%)
diff --git a/LICENSE b/LICENCE.rst
similarity index 100%
rename from LICENSE
rename to LICENCE.rst
diff --git a/pyproject.toml b/pyproject.toml
index 406980d..587fd03 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -66,7 +66,7 @@ name = "sphinxcontrib.htmlhelp"
[tool.flit.sdist]
include = [
"CHANGES.rst",
- "LICENSE",
+ "LICENCE.rst",
# Tests
"tests/",
"tox.ini",
From 16b26c612d157298c8254401cd6172cd03d4afe7 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 28 Jul 2024 19:32:59 +0100
Subject: [PATCH 12/14] Update CHANGES links
---
.github/workflows/create-release.yml | 2 +-
pyproject.toml | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml
index 78e6b0e..c6d3a57 100644
--- a/.github/workflows/create-release.yml
+++ b/.github/workflows/create-release.yml
@@ -87,4 +87,4 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
with:
name: "sphinxcontrib-htmlhelp ${{ steps.get_version.outputs.version }}"
- body: "Changelog: https://www.sphinx-doc.org/en/master/changes.html"
+ body: "Changelog: https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/blob/master/CHANGES.rst"
diff --git a/pyproject.toml b/pyproject.toml
index 587fd03..86da7e5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,11 +7,11 @@ build-backend = "flit_core.buildapi"
name = "sphinxcontrib-htmlhelp"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
readme = "README.rst"
-urls.Changelog = "https://www.sphinx-doc.org/en/master/changes.html"
-urls.Code = "https://github.com/sphinx-doc/sphinxcontrib-htmlhelp"
+urls.Changelog = "https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/blob/master/CHANGES.rst"
+urls.Code = "https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/"
urls.Download = "https://pypi.org/project/sphinxcontrib-htmlhelp/"
urls.Homepage = "https://www.sphinx-doc.org/"
-urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx/issues"
+urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx/issues/"
license.text = "BSD-2-Clause"
requires-python = ">=3.9"
From ec1353cfe396f6c28ff60f8ec7561b75a73c6b85 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Mon, 29 Jul 2024 01:14:17 +0100
Subject: [PATCH 13/14] Escape HTML entities
---
sphinxcontrib/htmlhelp/__init__.py | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/sphinxcontrib/htmlhelp/__init__.py b/sphinxcontrib/htmlhelp/__init__.py
index 90c61bb..f24dbb9 100644
--- a/sphinxcontrib/htmlhelp/__init__.py
+++ b/sphinxcontrib/htmlhelp/__init__.py
@@ -4,6 +4,8 @@
import html
import os
+import re
+from html.entities import codepoint2name
from os import path
from pathlib import Path
from typing import TYPE_CHECKING, Any
@@ -21,7 +23,7 @@
from sphinx.util.template import SphinxRenderer
if TYPE_CHECKING:
- from docutils.nodes import Element, Node, document
+ from docutils.nodes import Element, Node
from sphinx.application import Sphinx
from sphinx.config import Config
@@ -91,7 +93,7 @@ def chm_htmlescape(s: str, quote: bool = True) -> str:
class ToCTreeVisitor(nodes.NodeVisitor):
- def __init__(self, document: document) -> None:
+ def __init__(self, document: nodes.document) -> None:
super().__init__(document)
self.body: list[str] = []
self.depth = 0
@@ -181,13 +183,25 @@ def update_page_context(
) -> None:
ctx['encoding'] = self.encoding
+ # escape the `body` part to 7-bit ASCII
+ body = ctx.get("body")
+ if body is not None:
+ ctx["body"] = re.sub(r"[^\x00-\x7F]", self._escape, body)
+
+ @staticmethod
+ def _escape(match: re.Match[str]) -> str:
+ codepoint = ord(match.group(0))
+ if codepoint in codepoint2name:
+ return f"&{codepoint2name[codepoint]};"
+ return f"{codepoint};"
+
def handle_finish(self) -> None:
self.copy_stopword_list()
self.build_project_file()
self.build_toc_file()
self.build_hhx(self.outdir, self.config.htmlhelp_basename)
- def write_doc(self, docname: str, doctree: document) -> None:
+ def write_doc(self, docname: str, doctree: nodes.document) -> None:
for node in doctree.findall(nodes.reference):
# add ``target=_blank`` attributes to external links
if node.get('internal') is None and 'refuri' in node:
@@ -265,7 +279,7 @@ def build_toc_file(self) -> None:
def build_hhx(self, outdir: str | os.PathLike[str], outname: str) -> None:
logger.info(__('writing index file...'))
index = IndexEntries(self.env).create_index(self)
- filename = path.join(outdir, outname + '.hhk')
+ filename = Path(outdir, outname + '.hhk')
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
f.write('\n')
@@ -299,6 +313,9 @@ def write_param(name: str, value: str) -> None:
for title, (refs, subitems, _category_key) in group:
write_index(title, refs, subitems)
f.write('
\n')
+ # Fixup keywords (HTML escapes in keywords file)
+ content = filename.read_bytes().replace(b''', b''')
+ filename.write_bytes(content)
def default_htmlhelp_basename(config: Config) -> str:
From f7f5d4ecf27fad97e2454fbeda94c6a105c994ff Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Mon, 29 Jul 2024 01:52:27 +0100
Subject: [PATCH 14/14] Bump to 2.1.0
---
CHANGES.rst | 8 ++++++++
sphinxcontrib/htmlhelp/__init__.py | 4 ++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index c4ebd56..14bd960 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,3 +1,11 @@
+Release 2.1.0 (2024-07-28)
+==========================
+
+* Adopt Ruff
+* Tighten MyPy settings
+* Update GitHub actions versions
+* Escape HTML entities
+
Release 2.0.6 (2024-07-20)
==========================
diff --git a/sphinxcontrib/htmlhelp/__init__.py b/sphinxcontrib/htmlhelp/__init__.py
index f24dbb9..3127554 100644
--- a/sphinxcontrib/htmlhelp/__init__.py
+++ b/sphinxcontrib/htmlhelp/__init__.py
@@ -32,8 +32,8 @@
else:
from sphinx.util import progress_message # type: ignore[no-redef]
-__version__ = '2.0.6'
-__version_info__ = (2, 0, 6)
+__version__ = '2.1.0'
+__version_info__ = (2, 1, 0)
logger = logging.getLogger(__name__)
__ = get_translation(__name__, 'console')