diff --git a/CHANGELOG.md b/CHANGELOG.md index 78fd3c3c..f732c04a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ## Unreleased: pdoc next +- Improve rendering of enums on Python 3.12+. + ([#708](https://github.com/mitmproxy/pdoc/pull/708), @mhils) - Fix a bug where hyperlinks would get parsed as docstring references. ([#709](https://github.com/mitmproxy/pdoc/pull/709), @mhils) diff --git a/pdoc/doc.py b/pdoc/doc.py index 921e88de..c6fac635 100644 --- a/pdoc/doc.py +++ b/pdoc/doc.py @@ -587,6 +587,9 @@ def docstring(self) -> str: if doc == dict.__doc__: # Don't display default docstring for dict subclasses (primarily TypedDict). return "" + if doc in _Enum_default_docstrings: + # Don't display default docstring for enum subclasses. + return "" is_dataclass_with_default_docstring = ( dataclasses.is_dataclass(self.obj) # from https://github.com/python/cpython/blob/3.10/Lib/dataclasses.py @@ -1306,6 +1309,15 @@ def _safe_getdoc(obj: Any) -> str: return doc.strip() +_Enum_default_docstrings = tuple( + { + _safe_getdoc(enum.Enum), + _safe_getdoc(enum.IntEnum), + _safe_getdoc(_safe_getattr(enum, "StrEnum", enum.Enum)), + } +) + + def _remove_memory_addresses(x: str) -> str: """Remove memory addresses from repr() output""" return re.sub(r" at 0x[0-9a-fA-F]+(?=>)", "", x) diff --git a/test/test_snapshot.py b/test/test_snapshot.py index 76eaf4d9..d2d538b7 100755 --- a/test/test_snapshot.py +++ b/test/test_snapshot.py @@ -97,6 +97,7 @@ def outfile(self, format: str) -> Path: snapshots = [ Snapshot("ast_parsing"), Snapshot("demo", min_version=(3, 9)), + Snapshot("enums", min_version=(3, 12)), Snapshot("flavors_google"), Snapshot("flavors_numpy"), Snapshot("flavors_rst"), diff --git a/test/testdata/enums.html b/test/testdata/enums.html new file mode 100644 index 00000000..965178a0 --- /dev/null +++ b/test/testdata/enums.html @@ -0,0 +1,443 @@ + + + + + + + enums API documentation + + + + + + + + + +
+
+

+enums

+ + + + + + +
 1import enum
+ 2
+ 3
+ 4class EnumDemo(enum.Enum):
+ 5    """
+ 6    This is an example of an Enum.
+ 7
+ 8    As usual, you can link to individual properties: `GREEN`.
+ 9    """
+10
+11    RED = 1
+12    """I am the red."""
+13    GREEN = 2
+14    """I am green."""
+15    BLUE = enum.auto()
+16
+17
+18class EnumWithoutDocstrings(enum.Enum):
+19    FOO = enum.auto()
+20    BAR = enum.auto()
+21
+22
+23class IntEnum(enum.IntEnum):
+24    FOO = enum.auto()
+25    BAR = enum.auto()
+26
+27
+28class StrEnum(enum.StrEnum):
+29    FOO = enum.auto()
+30    BAR = enum.auto()
+
+ + +
+
+ +
+ + class + EnumDemo(enum.Enum): + + + +
+ +
 5class EnumDemo(enum.Enum):
+ 6    """
+ 7    This is an example of an Enum.
+ 8
+ 9    As usual, you can link to individual properties: `GREEN`.
+10    """
+11
+12    RED = 1
+13    """I am the red."""
+14    GREEN = 2
+15    """I am green."""
+16    BLUE = enum.auto()
+
+ + +

This is an example of an Enum.

+ +

As usual, you can link to individual properties: GREEN.

+
+ + +
+
+ RED = +<EnumDemo.RED: 1> + + +
+ + +

I am the red.

+
+ + +
+
+
+ GREEN = +<EnumDemo.GREEN: 2> + + +
+ + +

I am green.

+
+ + +
+
+
+ BLUE = +<EnumDemo.BLUE: 3> + + +
+ + + + +
+
+
Inherited Members
+
+
enum.Enum
+
name
+
value
+ +
+
+
+
+
+ +
+ + class + EnumWithoutDocstrings(enum.Enum): + + + +
+ +
19class EnumWithoutDocstrings(enum.Enum):
+20    FOO = enum.auto()
+21    BAR = enum.auto()
+
+ + + + +
+
+ FOO = +<EnumWithoutDocstrings.FOO: 1> + + +
+ + + + +
+
+
+ BAR = +<EnumWithoutDocstrings.BAR: 2> + + +
+ + + + +
+
+
Inherited Members
+
+
enum.Enum
+
name
+
value
+ +
+
+
+
+
+ +
+ + class + IntEnum(enum.IntEnum): + + + +
+ +
24class IntEnum(enum.IntEnum):
+25    FOO = enum.auto()
+26    BAR = enum.auto()
+
+ + + + +
+
+ FOO = +<IntEnum.FOO: 1> + + +
+ + + + +
+
+
+ BAR = +<IntEnum.BAR: 2> + + +
+ + + + +
+
+
Inherited Members
+
+
enum.Enum
+
name
+
value
+ +
+
builtins.int
+
conjugate
+
bit_length
+
bit_count
+
to_bytes
+
from_bytes
+
as_integer_ratio
+
is_integer
+
real
+
imag
+
numerator
+
denominator
+ +
+
+
+
+
+ +
+ + class + StrEnum(enum.StrEnum): + + + +
+ +
29class StrEnum(enum.StrEnum):
+30    FOO = enum.auto()
+31    BAR = enum.auto()
+
+ + + + +
+
+ FOO = +<StrEnum.FOO: 'foo'> + + +
+ + + + +
+
+
+ BAR = +<StrEnum.BAR: 'bar'> + + +
+ + + + +
+
+
Inherited Members
+
+
enum.Enum
+
name
+
value
+ +
+
builtins.str
+
encode
+
replace
+
split
+
rsplit
+
join
+
capitalize
+
casefold
+
title
+
center
+
count
+
expandtabs
+
find
+
partition
+
index
+
ljust
+
lower
+
lstrip
+
rfind
+
rindex
+
rjust
+
rstrip
+
rpartition
+
splitlines
+
strip
+
swapcase
+
translate
+
upper
+
startswith
+
endswith
+
removeprefix
+
removesuffix
+
isascii
+
islower
+
isupper
+
istitle
+
isspace
+
isdecimal
+
isdigit
+
isnumeric
+
isalpha
+
isalnum
+
isidentifier
+
isprintable
+
zfill
+
format
+
format_map
+
maketrans
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/test/testdata/enums.py b/test/testdata/enums.py new file mode 100644 index 00000000..b726f059 --- /dev/null +++ b/test/testdata/enums.py @@ -0,0 +1,30 @@ +import enum + + +class EnumDemo(enum.Enum): + """ + This is an example of an Enum. + + As usual, you can link to individual properties: `GREEN`. + """ + + RED = 1 + """I am the red.""" + GREEN = 2 + """I am green.""" + BLUE = enum.auto() + + +class EnumWithoutDocstrings(enum.Enum): + FOO = enum.auto() + BAR = enum.auto() + + +class IntEnum(enum.IntEnum): + FOO = enum.auto() + BAR = enum.auto() + + +class StrEnum(enum.StrEnum): + FOO = enum.auto() + BAR = enum.auto() diff --git a/test/testdata/enums.txt b/test/testdata/enums.txt new file mode 100644 index 00000000..44aeb4d5 --- /dev/null +++ b/test/testdata/enums.txt @@ -0,0 +1,85 @@ + # I am the red.> + # I am green.> + > + + + > + > + > + + + > + > + > + + + + + + + + + + + + + + > + > + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + > +> \ No newline at end of file