diff --git a/doc/python_api/conf.py b/doc/python_api/conf.py
new file mode 100644
index 00000000000..f087d00cbf6
--- /dev/null
+++ b/doc/python_api/conf.py
@@ -0,0 +1,116 @@
+# SPDX-FileCopyrightText: 2024 Blender Authors
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from string import Template
+import time
+
+
+# These are substituted when this file is copied to the build directory.
+BLENDER_VERSION_STRING = "${BLENDER_VERSION_STRING}"
+BLENDER_VERSION_DOTS = "${BLENDER_VERSION_DOTS}"
+BLENDER_REVISION = "${BLENDER_REVISION}"
+BLENDER_REVISION_TIMESTAMP = "${BLENDER_REVISION_TIMESTAMP}"
+
+if BLENDER_REVISION != "Unknown":
+ # SHA1 Git hash
+ BLENDER_VERSION_HASH = BLENDER_REVISION
+ BLENDER_VERSION_HASH_HTML_LINK = "%s" % (
+ BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
+ BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
+else:
+ # Fallback: Should not be used
+ BLENDER_VERSION_HASH = "Hash Unknown"
+ BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
+ BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
+
+extensions = ['sphinx.ext.intersphinx']
+intersphinx_mapping = {'blender_manual': ("https://docs.blender.org/manual/en/dev/", None)}
+project = "Blender %s Python API" % BLENDER_VERSION_STRING
+root_doc = "index"
+copyright = "Blender Authors"
+version = BLENDER_VERSION_DOTS
+release = BLENDER_VERSION_DOTS
+
+# Set this as the default is a super-set of Python3.
+highlight_language = 'python3'
+# No need to detect encoding.
+highlight_options = {'default': {'encoding': 'utf-8'}}
+
+# Quiet file not in table-of-contents warnings.
+exclude_patterns = [
+ "include__bmesh.rst",
+]
+
+html_title = "Blender Python API"
+
+# The fallback to a built-in theme when furo is not found.
+html_theme = 'default'
+
+try:
+ import furo
+ html_theme = "furo"
+ del furo
+except ModuleNotFoundError:
+ pass
+
+if html_theme == "furo":
+ html_theme_options = {
+ "light_css_variables": {
+ "color-brand-primary": "#265787",
+ "color-brand-content": "#265787",
+ },
+ }
+
+ html_sidebars = {
+ "**": [
+ "sidebar/brand.html",
+ "sidebar/search.html",
+ "sidebar/scroll-start.html",
+ "sidebar/navigation.html",
+ "sidebar/scroll-end.html",
+ "sidebar/variant-selector.html",
+ ]
+ }
+
+# not helpful since the source is generated, adds to upload size.
+html_copy_source = False
+html_show_sphinx = False
+html_baseurl = "https://docs.blender.org/api/current/"
+html_use_opensearch = "https://docs.blender.org/api/current"
+html_show_search_summary = True
+html_split_index = True
+html_static_path = ["static"]
+templates_path = ["templates"]
+html_context = {"commit": "%s - %s" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE)}
+html_extra_path = ["static"]
+html_favicon = "static/favicon.ico"
+html_logo = "static/blender_logo.svg"
+# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
+html_last_updated_fmt = None
+if html_theme == 'furo':
+ html_css_files = ["css/theme_overrides.css", "css/version_switch.css"]
+ html_js_files = ["js/version_switch.js"]
+
+# needed for latex, pdf gen
+latex_elements = {
+ 'papersize': 'a4paper',
+}
+
+latex_documents = [("contents", "contents.tex", "Blender Index", "Blender Foundation", "manual"), ]
+
+# Workaround for useless links leading to compile errors
+# See https://github.com/sphinx-doc/sphinx/issues/3866
+from sphinx.domains.python import PythonDomain
+
+
+class PatchedPythonDomain(PythonDomain):
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ if 'refspecific' in node:
+ del node['refspecific']
+ return super(PatchedPythonDomain, self).resolve_xref(
+ env, fromdocname, builder, typ, target, node, contnode)
+
+
+def setup(app):
+ app.add_domain(PatchedPythonDomain, override=True)
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index bc0fbc15e41..39b80d5f43d 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -486,19 +486,6 @@ BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
BLENDER_VERSION_STRING = bpy.app.version_string
BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
-if BLENDER_REVISION != "Unknown":
- # SHA1 Git hash
- BLENDER_VERSION_HASH = BLENDER_REVISION
- BLENDER_VERSION_HASH_HTML_LINK = "%s" % (
- BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
- )
- BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
-else:
- # Fallback: Should not be used
- BLENDER_VERSION_HASH = "Hash Unknown"
- BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
- BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
-
# Example: `2_83`.
BLENDER_VERSION_PATH = "%d_%d" % (bpy.app.version[0], bpy.app.version[1])
@@ -1895,110 +1882,6 @@ def pyrna2sphinx(basepath):
write_ops()
-def write_sphinx_conf_py(basepath):
- """
- Write sphinx's ``conf.py``.
- """
- filepath = os.path.join(basepath, "conf.py")
- file = open(filepath, "w", encoding="utf-8")
- fw = file.write
-
- fw("import sys, os\n\n")
- fw("extensions = ['sphinx.ext.intersphinx']\n\n")
- fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
- fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
- fw("root_doc = 'index'\n")
- fw("copyright = 'Blender Authors'\n")
- fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
- fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
-
- # Set this as the default is a super-set of Python3.
- fw("highlight_language = 'python3'\n")
- # No need to detect encoding.
- fw("highlight_options = {'default': {'encoding': 'utf-8'}}\n\n")
-
- # Quiet file not in table-of-contents warnings.
- fw("exclude_patterns = [\n")
- fw(" 'include__bmesh.rst',\n")
- fw("]\n\n")
-
- fw("html_title = 'Blender Python API'\n")
-
- fw("html_theme = 'default'\n")
- # The theme 'sphinx_rtd_theme' is no longer distributed with sphinx by default, only use when available.
- fw(r"""
-try:
- import furo
- html_theme = "furo"
- del furo
-except ModuleNotFoundError:
- pass
-if html_theme == "furo":
- html_theme_options = {
- "light_css_variables": {
- "color-brand-primary": "#265787",
- "color-brand-content": "#265787",
- },
- }
-
- html_sidebars = {
- "**": [
- "sidebar/brand.html",
- "sidebar/search.html",
- "sidebar/scroll-start.html",
- "sidebar/navigation.html",
- "sidebar/scroll-end.html",
- "sidebar/variant-selector.html",
- ]
- }
-""")
-
- # not helpful since the source is generated, adds to upload size.
- fw("html_copy_source = False\n")
- fw("html_show_sphinx = False\n")
- fw("html_baseurl = 'https://docs.blender.org/api/current/'\n")
- fw("html_use_opensearch = 'https://docs.blender.org/api/current'\n")
- fw("html_show_search_summary = True\n")
- fw("html_split_index = True\n")
- fw("html_static_path = ['static']\n")
- fw("templates_path = ['templates']\n")
- fw("html_context = {'commit': '%s - %s'}\n" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE))
- fw("html_extra_path = ['static']\n")
- fw("html_favicon = 'static/favicon.ico'\n")
- fw("html_logo = 'static/blender_logo.svg'\n")
- # Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
- fw("html_last_updated_fmt = None\n\n")
- fw("if html_theme == 'furo':\n")
- fw(" html_css_files = ['css/theme_overrides.css', 'css/version_switch.css']\n")
- fw(" html_js_files = ['js/version_switch.js']\n")
-
- # needed for latex, pdf gen
- fw("latex_elements = {\n")
- fw(" 'papersize': 'a4paper',\n")
- fw("}\n\n")
-
- fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
-
- # Workaround for useless links leading to compile errors
- # See https://github.com/sphinx-doc/sphinx/issues/3866
- fw(r"""
-from sphinx.domains.python import PythonDomain
-
-class PatchedPythonDomain(PythonDomain):
- def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
- if 'refspecific' in node:
- del node['refspecific']
- return super(PatchedPythonDomain, self).resolve_xref(
- env, fromdocname, builder, typ, target, node, contnode)
-
-def setup(app):
- app.add_domain(PatchedPythonDomain, override=True)
-""")
- # end workaround
-
- file.close()
-
-
def write_rst_index(basepath):
"""
Write the RST file of the main page, needed for sphinx: ``index.html``.
@@ -2411,7 +2294,7 @@ def copy_handwritten_extra(basepath):
shutil.copy2(f_src, f_dst)
-def copy_theme_assets(basepath):
+def copy_sphinx_files(basepath):
shutil.copytree(
os.path.join(SCRIPT_DIR, "static"),
os.path.join(basepath, "static"),
@@ -2423,17 +2306,31 @@ def copy_theme_assets(basepath):
copy_function=shutil.copy,
)
+ shutil.copy2(os.path.join(SCRIPT_DIR, "conf.py"), basepath, )
+
+
+def format_config(basepath):
+ """
+ Updates conf.py with context infromation from Blender.
+ """
+ from string import Template
+
+ substitutions = {
+ 'BLENDER_VERSION_STRING': BLENDER_VERSION_STRING,
+ 'BLENDER_VERSION_DOTS': BLENDER_VERSION_DOTS,
+ 'BLENDER_REVISION_TIMESTAMP': BLENDER_REVISION_TIMESTAMP,
+ 'BLENDER_REVISION': BLENDER_REVISION,
+ }
+
+ # Read the template string from the template file
+ with open(os.path.join(basepath, "conf.py"), 'r') as file:
+ template_file = file.read()
+
+ with open(os.path.join(basepath, "conf.py"), 'w') as file:
+ file.write(Template(template_file).substitute(substitutions))
+
def rna2sphinx(basepath):
-
- try:
- os.mkdir(basepath)
- except:
- pass
-
- # sphinx setup
- write_sphinx_conf_py(basepath)
-
# main page
write_rst_index(basepath)
@@ -2460,9 +2357,6 @@ def rna2sphinx(basepath):
# copy source files referenced
copy_handwritten_extra(basepath)
- # copy extra files needed for theme
- copy_theme_assets(basepath)
-
def align_sphinx_in_to_sphinx_in_tmp(dir_src, dir_dst):
"""
@@ -2583,10 +2477,22 @@ def main():
copy_function=shutil.copy,
)
- # Dump the API in RST files.
+ # start from a clean directory everytime
if os.path.exists(SPHINX_IN_TMP):
shutil.rmtree(SPHINX_IN_TMP, True)
+ try:
+ os.mkdir(SPHINX_IN_TMP)
+ except:
+ pass
+
+ # copy extra files needed for theme
+ copy_sphinx_files(SPHINX_IN_TMP)
+
+ # write infromation needed for 'conf.py'
+ format_config(SPHINX_IN_TMP)
+
+ # Dump the API in RST files.
rna2sphinx(SPHINX_IN_TMP)
if ARGS.changelog: