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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

Sphinx directive for documenting dataclass enums in tabular format, with support for enum-properties.

Render [dataclass](https://docs.python.org/3/library/dataclasses.html) enums as tables with a row for each member and a column for every field. Each table has CSV and JSON download buttons. Enums with dataclass values, named tuple values and plain enums work too, and [enum-properties](https://enum-properties.readthedocs.io) enums are supported as a special case: each property becomes a column.
Render [dataclass](https://docs.python.org/3/library/dataclasses.html) enums as tables with a row for each member and a column for every field. Tables can optionally offer CSV and JSON download buttons. Enums with dataclass values, named tuple values and plain enums work too, and [enum-properties](https://enum-properties.readthedocs.io) enums are supported as a special case: each property becomes a column.

## Installation

Expand Down Expand Up @@ -70,7 +70,7 @@ Which renders a table with `name`, `mass` and `radius` columns. Columns, members
:columns: name, radius
:members: EARTH, MERCURY
:headers: name=Planet, radius=Radius (m)
:download: csv
:download: csv, json
```

## Documentation
Expand Down
2 changes: 1 addition & 1 deletion doc/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Changelog
0.1.0 (2026-09-28)
------------------

* Initial release: the ``enum-table`` directive with CSV and JSON downloads.
* Initial release: the ``enum-table`` directive with optional CSV and JSON downloads.
* Tables render in PDF (LaTeX) builds, large tables wrap long cells and break across pages.
3 changes: 3 additions & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@

# xelatex handles the unicode in the module docstring banner
latex_engine = "xelatex"

# show the download buttons on every example table
enum_table_download = True
4 changes: 2 additions & 2 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ sphinxcontrib-enum


A Sphinx_ directive for documenting dataclass_ enums in tabular format. Each member is a row and
each dataclass field is a column. Tables can be downloaded as CSV or JSON.
each dataclass field is a column. Tables can optionally be downloaded as CSV or JSON.

* Documents enums that mix in a dataclass_ or whose values are dataclasses (or named tuples).
* Columns may be any attribute, property or dotted path on the member or its value.
* Filter and reorder columns and members, rename headers, add captions and cross references.
* Customize how cells render with a formatter function.
* CSV and JSON download buttons (html builders only).
* Optional CSV and JSON download buttons (html builders only).
* :ref:`Supports enum-properties <enum_properties>` enums as a special case, and plain enums work
too.

Expand Down
20 changes: 15 additions & 5 deletions doc/source/reference/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,28 @@ The following configuration values can be set in your
"sphinxcontrib_enum",
]

# only offer json downloads
# offer csv and json downloads for every table (off by default)
enum_table_download = True

# or only offer json downloads
enum_table_download = ["json"]

# format cells with a custom function
enum_table_formatter = "mypackage.docs.format_cell"

.. confval:: enum_table_download
:type: ``list[str]``
:default: ``["csv", "json"]``
:type: ``bool | list[str] | str | None``
:default: ``False``

The download formats to offer beneath every table. Downloads are off by default.

* ``False``, ``None`` or an empty list - no download buttons.
* ``True`` - offer every supported format (``csv`` and ``json``).
* A list of formats, e.g. ``["json"]`` or ``["csv", "json"]``, or the same as a comma
separated string (``"csv, json"``). Buttons are rendered in the order given.

The download formats to offer beneath every table. Set to an empty list to disable downloads.
Can be overridden per table with :rst:dir:`enum-table:download`.
Unsupported formats are a configuration error. Can be overridden per table with
:rst:dir:`enum-table:download`, so individual tables can opt in or out.

.. confval:: enum_table_formatter
:type: ``str | Callable | None``
Expand Down
3 changes: 2 additions & 1 deletion doc/source/reference/directive.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ Directive
**default**: :confval:`enum_table_download`

The download formats to offer for this table. Supports ``csv`` and ``json``, or ``none`` to
disable downloads.
disable downloads. Overrides :confval:`enum_table_download`, which is off by default, so
use this to add downloads to individual tables.

.. rst:directive:option:: formatter: import path of a cell formatter
:type: text
Expand Down
19 changes: 13 additions & 6 deletions doc/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,16 @@ to the default formatting:
Downloads
=========

HTML builders render download buttons for CSV and JSON versions of the table below it. Other
builders (e.g. LaTeX/PDF, text and epub) omit them. Tables render natively in every
builder, including PDF.
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 :confval:`enum_table_download`:

.. code-block:: python

# 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
Expand All @@ -138,13 +145,13 @@ builder, including PDF.
"VENUS": {"mass": 4.869e+24, "radius": 6051800.0, "moons": 0}
}

Use :confval:`enum_table_download` to change the default formats for all tables or
:rst:dir:`enum-table:download` for a single table:
Use :rst:dir:`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:

.. code-block:: rst

.. enum-table:: examples.Planet
:download: json
:download: csv, json

.. enum-table:: examples.Planet
:download: none
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ classifiers = [
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
"Typing :: Typed",
"Topic :: Software Development :: Libraries",
]

Expand Down
49 changes: 44 additions & 5 deletions src/sphinxcontrib_enum/directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from docutils import nodes
from docutils.parsers.rst import directives
from sphinx.application import Sphinx
from sphinx.config import Config
from sphinx.errors import ConfigError
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective, SphinxTranslator
from sphinx.util.osutil import ensuredir, relative_uri
Expand All @@ -34,6 +36,7 @@
"DOWNLOAD_FORMATS",
"EnumTableDirective",
"Formatter",
"download_formats",
"enum_table_downloads",
]

Expand Down Expand Up @@ -100,9 +103,24 @@ def headers_option(argument: str | None) -> dict[str, str]:
return headers


def download_option(argument: str | None) -> list[str]:
formats = [fmt.lower() for fmt in _split(argument)]
if formats in ([], ["none"]):
def download_formats(value: t.Any) -> list[str]:
"""
Normalize a download setting into a list of formats.

* falsey values (``False``, ``None``, empty) disable downloads
* ``True`` enables every supported format
* strings are comma or whitespace separated formats (or ``none``)
* any other iterable is a collection of formats

:raises ValueError: If a format is not supported.
"""
if not value:
return []
if value is True:
return list(DOWNLOAD_FORMATS)
items = _split(value) if isinstance(value, str) else list(value)
formats = [str(fmt).strip().lower() for fmt in items]
if formats == ["none"]:
return []
for fmt in formats:
if fmt not in DOWNLOAD_FORMATS:
Expand All @@ -113,6 +131,10 @@ def download_option(argument: str | None) -> list[str]:
return list(dict.fromkeys(formats))


def download_option(argument: str | None) -> list[str]:
return download_formats(argument)


def widths_option(argument: str | None) -> str | list[int]:
if (argument or "").strip().lower() in ("auto", "grid"):
return (argument or "").strip().lower()
Expand Down Expand Up @@ -218,7 +240,9 @@ def run(self) -> list[nodes.Node]:
container = nodes.container(classes=["enum-table-container"])
container += table

formats = self.options.get("download", self.config.enum_table_download)
formats = self.options.get(
"download", download_formats(self.config.enum_table_download)
)
if formats:
text = [[_text(cell) for cell in row] for row in display]
contents = {
Expand Down Expand Up @@ -450,6 +474,13 @@ def _latex_width_hints(table: nodes.table, rows: list[nodes.row]) -> None:
colspec["colwidth"] = round(width) + _LATEX_CELL_PADDING


def _check_download_config(app: Sphinx, config: Config) -> None:
try:
download_formats(config.enum_table_download)
except (TypeError, ValueError) as err:
raise ConfigError(f"Invalid enum_table_download: {err}") from err


def setup(app: Sphinx) -> None:
app.add_node(
enum_table_downloads,
Expand All @@ -458,5 +489,13 @@ def setup(app: Sphinx) -> None:
app.add_directive("enum-table", EnumTableDirective)
app.connect("doctree-resolved", _remove_downloads)
app.connect("doctree-resolved", _wrap_latex_longtables)
app.add_config_value("enum_table_download", list(DOWNLOAD_FORMATS), "env")
app.add_config_value(
"enum_table_download",
False,
"env",
# frozenset/set must not be listed, sphinx converts sequences to frozensets
# when they are, losing the format order
types=(bool, list, tuple, str, type(None)),
)
app.connect("config-inited", _check_download_config)
app.add_config_value("enum_table_formatter", None, "env")
Loading
Loading