Numpydoc docstrings#
When writing docstrings for PyAnsys libraries, follow the syntax and best practices described in Style guide in the numpydoc Manual.
For consistency within PyAnsys libraries, always use """
to introduce and conclude a
docstring, keeping the line length shorter than 70 characters. Ensure that there are
no blank spaces at the end of a line because they cause errors in build checks that you
must then resolve.
A blank line signifies the start of a new paragraph. To create a bulleted or numbered list, ensure that there is a blank line before the first item and after the last item. Because you use the same markup in docstrings as you do in RST files, see Quick reStructuredText for a markup summary.
Surround any text that you want to set apart as literal text (code entities) in double backticks to render it in a monospaced font within a gray box. Use double backticks to surround the names of files, folders, classes, methods, and variables.
For example:
"""Initialize the ``Desktop`` class with the version of AEDT to use."""
Note
While the numpydoc style guide says to surround the names of classes, methods, and variables in a single backtick, you must use double backticks. Surrounding text in a single backtick in a PyAnsys library formats it in italic type rather than as a code entity.
Required docstring sections#
PyAnsys library docstrings contain these numpydoc sections as a minimum:
Extended Summary if applicable
Parameters if applicable
Returns if applicable
These sections should follow numpydoc style. To avoid inconsistencies between PyAnsys libraries, adhere to the additional style guidelines that follow.
Short summary#
This is a single line that goes immediately after the declaration of the class or function to briefly describe what the class or function does. The short summary is mandatory. If it is not present, Documentation style tools raises an error.
The short summary can be declared on the same line as the opening quotes or on
the next line. While PEP 257 accepts both ways, you must be consistent across your
project. If you decide to declare the short summary on the same line,
see Numpydoc validation because "GL01"
checking must be
turned off.
The guidelines for documenting short summaries differ for classes versus functions.
Short summaries for classes#
A class is a noun representing a collection of methods. For consistency within PyAnsys libraries, always start the brief description for a class with a verb ending in “s” followed by an extended summary in a new line if additional information is needed:
class FieldAnalysis3D(Analysis):
"""Manages 3D field analysis setup in HFSS, Maxwell 3D, and Q3D.
This class is automatically initialized by an application call from one of
the 3D tools. For parameter definitions, see the application function.
...
"""
Ensure that there is a line break between the end of a class docstring and the subsequent methods.
Short summaries for methods#
A method is a verb representing an action that can be performed. For consistency within PyAnsys libraries, always start the brief description for a method with a verb not ending in “s” followed by an extended summary in a new line if additional information is needed:
def export_mesh_stats(self, setup_name, variation_string="", mesh_path=None):
"""Export mesh statistics to a file.
...
"""
Methods with a leading underscore (_) are protected methods, meaning that they are not rendered in the documentation unless an explicit request is made to add them using Sphinx directives. However, clearly written descriptions for private methods are still important.
If a method has the decorator @property
, it is turned into a property, which is described as a
noun rather than a verb. Because the resulting property cannot have parameters, you remove
the “Parameters” section for this method. If a setter follows the decorator @property
, do not
add a docstring for the setter. A setter simply exposes both the GET and SET methods rather
only the GET method. You should include examples to demonstrate usage.
Parameters#
Functions may have parameters in their signatures. All these parameters should be documented in the “Parameters” section.
Here is an example of a “Parameters” section for a class in PyAEDT:
Parameters
----------
application : str
3D application that is to initialize the call.
projectname : str, optional
Name of the project to select or the full path to the project
or AEDTZ archive to open. The default is ``None``, in which
case an attempt is made to get an active project. If no
projects are present, an empty project is created.
designname : str, optional
Name of the design to select. The default is ``None``, in
which case an attempt is made to get an active design. If no
designs are present, an empty design is created.
solution_type : str, optional
Solution type to apply to the design. The default is
``None``, in which case the default type is applied.
setup_name : str, optional
Name of the setup to use as the nominal. The default is
``None``, in which case the active setup is used or
nothing is used if no setup is active.
specified_version : str, optional
Version of AEDT to use. The default is ``None``, in which case
the active version or latest installed version is used.
non_graphical : bool, optional
Whether to run AEDT in the non-graphical mode. The default
is ``False``, in which case AEDT is launched in the graphical mode.
new_desktop_session : bool, optional
Whether to launch an instance of AEDT in a new thread, even if
another instance of the ``specified_version`` is active on the
machine. The default is ``True``.
close_on_exit : bool, optional
Whether to release AEDT on exit. The default is ``False``.
student_version : bool, optional
Whether to enable the student version of AEDT. The default
is ``False``.
The name of each parameter is followed by a space, a colon, a space, and then
the data type. A parameter is optional if its keyword argument displays a default
in the function, class, or method signature. For an optional parameter, the
data type is followed by a comma and optional
or default:
followed by a
space and then the value (if supported).
For example, if the library in the preceding example supported specifying the default
after the data type, the description for the close_on_exit
parameter would look
like this:
close_on_exit : bool, default: False
Whether to release AEDT on exit.
The brief description for a parameter is a sentence fragment. However, all
additional information is provided in clear, complete sentences. For an optional
parameter, if the behavior that occurs when the default is used is unclear,
the behavior should be described. The preceding “Parameters” section provides
many examples. However, here is how you would format the description for the
setup_name
parameter if the default is specified after the data type:
setup_name : str, default: None
Name of the setup to use as the nominal. If ``None``,
the active setup is used or nothing is used if no
setup is active.
Returns#
A class does not have a “Returns” section. However functions and methods generally do a “Returns” section. This section contains the return data type and a brief description of what is returned, which is followed by a period:
Returns
-------
dict
Dictionary of components with their absolute paths.
If a Boolean is returned, format the “Returns” section like this:
Returns
-------
bool
``True`` when successful, ``False`` when failed.
It is possible for the “Returns” section to look like the “Parameters” section if variable names are provided:
Returns
-------
has_succeeded : bool
``True`` when successful, ``False`` when failed.
It is also possible for more than one item to be returned:
Returns
-------
type
Ground object.
str
Ground name.
If a method does not have a decorator, the basic implementation of Python
methods is used. In this case, while None
is returned, you do not document it.
Consequently, such a method does not have a “Returns” section.
Examples#
The “Examples” section provides one or more small code samples that make usage of a method or function clear. They provide an easy place to start when trying out the API.
Here is a sample “Examples” section from a Python file for PyAEDT.
Examples
--------
Create an instance of HFSS and connect to an existing HFSS
design or create a new HFSS design if one does not exist.
>>> from pyaedt import Hfss
>>> hfss = Hfss()
pyaedt info: No project is defined...
pyaedt info: Active design is set to...
Code supplied in an “Examples” section must be compliant with the doctest format. This allows the code to be used through pytest to perform regression testing to verify that the code is executing as expected.
If the definition of a method or function is updated, the code in the “Examples” section
must be updated. Any change within the API without a corresponding change
in the example code triggers a doctest
failure.
Examples are not meant to replace a test suite but rather complement it. Because examples must always match the API that they are documenting, they are an important feature of maintainable documentation.
Type hints#
By default, Sphinx renders type hints as part of the function signature per PEP 484 – Type Hints. This can become difficult to read because the signature becomes very long.
Instead, you should render type hints as part of each parameter’s description. To
accomplish this, you must combine the sphinx.ext.autodoc.typehints
, sphinx.ext.napoleon
,
and numpydoc
extensions in the conf.py
file in this order:
extensions = [
...,
"sphinx.ext.autodoc.typehints",
"sphinx.ext.napoleon",
"numpydoc",
...,
]
autodoc_typehints = "description"
When using type hints in this way, you can omit the type information in the “Parameters” and “Returns” sections.
Additional directives#
Because Python docstrings are written using reStructuredText syntax, you can take advantage of some of the directives available in this plaintext markup language. Here are some Sphinx directives that can be used in docstrings, although they should be used sparingly as they do not look very good in text terminals.
note
: Highlights important information to be aware of.warning
: Points out an action that might result in data loss or cause some other issue, such as performance degradation.deprecated
:X.Y.Z
Indicates the deprecation status of an object or feature.
Example#
Here is a generic docstring example compliant with PyAnsys guidelines:
def func(arg1, arg2):
"""Summary line <should be only one line>.
Extended description of the function. The extended description,
which can span multiple lines, should provide a general overview
of the function.
.. warning::
Use the ``warning`` directive within the docstring for any
warnings that need to be explicitly stated. For example, you
want to include a warning for a method that is to be deprecated
in the next release.
Parameters
----------
arg1 : int
Description of ``arg1``.
arg2 : str
Description of ``arg2``.
Returns
-------
bool
Description of the return value.
Examples
--------
>>> func(1, 'foo')
True
"""
return True
To include the docstring of a function within Sphinx, you use the
autofunction
directive:
.. autofunction:: ansys_sphinx_theme.examples.sample_func.func
This directive renders the sample function as:
- ansys_sphinx_theme.examples.sample_func.func(arg1, arg2)#
Summary line <should be one one line>.
Extended description of function. Can span multiple lines and provides a general overview of the function.
Warning
Use the
.. warning::
directive within the doc-string for any warnings you would like to explicitly state. For example, if this method will be deprecated in the next release.- Parameters:
- Returns:
Description of return value.
- Return type:
Examples
>>> func(1, "foo") True