Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
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