Skip to content
Open
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
9 changes: 8 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ jobs:
uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c # v2.0.2
with:
macos-skip-brew-update: "true"
- uses: actions/cache@v5
- uses: actions/cache/restore@v5
id: theme-build-cache
with:
path: ${{ github.workspace }}/theme_build_cache
key: theme-build-cache-${{ runner.os }}-${{ github.run_id }}
Expand All @@ -141,6 +142,12 @@ jobs:
with:
name: doc-builds-${{ runner.os }}
path: docs/_build/
- name: Save theme build cache
if: always() && steps.theme-build-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: ${{ github.workspace }}/theme_build_cache
key: theme-build-cache-${{ runner.os }}-${{ github.run_id }}
- name: upload docs to github pages
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && runner.os == 'Linux'
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # pinned to v4.0.0
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,8 @@ def get_colors(color_t: str):
("cpp:identifier", "my_ns3"),
("cpp:identifier", "cpp_apigen_demo"),
# Example JavaScript types
("js:func", "string"),
("js:func", "SomeError"),
("js:class", "string"),
("js:class", "SomeError"),
# pydantic_extra_types.color not present in object inventory
("py:class", "pydantic_extra_types.color.Color"),
]
Expand Down
12 changes: 7 additions & 5 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
"check_lf",
]

SUPPORTED_PY_VER = list(f"3.{x}" for x in range(10, 14))
SUPPORTED_PY_VER = list(f"3.{x}" for x in range(10, 15))


def uv_sync(session: nox.Session, *args: list[str]):
def uv_sync(session: nox.Session, *args: str):
session.run_install(
"uv",
"sync",
Expand Down Expand Up @@ -73,7 +73,7 @@ def mypy(session: nox.Session):
"__pycache__",
"^src",
"^sphinx_immaterial/(?:\\.icons|bundles|static|.*\\.html)",
"^tests/issue_134/.*(?:/build|\\.egg\\-info)",
"^tests/issue_134/.*(?:/build|\\.egg\\-info|\\.pyd)",
"^node_modules",
"^dist/",
"^docs/(?:_build|\\w+_apigen_generated)",
Expand Down Expand Up @@ -208,9 +208,11 @@ def docs(session: nox.Session, builder: str):
ci_logger.info("::endgroup::")


SUPPORTED_SPHINX = [6, 7, 8]
SUPPORTED_SPHINX = [6, 7, 8, 9]

EXCLUDED_PYTHON_SPHINX = {}
EXCLUDED_PYTHON_SPHINX: set[tuple[str, str]] = {
("3.10", "9"),
}


@nox.session
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ sphinx7 = [
sphinx8 = [
"sphinx>=8,<9",
]
sphinx9 = [
"sphinx>=9,<10; python_version >= '3.11'",
]

[project.optional-dependencies]
json = [
Expand Down Expand Up @@ -226,6 +229,7 @@ conflicts = [
{ group = "sphinx6" },
{ group = "sphinx7" },
{ group = "sphinx8" },
{ group = "sphinx9" },
],
]

Expand Down
29 changes: 21 additions & 8 deletions sphinx_immaterial/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import os
import re
from typing import Dict, List, Mapping, Optional, Type, cast
from typing import Dict, Mapping, Optional, Type, cast
from urllib.parse import urlparse

import docutils.nodes
Expand All @@ -18,6 +18,14 @@
from sphinx.application import Sphinx
from sphinxcontrib.serializinghtml import JSONHTMLBuilder

if version_info < (7, 2):
from sphinx.builders.html import JavaScript # type: ignore[attr-defined]
from sphinx.builders.html import ( # type: ignore[attr-defined]
Stylesheet as StyleSheet,
)
else:
from sphinx.builders.html._assets import _CascadingStyleSheet as StyleSheet
from sphinx.builders.html._assets import _JavaScript as JavaScript
from . import (
html_translator_mixin,
json_builder_serializing_implementation,
Expand Down Expand Up @@ -62,9 +70,9 @@ def _get_html_builder(base_builder: Type[sphinx.builders.html.StandaloneHTMLBuil

class CustomHTMLBuilder(base_builder): # type: ignore
if version_info < (7, 2):
css_files: List[sphinx.builders.html.Stylesheet]
css_files: list[StyleSheet]
else:
_css_files: List[sphinx.builders.html._assets._CascadingStyleSheet] # type: ignore[name-defined]
_css_files: list[StyleSheet] # type: ignore[name-defined]
theme: sphinx.theming.Theme
templates: sphinx.jinja2glue.BuiltinTemplateLoader

Expand Down Expand Up @@ -98,11 +106,11 @@ def init_js_files(self):
excluded_scripts.add("_static/jquery.js")
excluded_scripts.add("_static/_sphinx_javascript_frameworks_compat.js")
if version_info < (7, 2):
self.script_files: List[sphinx.builders.html.JavaScript] = [
self.script_files: list[JavaScript] = [
x for x in self.script_files if x.filename not in excluded_scripts
]
else:
self._js_files: List[sphinx.builders.html._assets._JavaScript] = [ # type: ignore[name-defined]
self._js_files: list[JavaScript] = [ # type: ignore[name-defined]
x for x in self._js_files if x.filename not in excluded_scripts
]

Expand All @@ -121,14 +129,14 @@ def init_css_files(self):
if version_info < (7, 2):
self.css_files = [
x
for x in cast(List[sphinx.builders.html.Stylesheet], self.css_files)
for x in cast(list[StyleSheet], self.css_files)
if x.filename not in excluded
]
else:
self._css_files = [
x
for x in cast(
List[sphinx.builders.html._assets._CascadingStyleSheet], # type: ignore[name-defined]
list[StyleSheet], # type: ignore[name-defined]
self._css_files,
)
if x.filename not in excluded
Expand Down Expand Up @@ -324,9 +332,14 @@ def _config_inited(
+ "The sphinx.ext.napoleon extension may be used instead for NumPy-style docstring support."
)

# Enable the legacy (``Documenter``) autodoc implementation
# for all users of the theme
config.autodoc_use_legacy_class_based = True


def setup(app: Sphinx):
app.connect("config-inited", _config_inited)
# Run before sphinx.ext.autodoc._register_directives()
app.connect("config-inited", _config_inited, priority=50)

app.setup_extension("sphinx_immaterial.css_and_javascript_bundles")
app.setup_extension("sphinx_immaterial.external_resource_cache")
Expand Down
6 changes: 3 additions & 3 deletions sphinx_immaterial/apidoc/json/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ def _add_sub_schema(
return sphinx_utils.parse_rst(
self.state,
sphinx_utils.format_directive("json:schema", entry.id, options=kwargs),
*self.get_source_info(),
*cast(tuple[str, int], self.get_source_info()),
)

def _make_field(
Expand Down Expand Up @@ -1107,7 +1107,7 @@ class JsonSchemaDomain(sphinx.domains.Domain):
"schema": JsonSchemaRole(warn_dangling=True),
}

object_types: Dict[str, sphinx.domains.ObjType] = {
object_types: Dict[str, sphinx.domains.ObjType] = { # type: ignore[misc]
"schema": sphinx.domains.ObjType("type", "schema"),
"subschema": sphinx.domains.ObjType("member", "schema"),
}
Expand All @@ -1116,7 +1116,7 @@ class JsonSchemaDomain(sphinx.domains.Domain):
"schema": JsonSchemaDirective,
}

initial_data: Dict[str, DomainSchemaEntry] = {
initial_data: Dict[str, DomainSchemaEntry] = { # type: ignore[misc]
"schemas": cast(DomainSchemaEntry, {}),
}

Expand Down
8 changes: 6 additions & 2 deletions sphinx_immaterial/apidoc/python/type_param_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ def get_base_class_type_param_substitutions(
}

if sys.version_info >= (3, 10):
_ENCODE_TYPE_PARAM[typing.ParamSpec] = (
lambda annotation: TYPE_VAR_ANNOTATION_PREFIX + "P_" + annotation.__name__
_ENCODE_TYPE_PARAM[typing.ParamSpec] = lambda annotation: (
TYPE_VAR_ANNOTATION_PREFIX + "P_" + annotation.__name__
)
_DECODE_TYPE_PARAM["P"] = typing.ParamSpec
if sys.version_info >= (3, 11):
Expand Down Expand Up @@ -232,6 +232,10 @@ def stringify_annotation(
for module in [
"sphinx.util.typing",
"sphinx.ext.autodoc",
"sphinx.ext.autodoc._dynamic._loader",
"sphinx.ext.autodoc._dynamic._type_annotations",
"sphinx.ext.autodoc._legacy_class_based._documenters",
"sphinx.ext.autodoc._generate",
"sphinx.ext.autodoc.typehints",
"sphinx.util.inspect",
"sphinx.ext.napoleon.docstring",
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sphinx

if sphinx.version_info < (7, 2):
from sphinx.testing.path import path as SphinxPath
from sphinx.testing.path import path as SphinxPath # type: ignore[import-not-found]
else:
from pathlib import Path as SphinxPath # type: ignore[assignment]

Expand Down
2 changes: 1 addition & 1 deletion tests/python_apigen_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)

if sphinx.version_info < (7, 2):
from sphinx.testing.path import path as SphinxPath
from sphinx.testing.path import path as SphinxPath # type: ignore[import-not-found]
else:
from pathlib import Path as SphinxPath # type: ignore[assignment]

Expand Down
2 changes: 1 addition & 1 deletion tests/python_transform_type_annotations_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sphinx.domains.python

if sphinx.version_info < (7, 2):
from sphinx.testing.path import path as SphinxPath
from sphinx.testing.path import path as SphinxPath # type: ignore[import-not-found]
else:
from pathlib import Path as SphinxPath # type: ignore[assignment]

Expand Down
Loading