Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
46f925a79This file is pinned to the selected release. Download the original to open it in your design tool.
# Copyright 2026 DeepMind Technologies Limited
#
# Licensed 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.
# ==============================================================================
"""Generates functions API for APIreference.rst."""
import os
import re
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
import resource_loader # pyrefly: ignore[missing-import]
import generate_api_header # pyrefly: ignore[missing-import]
except ImportError:
raise
# File for section paragraphs and function doc overrides.
_FUNCTIONS_OVERRIDE = 'doc/APIreference/functions_override.rst'
_RST_SECTION_REGEX = re.compile(r'^\.\. (?P<section>_[A-Z].+):')
_RST_FUNCTION_REGEX = re.compile(r'^\.\. _(?P<function>mj.+):')
rst_to_section = {
'_Parseandcompile': ['Parse and compile', ''],
'_Mainsimulation': ['Main simulation', ''],
'_Support': ['Support', ''],
'_Components': ['Components', ''],
'_Subcomponents': ['Sub components', ''],
'_Raycollisions': ['Ray casting', ''],
'_Printing': ['Printing', ''],
'_Virtualfilesystem': ['Virtual file system', ''],
'_Assetcache': ['Asset cache', ''],
'_Resources': ['Resources', ''],
'_Initialization': ['Initialization', ''],
'_Errorandmemory': ['Error and memory', ''],
'_Miscellaneous': ['Miscellaneous', ''],
'_Interaction': ['Interaction', ''],
'_Visualization-api': ['Visualization', ''],
'_OpenGLrendering': ['OpenGL rendering', ''],
'_FilamentRenderingApi': ['Filament rendering', ''],
'_UIframework': ['UI framework', ''],
'_Derivatives-api': ['Derivatives', ''],
'_Signeddistancefunction': ['Signed Distance Functions', ''],
'_Plugins-api': ['Plugins', ''],
'_Thread': ['Threads', ''],
'_Standardmath': ['Standard math', ''],
'_Vectormath': ['Vector math', ''],
'_Sparsemath': ['Sparse math', ''],
'_Quaternions': ['Quaternions', ''],
'_Poses': ['Poses', ''],
'_Decompositions': ['Decompositions / Solvers', ''],
'_Attachment': ['Attachment', ''],
'_AddTreeElements': ['Tree elements', ''],
'_AddNonTreeElements': ['Non-tree elements', ''],
'_Setactuatorparameters': ['Set actuator parameters', ''],
'_AddAssets': ['Assets', ''],
'_FindAndGetUtilities': ['Find and get utilities', ''],
'_AttributeSetters': ['Attribute setters', ''],
'_AttributeGetters': ['Attribute getters', ''],
'_SpecUtilities': ['Spec utilities', ''],
'_ElementInitialization': ['Element initialization', ''],
'_ElementCasting': ['Element casting', ''],
}
def generate() -> str:
"""Generates functions.rst."""
rst_str = ''
api = generate_api_header.read_headers()
filepath = resource_loader.resolve_path(_FUNCTIONS_OVERRIDE)
with open(filepath, 'r', encoding='utf-8') as file:
current_section = None
current_function = None
for line in file:
# Try matching a section.
match = _RST_SECTION_REGEX.search(line)
if match is not None:
current_section = match.group('section')
if current_section in rst_to_section:
current_function = None
else:
current_section = None
continue
# Try matching a function
match = _RST_FUNCTION_REGEX.search(line)
if match is not None:
current_function = match.group('function')
if current_function in api:
api[current_function].doc = ''
current_section = None
else:
current_function = None
continue
# Update section doc.
if current_section is not None:
rst_to_section[current_section][1] += line
# Override doc.
if current_function is not None:
api[current_function].doc += line
# Check that all function sections from the headers are mapped.
mapped_sections = {v[0] for v in rst_to_section.values()}
for token, defn in api.items():
if defn.c_type == 'FUNCTION' and defn.section not in mapped_sections:
raise ValueError(
f'Function {token!r} is in unmapped section {defn.section!r}. '
f'Add an entry to rst_to_section in generate_functions.py.'
)
# Write out RST file.
rst_str += ("""
..
AUTOGENERATED: DO NOT EDIT MANUALLY
""".lstrip())
for section in rst_to_section:
section_title = rst_to_section[section][0]
rst_str += (
f"""
.. {section}:
{section_title}
{'^'*len(section_title)}
{rst_to_section[section][1]}""".lstrip())
for token in api:
if api[token].c_type != 'FUNCTION' or api[token].section != section_title:
continue
doc = api[token].doc.strip()
doc = doc.replace(' ', '`` ``')
rst_str += (f"""
.. _{token}:
`{token} <#{token}>`__
{'~'*(2*len(token)+8)}
.. mujoco-include:: {token}
{doc}
""".lstrip())
return rst_str.rstrip('\n') + '\n'
def main() -> None:
if len(sys.argv) > 1:
sys.exit('Too many command-line arguments.')
sys.stdout.buffer.write(generate().encode('utf-8'))
if __name__ == '__main__':
main()