Skip to content

Commit

Permalink
Fix: Inaccurate Attribute Listing with dir(obj) (scikit-learn#28558)
Browse files Browse the repository at this point in the history
Inaccurate Attribute Listing with dir(obj) in classes with conditional methods, I overwrote the python method _dir_ in all the classes that contain conditional methods
  • Loading branch information
MiguelParece committed Apr 1, 2024
1 parent 342a7ef commit 2c6b8b3
Show file tree
Hide file tree
Showing 16 changed files with 56 additions and 0 deletions.
3 changes: 3 additions & 0 deletions sklearn/ensemble/_bagging.py
Expand Up @@ -833,6 +833,9 @@ def __init__(
verbose=verbose,
)

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _get_estimator(self):
"""Resolve which estimator to return (default is DecisionTreeClassifier)"""
return self.estimator or DecisionTreeClassifier()
Expand Down
3 changes: 3 additions & 0 deletions sklearn/ensemble/_stacking.py
Expand Up @@ -597,6 +597,9 @@ def __init__(
verbose=verbose,
)

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _validate_final_estimator(self):
self._clone_final_estimator(default=LogisticRegression())
if not is_classifier(self.final_estimator_):
Expand Down
3 changes: 3 additions & 0 deletions sklearn/ensemble/_voting.py
Expand Up @@ -352,6 +352,9 @@ def __init__(
self.flatten_transform = flatten_transform
self.verbose = verbose

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@_fit_context(
# estimators in VotingClassifier.estimators are not validated yet
prefer_skip_nested_validation=False
Expand Down
3 changes: 3 additions & 0 deletions sklearn/feature_selection/_from_model.py
Expand Up @@ -270,6 +270,9 @@ def __init__(
self.norm_order = norm_order
self.max_features = max_features

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _get_support_mask(self):
estimator = getattr(self, "estimator_", self.estimator)
max_features = getattr(self, "max_features_", self.max_features)
Expand Down
3 changes: 3 additions & 0 deletions sklearn/feature_selection/_rfe.py
Expand Up @@ -225,6 +225,9 @@ def __init__(
self.importance_getter = importance_getter
self.verbose = verbose

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@property
def _estimator_type(self):
return self.estimator._estimator_type
Expand Down
3 changes: 3 additions & 0 deletions sklearn/linear_model/_stochastic_gradient.py
Expand Up @@ -1273,6 +1273,9 @@ def __init__(
average=average,
)

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _check_proba(self):
if self.loss not in ("log_loss", "modified_huber"):
raise AttributeError(
Expand Down
3 changes: 3 additions & 0 deletions sklearn/model_selection/_search.py
Expand Up @@ -431,6 +431,9 @@ def __init__(
def _estimator_type(self):
return self.estimator._estimator_type

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _more_tags(self):
# allows cross-validation to see 'precomputed' metrics
return {
Expand Down
9 changes: 9 additions & 0 deletions sklearn/multiclass.py
Expand Up @@ -321,6 +321,9 @@ def __init__(self, estimator, *, n_jobs=None, verbose=0):
self.n_jobs = n_jobs
self.verbose = verbose

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@_fit_context(
# OneVsRestClassifier.estimator is not validated yet
prefer_skip_nested_validation=False
Expand Down Expand Up @@ -752,6 +755,9 @@ def __init__(self, estimator, *, n_jobs=None):
self.estimator = estimator
self.n_jobs = n_jobs

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@_fit_context(
# OneVsOneClassifier.estimator is not validated yet
prefer_skip_nested_validation=False
Expand Down Expand Up @@ -1141,6 +1147,9 @@ def __init__(self, estimator, *, code_size=1.5, random_state=None, n_jobs=None):
self.random_state = random_state
self.n_jobs = n_jobs

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@_fit_context(
# OutputCodeClassifier.estimator is not validated yet
prefer_skip_nested_validation=False
Expand Down
4 changes: 4 additions & 0 deletions sklearn/multioutput.py
Expand Up @@ -409,6 +409,10 @@ class MultiOutputRegressor(RegressorMixin, _MultiOutputEstimator):
def __init__(self, estimator, *, n_jobs=None):
super().__init__(estimator, n_jobs=n_jobs)

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]


@_available_if_estimator_has("partial_fit")
def partial_fit(self, X, y, sample_weight=None, **partial_fit_params):
"""Incrementally fit the model to data, for each output variable.
Expand Down
3 changes: 3 additions & 0 deletions sklearn/neighbors/_lof.py
Expand Up @@ -218,6 +218,9 @@ def __init__(
self.contamination = contamination
self.novelty = novelty

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _check_novelty_fit_predict(self):
if self.novelty:
msg = (
Expand Down
3 changes: 3 additions & 0 deletions sklearn/neural_network/_multilayer_perceptron.py
Expand Up @@ -150,6 +150,9 @@ def __init__(
self.n_iter_no_change = n_iter_no_change
self.max_fun = max_fun

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _unpack(self, packed_parameters):
"""Extract the coefficients and intercepts from packed_parameters."""
for i in range(self.n_layers_ - 1):
Expand Down
4 changes: 4 additions & 0 deletions sklearn/pipeline.py
Expand Up @@ -2,6 +2,7 @@
The :mod:`sklearn.pipeline` module implements utilities to build a composite
estimator, as a chain of transforms and estimators.
"""

# Author: Edouard Duchesnay
# Gael Varoquaux
# Virgile Fritsch
Expand Down Expand Up @@ -170,6 +171,9 @@ def __init__(self, steps, *, memory=None, verbose=False):
self.memory = memory
self.verbose = verbose

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def set_output(self, *, transform=None):
"""Set the output container when `"transform"` and `"fit_transform"` are called.
Expand Down
3 changes: 3 additions & 0 deletions sklearn/preprocessing/_function_transformer.py
Expand Up @@ -185,6 +185,9 @@ def __init__(
self.kw_args = kw_args
self.inv_kw_args = inv_kw_args

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _check_input(self, X, *, reset):
if self.validate:
return self._validate_data(X, accept_sparse=self.accept_sparse, reset=reset)
Expand Down
3 changes: 3 additions & 0 deletions sklearn/semi_supervised/_self_training.py
Expand Up @@ -184,6 +184,9 @@ def __init__(
self.max_iter = max_iter
self.verbose = verbose

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

@_fit_context(
# SelfTrainingClassifier.base_estimator is not validated yet
prefer_skip_nested_validation=False
Expand Down
3 changes: 3 additions & 0 deletions sklearn/svm/_base.py
Expand Up @@ -734,6 +734,9 @@ def __init__(
random_state=random_state,
)

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def _validate_targets(self, y):
y_ = column_or_1d(y, warn=True)
check_classification_targets(y)
Expand Down
3 changes: 3 additions & 0 deletions sklearn/utils/_mocking.py
Expand Up @@ -383,6 +383,9 @@ class _MockEstimatorOnOffPrediction(BaseEstimator):
def __init__(self, response_methods=None):
self.response_methods = response_methods

def __dir__(self):
return [attr for attr in super().__dir__() if hasattr(self, attr)]

def fit(self, X, y):
self.classes_ = np.unique(y)
return self
Expand Down

0 comments on commit 2c6b8b3

Please sign in to comment.