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

[flake8-return] Exempt cached properties and other property-like decorators from explicit return rule (RET501) #12563

Merged
merged 6 commits into from
Jul 30, 2024

Conversation

epenet
Copy link
Contributor

@epenet epenet commented Jul 29, 2024

Summary

Follow-up to #12243, in which regular properties were exempted but not cached properties.

Still linked to home-assistant/core#115031

Test Plan

@epenet epenet marked this pull request as draft July 29, 2024 06:24
Copy link

codspeed-hq bot commented Jul 29, 2024

CodSpeed Performance Report

Merging #12563 will not alter performance

Comparing epenet:20240729-0822 (c2c96bc) with epenet:20240729-0822 (f452453)

Summary

✅ 33 untouched benchmarks

@epenet epenet marked this pull request as ready for review July 29, 2024 07:08
Copy link
Contributor

github-actions bot commented Jul 29, 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.

LGTM. Thank you. I let @AlexWaygood merge to get the blessing of someone who actually understands Python ;)

@MichaReiser MichaReiser added the rule Implementing or modifying a lint rule label Jul 30, 2024
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.

LGTM. I added support for other stdlib property-like decorators as well, such as @abc.abstractproperty, @enum.property, and @types.DynamicClassAttribute. I think the same rationale applies for special-casing these decorators as it does for special-casing @functools.cached_property.

/// hardcoding these is a little hacky.
fn is_property_like_decorator(decorator: &Decorator, semantic: &SemanticModel) -> bool {
semantic
.resolve_qualified_name(&decorator.expression)
Copy link
Member

Choose a reason for hiding this comment

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

@epenet -- you had semantic.resolve_qualified_name(map_callable(&decorator.expression)) here. I think using map_callable would be incorrect in this instance. map_callable() is a convenience function for when we don't care whether e.g. a function is decorated with @functools.lru_cache or @functools.lru_cache() (whether the decorator is a call-expression or not is irrelevant). But for all of these property-like decorators, you can only use them as @property; it's invalid to use them as @property(). So for these decorators, we just want to call resolve_qualified_name directly on the expression, instead of passing it through map_callable first.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I copied it from elsewhere in the code base.
I wonder if this applies there as well...
And would it make sense to move this function to a shared location?

Copy link
Member

Choose a reason for hiding this comment

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

I copied it from elsewhere in the code base.
I wonder if this applies there as well...

It's hard to say in general. For a lot of decorators (like @lru_cache), you really don't care about whether it's been decorated with @lru_cache or @lru_cache(). So while there may be other places in the codebase where it's being used incorrectly, I'm pretty confident they're not all incorrect ;-)

And would it make sense to move this function to a shared location?

Possibly...

Copy link
Member

@AlexWaygood AlexWaygood Jul 30, 2024

Choose a reason for hiding this comment

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

Good that you asked. It seems we already have a general-purpose function for this:

/// Returns `true` if a function definition is a `@property`.
/// `extra_properties` can be used to check additional non-standard
/// `@property`-like decorators.
pub fn is_property(
decorator_list: &[Decorator],
extra_properties: &[QualifiedName],
semantic: &SemanticModel,
) -> bool {
decorator_list.iter().any(|decorator| {
semantic
.resolve_qualified_name(map_callable(&decorator.expression))
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["" | "builtins", "property"] | ["functools", "cached_property"]
) || extra_properties
.iter()
.any(|extra_property| extra_property.segments() == qualified_name.segments())
})
})
}

We should just use that for now. I'll apply some fixes to it in a followup PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For reference, I wonder if it might make sense to look at rules/pydoclint/rules/check_docstring.rs also:

// Checks if a function has a `@property` decorator
fn is_property(definition: &Definition, checker: &Checker) -> bool {
let Some(function) = definition.as_function_def() else {
return false;
};
let Some(last_decorator) = function.decorator_list.last() else {
return false;
};
checker
.semantic()
.resolve_qualified_name(&last_decorator.expression)
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["", "property"] | ["functools", "cached_property"]
)
})
}

Copy link
Member

Choose a reason for hiding this comment

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

nice, thanks

@AlexWaygood AlexWaygood changed the title [flake8-return] Exempt cached properties from explicit return rule (RET501) [flake8-return] Exempt cached properties and other property-like decorators from explicit return rule (RET501) Jul 30, 2024
@AlexWaygood AlexWaygood enabled auto-merge (squash) July 30, 2024 11:03
@AlexWaygood AlexWaygood merged commit 459c85b into astral-sh:main Jul 30, 2024
18 checks passed
@epenet epenet deleted the 20240729-0822 branch July 30, 2024 11:12
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