Skip to content

Commit

Permalink
Update for sphinx v7.3.x (#346)
Browse files Browse the repository at this point in the history
* remove sys module from jinja contexts
* updates for changes to python domain
* support new versionremoved directive
* fix typing problems
* bump mypy version
* switch apigen data from builder env to app instance
* ensure monkeypatch is applied to sphinx/domains/python/*.py
* pin libclang to < v17 on macos
  • Loading branch information
2bndy5 authored Jun 12, 2024
1 parent 9519601 commit 14f75c0
Show file tree
Hide file tree
Showing 30 changed files with 170 additions and 98 deletions.
2 changes: 1 addition & 1 deletion docs/admonitions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ usage in other sphinx-based themes.
Version Directives
******************

The `versionadded`, `versionchanged`, and `deprecated` directives defined by Sphinx are also
The `versionadded`, `versionchanged`, `deprecated`, and `versionremoved` directives defined by Sphinx are also
rendered by the sphinx-immaterial theme as admonitions. The directives are optionally
overridden to support additional :rst:dir:`admonition` options :rst:`:collapsible:`,
:rst:`:name:`, and :rst:`:class:`.
Expand Down
25 changes: 4 additions & 21 deletions docs/apidoc/python/apigen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,24 +306,7 @@ Configuration
The following generated documents will be used (depending on the value of
:confval:`python_apigen_case_insensitive_filesystem`):

.. jinja:: sys

{%- set example_python_apigen_modules = {
"my_module": "my_api/",
"my_other_module": "other_api/my_other_module.",
}
%}
{%- set example_python_apigen_objects = [
("my_module.foo", ""),
("my_module.Foo", ""),
("my_module.Foo.method", ""),
("my_module.Foo.__init__", "json"),
("my_module.Foo.__init__", "values"),
("my_module.Bar", ""),
("my_other_module.Baz", ""),
]
%}
{%- set python_apigen_get_docname = sys.modules["sphinx_immaterial.apidoc.python.apigen"]._get_docname %}
.. jinja:: python_apigen_path_examples

.. list-table::
:widths: auto
Expand All @@ -334,11 +317,11 @@ Configuration
- Document (case-sensitive)
- Document (case-insensitive)

{%- for full_name, overload_id in example_python_apigen_objects %}
{%- for full_name, overload_id, case_sensitive, case_insensitive in example_python_apigen_objects %}
* - :python:`{{ full_name }}`
- {{ "``" + overload_id + "``" if overload_id else "" }}
- :file:`{{ python_apigen_get_docname(example_python_apigen_modules, full_name, overload_id, False) }}`
- :file:`{{ python_apigen_get_docname(example_python_apigen_modules, full_name, overload_id, True) }}`
- :file:`{{ case_sensitive }}`
- :file:`{{ case_insensitive }}`
{%- endfor %}

.. note::
Expand Down
8 changes: 4 additions & 4 deletions docs/apidoc/python/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ Python domain customization
Specifies whether to add the following mappings to
:confval:`python_type_aliases`:

.. jinja:: sys
.. jinja:: typing_names

{%- for x in sys.modules["sphinx_immaterial.apidoc.python.type_annotation_transforms"].TYPING_NAMES %}
{%- for x in TYPING_NAMES %}
- :python:`{{ x }}` -> :python:`typing.{{ x }}`
{%- endfor %}

Expand All @@ -63,9 +63,9 @@ Python domain customization
Specifies whether to add the following :pep:`585` mappings to
:confval:`python_type_aliases`:

.. jinja:: sys
.. jinja:: pep685_aliases

{%- for k, v in sys.modules["sphinx_immaterial.apidoc.python.type_annotation_transforms"].PEP585_ALIASES.items() %}
{%- for k, v in aliases.items() %}
- :python:`{{ k }}` -> :python:`{{ v }}`
{% endfor %}

Expand Down
33 changes: 31 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
from sphinx_immaterial.apidoc import (
object_description_options as _object_description_options,
)
from sphinx_immaterial.apidoc.python import (
type_annotation_transforms,
apigen as python_apigen,
)

logger = sphinx.util.logging.getLogger(__name__)

Expand Down Expand Up @@ -349,9 +353,34 @@ def get_colors(color_t: str):
unique_colors.append(m.group(1))
return unique_colors


# jinja contexts
example_python_apigen_modules = {
"my_module": "my_api/",
"my_other_module": "other_api/my_other_module.",
}
example_python_apigen_objects = [
("my_module.foo", ""),
("my_module.Foo", ""),
("my_module.Foo.method", ""),
("my_module.Foo.__init__", "json"),
("my_module.Foo.__init__", "values"),
("my_module.Bar", ""),
("my_other_module.Baz", ""),
]
jinja_contexts = {
"sys": {"sys": sys},
"python_apigen_path_examples": {
"example_python_apigen_objects": [
(
full_name,
overload_id,
python_apigen._get_docname(example_python_apigen_modules, full_name, overload_id, False),
python_apigen._get_docname(example_python_apigen_modules, full_name, overload_id, True),
)
for full_name, overload_id in example_python_apigen_objects
],
},
"typing_names": {"TYPING_NAMES": type_annotation_transforms.TYPING_NAMES},
"pep685_aliases": {"aliases": type_annotation_transforms.PEP585_ALIASES},
"colors": {
"supported_primary": get_colors("primary"),
"supported_accent": get_colors("accent"),
Expand Down
4 changes: 3 additions & 1 deletion requirements/cpp.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
libclang
# https://github.com/sighingnow/libclang/issues/71
libclang < 17 ; sys_platform == 'darwin'
libclang ; sys_platform != 'darwin'
2 changes: 1 addition & 1 deletion requirements/dev-mypy.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mypy==1.8.0
mypy==1.9.0
types-PyYAML
docutils-stubs
types-beautifulsoup4
Expand Down
1 change: 0 additions & 1 deletion sphinx_immaterial/apidoc/apigen_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ def case_insensitive_filesystem(self) -> bool:
def clear_existing_generated_files(self):
srcdir = self.app.srcdir
for output_prefix in self.output_prefixes:
glob_pattern = os.path.join(srcdir, output_prefix)
for p in glob.glob(
os.path.join(srcdir, output_prefix + "*.rst"), recursive=True
):
Expand Down
30 changes: 17 additions & 13 deletions sphinx_immaterial/apidoc/cpp/api_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,10 @@ def _substitute_name(
name_substitute_with_args += str(template_args)

template_prefix = ""
if top_ast.templatePrefix is not None:
if (
top_ast.templatePrefix is not None
and top_ast.templatePrefix.templates is not None
):
template_prefix = str(top_ast.templatePrefix.templates[-1])

ast.name = _parse_name(name_substitute_with_args, template_prefix=template_prefix)
Expand Down Expand Up @@ -1348,20 +1351,21 @@ def _transform_unexposed_decl(config: Config, decl: Cursor) -> Optional[VarEntit
assert initializer is not None
if _is_internal_initializer(config, initializer):
initializer = None

template_params = []
templates = cast(
sphinx.domains.cpp.ASTTemplateDeclarationPrefix, ast.templatePrefix
).templates
assert templates is not None
for templ_param in templates[-1].params:
template_params.append(
_sphinx_ast_template_parameter_to_json(
config, cast(sphinx.domains.cpp.ASTTemplateParam, templ_param)
)
)
obj: VarEntity = {
"kind": "var",
"name": name,
"template_parameters": [
_sphinx_ast_template_parameter_to_json(
config, cast(sphinx.domains.cpp.ASTTemplateParam, t)
)
for t in cast(
sphinx.domains.cpp.ASTTemplateDeclarationPrefix, ast.templatePrefix
)
.templates[-1]
.params
],
"template_parameters": template_params,
"declaration": decl_string,
"name_substitute": name_substitute,
"initializer": initializer,
Expand Down Expand Up @@ -1912,7 +1916,7 @@ def _normalize_requires_terms(terms: List[str]) -> List[str]:
new_terms = []

def process(
expr: Union[sphinx.domains.cpp.ASTType, sphinx.domains.cpp.ASTExpression]
expr: Union[sphinx.domains.cpp.ASTType, sphinx.domains.cpp.ASTExpression],
):
while True:
if isinstance(expr, sphinx.domains.cpp.ASTParenExpr):
Expand Down
16 changes: 8 additions & 8 deletions sphinx_immaterial/apidoc/cpp/apigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def _get_cpp_api_data(
env: sphinx.environment.BuildEnvironment, warn: bool = False
) -> CppApiData:
KEY = "_sphinx_immaterial_cpp_apigen_data"
data = getattr(env, KEY, None)
data = getattr(env.app, KEY, None)
if data is not None:
return data

Expand Down Expand Up @@ -179,7 +179,7 @@ def _get_cpp_api_data(
location=api_parser.json_location_to_string(diag["location"]),
)

setattr(env, KEY, data)
setattr(env.app, KEY, data)
return data


Expand Down Expand Up @@ -483,7 +483,7 @@ def _add_entity_description(
summary: bool,
state: docutils.parsers.rst.states.RSTState,
) -> None:
kind = entity["kind"]
# kind = entity["kind"]
out = docutils.statemachine.StringList()
location = entity["location"]
parent_id = entity.get("parent")
Expand All @@ -493,12 +493,12 @@ def _add_entity_description(
include_scope = True

if parent_id:
parent = api_data.entities[parent_id]
# parent = api_data.entities[parent_id]
scope_template_prefix = _format_template_prefix(
api_data, api_data.entities[parent_id], summary=False
)
else:
parent = None
# parent = None
scope_template_prefix = ""

scope = api_data.get_entity_scope(entity).rstrip(":")
Expand Down Expand Up @@ -637,7 +637,7 @@ def _add_enumerators(
obj_content: sphinx.addnodes.desc_content,
state: docutils.parsers.rst.states.RSTState,
) -> None:
parent_object_name = api_data.get_entity_object_name(entity)
# parent_object_name = api_data.get_entity_object_name(entity)
for child in entity["enumerators"]:
name = child["name"]
location = child["location"]
Expand Down Expand Up @@ -766,7 +766,7 @@ def run(self) -> List[docutils.nodes.Node]:
section = docutils.nodes.section()
section["ids"].append("")

# Sphinx treates the first child of a `section` node as the title,
# Sphinx treats the first child of a `section` node as the title,
# regardless of its type. We use a comment node to avoid adding a title
# that would be redundant with the object description.
comment_placeholder = docutils.nodes.comment("", "")
Expand Down Expand Up @@ -953,7 +953,7 @@ def setup(app: sphinx.application.Sphinx):
app.add_config_value(
"cpp_apigen_case_insensitive_filesystem",
default=None,
types=(bool, type(None)),
types=(bool, type(None)), # type: ignore[arg-type]
rebuild="env",
)
app.add_config_value(
Expand Down
2 changes: 1 addition & 1 deletion sphinx_immaterial/apidoc/cpp/cppreference.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def setup(app: sphinx.application.Sphinx):
app.add_config_value(
name="cppreference_xml_files",
default=None,
types=(typing.Optional[typing.List[typing.Tuple[str, str]]],),
types=(typing.Optional[typing.List[typing.Tuple[str, str]]],), # type: ignore[arg-type]
rebuild="env",
)
return {"parallel_read_safe": True, "parallel_write_safe": True}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _find_named_symbols(
results = orig_find_named_symbols(
self,
identOrOp,
None,
None, # type: ignore[arg-type]
None, # type: ignore[arg-type]
templateShorthand,
matchSelf,
Expand Down
1 change: 1 addition & 0 deletions sphinx_immaterial/apidoc/cpp/macro_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def get_id(
self: ASTMacroParameter, version: int, objectType: str, symbol: CSymbol
) -> str:
# the anchor will be our parent
assert symbol.parent is not None
declaration = symbol.parent.declaration
assert declaration is not None
return declaration.get_id(version, prefixed=False)
Expand Down
12 changes: 8 additions & 4 deletions sphinx_immaterial/apidoc/cpp/symbol_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def _monkey_patch_override_ast_id(
ast_declaration_class: Union[
Type[sphinx.domains.c.ASTDeclaration], Type[sphinx.domains.cpp.ASTDeclaration]
]
],
):
"""Allows the Symbol id to be overridden."""
orig_get_id = ast_declaration_class.get_id
Expand All @@ -34,9 +34,11 @@ def get_id(


def get_symbol_anchor(
symbol: Union[sphinx.domains.c.Symbol, sphinx.domains.cpp.Symbol]
symbol: Union[sphinx.domains.c.Symbol, sphinx.domains.cpp.Symbol],
) -> str:
anchor = getattr(symbol.declaration, ANCHOR_ATTR, None)
anchor = None
if symbol.declaration is not None:
anchor = getattr(symbol.declaration, ANCHOR_ATTR, None)
if anchor is None:
assert symbol.declaration is not None
anchor = symbol.declaration.get_newest_id()
Expand Down Expand Up @@ -144,6 +146,8 @@ def add_target_and_index(
node_id = self.options.get("node-id")
if node_id is not None:
symbol = ast.symbol
assert symbol is not None
assert symbol.declaration is not None
setattr(symbol.declaration, ANCHOR_ATTR, node_id)
symbol.docname = self.env.docname
if ast is self.names[0] and node_id:
Expand All @@ -157,7 +161,7 @@ def add_target_and_index(
orig_run = object_class.run

def run(
self: Union[sphinx.domains.c.CObject, sphinx.domains.cpp.CPPObject]
self: Union[sphinx.domains.c.CObject, sphinx.domains.cpp.CPPObject],
) -> List[docutils.nodes.Node]:
result = orig_run(self) # type: ignore[arg-type]

Expand Down
6 changes: 2 additions & 4 deletions sphinx_immaterial/apidoc/json/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ class JsonSchemaDirective(sphinx.directives.ObjectDescription):

objtype = "schema"

option_spec = {
option_spec = { # type: ignore[misc]
"fully_qualified_name": str,
"title": str,
"toc_title": str,
Expand Down Expand Up @@ -1147,9 +1147,7 @@ def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
else OBJECT_PRIORITY_UNIMPORTANT,
)

def merge_domaindata(
self, docnames: List[str], otherdata: Dict
) -> None: # pylint: disable=g-bare-generic
def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None: # pylint: disable=g-bare-generic
self.schemas.update(otherdata["schemas"])

def _find_schema(
Expand Down
10 changes: 9 additions & 1 deletion sphinx_immaterial/apidoc/python/annotation_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import docutils.nodes
import sphinx.domains.python
import sphinx.environment
import sphinx
import sphinx.addnodes


def ensure_wrapped_in_desc_type(
Expand All @@ -18,13 +20,19 @@ def _monkey_patch_python_parse_annotation():
This allows them to be distinguished from parameter names in CSS rules.
"""
orig_parse_annotation = sphinx.domains.python._parse_annotation
if sphinx.version_info >= (7, 3):
orig_parse_annotation = sphinx.domains.python._annotations._parse_annotation # type: ignore[attr-defined]
else:
orig_parse_annotation = sphinx.domains.python._parse_annotation

def parse_annotation(
annotation: str, env: Optional[sphinx.environment.BuildEnvironment] = None
) -> List[docutils.nodes.Node]:
return ensure_wrapped_in_desc_type(orig_parse_annotation(annotation, env)) # type: ignore[arg-type]

if sphinx.version_info >= (7, 3):
sphinx.domains.python._annotations._parse_annotation = parse_annotation # type: ignore[attr-defined]
sphinx.domains.python._object._parse_annotation = parse_annotation # type: ignore[attr-defined]
sphinx.domains.python._parse_annotation = parse_annotation


Expand Down
Loading

0 comments on commit 14f75c0

Please sign in to comment.