Usage¶
The enum-table directive takes the import path of an enumeration and renders a table
with a row for each member. It is designed for dataclass enums, where each field of the dataclass
becomes a column. By default the columns are:
name- the member’s name.dataclass fields - if the enum mixes in a dataclass or its values are dataclasses or named tuples.
value- the member’s value, only included when the values are not dataclasses or named tuples.enum-properties properties - a special case, in the order they are declared.
doc- member docstrings, if any member has one.
Dataclass Enums¶
Mixing a dataclass into an enumeration makes each member a dataclass instance. Each field is rendered as a column:
@dataclass(frozen=True)
class PlanetData:
mass: float
"""Mass in kilograms."""
radius: float
"""Radius in meters."""
#: Number of known moons.
moons: int
class Planet(PlanetData, Enum):
MERCURY = 3.303e23, 2.4397e6, 0
VENUS = 4.869e24, 6.0518e6, 0
EARTH = 5.976e24, 6.37814e6, 1
MARS = 6.421e23, 3.3972e6, 2
.. enum-table:: examples.Planet
:caption: The inner planets.
name |
mass |
radius |
moons |
|---|---|---|---|
|
3.303e+23 |
2439700.0 |
0 |
|
4.869e+24 |
6051800.0 |
0 |
|
5.976e+24 |
6378140.0 |
1 |
|
6.421e+23 |
3397200.0 |
2 |
Dataclass Values¶
Enumerations whose values are dataclass (or namedtuple()) instances are rendered
the same way. The value’s fields replace the value column:
@dataclass(frozen=True)
class RGB:
red: int
green: int
blue: int
class Color(Enum):
RED = RGB(255, 0, 0)
GREEN = RGB(0, 255, 0)
BLUE = RGB(0, 0, 255)
.. enum-table:: examples.Color
Member Docstrings¶
If any member in the table has a docstring, the docstrings are added in a column called doc.
Docstrings are found the same way autodoc finds them: a string literal
immediately after the member, or a #: comment before it. A __doc__ attribute set on the
member itself (for example by the enum’s __init__) takes precedence. Members without a
docstring have an empty cell.
class Severity(IntEnum):
DEBUG = 10
"""Diagnostic detail, usually disabled in production."""
INFO = 20
"""Routine operational messages."""
#: Something unexpected happened that the application **recovered** from.
WARNING = 30
ERROR = 40
"""A failure that needs attention.
See :ref:`usage` for how to render these tables."""
CRITICAL = 50
.. enum-table:: examples.Severity
name |
value |
doc |
|---|---|---|
|
10 |
Diagnostic detail, usually disabled in production. |
|
20 |
Routine operational messages. |
|
30 |
Something unexpected happened that the application recovered from. |
|
40 |
A failure that needs attention. See Usage for how to render these tables. |
|
50 |
Docstrings are parsed as reStructuredText, so inline markup, cross references and multiple paragraphs work. CSV and JSON downloads contain the rendered text of the docstring.
The doc column is appended after the other columns. If a column with the same name already exists (e.g. a dataclass field called
doc) the docstrings override it in place.Use
enum-table:doc-columnto give the column a different name, for example if you want to keep adocfield as well as the docstrings.Use
enum-table:docsto turn the doc column off. The column name is then an ordinary column again.When
enum-table:columnsis given, the doc column is only included where it is listed.Only the rendered members are considered. If none of them has a docstring there is no doc column.
.. enum-table:: examples.Severity
:doc-column: description
:headers: description=Description
.. enum-table:: examples.Severity
:docs: false
Column Legend¶
Set enum-table:legend to describe the table’s columns in a legend beneath it. Column
descriptions come from the docstrings of the attributes behind each column:
dataclass fields - a string literal immediately after the field, a
#:comment before it, ordataclasses.field(doc=...)on Python 3.14+. Fields inherited from base dataclasses are included.enum-properties properties - docstrings on the property annotations (see enum-properties Enums).
named tuple fields, and properties defined with
@property(their__doc__).
Only documented columns are listed, in column order and labeled with their headers. If no rendered column is documented, there is no legend. Descriptions are parsed as reStructuredText.
.. enum-table:: examples.Planet
:legend:
name |
mass |
radius |
moons |
|---|---|---|---|
|
3.303e+23 |
2439700.0 |
0 |
|
4.869e+24 |
6051800.0 |
0 |
|
5.976e+24 |
6378140.0 |
1 |
|
6.421e+23 |
3397200.0 |
2 |
- mass
Mass in kilograms.
- radius
Radius in meters.
- moons
Number of known moons.
The legend is a definition list, so it renders in every builder, including PDF. In HTML the table
is linked to its legend with aria-describedby so screen readers announce the descriptions
with the table. Legends are off by default.
Note
Column descriptions are rendered as a visible legend rather than as tooltips on the headers
because tooltips (title attributes) are only available to mouse users and are not reliably
announced by screen readers.
Selecting Columns¶
Use enum-table:columns to choose which columns are shown and in what order. Columns may
be any attribute on the member (including properties and methods decorated with @property) or
a dotted path. Attributes that are not found on the member are looked up on the member’s value.
Use enum-table:exclude to drop columns from the defaults instead.
class Priority(IntEnum):
LOW = 1
MEDIUM = 5
HIGH = 10
@property
def urgent(self) -> bool:
return self >= Priority.HIGH
.. enum-table:: examples.Priority
:columns: name, value, urgent
:headers: name=Priority, value=Weight, urgent=Urgent?
Selecting Members¶
Use enum-table:members to choose which members are shown and in what order and
enum-table:exclude-members to drop members.
.. enum-table:: examples.Planet
:members: EARTH, MARS
:exclude: moons
Formatting Cells¶
By default cells are converted to text with format_value(). Enum members
render as ClassName.MEMBER, sequences render as comma separated values and name cells
render as inline literals. You can change how cells render by supplying a formatter function,
either for all tables with the enum_table_formatter configuration value or for a
single table with the enum-table:formatter option. Formatters are passed the member,
the column name and the raw value. They may return text, a docutils node or None to fall back
to the default formatting:
def planet_formatter(member: Enum, column: str, value: t.Any):
if column in ("mass", "radius"):
unit = "kg" if column == "mass" else "m"
return nodes.Text(f"{value:.3e} {unit}")
return None # use the default formatting
.. enum-table:: examples.Planet
:formatter: examples.planet_formatter
Downloads¶
Tables can offer download buttons for CSV and JSON versions of their data. Downloads are off by
default. Turn them on for every table with enum_table_download:
# conf.py
enum_table_download = True # or a list of formats, e.g. ["json"]
HTML builders render the buttons below the table. Other builders (e.g. LaTeX/PDF, text and epub) omit them. Tables render natively in every builder, including PDF.
CSV files contain the header row and the display text of every cell, exactly as rendered.
JSON files contain an object keyed by member name. Each member maps to an object keyed by column name (the
namecolumn is omitted since it is the key). Native JSON types (strings, numbers, booleans andnull) are preserved. Lists, tuples, dicts, dataclasses and named tuples are converted to their JSON equivalents, and any other values use their display text. For example:{ "MERCURY": {"mass": 3.303e+23, "radius": 2439700.0, "moons": 0}, "VENUS": {"mass": 4.869e+24, "radius": 6051800.0, "moons": 0} }
Use enum-table:download to override the setting for a single table, either to add
downloads to a table when they are off globally or to remove them when they are on. Given without
a value it offers every format:
.. enum-table:: examples.Planet
:download:
.. enum-table:: examples.Planet
:download: json
.. enum-table:: examples.Planet
:download: none
Theme Styling¶
Tables are ordinary Sphinx tables, so they are styled by your html theme. The extension adds a small theme-neutral stylesheet for the layout of the legend and the download buttons, and extra styles for themes it knows:
furo - striped rows, a row hover highlight, left-aligned headers and a visible table edge in dark mode. These use furo’s color variables, so they follow its light, dark and auto modes.
Every rendered table is a table.enum-table inside a div.enum-table-container. To change
the styling, add your own stylesheet with html_css_files, it
is loaded after the extension’s stylesheets:
# conf.py
html_static_path = ["_static"]
html_css_files = ["custom.css"]
/* _static/custom.css - turn off the striped rows */
.enum-table-container table.enum-table > tbody > tr:nth-child(even) {
background: none;
}
enum-properties Enums¶
enum-properties enums are supported as a special case. Each declared property is rendered as a
column after the value column (and after any dataclass fields if the enum also mixes in a
dataclass). enum-properties is not a dependency of this extension. Its enums are detected
automatically. Docstrings on the property annotations describe their columns in the
column legend.
class Shade(EnumProperties):
label: t.Annotated[str, Symmetric()]
"""A human readable label."""
hex: t.Annotated[str, Symmetric(case_fold=True)]
"""The hex color code, without a leading ``#``."""
RED = 1, "Red", "ff0000"
GREEN = 2, "Green", "00ff00"
BLUE = 3, "Blue", "0000ff"
.. enum-table:: examples.Shade
:legend:
Cross Referencing¶
Give a table a enum-table:name to reference it with ref or, when
numfig is enabled and the table has a caption, numref.
.. enum-table:: examples.Planet
:caption: The inner planets.
:name: planets
See :ref:`planets`.
Named tables are added to the project’s intersphinx inventory as std:label entries, so
other projects can link to them too (e.g. :ref:`yourdocs:planets`). Tables without a name
are not in the inventory.
Note
The directive only documents the enumeration as a table. It does not register the enum class
or its members as Python objects, so roles like py:class and
py:attr will not resolve to the table (locally or through intersphinx). Member
names and enum-valued cells are rendered as text, not links. To make the enum and its members
referenceable, also document them with autodoc (e.g.
autoclass) and those references will resolve to the autodoc entries.