From 42be9595387088e95993170d7c31860c747c328c Mon Sep 17 00:00:00 2001 From: alisonpetersonhq Date: Wed, 12 Aug 2026 10:19:08 -0400 Subject: [PATCH 1/4] Escape * in generated function signatures for Sphinx Signed-off-by: alisonpetersonhq --- include/pybind11/pybind11.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index eebb130694..0305f83d7b 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -855,6 +855,14 @@ class cpp_function : public function { std::string signatures; int index = 0; + auto append_doc_signature = [&signatures](const char *sig) { + for (const char *p = sig; *p != '\0'; ++p) { + if (*p == '*') { + signatures += '\\'; + } + signatures += *p; + } + }; /* Create a nice pydoc rec including all signatures and docstrings of the functions in the overload chain */ if (chain && options::show_function_signatures() @@ -876,7 +884,7 @@ class cpp_function : public function { signatures += std::to_string(++index) + ". "; } signatures += rec->name; - signatures += it->signature; + append_doc_signature(it->signature); signatures += '\n'; } if (it->doc && it->doc[0] != '\0' && options::show_user_defined_docstrings()) { From 9145404d4ba9c013fedbbc478823682c12351bf1 Mon Sep 17 00:00:00 2001 From: alisonpetersonhq Date: Sun, 16 Aug 2026 00:38:14 -0400 Subject: [PATCH 2/4] docs: escape * for Sphinx via autodoc-process-docstring (#4537) Signed-off-by: alisonpetersonhq --- include/pybind11/pybind11.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 0305f83d7b..eebb130694 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -855,14 +855,6 @@ class cpp_function : public function { std::string signatures; int index = 0; - auto append_doc_signature = [&signatures](const char *sig) { - for (const char *p = sig; *p != '\0'; ++p) { - if (*p == '*') { - signatures += '\\'; - } - signatures += *p; - } - }; /* Create a nice pydoc rec including all signatures and docstrings of the functions in the overload chain */ if (chain && options::show_function_signatures() @@ -884,7 +876,7 @@ class cpp_function : public function { signatures += std::to_string(++index) + ". "; } signatures += rec->name; - append_doc_signature(it->signature); + signatures += it->signature; signatures += '\n'; } if (it->doc && it->doc[0] != '\0' && options::show_user_defined_docstrings()) { From 12862b7e16da1d2e508593c49d5b85712a4f76a4 Mon Sep 17 00:00:00 2001 From: alisonpetersonhq Date: Sun, 16 Aug 2026 00:38:17 -0400 Subject: [PATCH 3/4] docs: escape * for Sphinx via autodoc-process-docstring (#4537) Signed-off-by: alisonpetersonhq --- docs/advanced/misc.rst | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/advanced/misc.rst b/docs/advanced/misc.rst index 1902ba21de..986ee3f5f3 100644 --- a/docs/advanced/misc.rst +++ b/docs/advanced/misc.rst @@ -499,7 +499,7 @@ strings in pybind11-based extension modules to automatically generate beautiful documentation in a variety formats. The python_example repository [#f5]_ contains a simple example repository which uses this approach. -There are two potential gotchas when using this approach: first, make sure that +There are a few potential gotchas when using this approach: first, make sure that the resulting strings do not contain any :kbd:`TAB` characters, which break the docstring parsing routines. You may want to use C++11 raw string literals, which are convenient for multi-line comments. Conveniently, any excess @@ -523,6 +523,27 @@ work, it is important that all lines are indented consistently, i.e.: ---------- )mydelimiter"); +Second, auto-generated signatures intentionally contain a literal ``*`` (for +``*args``, ``py::args``, ``py::kw_only``, and similar). That matches normal +Python / ``help()`` / stubgen conventions, and Sphinx's own +``autodoc_docstring_signature`` expects it. Sphinx reStructuredText, however, +treats unpaired ``*`` as emphasis and may warn with +``Inline emphasis start-string without end-string``. + +Do **not** escape ``*`` inside the generated docstring itself. Instead, escape +it when Sphinx processes the docstring by connecting an +``autodoc-process-docstring`` handler in your project's ``conf.py`` (with +``sphinx.ext.autodoc`` enabled): + +.. code-block:: python + + def process_docstring(app, what, name, obj, options, lines): + for i, line in enumerate(lines): + lines[i] = line.replace("*", r"\*") + + def setup(app): + app.connect("autodoc-process-docstring", process_docstring) + By default, pybind11 automatically generates and prepends a signature to the docstring of a function registered with ``module_::def()`` and ``class_::def()``. Sometimes this behavior is not desirable, because you want to provide your own signature or remove From cb02521e70435d307f112a2576c2af63e4e8ccc2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 16 Aug 2026 04:38:48 +0000 Subject: [PATCH 4/4] style: pre-commit fixes --- docs/advanced/misc.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/advanced/misc.rst b/docs/advanced/misc.rst index 986ee3f5f3..e347664f11 100644 --- a/docs/advanced/misc.rst +++ b/docs/advanced/misc.rst @@ -541,6 +541,7 @@ it when Sphinx processes the docstring by connecting an for i, line in enumerate(lines): lines[i] = line.replace("*", r"\*") + def setup(app): app.connect("autodoc-process-docstring", process_docstring)