Doxygen comments take precedence over the autodoc feature.

If a "docstring" feature is present it will still override a Doxygen comment.
If the "autodoc" feature is also present, the combined "autodoc" and "docstring"
will override the Doxygen comment. If no "docstring" is present then the
"autodoc" feature will not be generated when there is a Doxygen comment.

This way the "autodoc" feature can be specified and used to provide documentation
for 'missing' Doxygen comments.

Closes #1635
This commit is contained in:
William S Fulton 2022-04-06 08:08:14 +01:00
commit b35ebc81a9
7 changed files with 175 additions and 22 deletions

View file

@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2022-04-06: wsfulton
[Python] #1635 The "autodoc" feature no longer overrides Doxygen comments
in the generated docstring.
If a "docstring" feature is present it will still override a Doxygen comment.
If the "autodoc" feature is also present, the combined "autodoc" and "docstring"
will override the Doxygen comment. If no "docstring" is present then the
"autodoc" feature will not be generated when there is a Doxygen comment.
This way the "autodoc" feature can be specified and used to provide documentation
for 'missing' Doxygen comments.
*** POTENTIAL INCOMPATIBILITY ***
2022-04-01: olly
Remove undocumented and non-functional -browse command line option.

View file

@ -1464,6 +1464,7 @@
<li><a href="Python.html#Python_nn70">%feature("autodoc", "docstring")</a>
</ul>
<li><a href="Python.html#Python_nn71">%feature("docstring")</a>
<li><a href="Python.html#Python_doxygen_docstrings">Doxygen comments</a>
</ul>
<li><a href="Python.html#Python_nn72">Python Packages</a>
<ul>

View file

@ -114,6 +114,7 @@
<li><a href="#Python_nn70">%feature("autodoc", "docstring")</a>
</ul>
<li><a href="#Python_nn71">%feature("docstring")</a>
<li><a href="#Python_doxygen_docstrings">Doxygen comments</a>
</ul>
<li><a href="#Python_nn72">Python Packages</a>
<ul>
@ -152,6 +153,7 @@
<!-- INDEX -->
<p>
This chapter describes SWIG's support of Python. SWIG is compatible
with all recent Python versions (Python 2.7 and Python &gt;= 3.2). If you
@ -5898,6 +5900,28 @@ with more than one line.
</pre>
</div>
<H3><a name="Python_doxygen_docstrings">33.10.4 Doxygen comments</a></H3>
<p>
Please see the separate <a href="Doxygen.html#Doxygen">Doxygen</a> chapter for information
on making use of C++ Doxygen comments and translating them into Python docstring comments.
</p>
<p>
Note that when generating docstrings and Doxygen comments have also been turned on,
the <a href="#Python_nn71">docstring feature</a> will take precedence over a Doxygen comment.
If the <a href="#Python_nn67">autodoc feature</a> is also turned on, then it will be
used in conjunction with the docstring feature.
However, if there is no docstring feature present and there is a Doxygen comment, then the autodoc docstring will not be generated. The Doxygen comment alone will be used.
</p>
<p>
This way, if the autodoc feature is specified globally it will fill in any missing
Doxygen documentation comments.
Doxygen comments can be overridden by using the docstring feature.
</p>
<H2><a name="Python_nn72">33.11 Python Packages</a></H2>

View file

@ -638,6 +638,7 @@ endif
ifdef HAS_DOXYGEN
DOXYGEN_TEST_CASES += \
doxygen_alias \
doxygen_autodoc_docstring \
doxygen_basic_notranslate \
doxygen_basic_translate \
doxygen_basic_translate_style2 \

View file

@ -0,0 +1,66 @@
%module doxygen_autodoc_docstring
%feature("autodoc", 1);
%feature("docstring") ClassWithDocString "Class doc from docstring";
%feature("docstring") functionWithDocString "Function doc from docstring";
%feature("docstring") ClassWithDocStringAndDoxygenComment "Class doc from docstring overriding doxycomment";
%feature("docstring") functionWithDocStringAndDoxygenComment "Function doc from docstring overriding doxycomment";
%inline %{
class ClassWithoutDoxygenComment {};
void functionWithoutDoxygenComment(int number) {}
/**
* Class doxygen comment
*/
class ClassWithDoxygenComment {};
/**
* Function doxygen comment
*/
void functionWithDoxygenComment(int number) {}
class ClassWithDocString {};
void functionWithDocString(int number) {}
/**
* Class doxygen comment
*/
class ClassWithDocStringAndDoxygenComment {};
/**
* Function doxygen comment
*/
void functionWithDocStringAndDoxygenComment(int number) {}
%}
%feature("autodoc", ""); // clear autodoc
%feature("docstring") ClassWithDocStringAndDoxygenCommentNoAutodoc "Class doc from docstring overriding doxycomment (no autodoc)";
%feature("docstring") functionWithDocStringAndDoxygenCommentNoAutodoc "Function doc from docstring overriding doxycomment (no autodoc)";
%inline %{
/**
* Class doxygen comment
*/
class ClassWithDocStringAndDoxygenCommentNoAutodoc {};
/**
* Function doxygen comment
*/
void functionWithDocStringAndDoxygenCommentNoAutodoc(int number) {}
/**
* Class doxygen comment 2
*/
class ClassWithDoxygenComment2 {};
/**
* Function doxygen comment 2
*/
void functionWithDoxygenComment2(int number) {}
%}

View file

@ -0,0 +1,44 @@
from doxygen_autodoc_docstring import *
import inspect
import string
import os
import sys
import comment_verifier
# documentation from autogenerated 'feature:autodoc'
comment_verifier.check(inspect.getdoc(ClassWithoutDoxygenComment),
"Proxy of C++ ClassWithoutDoxygenComment class.")
comment_verifier.check(inspect.getdoc(functionWithoutDoxygenComment),
"functionWithoutDoxygenComment(int number)")
# documentation from doxygen comments
comment_verifier.check(inspect.getdoc(ClassWithDoxygenComment),
"Class doxygen comment")
comment_verifier.check(inspect.getdoc(functionWithDoxygenComment),
"Function doxygen comment")
# documentation from 'feature:docstring'
comment_verifier.check(inspect.getdoc(ClassWithDocString),
"Class doc from docstring")
comment_verifier.check(inspect.getdoc(functionWithDocString),
"functionWithDocString(int number)\n"
"Function doc from docstring")
# documentation from 'feature:docstring' + autodoc (overriding doxycomment)
comment_verifier.check(inspect.getdoc(ClassWithDocStringAndDoxygenComment),
"Class doc from docstring overriding doxycomment")
comment_verifier.check(inspect.getdoc(functionWithDocStringAndDoxygenComment),
"functionWithDocStringAndDoxygenComment(int number)\n"
"Function doc from docstring overriding doxycomment")
# documentation from 'feature:docstring' (overriding doxycomment)
comment_verifier.check(inspect.getdoc(ClassWithDocStringAndDoxygenCommentNoAutodoc),
"Class doc from docstring overriding doxycomment (no autodoc)")
comment_verifier.check(inspect.getdoc(functionWithDocStringAndDoxygenCommentNoAutodoc),
"Function doc from docstring overriding doxycomment (no autodoc)")
# documentation from doxygen comments (2) no autodoc feature present
comment_verifier.check(inspect.getdoc(ClassWithDoxygenComment2),
"Class doxygen comment 2")
comment_verifier.check(inspect.getdoc(functionWithDoxygenComment2),
"Function doxygen comment 2")

View file

@ -1492,16 +1492,18 @@ public:
/* ------------------------------------------------------------
* build_combined_docstring()
*
* Build the full docstring which may be a combination of the
* explicit docstring and autodoc string or, if none of them
* is specified, obtained by translating Doxygen comment to
* Python.
* Build the full docstring:
* Use the docstring if there is one present otherwise
* use the Doxygen comment if there is one present.
* Ignore autodoc if there is a Doxygen comment, otherwise
* create the autodoc string and append to any docstring.
*
* Return new string to be deleted by caller (never NIL but
* may be empty if there is no docstring).
* ------------------------------------------------------------ */
String *build_combined_docstring(Node *n, autodoc_t ad_type, const String *indent = "", bool low_level = false) {
bool add_autodoc = true;
String *docstr = Getattr(n, "feature:docstring");
if (docstr) {
// Simplify the code below by just ignoring empty docstrings.
@ -1519,26 +1521,10 @@ public:
}
}
if (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) {
String *autodoc = make_autodoc(n, ad_type, low_level);
if (autodoc && Len(autodoc) > 0) {
if (docstr) {
Append(autodoc, "\n");
Append(autodoc, docstr);
}
String *tmp = autodoc;
autodoc = docstr;
docstr = tmp;
}
Delete(autodoc);
}
if (!docstr) {
if (doxygen) {
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
docstr = Getattr(n, "python:docstring");
if (!docstr && doxygenTranslator->hasDocumentation(n)) {
if (!docstr) {
docstr = doxygenTranslator->getDocumentation(n, 0);
// Avoid rebuilding it again the next time: notice that we can't do
@ -1554,9 +1540,26 @@ public:
// the cached object!
docstr = Copy(docstr);
}
add_autodoc = false;
}
}
if (add_autodoc && Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) {
String *autodoc = make_autodoc(n, ad_type, low_level);
if (autodoc && Len(autodoc) > 0) {
if (docstr) {
Append(autodoc, "\n");
Append(autodoc, docstr);
}
String *tmp = autodoc;
autodoc = docstr;
docstr = tmp;
}
Delete(autodoc);
}
if (!docstr)
docstr = NewString("");