Skip to content

Commit

Permalink
Add support for Sphinx 3.5 and 4.x (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
domdfcoding authored Dec 28, 2021
1 parent 2dcffbe commit 977fabe
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 176 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/python_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ jobs:
fail-fast: False
matrix:
config:
- {python-version: "3.6", testenvs: "py36,build", experimental: False}
- {python-version: "3.7", testenvs: "py37,build", experimental: False}
- {python-version: "3.8", testenvs: "py38,build", experimental: False}
- {python-version: "3.9", testenvs: "py39,build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev,build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True}
- {python-version: "3.6", testenvs: "py36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.7", testenvs: "py37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.8", testenvs: "py38-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.9", testenvs: "py39-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}

steps:
- name: Checkout 🛎️
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/python_ci_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ jobs:
fail-fast: False
matrix:
config:
- {python-version: "3.6", testenvs: "py36,build", experimental: False}
- {python-version: "3.7", testenvs: "py37,build", experimental: False}
- {python-version: "3.8", testenvs: "py38,build", experimental: False}
- {python-version: "3.9", testenvs: "py39,build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev,build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True}
- {python-version: "3.6", testenvs: "py36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.7", testenvs: "py37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.8", testenvs: "py38-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.9", testenvs: "py39-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}

steps:
- name: Checkout 🛎️
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/python_ci_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ jobs:
fail-fast: False
matrix:
config:
- {python-version: "3.6", testenvs: "py36,build", experimental: False}
- {python-version: "3.7", testenvs: "py37,build", experimental: False}
- {python-version: "3.8", testenvs: "py38,build", experimental: False}
- {python-version: "3.9", testenvs: "py39,build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev,build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True}
- {python-version: "3.6", testenvs: "py36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.7", testenvs: "py37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.8", testenvs: "py38-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.9", testenvs: "py39-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "3.10", testenvs: "py310-dev-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}
- {python-version: "pypy-3.6", testenvs: "pypy36-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: False}
- {python-version: "pypy-3.7", testenvs: "pypy37-sphinx{3.2,3.3,3.4,3.5,4.0,4.1,4.2,4.3},build", experimental: True}

steps:
- name: Checkout 🛎️
Expand Down
4 changes: 2 additions & 2 deletions __pkginfo__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
__all__ = ["extras_require"]

extras_require = {
"sphinx": ["sphinx<3.5.0,>=3.0.3", "sphinx-toolbox>=1.2.0"],
"all": ["sphinx<3.5.0,>=3.0.3", "sphinx-toolbox>=1.2.0"]
"sphinx": ["sphinx<4.4,>=3.2.0", "sphinx-toolbox>=1.2.0"],
"all": ["sphinx<4.4,>=3.2.0", "sphinx-toolbox>=1.2.0"]
}
50 changes: 43 additions & 7 deletions enum_tools/autoenum.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,26 @@
# stdlib
from contextlib import suppress
from enum import Enum
from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Dict, List, Optional, Tuple, get_type_hints

# 3rd party
from docutils.nodes import Element # nodep
from sphinx.application import Sphinx # nodep
from sphinx.domains import ObjType # nodep
from sphinx.domains.python import PyClasslike, PyXRefRole # nodep
from sphinx.environment import BuildEnvironment # nodep
from sphinx.ext.autodoc import ALL, INSTANCEATTR, AttributeDocumenter, ClassDocumenter, Documenter # nodep
from sphinx.ext.autodoc import ( # nodep
ALL,
INSTANCEATTR,
SUPPRESS,
AttributeDocumenter,
ClassDocumenter,
ClassLevelDocumenter,
Documenter
)
from sphinx.locale import _ # nodep
from sphinx.util.inspect import object_description # nodep
from sphinx.util.inspect import memory_address_re, safe_getattr # nodep
from sphinx.util.typing import stringify as stringify_typehint # nodep
from sphinx_toolbox.more_autodoc.typehints import format_annotation # nodep
from sphinx_toolbox.utils import begin_generate # nodep

Expand Down Expand Up @@ -321,7 +330,6 @@ def import_object(self, raiseerror: bool = False) -> bool:
.. latex:clearpage::
"""

self._datadescriptor = False
return Documenter.import_object(self, raiseerror=raiseerror)

def generate(
Expand Down Expand Up @@ -366,12 +374,40 @@ def add_directive_header(self, sig: str) -> None:
:param sig:
"""

super().add_directive_header(sig)
ClassLevelDocumenter.add_directive_header(self, sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
# obtain type annotation for this attribute
try:
annotations = get_type_hints(self.parent)
except NameError:
# Failed to evaluate ForwardRef (maybe TYPE_CHECKING)
annotations = safe_getattr(self.parent, "__annotations__", {})
except (TypeError, KeyError, AttributeError):
# KeyError = a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084)
# AttributeError is raised on 3.5.2 (fixed by 3.5.3)
annotations = {}

if self.objpath[-1] in annotations:
objrepr = stringify_typehint(annotations.get(self.objpath[-1]))
self.add_line(" :type: " + objrepr, sourcename)
else:
key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
if self.analyzer and key in self.analyzer.annotations:
self.add_line(" :type: " + self.analyzer.annotations[key], sourcename)

elif self.options.annotation is SUPPRESS:
pass
else:
self.add_line(" :annotation: %s" % self.options.annotation, sourcename)

if not self.options.annotation:
with suppress(ValueError):
with suppress(Exception):
if self.object is not INSTANCEATTR:
objrepr = object_description(self.object)

# Workaround for https://github.com/sphinx-doc/sphinx/issues/9272
# which broke Enum displays in 4.1.0
objrepr = memory_address_re.sub('', repr(self.object)).replace('\n', ' ')
self.add_line(f' :value: {objrepr}', self.get_sourcename())


Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Homepage = "https://github.com/domdfcoding/enum_tools"
Documentation = "https://enum_tools.readthedocs.io/en/latest"

[project.optional-dependencies]
sphinx = [ "sphinx<3.5.0,>=3.0.3", "sphinx-toolbox>=1.2.0",]
all = [ "sphinx<3.5.0,>=3.0.3", "sphinx-toolbox>=1.2.0",]
sphinx = [ "sphinx<4.4,>=3.2.0", "sphinx-toolbox>=1.2.0",]
all = [ "sphinx<4.4,>=3.2.0", "sphinx-toolbox>=1.2.0",]

[tool.whey]
base-classifiers = [
Expand Down
16 changes: 14 additions & 2 deletions repo_helper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ short_desc: "Tools to expand Python's enum module."
use_whey: true
tox_testenv_extras: all
standalone_contrib_guide: true
min_coverage: 85
min_coverage: 88
docs_fail_on_warning: true

conda_channels:
Expand Down Expand Up @@ -51,7 +51,7 @@ keywords:

extras_require:
sphinx:
- sphinx<3.5.0,>=3.0.3
- sphinx<4.4,>=3.2.0
- sphinx-toolbox>=1.2.0

extra_sphinx_extensions:
Expand All @@ -76,3 +76,15 @@ sphinx_conf_epilogue:
- enum_tools.autoenum.Type = Type

preserve_custom_theme: true


third_party_version_matrix:
sphinx:
- 3.2
- 3.3
- 3.4
- 3.5
- 4.0
- 4.1
- 4.2
- 4.3
2 changes: 1 addition & 1 deletion tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ pytest-regressions>=2.0.1
pytest-rerunfailures>=9.0
pytest-timeout>=1.4.2
sphinx>=3.2.1
sphinx-toolbox[testing]>=0.3.0
sphinx-toolbox[testing]>=2.15.2
54 changes: 41 additions & 13 deletions tests/test_autoenum.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

# 3rd party
import pytest
from bs4 import BeautifulSoup # type: ignore
import sphinx
from bs4 import BeautifulSoup, NavigableString # type: ignore
from pytest_regressions.file_regression import FileRegressionFixture # type: ignore
from sphinx_toolbox.testing import HTMLRegressionFixture

Expand Down Expand Up @@ -53,6 +54,33 @@ def test(app):

# pytestmark = pytest.mark.sphinx('html', testroot='root')

return_arrow = " → "


def preprocess_soup(soup: BeautifulSoup):

if sphinx.version_info >= (3, 5): # pragma: no cover
for em in soup.select("em.property"):
child = ''.join(c.string for c in em.contents)
for c in em.children:
c.extract()
em.contents = []
em.insert(0, child)

for dl in soup.select("dl.py.method dt"): # .sig.sig-object.py
if return_arrow in dl.contents:
arrow_idx = dl.contents.index(return_arrow)
dl.contents[arrow_idx] = NavigableString(
dl.contents[arrow_idx] + dl.contents[arrow_idx + 1].contents[0]
)
dl.contents[arrow_idx + 1].extract()

for dt in soup.select("span.pre"):
dt.replace_with_children()

for dt in soup.select("span.sig-return"):
dt.replace_with(NavigableString(dt.get_text()))


@pytest.mark.parametrize(
"page", [
Expand All @@ -64,6 +92,8 @@ def test_index(page: BeautifulSoup, html_regression: HTMLRegressionFixture):
title = page.find("h1").contents[0].strip()
assert "autoenum Demo" == title

preprocess_soup(page)

html_regression.check(page, jinja2=True)

# Now test the directive
Expand All @@ -81,10 +111,8 @@ def test_index(page: BeautifulSoup, html_regression: HTMLRegressionFixture):
assert class_.find("dt")["id"] == "enum_tools.demo.NoMethods"
assert class_.find("dd").findAll('p')[0].contents[0] == "An enumeration of people without any methods."

assert str(class_.find("dd").findAll('p')[1].contents[0]) == (
'<code class="xref py py-class docutils literal notranslate">'
'<span class="pre">int</span></code>'
)
tag = '<code class="xref py py-class docutils literal notranslate">int</code>'
assert str(class_.find("dd").findAll('p')[1].contents[0]) == tag
assert class_.find("dd").findAll('p')[2].contents[0] == "Valid values are as follows:"

attr_count = 0
Expand Down Expand Up @@ -147,6 +175,8 @@ def test_flag(page: BeautifulSoup, html_regression: HTMLRegressionFixture):
title = page.find("h1").contents[0].strip()
assert "autoenum Demo - Flag" == title

preprocess_soup(page)

html_regression.check(page, jinja2=True)

# Now test the directive
Expand All @@ -164,10 +194,8 @@ def test_flag(page: BeautifulSoup, html_regression: HTMLRegressionFixture):

assert class_.find("dd").findAll('p')[0].contents[0] == "An enumeration of status codes."

assert str(class_.find("dd").findAll('p')[1].contents[0]) == (
'<code class="xref py py-class docutils literal notranslate">'
'<span class="pre">int</span></code>'
)
tag = '<code class="xref py py-class docutils literal notranslate">int</code>'
assert str(class_.find("dd").findAll('p')[1].contents[0]) == tag
assert class_.find("dd").findAll('p')[2].contents[0] == "Valid values are as follows:"

attr_count = 0
Expand Down Expand Up @@ -232,6 +260,8 @@ def test_no_member_doc(page: BeautifulSoup, html_regression: HTMLRegressionFixtu
title = page.find("h1").contents[0].strip()
assert "autoenum Demo - Members without docstrings" == title

preprocess_soup(page)

html_regression.check(page, jinja2=True)

# Now test the directive
Expand All @@ -247,10 +277,8 @@ def test_no_member_doc(page: BeautifulSoup, html_regression: HTMLRegressionFixtu
0] == "An enumeration of people without any member docstrings."

if class_count == 0:
assert str(class_.find("dd").findAll('p')[1].contents[0]) == (
'<code class="xref py py-class docutils literal notranslate">'
'<span class="pre">int</span></code>'
)
tag = '<code class="xref py py-class docutils literal notranslate">int</code>'
assert str(class_.find("dd").findAll('p')[1].contents[0]) == tag
assert class_.find("dd").findAll('p')[2].contents[0] == "Valid values are as follows:"
else:
assert class_.find("dd").findAll('p')[1].contents[0] == "Valid values are as follows:"
Expand Down
Loading

0 comments on commit 977fabe

Please sign in to comment.