Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

adrinjalali
Copy link
Member

If a class implements a set_{method}_request explicitly (like done in scorers), then the descriptor shouldn't be overriding it.

xref: #30859 (comment)

cc @antoinebaker @OmarManzoor

This fixes some existing issues. The added tests should represent where things were failing.

adrinjalali and others added 30 commits June 12, 2025 15:03
Co-authored-by: Stefanie Senger <[email protected]>
Copy link

github-actions bot commented Sep 5, 2025

✔️ Linting Passed

All linting checks passed. Your pull request is in excellent shape! ☀️

Generated for commit: 72132e1. Link to the linter CI: here

# metadata with an UNUSED marker, and that the parent class has
# the method already. In this case, we cannot remove the method
# since it exists in the parent class, and instead we set it with
# an empty set of requests.
Copy link
Contributor

Choose a reason for hiding this comment

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

Aren't we simply not setting any RequestMethod for such cases instead of an empty set of requests?

Copy link
Member Author

Choose a reason for hiding this comment

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

The issue is "not setting a RequestMethod" means we inherit the one from the parent class, which in the case of LogisticRegressionCV means having one accepting a sample_weight

Copy link
Contributor

Choose a reason for hiding this comment

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

So we need to set one but with empty requests?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, exactly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then shouldn't we be setting requests = dict() in this branch rather than simply continuing the loop?

Copy link
Member Author

Choose a reason for hiding this comment

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

This branch has not hasattr(cls, set_method_name), otherwise we don't come here

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it.

Copy link
Member

Choose a reason for hiding this comment

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

I think the comment is a bit misleading, since it talks about the reason to add the not hasattr(cls, set_method_name) condition into the code compared to before rather than about the whole condition.

Copy link
Contributor

@OmarManzoor OmarManzoor 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 @adrinjalali

Copy link
Member

@StefanieSenger StefanieSenger left a comment

Choose a reason for hiding this comment

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

Thanks, @adrinjalali!

I have checked the rendered docs and built locally, but I don’t see that LogisticRegressionCV.set_score_request() has a different docstring compared to before. Maybe I misunderstand the PR, but I cannot see how the def set_score_request() in _BaseScorer would be prevented from being overridden while a CV meta-estimator is defined, since there is no inheritance between those two.
And searching the repo, _BaseScorer is the only place that defines their own set_score_request.

Is this PR rather for third party libraries?

I also suggested a few documentation improvements.

Comment on lines +1452 to +1454
def is_RequestMethod(obj, name: str):
value = inspect.getattr_static(obj, name)
return isinstance(value, RequestMethod)
Copy link
Member

Choose a reason for hiding this comment

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

Structurally, is_RequestMethod is a bit similar to defines_get_metadata_routing from #31695. Both check whether an estimator defines something itself or inherits it and feel like workarounds for going through MROs.
For maintainability, do you think we could reduce some of these MRO iterations (for instance via class methods, as you mentioned once)?

try:
for method in SIMPLE_METHODS:
set_method_name = f"set_{method}_request"
Copy link
Member

Choose a reason for hiding this comment

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

set_method_name could be called set_method_request as a more intuitive variable name.

# metadata with an UNUSED marker, and that the parent class has
# the method already. In this case, we cannot remove the method
# since it exists in the parent class, and instead we set it with
# an empty set of requests.
Copy link
Member

Choose a reason for hiding this comment

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

I think the comment is a bit misleading, since it talks about the reason to add the not hasattr(cls, set_method_name) condition into the code compared to before rather than about the whole condition.

Comment on lines +1463 to +1467
# The method is not a descriptor, which means it's explicitly
# defined in the class, therefore we skip overriding it with a
# descriptor here.
# This happens, for instance in Scorers where the
# `set_score_request` method is defined in the class.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# The method is not a descriptor, which means it's explicitly
# defined in the class, therefore we skip overriding it with a
# descriptor here.
# This happens, for instance in Scorers where the
# `set_score_request` method is defined in the class.
# `set_method_name` is not a `RequestMethod` so we skip
# overriding it. For example, in Scorers the `set_score_request`
# method is explicitly defined in the class.

Maybe a bit more straightforward?

@@ -1438,14 +1448,35 @@ def __init_subclass__(cls, **kwargs):
----------
.. [1] https://www.python.org/dev/peps/pep-0487
"""

def is_RequestMethod(obj, name: str):
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def is_RequestMethod(obj, name: str):
def _is_RequestMethod(obj, method_name: str):
# Check if a method is a descriptor.

I think it would be a private method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants