-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Current problem
The work on #5953 showed that specifically enabling just a single message is sometimes not working as expected.
This is due to either missing message declaration in a checkers msgs attribute or the incorrect usage of the @check_messages decorator.
Ideally I would like to implement a new, optional checker aimed at Pylint core development and custom checker development.
This checker would focus on correct message declaration and handling.
I already started working on it, but noticed that there is especially quite some problems with the @check_messages decorator. I totally understand that, because while being extensively used across all checker classes, there is not a single word on its purpose and effect in the documentation. Its docstring is also not really helpful, you have to dig deeper into the codebase to understand what it does.
Desired solution
Before continuing my work on the new checker, I want to address and clarify some questions about the intended use of @check_messages.
After that this issue can be closed with a PR that extends the documentation, and if necessary some code changes.
A brief explanation on what @check_messages does:
It helps the ASTWalker decide whether a callback for the current node type should be called or not.
This is done by adding the list of messages passed in as a checks_messages attribute on method object.
When a checker is added to the ASTWalker instance, it loops over all of its methods. Every method starting with visit_ or leave_ is now checked for the checks_messages attribute:
- if the attribute does not exist, this method will be added to the list of callbacks
- if it exists and at least one message of the
checks_messageslist is enabled, this method will be added to the list of callbacks - otherwise, it will not be added to the list of callbacks and will therefore not be executed
Essentially this means:
- The main (and only) intent of the
@check_messagesdecorator is to improve performance - Placing the
@check_messagesdecorator on any method which is not a "top level callback" (methods starting withvisit_orleave_does not have any effect - Forgetting to apply the
@check_messagesdecorator has no negative functional consequences, it only affects performance (which, of course, is always an issue) - Applying the decorator but forgetting to add messages that are emitted from this callback can lead to false negatives: if none of the messages actually included in the decorator are enabled, it will not be called
- Applying the decorator to a callback that not only emits messages but also does other things can have nasty side effects (false positives, false negatives, crashes)
What I want to gain a consensus on:
- Do we want to keep the name
check_messages? I don't think it really conveys the effect it has on the decorated method. - What shall we regard as best practice for this decorator? Should every callback be decorated and the list of messages must always be correct and consistent, or should we rather advise to use it only in cases where we expect a significant speedup when this callback is omitted?
- Do we want to keep the restriction that this decorator only has an effect on the "top level callbacks"? Seeing that a lot of those callbacks can emit quite a lot of messages and the logic for the checks is often split up into several subfunctions, it would be more flexible and also more robust (as it is easier to keep track of the messages that need to be included in the decorator) if one could apply it on the subfunctions rather than on the top level callback.
Looking over the code base there are quite a lot of places where the decorator is not used correctly:
- used with simply passing in all messages (which has the same effect as just omitting it):
@check_messages(*MSGS) - used on methods that are not a callback (which has no effect)
- Used, but not including all messages possibly emitted by the callback
Additional context
No response