From 10d1304806529861c16a19d2af5906520f1c0997 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 8 Mar 2017 12:32:42 -0500 Subject: [PATCH] Fix extra docstring newlines under `options.disable_function_signatures()` When using pybind::options to disable function signatures, user-defined docstrings only get appended if they exist, but newlines were getting appended unconditionally, so the docstring could end up with blank lines (depending on which overloads, in particular, provided docstrings). This commit suppresses the empty lines by only adding newlines for overloads when needed. --- include/pybind11/pybind11.h | 10 ++++++++-- tests/test_docstring_options.cpp | 9 +++++++++ tests/test_docstring_options.py | 12 +++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 74c8c0ff6..44c4b61cd 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -326,8 +326,10 @@ protected: signatures += "Overloaded function.\n\n"; } // Then specific overload signatures + bool first_user_def = true; for (auto it = chain_start; it != nullptr; it = it->next) { if (options::show_function_signatures()) { + if (index > 0) signatures += "\n"; if (chain) signatures += std::to_string(++index) + ". "; signatures += rec->name; @@ -335,12 +337,16 @@ protected: signatures += "\n"; } if (it->doc && strlen(it->doc) > 0 && options::show_user_defined_docstrings()) { + // If we're appending another docstring, and aren't printing function signatures, we + // need to append a newline first: + if (!options::show_function_signatures()) { + if (first_user_def) first_user_def = false; + else signatures += "\n"; + } if (options::show_function_signatures()) signatures += "\n"; signatures += it->doc; if (options::show_function_signatures()) signatures += "\n"; } - if (it->next) - signatures += "\n"; } /* Install docstring */ diff --git a/tests/test_docstring_options.cpp b/tests/test_docstring_options.cpp index 74178c272..9a9297cc3 100644 --- a/tests/test_docstring_options.cpp +++ b/tests/test_docstring_options.cpp @@ -24,6 +24,15 @@ test_initializer docstring_generation([](py::module &m) { m.def("test_function1", [](int, int) {}, py::arg("a"), py::arg("b")); m.def("test_function2", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring"); + m.def("test_overloaded1", [](int) {}, py::arg("i"), "Overload docstring"); + m.def("test_overloaded1", [](double) {}, py::arg("d")); + + m.def("test_overloaded2", [](int) {}, py::arg("i"), "overload docstring 1"); + m.def("test_overloaded2", [](double) {}, py::arg("d"), "overload docstring 2"); + + m.def("test_overloaded3", [](int) {}, py::arg("i")); + m.def("test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr"); + options.enable_function_signatures(); m.def("test_function3", [](int, int) {}, py::arg("a"), py::arg("b")); diff --git a/tests/test_docstring_options.py b/tests/test_docstring_options.py index 66ad6b89f..5e40f6868 100644 --- a/tests/test_docstring_options.py +++ b/tests/test_docstring_options.py @@ -3,13 +3,23 @@ def test_docstring_options(): from pybind11_tests import (test_function1, test_function2, test_function3, test_function4, test_function5, test_function6, - test_function7, DocstringTestFoo) + test_function7, DocstringTestFoo, + test_overloaded1, test_overloaded2, test_overloaded3) # options.disable_function_signatures() assert not test_function1.__doc__ assert test_function2.__doc__ == "A custom docstring" + # docstring specified on just the first overload definition: + assert test_overloaded1.__doc__ == "Overload docstring" + + # docstring on both overloads: + assert test_overloaded2.__doc__ == "overload docstring 1\noverload docstring 2" + + # docstring on only second overload: + assert test_overloaded3.__doc__ == "Overload docstr" + # options.enable_function_signatures() assert test_function3.__doc__ .startswith("test_function3(a: int, b: int) -> None")