Skip to content
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

Add consider-using-assignment-expr to CodeStyleChecker #4876

Merged
merged 5 commits into from Aug 30, 2021

Conversation

cdce8p
Copy link
Member

@cdce8p cdce8p commented Aug 19, 2021

Type of Changes

Type
✨ New feature
🔨 Refactoring

Description

Add consider-using-assignment-expr check to CodeStyleChecker extension.

# old
x = 2
if x:
    ...

# new
if (x := 2):
    ...

In this basic example brackets aren't really necessary. However I would still like to suggest them, as this will prevent errors in the future if the test changes.

Since the assignment expression requires Python 3.8, I modified the existing py-version setting from the TypingChecker extension, to be a global setting in the [MASTER] section. The current implementation is fully backwards compatible. It doesn't matter in which section py-version is defined. If not set, this will default to the current interpreter version.

The config change is already quite isolated. It wouldn't be an issue to create a separate PR for that if we want that.

Closes #4862

@cdce8p cdce8p added checker-CodeStyle Issues and PRs that relate to the `CodeStyleChecker` Enhancement ✨ Improvement to a component labels Aug 19, 2021
@cdce8p cdce8p added this to the 2.10.0 milestone Aug 19, 2021
@cdce8p cdce8p marked this pull request as draft August 19, 2021 22:49
@coveralls
Copy link

coveralls commented Aug 19, 2021

Pull Request Test Coverage Report for Build 1181085932

  • 73 of 73 (100.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 92.771%

Totals Coverage Status
Change from base Build 1181080409: 0.02%
Covered Lines: 13539
Relevant Lines: 14594

💛 - Coveralls

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace all reference to 'assignment expression' by 'walrus operator', this is the description I've seen in all python ressources talking about this personally.

@cdce8p
Copy link
Member Author

cdce8p commented Aug 20, 2021

I would replace all reference to 'assignment expression' by 'walrus operator', this is the description I've seen in all python ressources talking about this personally.

Assignment expression is the official name for it. Also the one used in the Python documentation.
https://docs.python.org/3.10/reference/expressions.html?highlight=walrus#assignment-expressions

--
This here is from PEP 572:

During discussion of this PEP, the operator became informally known as "the walrus operator". The construct's formal name is "Assignment Expressions" (as per the PEP title), but they may also be referred to as "Named Expressions" (e.g. the CPython reference implementation uses that name internally).

https://www.python.org/dev/peps/pep-0572/#abstract

--
The help text mentioned := directly and there is even a suggestion for what to use instead. So I don't think it's necessary to change that.

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 2.10.0, 2.11.0 Aug 20, 2021
@cdce8p cdce8p force-pushed the cs_walrus branch 3 times, most recently from 80b12c4 to a44d486 Compare August 20, 2021 23:04
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checker itself is nice and could go in 2.11.

1,
)
suggestion = f"if {test_str}:"
if len(suggestion) > 88:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine 88 is the length of a line for black. The problem with that is that not everyone is using black, we also have a settings ourselves for lines too long that we could use. If we really want to do this I imagine we should behave differently if line-too-long is disabled or not and we should review all the checkers to see if it would also make sense... This would become very complicated and time intensive very quick. But beside that I think it's counterintuitive to have a message change if the line is shorter or longer. I don't think we want to surprise user like that. I know I suggested this idea in the ternary checker review and I think it made sense at the time because long ternary are awful but this would create confusion and makes pylint behave unexpectedly. I think it's more reasonable to let the user know all the time that they can use a walrus operator, and if the line become too long because of it, they could refactor it so it's shorter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't pushed that latest changes yet as I'm still working on it. There I added a new config value so users can change it.

If we really want to do this I imagine we should behave differently if line-too-long is disabled or not and we should review all the checkers to see if it would also make sense...

I don't think that is necessary. Personally, I consider assignment expressions a special case as they are a truly optional feature that should only be used where it makes sense. It is completely independent from line-too-long.

Furthermore, I can't thing of any specific existing and none optional check that could benefit from such a setting. At least not of the top of my head. Once we add it and users would expect it to work for check x / y that doesn't work yet, I'm sure we would see requests for it and can change it then.

But beside that I think it's counterintuitive to have a message change if the line is shorter or longer. I don't think we want to surprise user like that. [...] I think it's more reasonable to let the user know all the time that they can use a walrus operator, and if the line become too long because of it, they could refactor it so it's shorter.

Again, I would disagree here. A refactor is not always possible (or easy do accomplish). It's much more helpful to only recommend it in cases where there is a clear benefit from using it. It's just a recommendation for an optional feature after all.

One example, I think users won't like it if we recommend the use of :=, but it results in an additional line because black reformatted it. Now they will need to add a pylint: disable. If they do it two, three times, they will just disable the check completely and don't get anything from it. That doesn't help anyone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is completely independent from line-too-long.

I don't think a checker that change behavior based on line length should be separated from our max-line-length option. If the value is 120 in max-line-length it means the user want to make 120 char lines. It would be strange to not raise a warning because more than 88 char is considered too much by this checker, when the user already explicitly said that 120 is okay.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two sides I would like to emphasis here:

  1. max-line-length > max-line-length-suggestions
    Although the assignment expression would fit, it might not as easily readable. You have to consider that long lines especially with lots of brackets add quite a bit of complexity. The idea behind the suggestion in contrast is to make code better readable which is far easier accomplished by a shorter line.

  2. max-line-length < max-line-length-suggestions
    I would like to refer back to your point from the beginning: Why shouldn't we just warn about all cases? It can be formatted after the fact to fit within the max-line-length.

IMO both of these cases are valid arguments to decouple max-line-length and max-line-length-suggestions. With a separate setting users are free to choose how they would like to customize it. My personal recommendation btw would be around 72 characters.

pylintrc Show resolved Hide resolved
@cdce8p
Copy link
Member Author

cdce8p commented Aug 22, 2021

The checker itself is nice and could go in 2.11.

That is my intention 🙂
I'll continue working on it over the next few days and let you know then.

@Pierre-Sassoulas Pierre-Sassoulas added the Blocked 🚧 Blocked by a particular issue label Aug 26, 2021
@cdce8p cdce8p marked this pull request as ready for review August 27, 2021 20:07
@cdce8p
Copy link
Member Author

cdce8p commented Aug 27, 2021

@Pierre-Sassoulas Took me a bit longer than expected, but I think it's ready for review now. Let me know what you think

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have minor comment, great work !

pylint/extensions/code_style.py Outdated Show resolved Hide resolved
pylint/extensions/code_style.py Show resolved Hide resolved
pylint/extensions/typing.py Show resolved Hide resolved
setup.cfg Show resolved Hide resolved


# -----
# Don't emit warning if match statement would be a better fit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we're not emitting warning for match statement yet 😄 Is that a glimpse of your future plan ? 😛

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be 😄
But tbh I like it a bit better without := in this case. There is a certain pattern in it that makes it beautiful (and better readable).

o1 = 2
if o1 == 1:
    ...
elif o1 == 2:
    ...
elif o1 == 3:
    ...

@Pierre-Sassoulas Pierre-Sassoulas merged commit a754d8d into pylint-dev:main Aug 30, 2021
@Pierre-Sassoulas Pierre-Sassoulas removed the Blocked 🚧 Blocked by a particular issue label Aug 30, 2021
@cdce8p cdce8p deleted the cs_walrus branch August 30, 2021 11:39
@nickdrozd
Copy link
Collaborator

@cdce8p @Pierre-Sassoulas This check is enabled for the Pylint codebase, right? Shouldn't it have flagged a bunch of stuff? I was hoping to see what would turn up, but it looks like it isn't running.

@Pierre-Sassoulas
Copy link
Member

It's because we're supporting Python 3.6 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
checker-CodeStyle Issues and PRs that relate to the `CodeStyleChecker` Enhancement ✨ Improvement to a component
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New check: Walrus operator recommended
4 participants