This is fixed if we use .. autoproperty::; Sphinx will correctly set the return type.
So, why not use .. autoproperty::?
This is specifically an issue when we use .. autosummary:: to document a class. Properties work correctly when you use .. autoclass::, such as for inline class documentation in a module page.
The issue is that our template tells .. autoclass:: to not document any members so that we can instead manually document them by calling .. autoattribute and .. automethod:
In our Autosummary template, we manually list out every member so that we can add the lines .. rubric:: Attributes and .. rubric:: Methods, which get converted into h2 headings. These headings give important hierarchy to class pages that we do not want to lose:
So, we cannot simply use .. autoclass:: to list all the members for us because we would lose the Attributes and Methods headings.
Ideally, we could do something like this:
{% block attributes_summary %}
{% if attributes %}
.. rubric:: Attributes
{% for item in attributes %}
{% if item is property %}
.. autoproperty:: {{ item}}
{% else %}
.. autoattribute:: {{ item }}
{% endif %}
{%- endfor %}
{% endif %}
{% endblock -%}
However, that type of if statement will not work because attributes is simply a list of strings, with both normal attributes and properties, such as ['foo', 'bar', 'my_prop']. There is no way in the Jinja template to determine whether the string corresponds to an @property, and Sphinx fails if you try using any Python builtins like dir() or hasattr(). What we really would need is for Autosummary to inject a properties variable, but it's not available: https://www.sphinx-doc.org/en/master/usage/extensions/autosummary.html#customizing-templates.
Rejected workaround: manually list every class
This wouldn't be a problem if we had docs authors give up on autosummary and manually call .. autoclass::, .. autoproperty::, .. autoattribute::, and .. automethod::, along with adding .. rubric:: Attributes and .. rubric:: Methods where appropriate. However, that is not realistic to expect.
Proposed solution: our script
We will switch the APIs to use .. autoclass:: in their Autosummary template to document their members, rather than manually iterating through them. Their template will look like this:
That will fix the property issue, but now we'll be missing the Attributes and Methods h2 headings! So, we will have our qiskit/documentation script add back those headings to our MDX files in the appropriate location.
TBD:
Decide whether we should add the Attributes and Methods headings for inline classes on module pages.
Downside: increase the heading hierarchy for those classes.
Upside: more clear what is a method vs. attribute/property
Problem: missing type hints
With Sphinx's autosummary extension, we're using
.. autoattribute::
for functions marked with@property
, rather than.. autoproperty::
:https://github.com/Qiskit/qiskit-addon-obp/blob/2412cb29c9d314a5ad568acdd5be558f7053c0f2/docs/_templates/autosummary/class.rst?plain=1#L20
This messes up the return type for properties. For example, the return type is defined on this
@property
:https://github.com/Qiskit/qiskit-addon-mpf/blob/191dc8162510719ca3b50e5a25e9a1453419629a/qiskit_addon_mpf/backends/tenpy_tebd/evolver.py#L59-L62
However, the Sphinx output—and thus our docs—are missing that return type:
https://github.com/Qiskit/documentation/blob/298d8a3fcf84c741cd04ab372db4f4ee9dd2bfc7/docs/api/qiskit-addon-mpf/backends-tenpy-tebd-tebd-evolver.mdx?plain=1#L40-L44
This is fixed if we use
.. autoproperty::
; Sphinx will correctly set the return type.So, why not use
.. autoproperty::
?This is specifically an issue when we use
.. autosummary::
to document a class. Properties work correctly when you use.. autoclass::
, such as for inline class documentation in a module page.The issue is that our template tells
.. autoclass::
to not document any members so that we can instead manually document them by calling.. autoattribute
and.. automethod
:In our Autosummary template, we manually list out every member so that we can add the lines
.. rubric:: Attributes
and.. rubric:: Methods
, which get converted into h2 headings. These headings give important hierarchy to class pages that we do not want to lose:So, we cannot simply use
.. autoclass::
to list all the members for us because we would lose theAttributes
andMethods
headings.Ideally, we could do something like this:
However, that type of if statement will not work because
attributes
is simply a list of strings, with both normal attributes and properties, such as['foo', 'bar', 'my_prop']
. There is no way in the Jinja template to determine whether the string corresponds to an@property
, and Sphinx fails if you try using any Python builtins likedir()
orhasattr()
. What we really would need is for Autosummary to inject aproperties
variable, but it's not available: https://www.sphinx-doc.org/en/master/usage/extensions/autosummary.html#customizing-templates.Rejected workaround: manually list every class
This wouldn't be a problem if we had docs authors give up on autosummary and manually call
.. autoclass::
,.. autoproperty::
,.. autoattribute::
, and.. automethod::
, along with adding.. rubric:: Attributes
and.. rubric:: Methods
where appropriate. However, that is not realistic to expect.Proposed solution: our script
We will switch the APIs to use
.. autoclass::
in their Autosummary template to document their members, rather than manually iterating through them. Their template will look like this:That will fix the property issue, but now we'll be missing the
Attributes
andMethods
h2 headings! So, we will have our qiskit/documentation script add back those headings to our MDX files in the appropriate location.TBD:
Attributes
andMethods
headings for inline classes on module pages.