diff -r 7ed237478fcc Lib/test/test_capi.py --- a/Lib/test/test_capi.py Tue Aug 05 11:54:34 2014 -0500 +++ b/Lib/test/test_capi.py Tue Aug 05 15:10:05 2014 -0500 @@ -118,7 +118,7 @@ self.assertEqual(_testcapi.no_docstring.__doc__, None) self.assertEqual(_testcapi.no_docstring.__text_signature__, None) - self.assertEqual(_testcapi.docstring_empty.__doc__, "") + self.assertEqual(_testcapi.docstring_empty.__doc__, None) self.assertEqual(_testcapi.docstring_empty.__text_signature__, None) self.assertEqual(_testcapi.docstring_no_signature.__doc__, @@ -145,6 +145,10 @@ "This docstring has a valid signature.") self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)") + self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__doc__, None) + self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__text_signature__, + "($module, /, sig)") + self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__, "\nThis docstring has a valid signature and some extra newlines.") self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__, diff -r 7ed237478fcc Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Tue Aug 05 11:54:34 2014 -0500 +++ b/Lib/test/test_inspect.py Tue Aug 05 15:10:05 2014 -0500 @@ -1826,6 +1826,9 @@ test_unbound_method(dict.__delitem__) test_unbound_method(property.__delete__) + # Regression test for issue #20586 + test_callable(_testcapi.docstring_with_signature_but_no_doc) + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, diff -r 7ed237478fcc Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Tue Aug 05 11:54:34 2014 -0500 +++ b/Modules/_testcapimodule.c Tue Aug 05 15:10:05 2014 -0500 @@ -2954,6 +2954,12 @@ "This docstring has a valid signature." ); +PyDoc_STRVAR(docstring_with_signature_but_no_doc, +"docstring_with_signature_but_no_doc($module, /, sig)\n" +"--\n" +"\n" +); + PyDoc_STRVAR(docstring_with_signature_and_extra_newlines, "docstring_with_signature_and_extra_newlines($module, /, parameter)\n" "--\n" @@ -3211,6 +3217,9 @@ {"docstring_with_signature", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_signature}, + {"docstring_with_signature_but_no_doc", + (PyCFunction)test_with_docstring, METH_NOARGS, + docstring_with_signature_but_no_doc}, {"docstring_with_signature_and_extra_newlines", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_signature_and_extra_newlines}, diff -r 7ed237478fcc Objects/typeobject.c --- a/Objects/typeobject.c Tue Aug 05 11:54:34 2014 -0500 +++ b/Objects/typeobject.c Tue Aug 05 15:10:05 2014 -0500 @@ -128,7 +128,7 @@ { const char *doc = _PyType_DocWithoutSignature(name, internal_doc); - if (!doc) { + if (!doc || *doc == '\0') { Py_INCREF(Py_None); return Py_None; } diff -r 7ed237478fcc Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py Tue Aug 05 11:54:34 2014 -0500 +++ b/Tools/clinic/clinic.py Tue Aug 05 15:10:05 2014 -0500 @@ -66,6 +66,8 @@ unknown = Unknown() +sig_end_marker = '--' + def _text_accumulator(): text = [] @@ -555,8 +557,13 @@ add(quoted_for_c_string(line)) add('\\n"\n') - text.pop() - add('"') + if text[-2] == sig_end_marker: + # If we only have a signature, add the blank line that the + # __text_signature__ getter expects to be there. + add('"\\n"') + else: + text.pop() + add('"') return ''.join(text) def output_templates(self, f): @@ -3965,7 +3972,7 @@ # add(f.return_converter.py_default) if not f.docstring_only: - add("\n--\n") + add("\n" + sig_end_marker + "\n") docstring_first_line = output()