-
-
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
Make invalid-name
distinguish between module constants and module variables
#3585
Comments
variable is only assigned once, why is it not constant? |
@Project-Magenta
which prints
|
oh ok i see |
The variable is assigned once but as long as it is a |
Interesting. Coming from C++, I thought I knew what a "constant" is - will have to adapt apparently. Now, the fact that this code does not give
Or this one?
Or this one?
Something is inconsistent here, I don't think this is ready to be closed. |
Thanks for the additional examples. Something is definitely inconsistent with this check. In the latter examples you gave, pylint cannot fully infer that the variable is a constant or not, while it can do so in the original example. I believe in this case we should simply emit the |
but it is assigned 3 times because python variables are module/function scoped |
Yes, something is off with this check. While I get a warning in the original code,
I do not get any in this case:
|
This seems related: x = 0
for i in range(7):
x+=1 Here pylint also says |
Whoever works on this, please consider adapting the error message if required. Currently, it says
|
I had a very simple script, similar to the above, which pylint failed with the same apparently false-positive and which led me to this bug and #3466. The discussion in #3466 was revealing: pylint raises C0103 when a variable is declared at module level and does not conform to the naming style. The coding style this is expressing is "a variable declared at module level should be a constant". Defining a function and declaring the variables inside the function avoided pylint raising C0103. As I was running this script from the command line I used: def main():
"""Do some stuff"""
for i in (0, 1, 2):
variable = i
if __name__ == "__main__":
main() While doing it this way obviously incurs some overhead, it is compliant with pylint's style rules. |
@Pierre-Sassoulas or @PCManticore do we actually consider this a false positive and should |
There's actually an example where we don't want this to be a constant : |
So, we want to start recognising non-constant module-level variables? Guess we can stick the |
No, I think we need to keep it simple but also enforce one convention or the other but still have a rule (ie |
Okay, so what's needed to close this issue? A better way to set the pattern for module level variables? |
I think a functional test like this would do it: for i in (0, 1, 2):
variable = i # okay
for i in (0, 1, 2):
VARIABLE= i # also okay
for i in (0, 1, 2):
vAriAbLE = i #[invalid-name] Maybe an option for configuring what module level variable are acceptable or not ? (UPPERCASE, snake_case, both) |
invalid-name
only check internal consistency for for module level variable
invalid-name
only check internal consistency for for module level variableinvalid-name
only check internal consistency for module level variables
I happened to also notice this using pylint 2.14.4 using the following code example:
In this case, I'm trying to do a safety check against dividing by zero. The variables sym_curr_val and sym_exp_val are floating-point numbers that vary based on calculations made in a loop, and don't get flagged. |
This require a prior refactor to accept multiple name style for a node type in |
Revisiting that example: I'm not sure I agree anymore. #3585 (comment) seems to indicate what The use of This argument applies to all examples in this issue, even those that get assigned multiple times: they are importable by other modules and can therefore be considered "module constants". Since the current status quo is actually predictable I would vote to keep it. The only thing I would change is:
To:
|
The biggest issue with this is, although Since the entirety of the module is within an |
Inside a function looks like it works; that'll be sufficient for what I'm seeking. |
@DanielNoord You are correct that PEP8 recommends constants be UPPER_CASE. However, PEP8 also acknowledges that module level variable are a thing, and recommends formatting them the same way as function variables, i.e. lower_case. Pylint is entirely right to enforce that constants be uppercase, but it is wrong in assuming that every module-level name is a constants and not a variable. The best solution would be to detect whether a given name is a constant or a variable and enforce the appropriate convention. However, this would be difficult; for example, I have a case where a module-level variable only has a single module-level assignment (setting it to None at definition), but gets initialized and modified by functions using The second-best solution would be to acknowledge that any given module-level name might be a constant or a variable, and allow by default either naming convention (while still enforcing that it must be one of the two conventions; mixed-case is still out). |
invalid-name
only check internal consistency for module level variablesinvalid-name
distinguish between module constants and module variables
I find the reply at #3585 (comment) convincing, and I think fits well with our principle when in doubt, be less opinionated. WDYT -- can we mark this as ready for an implementation? In other words, accept a PR that removes false positives for |
Considering the high amount of 👍 I guess this is what the people want 😄 I'm fine with changing this but it should probably happen in a |
That's fair, it's a pretty clear breakage from the current documentation. Also, that gives us time to try to do it the "right way":
Honestly the |
Two kinds of implementations could be accepted here, I think:
The second approach is simpler but probably involves a small refactor to allow "as-if" checking against regexes without immediately emitting a message. Another consideration is whether we need a new regex for module-level variables versus reusing the function variable regex (and updating the doc). |
Steps to reproduce
pylint bug.py
Current behavior
Expected behavior
Perfect score.
pylint --version output
Problem does not appear with
range(3)
. Problem does not appear withpylint<2.5
.The text was updated successfully, but these errors were encountered: