-
-
Notifications
You must be signed in to change notification settings - Fork 162
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
MAINT: Changed class constructor __init__ GL08 reporting #592
base: main
Are you sure you want to change the base?
Conversation
Had a quick look at the code and this looks reasonable to me!
Sounds good, do you want to add it here? |
@larsoner I've added new doc comments in the diff in format.rst ->
|
I think you maybe forgot to push (?), I don't see the changes in the files changed tab |
Ohh wait nevermind you already made the changes before I just didn't notice. And failed to notice again! 🤦 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stefanv did you want to look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general gist of this is correct, I think. I left some comments that I think may help future developers (ourselves, likely 😅) know what we did here.
numpydoc/tests/test_validate.py
Outdated
@@ -1198,6 +1198,90 @@ def missing_whitespace_after_comma(self): | |||
""" | |||
|
|||
|
|||
class GoodConstructorInclusion: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it correct to have parameters both in class docstr and init? Maybe it's OK 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good point, particularly if both exist. I haven't captured this complexity.
I think it's logical to allow both; particularly as the class docstr can be comprehensive (i.e. listing atrributes and properties which wouldn't be listed on init). I think where this really makes a difference is in linting for UI interpret hints - for accessible hinting you want to enforce parameter documentation.
For example, Pylance (vscode) will use both the class docstr and init docstr to display documentation for references / initialisation. When a init docstr hasn't been provided, initialisation hinting defaults to the class docstr.
We might be missing one thing here. The current revision checks if the missing docstr belongs to a constructor, and if it is satisfied by the class docstr. Perhaps we should likewise check class docstrs, silencing parameters mismatch warnings if parameters are satisfied by an (existing) init docstr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can perhaps think of that as some additional follow-up logic, if you want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I meant separate PR, so as to not slow this one down.)
# Check if the object is a class and has a docstring in the constructor | ||
if doc.name.endswith("__init__") and doc.is_function_or_method: | ||
cls_name = doc.code_obj.__qualname__.split(".")[0] | ||
cls = getattr(importlib.import_module(doc.code_obj.__module__), cls_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larsoner I don't know enough about current internals to know if this is how we do things; no utility functions / class methods for this purpose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like Validator._load_obj(f"{doc.code_obj.__module__}.{doc.code_obj.__qualname__}")
might do it, or maybe simpler Validator._load_obj(doc.name[:-9])
could work. @mattgebert do you want to try it (probably the second one)?
…e conditions they're used to check
…hen the constructor has no parameters, also modified docstring descriptions for clarity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larsoner Would appreciate your eyes on lines 641 through 652. Otherwise LGTM.
constructor's parameters. | ||
constructor's parameters. While repetition is unnecessary, a docstring for | ||
the class constructor (``__init__``) can be added optionally to provide | ||
detailed initialization documentation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We recommended only the class docstring before. How do documentation writers decide what to put in the two docstrings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above my introductory pay grade, but I would stick to recommending class docstring only? The changes only allow flexibility for a constructor docstring if desired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes:
There should be one-- and preferably only one --obvious way to do it.
And all that :)
Co-authored-by: Stefan van der Walt <[email protected]>
# Check if the object is a class and has a docstring in the constructor | ||
if doc.name.endswith("__init__") and doc.is_function_or_method: | ||
cls_name = doc.code_obj.__qualname__.split(".")[0] | ||
cls = getattr(importlib.import_module(doc.code_obj.__module__), cls_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like Validator._load_obj(f"{doc.code_obj.__module__}.{doc.code_obj.__qualname__}")
might do it, or maybe simpler Validator._load_obj(doc.name[:-9])
could work. @mattgebert do you want to try it (probably the second one)?
if "GL08" not in ignore_validation_comments: | ||
report_GL08: bool = True | ||
# Check if the object is a class and has a docstring in the constructor | ||
if doc.name.endswith("__init__") and doc.is_function_or_method: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this is a tiny bit safer
if doc.name.endswith("__init__") and doc.is_function_or_method: | |
if doc.name.endswith(".__init__") and doc.is_function_or_method: |
Changed
validate
function invalidate.py
for empty docstring errorGL08
("The object does not have a docstring"), specifically for__init__
constructors. If an empty docstring for__init__
, will first check if class docstring is satisfied for parameter mismatches, before deciding to reportGL08
(if mismatches exist, i.e. incomplete documentation).Implemented new docstring test classes in
test_validate.py
to verify correct functionality.Also updated readthedocs
format.rst
andvalidation.rst
to reflect new changes to constructor checking behavior.Solves #591.
Note, I think a modification to the readthedocs https://numpydoc.readthedocs.io/en/latest/validation.html#ignoring-validation-checks-with-inline-comments ought to be made
P.s. First time pull requesting to a public repo, let me know if anything is insufficient.