Files
2026-08-28 18:20:00 +02:00

144 lines
4.2 KiB
Python

"""Sphinx configuration for the eco documentation.
Loosely modelled on the escape-fel docs so the two read consistently.
The docs mix reStructuredText (index/api) and Markdown (concepts, examples,
installation) via the MyST parser.
"""
import os
import sys
# Make the eco package importable for autodoc even when the docs are built
# without a full `pip install .` (e.g. locally with `make html`).
sys.path.insert(0, os.path.abspath(".."))
# -- Project information -----------------------------------------------------
project = "eco"
author = "Paul Scherrer Institute"
copyright = "2026, Paul Scherrer Institute"
# Kept intentionally light; bump alongside eco/setup.py when it matters.
release = "0.0.2"
# -- General configuration ---------------------------------------------------
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.napoleon", # NumPy / Google style docstrings
"sphinx.ext.viewcode",
"sphinx.ext.intersphinx",
"myst_parser", # Markdown support
"sphinx_copybutton", # copy button on code blocks
"sphinx_design", # grids / cards / tabs used on the landing page
]
templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# Accept both .rst and .md sources.
source_suffix = {
".rst": "restructuredtext",
".md": "markdown",
}
# -- Autodoc -----------------------------------------------------------------
autosummary_generate = True
autodoc_member_order = "bysource"
autodoc_default_options = {
"members": True,
"undoc-members": True,
"show-inheritance": True,
"special-members": "__init__",
}
# eco pulls in a large stack of hardware / beamline / streaming libraries that
# are not (and need not be) installed on the docs builder. Mock them so that
# importing eco for autodoc does not fail or, worse, try to open live EPICS /
# beam-synchronous connections. Add to this list whenever autodoc trips over a
# new third-party import.
autodoc_mock_imports = [
"epics",
"pyepics",
"caproto",
"serial",
"bsread",
"datahub",
"cbor2",
"cam_server",
"cam_server_client",
"cachebox",
"pcaspy",
"slic",
"scilog",
"elog",
"PyQt5",
"pyqtgraph",
"ipywidgets",
"textual",
"rich",
"colorama",
"tqdm",
"requests",
"zmq",
"h5py",
"pandas",
"scipy",
"matplotlib",
# escape (SwissFEL's data-analysis package) transitively pulls in
# dask -> xarray, whose xarray/core/types.py defines a module-level
# `pd.Timestamp | datetime.datetime | ...` type alias evaluated eagerly
# at import time -- with `pandas` mocked above, that `|` on a mock
# object raises TypeError and takes down autodoc for every module in
# eco that imports escape transitively (eco.elements.assembly among
# them, via eco.acquisition.scan_data). Mocking escape itself avoids
# ever reaching xarray's import at all.
"escape",
]
# -- MyST (Markdown) ---------------------------------------------------------
myst_enable_extensions = [
"colon_fence",
"deflist",
"fieldlist",
]
# "linkify" (auto-linking bare URLs) needs the optional linkify-it-py package.
# Enable it only when available so a local build without it still succeeds;
# Read the Docs installs it via docs/requirements.txt (myst-parser[linkify]).
try:
import linkify_it # noqa: F401
myst_enable_extensions.append("linkify")
except ImportError:
pass
myst_heading_anchors = 3
# -- Intersphinx -------------------------------------------------------------
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"pandas": ("https://pandas.pydata.org/docs/", None),
}
# -- HTML output -------------------------------------------------------------
html_theme = "furo"
html_title = "eco"
html_static_path = ["_static"]
# SwissFEL/escape blue, so eco and escape docs feel related.
html_theme_options = {
"light_css_variables": {
"color-brand-primary": "#0071bc",
"color-brand-content": "#0071bc",
},
"dark_css_variables": {
"color-brand-primary": "#4aa8e0",
"color-brand-content": "#4aa8e0",
},
}