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

N811 & N814: eliminate false positives for single-letter names #14584

Merged

Conversation

snowdrop4
Copy link
Contributor

@snowdrop4 snowdrop4 commented Nov 25, 2024

Summary

Under PEP8, identifiers consisting of a single upper-case character could either be a class or a constant.

N811 (constant imported as non-constant) and N814 (camelcase imported as constant) are, however, incorrectly assuming these identifiers to always be constants, which leads to false-positives.

Although identifiers consisting of a single upper-case character are not advised under PEP8, it would be best if these cases were handled by more specific rule(s) that point out ambiguous identifiers and/or violations of PEP8, rather than rules that attempt to narrowly point out changes in identifier casing.

Addresses #11862.

Test Plan

Additional fixture cases.

Copy link
Contributor

github-actions bot commented Nov 25, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

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

Thanks.

I'm trying to understand the change in regards of PEP8 but I wasn't able to find the exception for single-letter non-constants. Could you extend the rule's documentation and mention the exception and reference PEP8. It will help to prevent future issues that ask for Ruff detecting single-letter uppercase imports to be flagged.

@MichaReiser MichaReiser added the rule Implementing or modifying a lint rule label Nov 25, 2024
@snowdrop4 snowdrop4 force-pushed the AVK/ConstantImportedAsNonConstant branch from 22e8b0a to 3da4c28 Compare November 25, 2024 23:11
@snowdrop4
Copy link
Contributor Author

snowdrop4 commented Nov 25, 2024

PEP8 doesn't explicitly mention the case. It leaves it undefined by failing to mention the obvious problem. It only says:

Class names should normally use the CapWords convention.

Constants are [...] written in all capital letters with underscores separating words

If there is only one character then CapWords and ALL_CAPS_SNAKE_CASE appear the same since the first character is always capitalised.

But if there are at least two characters, then 99.99% of the time, it isn't ambigious any more, since it would either be Ab (CapWords) or AB (ALL_CAPS_SNAKE_CASE).

But yeah, good point about the docs. I've added a ## Note section to the docs for both rules.

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

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

Thanks. This makes sense to me. @AlexWaygood it would be great if you could do a quick sanity check if the rule-change makes sense to you too.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Some docs nits. We refer to it elsewhere in our docs as CamelCase rather than PascalCase.

Comment on lines 68 to 69
// Single-character names are ambiguous. It could be a class or a constant.
name.chars().nth(1)?;
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 still want to forbid things like from foo import C as c from one of these rules, right? Won't these changes mean that we will no longer see that error?

Copy link
Contributor Author

@snowdrop4 snowdrop4 Nov 27, 2024

Choose a reason for hiding this comment

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

It's not possible to tell if C is a class or a constant. So even though from foo import C as c might not be advisable, it's not applicable to throw an error about this under a rule made for constants.

Copy link
Member

Choose a reason for hiding this comment

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

But regardless of whether you classify its original name as CamelCase or SCREAMING_SNAKE_CASE, the name it's being aliased to is neither CamelCase nor SCREAMING_SNAKE_CASE. I don't mind much which of these two rules flags that, but I think I would want a rule in this category to complain that the alias uses a different naming convention to the naming convention used for the object's original name.

Copy link
Contributor Author

@snowdrop4 snowdrop4 Nov 27, 2024

Choose a reason for hiding this comment

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

I could add a new rule, non_lowercase_imported_as_lowercase? (to compliment the already-existing lowercase_imported_as_non_lowercase).

Though I guess we'd need to prevent overlaps and check that the other rules aren't already firing?

Or maybe just name it single_uppercase_character_imported_as_lowercase?

Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to preserve the existing behavior for lower-case letters which is that both rules falg it?

Nice catch @AlexWaygood !

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would it be possible to preserve the existing behavior for lower-case letters which is that both rules falg it?

Yeah, that could be an option.

Copy link
Member

Choose a reason for hiding this comment

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

I've just pushed a change that makes N811 flags it. I think that rule makes more sense here, and I think it's not a great outcome if one lint error is flagged by two rules. I don't think the situation is common enough to justify its own rule.

Copy link
Member

Choose a reason for hiding this comment

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

a great outcome if one lint error is flagged by two rules

I don't disagree with this. I'm just slightly worried about bug reports if someone only enables one rule... But I'm fine with either

@AlexWaygood AlexWaygood force-pushed the AVK/ConstantImportedAsNonConstant branch from 8d59bf8 to 7ae363c Compare November 27, 2024 14:24
@AlexWaygood AlexWaygood merged commit c40b37a into astral-sh:main Nov 27, 2024
21 checks passed
@AlexWaygood
Copy link
Member

Thanks @snowdrop4!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants