-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Warning about 'optional' in Numpy-style docstrings with sphinx.ext.napoleon #6861
Comments
I noticed that doing:
works fine, but the example I provided above is lifted straight from the sphinx.ext.napoleon docs, and many projects don't write |
I also get warnings about |
And I also get warnings for the following syntax which is valid:
|
The docstring is expanded to following reST document inside napoleon:
But |
I don't think numpydoc says "array_like" is a valid type. It does not mention about validity. It seems it takes free formatted text. It also uses "data-type" and "iterable object" for example. But it is hard to resolve these type-like text. I think no-nitpicky mode is used for such ambiguous types. -1 for supporting these types. On the other hand, it would be better to suppress warnings for set of values like |
Regarding array_like, here's the text I was referring to:
So I think that is also a special term we should allow without reference. |
And I'm on board with not trying to allow things like data-type and iterable object - for those one can always add nitpick exceptions if really needed. The biggest blocker for me at the moment is the set of values, because everything else can be worked around with exceptions. |
I think this has to be fixed in
to the python domain:
which I believe should silence any nit-picky warnings? |
I had a look into this, and while The main problem, as @tk0miya pointed out, is that Napoleon will output something like:
At this point, rendering of the The second problem is that the available Info field options do not have an option for specifying if a parameter is optional, or what its default value is. I'm picturing that a possible solution could involve adding something like this. For example, for a function
Perhaps this would be redundant, since the fact that an argument is optional, and its default, are already reflected in the function signature line. But an explicit Then, on the Napoleon, |
Digging a little deeper, it seems that Napoleon does already monkeypatch the Python domain to add a distinct "Keyword Arguments" field to the docs, and keyword arguments can be added to it by marking them However, it only really creates |
Thanks for working on this, @embray. Just for reference, That would push most of the issue to the user but we'd still need to find a way to support sets of values. However, at least for |
Here's what I came up with, which seems to work fine for my own case. Of course, if others on this issue agree to a fix like this, it should be merged in directly. For now I am just monkey-patching in my # monkey-patch napoleon to better handle optional parameters in numpydoc
# docstrings; see https://github.com/sphinx-doc/sphinx/issues/6861
def _fixup_napoleon_numpydoc():
from sphinx.locale import _
from sphinx.ext.napoleon import NumpyDocstring
def _process_optional_params(self, fields):
"""
Split a fields list into separate lists of positional parameters and
keyword parameters.
Possibly moves some fields out of their original documented order,
though in practice, in most cases, optional/keyword parameters should
always be listed after positional parameters.
For Numpydoc, a parameter is treated as a keyword parameter if its type
list ends with the keyword "optional". In this case, the "optional" is
removed from its type list, and instead the text "(optional)" is
prepended to the field description.
"""
positional = []
keyword = []
for name, type_, desc in fields:
types = [t.strip() for t in type_.split(',')]
optional = types and types[-1].lower() == 'optional'
if optional:
type_ = ', '.join(types[:-1])
if not desc:
desc = ['']
desc[0] = ('*(optional)* – ' + desc[0]).rstrip()
if optional or name.startswith(r'\*\*'):
keyword.append((name, type_, desc))
else:
positional.append((name, type_, desc))
return positional, keyword
def _parse_parameters_section(self, section):
fields = self._consume_fields()
pos_fields, kw_fields = self._process_optional_params(fields)
if self._config.napoleon_use_param:
lines = self._format_docutils_params(pos_fields)
else:
lines = self._format_fields(_('Parameters'), pos_fields)
if self._config.napoleon_use_keyword:
if self._config.napoleon_use_param:
lines = lines[:-1]
lines.extend(self._format_docutils_params(
kw_fields, field_role='keyword', type_role='kwtype'))
else:
lines.extend(self._format_fields(
_('Keyword Arguments'), kw_fields))
return lines
def _parse_other_parameters_section(self, section):
fields = self._consume_fields()
pos_fields, kw_fields = self._process_optional_params(fields)
return self.format_fields(
_('Other Parameters'), pos_fields + kw_fields)
NumpyDocstring._process_optional_params = _process_optional_params
NumpyDocstring._parse_parameters_section = _parse_parameters_section
NumpyDocstring._parse_other_parameters_section = \
_parse_other_parameters_section
_fixup_napoleon_numpydoc() I think that, now that this adds all keyword arguments to a separate section, keeping the "(optional)" text is a bit redundant. But I keep it anyways, in the original spirit of the numpydoc format. For example, here is an actual docstring from my project, and the resulting output: def simulate_scenarios(self, scenario_params, n_cpus=1, verbose=False):
"""
Return an iterator over simulated SNPs given a scenario params table
(see `Simulator.load_scenario_params` for the format of this table).
This method should iterate over all scenarios in the simulation
(possibly generating the simulation as well, or reading it from an
existing simulation), which are then each passed to
`Simulator.simulate_scenario` for each scenario.
The items returned from the iterator should be a 3-tuple in the format
``(scenario_idx, rep_idx, SNPSample(snp=SNPs, pos=positions)``, where
``scenario_idx`` is the index into the scenario params table for the
parameters that were used to produce this simulation; ``rep_idx`` is
the replicate index, in the case where multiple replicates are
generated for each scenario, if not it can just be ``0``; the final
element is an `.SNPSample` instance containing the SNP matrix and
positions array generated by the simulator.
Parameters
----------
scenario_params : `pandas.DataFrame`
The scenario params table for the scenarios to simulate.
n_cpus : int, optional
If ``1``, scenarios are simulated in serial; for ``n_cpus > 1`` a
process of pool of size ``n_cpus`` is used. If ``n_cpus = 0`` or
`None`, use the default number of CPUs used by
`multiprocessing.pool.Pool`.
""" |
Describe the bug
When using
sphinx.ext.napoleon
with Numpy-format docstrings andnitpicky
mode, a warning is emitted aboutoptional
.To Reproduce
Create an empty directory and add the following files:
conf.py
:mycode.py
:index.rst
:Then run:
The output includes a warning about the
optional
string which should not be interpreted as a type:Expected behavior
No warning should be emitted since adding
, optional
is valid by the numpy doc spec.Environment info
The text was updated successfully, but these errors were encountered: