-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Pylint does not warn on assignment to constants #7232
Comments
Perhaps the warning should suggest annotating the constant with typing.Final; that way Pylint would avoid checking something that mypy already can take care of. |
I think this is also caused by the seemingly different interpretations of "constant" in Python and other languages. I can think of examples where module constants get re-assigned after certain operations are finished. The constant seems to refer to "something that holds value for a longer period of time" rather than a variable which is discarded sooner such as loop variables or variables within function scopes. I agree that this is a semantic difference and perhaps not everybody agrees with this, but warning for this by default might not be the right solution. I'm also thinking of the Const node in ast/astroid which has the same issue with being a constant that can be reassigned. |
Isn't that an issue with python itself ? There's no real constant in python. even |
Yeah I don't think pylint can do anything else without suggesting worse code/weird patterns. Using Final is also not the optimal solution in some cases and it assumes the user also uses mypy. |
I think this touches on the confusion because Pylint is naming it a constant but it doesn't behave that way in Python. |
I'm on mobile, but in a recent discussion we found that pep8 actually uses the term constant, which is where this rule comes from. |
The discussion become highly similar to #3585. It's hard/impossible to know if something is a constant or not for a module level variable. Right now we rely on mutability which is probably as good as it get. |
I agree with you @DanielNoord & @Pierre-Sassoulas; In my opinion this issue could be closed since the idea of constant for these variables is a convention in Python which doesn't stop you from re-assigning. |
Huh? Isn't a big point of a linter to warn you when you're breaking convention? |
PEP8 says this
Also PEP8 says they should be after imports and before anything else. I presume this is why C0103 warns that my global does not honor the naming convention. |
I've just checked, there is no warning for module-level variables in SCREAMING_SNAKE_CASE coming after classes or module-level functions. Is this a problem? |
We get the Having said that, one case where this logic breaks is global variables. You expect to re-assign the module-level value somewhere from within a function, and that would be a string, as an example, which Pylint considers a constant. I hope I'm not missing any point that was already made in the good discussion above, but since the issue here seems to be mainly around the complexity of identifying if a module-level variable is a constant or not, would it be an idea to tweak the logic so that the warning is emitted simply when Pylint sees a variable name which contains some upper & some lowercase characters? In other words, it looks like a user is trying to define a constant. Otherwise, snake_case should not emit the warning since the intention there is never clear if it will be re-assigned or not. |
I checked and it's not really immutable/mutable as for example in the following code aaa = 42 # [invalid-name]
aab = tuple("42")
aac = "42" # [invalid-name]
aad = [42]
aae = {42}
aaf = {"a": 42} Here's the related code : https://github.com/PyCQA/pylint/blob/main/pylint/checkers/base/name_checker/checker.py#L409 There's already something regarding "Final" as far as I understand: |
I meant immutable. Corrected my comment! So, it breaks for global string, for example, which is re-assigned. |
@Pierre-Sassoulas thank you regarding your most recent comment with the link to the Final logic! |
Do you think removing these lines would be acceptable & fix what we've discussed Pierre (sorry for tagging so much :D)? When you look at the annassign case, I think this is logical because it only regards a constant as something which is annotated with Final & then only emits the warning if it doesn't match the 'const' regex (all uppercase). |
No problem @mbyrnepr2 . The more we look into it, the more it seems there's a big issue with this check consistency and we added wart after wart on top of the existing code without exhaustive tests. I don't have the time for it right now, but I feel we should list what is happening at the moment (when we have typing / no typing, final / not final, mutable / immutable, in another scope like for loop or not...) from all the issues opened regarding this and then decide what we want from the check. What I started in #7232 (comment) already shows some inconsistencies regarding mutability. |
I'm also having the opposite issue as described in #7523 where the warning is raised on a variable initializer. I.e. I have a python script to be executed without any functions and the constant warning is raised. Simple example:
|
Thanks for everyone's help clarifying the issues. I think we can focus things a bit by continuing the conversation on distinct issues:
We also have other issues marked with the label |
Bug description
Here is the contents of the file
sglobals.py
Here is the output of
pylint sglobals.py
:Clearly the opinion is that
TheGreetingWithABadName
is a constant, so it must be a codesmell if we later assign to this. But pylint has nothing to say about the following file in the same directory:Similarly, assigning to module-level functions and so is not caught by pylint.
Configuration
No response
Command used
Pylint output
Expected behavior
I would have expected a warning to the effect that assigning to module level variables is at least frowned upon
Pylint version
OS / Environment
Debian 11.4
Additional dependencies
No response
The text was updated successfully, but these errors were encountered: