| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| # Configuration file for the Sphinx documentation builder. |
| # |
| # This file only contains a selection of the most common options. For a full |
| # list see the documentation: |
| # https://www.sphinx-doc.org/en/master/usage/configuration.html |
| |
| # -- Path setup -------------------------------------------------------------- |
| |
| # If extensions (or modules to document with autodoc) are in another directory, |
| # add these directories to sys.path here. If the directory is relative to the |
| # documentation root, use os.path.abspath to make it absolute, like shown here. |
| # |
| # import os |
| # import sys |
| # sys.path.insert(0, os.path.abspath('.')) |
| |
| # -- Project information ----------------------------------------------------- |
| |
| project = 'Apache DataFusion Comet' |
| copyright = '2023-2024, Apache Software Foundation' |
| author = 'Apache Software Foundation' |
| |
| |
| # -- General configuration --------------------------------------------------- |
| |
| # Add any Sphinx extension module names here, as strings. They can be |
| # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
| # ones. |
| extensions = [ |
| 'sphinx.ext.autodoc', |
| 'sphinx.ext.autosummary', |
| 'sphinx.ext.doctest', |
| 'sphinx.ext.ifconfig', |
| 'sphinx.ext.mathjax', |
| 'sphinx.ext.viewcode', |
| 'sphinx.ext.napoleon', |
| 'myst_parser', |
| 'sphinx_reredirects', |
| ] |
| |
| source_suffix = { |
| '.rst': 'restructuredtext', |
| '.md': 'markdown', |
| } |
| |
| # Add any paths that contain templates here, relative to this directory. |
| templates_path = ['_templates'] |
| |
| # List of patterns, relative to source directory, that match files and |
| # directories to ignore when looking for source files. |
| # This pattern also affects html_static_path and html_extra_path. |
| exclude_patterns = [ |
| # Per-Spark-version compatibility pages are generated by docs/build.sh from these |
| # templates; the templates themselves are not part of the rendered docs. |
| 'user-guide/latest/compatibility/expressions/_category_template', |
| ] |
| |
| # Show members for classes in .. autosummary |
| autodoc_default_options = { |
| "members": None, |
| "undoc-members": None, |
| "show-inheritance": None, |
| "inherited-members": None, |
| } |
| |
| autosummary_generate = True |
| |
| # -- Options for HTML output ------------------------------------------------- |
| |
| # The theme to use for HTML and HTML Help pages. See the documentation for |
| # a list of builtin themes. |
| # |
| html_theme = 'pydata_sphinx_theme' |
| |
| html_logo = "_static/images/DataFusionComet-Logo-Light.png" |
| |
| html_theme_options = { |
| "logo": { |
| "image_light": "_static/images/DataFusionComet-Logo-Light.png", |
| "image_dark": "_static/images/DataFusionComet-Logo-Dark.png", |
| }, |
| |
| "use_edit_page_button": False, |
| "secondary_sidebar_items": ["page-toc"], |
| "collapse_navigation": True, |
| "navbar_start": ["navbar-logo"], |
| "navbar_center": ["navbar-nav"], |
| "navbar_end": ["navbar-icon-links", "theme-switcher"], |
| "icon_links": [ |
| { |
| "name": "GitHub", |
| "url": "https://github.com/apache/datafusion-comet", |
| "icon": "fa-brands fa-github", |
| }, |
| ], |
| |
| } |
| |
| html_context = { |
| "default_mode": "light", |
| "github_user": "apache", |
| "github_repo": "datafusion-comet", |
| "github_version": "main", |
| "doc_path": "docs/source", |
| } |
| |
| # Add any paths that contain custom static files (such as style sheets) here, |
| # relative to this directory. They are copied after the builtin static files, |
| # so a file named "default.css" will overwrite the builtin "default.css". |
| html_static_path = ['_static'] |
| |
| html_css_files = [ |
| "theme_overrides.css" |
| ] |
| |
| html_js_files = [ |
| ("https://buttons.github.io/buttons.js", {'async': 'true', 'defer': 'true'}), |
| "comet-ux.js", |
| ] |
| |
| html_sidebars = { |
| "**": ["search-field.html", "docs-sidebar.html"], |
| # Landing page is a full-width marketing page — no left rail. |
| "index": [], |
| } |
| |
| # tell myst_parser to auto-generate anchor links for headers h1, h2, h3, h4 |
| myst_heading_anchors = 4 |
| |
| # enable nice rendering of checkboxes for the task lists |
| myst_enable_extensions = ["colon_fence", "deflist", "tasklist"] |
| |
| redirects = { |
| "overview.html": "index.html", |
| "gluten_comparison.html": "about/gluten_comparison.html", |
| "user-guide/overview.html": "../index.html", |
| "user-guide/gluten_comparison.html": "../about/gluten_comparison.html", |
| "user-guide/compatibility.html": "latest/compatibility.html", |
| "user-guide/configs.html": "latest/configs.html", |
| "user-guide/datasource.html": "latest/datasource.html", |
| "user-guide/datatypes.html": "latest/datatypes.html", |
| "user-guide/expressions.html": "latest/expressions.html", |
| "user-guide/iceberg.html": "latest/iceberg.html", |
| "user-guide/installation.html": "latest/installation.html", |
| "user-guide/kubernetes.html": "latest/kubernetes.html", |
| "user-guide/metrics.html": "latest/metrics.html", |
| "user-guide/operators.html": "latest/operators.html", |
| "user-guide/source.html": "latest/source.html", |
| "user-guide/tuning.html": "latest/tuning.html", |
| } |
| |
| |
| # -- $COMET_VERSION substitution ------------------------------------------- |
| # build.sh runs `replace_in_files` after copying source/ → temp/ to swap the |
| # $COMET_VERSION placeholder with the real version from pom.xml. When Sphinx |
| # is invoked directly against source/ (local dev, IDE preview, etc.), that |
| # substitution never runs and the literal "$COMET_VERSION" leaks into page |
| # titles, breadcrumbs, and the toctree caption. The hook below mirrors the |
| # build.sh substitution at Sphinx read-time so local builds match prod. |
| |
| def _read_comet_version(): |
| import os |
| import xml.etree.ElementTree as ET |
| pom_path = os.path.normpath(os.path.join(os.path.dirname(__file__), "..", "..", "pom.xml")) |
| try: |
| tree = ET.parse(pom_path) |
| root = tree.getroot() |
| ns = {"m": "http://maven.apache.org/POM/4.0.0"} |
| ver = root.find("m:version", ns) |
| if ver is not None and ver.text: |
| return ver.text.strip() |
| except Exception: |
| pass |
| return "latest" |
| |
| |
| _comet_version = _read_comet_version() |
| |
| |
| def _substitute_version(app, docname, source): |
| if "$COMET_VERSION" in source[0]: |
| source[0] = source[0].replace("$COMET_VERSION", _comet_version) |
| |
| |
| # -- User Guide sidebar: nest per-version pages under captions -------------- |
| # Every User Guide page groups its pages under captions (Getting Started, |
| # What Comet Supports, ...) via nested `.. toctree::` blocks in that version's |
| # own index page — except the tree rendered from user-guide/index itself |
| # (the version accordion: current version, Development Snapshot, Older |
| # Versions), where expanding a version used to show a flat list instead of |
| # the same captioned groups. That's because Sphinx's toctree resolution only |
| # keeps `:caption:` labels for the page acting as the root of the resolved |
| # fragment; once a version's toctree is merged as a *child* of the index page |
| # (two hops away), its captions are dropped. To nest them back in, we resolve |
| # each version's own toctree separately (as if it were the root, via |
| # pydata-sphinx-theme's internal toctree helpers) and splice the captioned |
| # fragment into that version's accordion in the outer, uncaptioned tree. |
| # Older Versions is left as-is; it isn't touched here. |
| # |
| # We render this same nested tree, always anchored at user-guide/index, for |
| # EVERY page under user-guide/ (not just the index page). Sub-pages used to |
| # fall back to a different, shallower anchor (the version's own index), |
| # which dropped the version accordion entirely and replaced the sidebar with |
| # a completely different tree on every navigation — jarring, and the reason |
| # an earlier commit on this branch flattened everything back to one |
| # consistent depth. Keeping one fixed anchor everywhere gets the same |
| # stability without giving up captions: only the "current" highlighting and |
| # which accordion is auto-expanded change between pages. |
| # |
| # This relies on two undocumented, module-level helpers from |
| # pydata_sphinx_theme.toctree (get_nonroot_toctree, add_collapse_checkboxes). |
| # They're pinned via requirements.txt (pydata-sphinx-theme<0.17.0), so a |
| # theme upgrade won't silently change this behavior. |
| |
| def _build_user_guide_sidebar_html(app, pagename, context): |
| from bs4 import BeautifulSoup |
| from pydata_sphinx_theme.toctree import ( |
| _get_ancestor_pagename, |
| add_collapse_checkboxes, |
| get_nonroot_toctree, |
| ) |
| from sphinx.environment.adapters.toctree import TocTree |
| |
| outer = context["generate_toctree_html"]( |
| "sidebar", startdepth=1, maxdepth=4, collapse=False, |
| includehidden=True, titles_only=True, |
| ) |
| # generate_toctree_html is memoized by the theme and returns a shared, |
| # mutable BeautifulSoup object; re-parse into an independent tree so the |
| # splicing below can't compound across repeated calls for this page. |
| soup = BeautifulSoup(str(outer), "html.parser") |
| |
| # Resolve the same depth-1 ancestor generate_toctree_html used above |
| # (user-guide/index, regardless of which user-guide/* page is actually |
| # being rendered) so we read its toctree's own doc list rather than |
| # pagename's — pagename is the page being viewed, not the page that |
| # owns the version-accordion toctree. |
| toctree = TocTree(app.env) |
| ancestorname, _ = _get_ancestor_pagename(app, pagename, startdepth=1) |
| |
| # That toctree lists, in order: the current stable version, the |
| # development snapshot, then Older Versions. Nest captions into the |
| # first two; Older Versions keeps its existing flat list. |
| version_docnames = app.env.toctree_includes.get(ancestorname, []) |
| top_level_items = soup.select("ul.bd-sidenav > li.toctree-l1") |
| |
| for li, docname in zip(top_level_items, version_docnames[:2]): |
| details = li.find("details") |
| inner_ul = details.find("ul") if details else None |
| if inner_ul is None: |
| continue |
| captioned = get_nonroot_toctree( |
| app, pagename, docname, toctree, |
| collapse=False, maxdepth=4, includehidden=True, titles_only=True, |
| ) |
| if captioned is None: |
| continue |
| frag_soup = BeautifulSoup( |
| app.builder.render_partial(captioned)["fragment"], "html.parser" |
| ) |
| # The fragment was resolved as its own root, so its items are labeled |
| # toctree-l1/-l2/...; shift by one to match the depth they actually |
| # sit at once nested inside this version's own l1 entry. |
| for tag in frag_soup.find_all(class_=True): |
| tag["class"] = [ |
| f"toctree-l{int(cl[len('toctree-l'):]) + 1}" |
| if cl.startswith("toctree-l") and cl[len("toctree-l"):].isdigit() |
| else cl |
| for cl in tag["class"] |
| ] |
| add_collapse_checkboxes(frag_soup) |
| for child in list(frag_soup.children): |
| inner_ul.insert_before(child) |
| inner_ul.decompose() |
| |
| return str(soup) |
| |
| |
| def _add_user_guide_sidebar_context(app, pagename, templatename, context, doctree): |
| if pagename.startswith("user-guide/"): |
| context["user_guide_sidebar_html"] = ( |
| lambda: _build_user_guide_sidebar_html(app, pagename, context) |
| ) |
| |
| |
| def setup(app): |
| app.connect("source-read", _substitute_version) |
| app.connect("html-page-context", _add_user_guide_sidebar_context) |
| return {"version": _comet_version, "parallel_read_safe": True, "parallel_write_safe": True} |