Napoleon: Don't use attribute type annotation for constructor parameters
Fix a bug where if a class has an attribute and a constructor parameter with the same name, napoleon will use the type annotation from the attribute for the constructor argument.
Feature or Bugfix
- Bugfix
Detail
Suppose we have a class that looks like
class Example:
"""
A Class
Parameters
----------
blah:
Description of parameter blah
"""
def __init__(self, blah: int):
pass
blah: bool
The processed docstring looks like:
A Class
:param blah: Description of parameter blah
:type blah: bool
Note that the parameter has type int but Napoleon took the type from the attribute which has type bool.
A more practical reason this would happen is that the parameter has type Optional[dict] and this is stored into an attribute of type dict where if None is passed a default dictionary is created.
I added a new parameter is_attribute to _lookup_annotation and _consume_field(s) which defaults to False. If is_attribute is False and what is "class" then we look up the type from the constructor arguments instead. With these changes it produces the correct output:
:param blah: Description of parameter blah
:type blah: int
merging into this the latest master update for CI checks
cc @cbarrick if you would have any time to look at this one?
A
It seems that this problem arises because the docstring for the class can also be used to document the parameters of __init__.
So I think the correct behavior is for the Attributes section to refer to class attributes and for the Parameters section to refer to __init__ parameters.
Can we add a test case for this? e.g.
class OverloadedParamAttribute:
"""
A class with both an attribute named ``blah`` and an __init__ parameter named ``blah``.
Both are documented in this docstring, but they have different type annotations in the
class definition. This tests that the generated docs use the correct type when using
``napoleon_use_param`` (for method params) and ``napoleon_attr_annotations`` (for
attributes).
Attributes
----------
blah:
Description of class attribute blah, of type bool.
Parameters
----------
blah:
Description of __init__ parameter blah, of type int.
"""
def __init__(self, blah: int):
pass
blah: bool
Resolved conflicts.
A