-
-
Notifications
You must be signed in to change notification settings - Fork 170
MAINT: Changed class constructor __init__ GL08 reporting #592
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
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! 🤦 |
larsoner
left a comment
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?
stefanv
left a comment
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
| """ | ||
|
|
||
|
|
||
| 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.)
numpydoc/validate.py
Outdated
| # 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)?
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 think the second one works; doc.name[:-9] is numpydoc.tests.test_validate.__init__ when testing IncompleteConstructorDocumentedInClass.__init__ (is this expected for doc.name, not including the class name?). This means you can't resolve the class without the __qualname__ like you used in the first suggestion. Two equivalent options seem to be:
cls = Validator._load_obj(f"{doc.code_obj.__module__}.{cls_name}")
cls = Validator._load_obj(f"{doc.name[:-9]}.{cls_name}")
Any preference?
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.
Either seems okay, hopefully they're equivalent!
…e conditions they're used to check
…hen the constructor has no parameters, also modified docstring descriptions for clarity
stefanv
left a comment
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 <sjvdwalt@gmail.com>
numpydoc/validate.py
Outdated
| # 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)?
MAINT: Changed constructor identification in validation by including class method '.' Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
…fined when checking constructor docstring to decide if reporting GL08 error hooks/validate_docstrings.py implmements an ASTValidator class that does not define a 'code_obj' attribute. Possibly another way to link to the class docstring.
…getattr module accessors
|
Thanks @mattgebert ! |
…checking for initialisation docstring Test written due to bug missed in numpy#592.
|
This change has caused regressions in half a dozen packages, see #638. |
| and doc.is_function_or_method | ||
| and hasattr(doc, "code_obj") | ||
| ): | ||
| cls_name = doc.code_obj.__qualname__.split(".")[0] |
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 line is incorrect and fixed by #622
Sorry this has happened! This feature honestly wasn't fully complete and had an active pull request in #622 when 1.9.0 was released last month. FYI, This pull request has an update that also integrates the AST (abstract syntax tree) validator for hooks in #622. I've added the suggested fix for #638 to #622, hopefully this is approved soon. |
) * build(pyproject.toml): drop support for python 3.9 (require 3.10+) In upgrading via #592 and #622, requires stable use of __qualname__, not supported in dataclasses in python3.9 (solves #637). * style: Replace isinstance calls that use tuples to the `|` operator as per ruff UP038 * refactor(cli.py): exchange union use for '|' as per ruff UP007 * refactor(test_docscrape): explicitly declare strict=True for testing zips * test(test_docscrape.py): use strict and include 4th parameter check for the docscrape test * refactor(validate.py): remove `Optional[X]` for use of `X | None` ruff UP007, UP045 * refactor(test_docscrape.py): ruff formatting
* fix(validate.py): Considers subclass nesting when checking GL08 constructor Introduced GL08 checking for constructors (i.e. __init__) but didn't traverse the parent class heireacy when importing the __init__ parent from a module. * test(validate.py): Added a test to check nested class docstring when checking for initialisation docstring Test written due to bug missed in #592. * fix(validate.py): Allows the validator to check AST constructor docstrings compliance with parent class The abstract syntax tree doesn't provide any link to a parent class at node level, so special traversal is required to check constructor parent implementation of docstrings. * test(test_validate_hook.py,-example_module.py): Wrote new example_module tests for AST (AbstractSyntaxTree) discovery of constructor method parent class. * ci(test.yml): Added --pre option to prerelease job to ensure pre-release installation, and changed pytest invocation to use `numpydoc` instead of `.`, for consistency with `test` job In response to discussion on #591 * refactor(tests): Remove `__init__.py` module status of `tests\hooks\` to match `tests\` directory * ci(test.yml): Added explicit call to hook tests to see if included in pytest execution * test(tests\hooks\test_validate_hook.py): Changed constructor validation to use AST ancestry, fixed hook tests and added Windows support for test_utils * ci(test.yml): Added file existance check for hook tests Workflows do not seem to be running hook pytests. * ci(test.yml): Correct the workflow task name/version * ci(test.yml): Added explicit pytest call to the hooks directory * ci(test.yml): Removed file existance test, after explicit call to hooks verifies execution * fix(validate.py): switched conditional GL08 check order to avoid property class failure for Validator.name Solves Issue #638, though lacks property support for property class attributes. * test(test_validate.py): add coverage for existing / expected functionality of property and dataclass objects * test(test_validate_hook.py): modify test strings and remove unused os.sep replacement Updates to make this PR compatible with the recent merge from #653
Changed
validatefunction invalidate.pyfor 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.pyto verify correct functionality.Also updated readthedocs
format.rstandvalidation.rstto 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.