diff --git a/pkgs/development/python-modules/mlxtend/0001-StackingCVClassifier-fit-ensure-compatibility-with-s.patch b/pkgs/development/python-modules/mlxtend/0001-StackingCVClassifier-fit-ensure-compatibility-with-s.patch
new file mode 100644
index 000000000000..2d807ef2c2e0
--- /dev/null
+++ b/pkgs/development/python-modules/mlxtend/0001-StackingCVClassifier-fit-ensure-compatibility-with-s.patch
@@ -0,0 +1,80 @@
+From 1fb59eb42f4bef229b953de313c7e78f0857ea42 Mon Sep 17 00:00:00 2001
+From: Philip Wilk
+Date: Sun, 23 Mar 2025 16:14:51 +0000
+Subject: [PATCH] StackingCVClassifier/fit: ensure compatibility with
+ *scikit-learn* versions 1.4 and above by dynamically selecting between
+ `fit_params` and `params`
+
+---
+ mlxtend/classifier/stacking_cv_classification.py | 5 ++++-
+ mlxtend/regressor/stacking_cv_regression.py | 6 +++++-
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/mlxtend/classifier/stacking_cv_classification.py b/mlxtend/classifier/stacking_cv_classification.py
+index 5bff6907..f4c45b8c 100644
+--- a/mlxtend/classifier/stacking_cv_classification.py
++++ b/mlxtend/classifier/stacking_cv_classification.py
+@@ -15,6 +15,7 @@ from sklearn.base import TransformerMixin, clone
+ from sklearn.model_selection import cross_val_predict
+ from sklearn.model_selection._split import check_cv
+ from sklearn.preprocessing import LabelEncoder
++from sklearn import __version__ as sklearn_version
+
+ from ..externals.estimator_checks import check_is_fitted
+ from ..externals.name_estimators import _name_estimators
+@@ -266,6 +267,8 @@ class StackingCVClassifier(
+ if self.verbose > 1:
+ print(_name_estimators((model,))[0][1])
+
++ param_name = "fit_params" if sklearn_version < "1.4" else "params"
++
+ prediction = cross_val_predict(
+ model,
+ X,
+@@ -273,10 +276,10 @@ class StackingCVClassifier(
+ groups=groups,
+ cv=final_cv,
+ n_jobs=self.n_jobs,
+- fit_params=fit_params,
+ verbose=self.verbose,
+ pre_dispatch=self.pre_dispatch,
+ method="predict_proba" if self.use_probas else "predict",
++ **{param_name: fit_params},
+ )
+
+ if not self.use_probas:
+diff --git a/mlxtend/regressor/stacking_cv_regression.py b/mlxtend/regressor/stacking_cv_regression.py
+index a1faf2ff..d2fb1c49 100644
+--- a/mlxtend/regressor/stacking_cv_regression.py
++++ b/mlxtend/regressor/stacking_cv_regression.py
+@@ -19,6 +19,7 @@ from sklearn.base import RegressorMixin, TransformerMixin, clone
+ from sklearn.model_selection import cross_val_predict
+ from sklearn.model_selection._split import check_cv
+ from sklearn.utils import check_X_y
++from sklearn import __version__ as sklearn_version
+
+ from ..externals.estimator_checks import check_is_fitted
+ from ..externals.name_estimators import _name_estimators
+@@ -211,6 +212,9 @@ class StackingCVRegressor(_BaseXComposition, RegressorMixin, TransformerMixin):
+ fit_params = None
+ else:
+ fit_params = dict(sample_weight=sample_weight)
++
++ param_name = "fit_params" if sklearn_version < "1.4" else "params"
++
+ meta_features = np.column_stack(
+ [
+ cross_val_predict(
+@@ -221,8 +225,8 @@ class StackingCVRegressor(_BaseXComposition, RegressorMixin, TransformerMixin):
+ cv=kfold,
+ verbose=self.verbose,
+ n_jobs=self.n_jobs,
+- fit_params=fit_params,
+ pre_dispatch=self.pre_dispatch,
++ **{param_name: fit_params},
+ )
+ for regr in self.regr_
+ ]
+--
+2.47.1
+
diff --git a/pkgs/development/python-modules/mlxtend/0001-fix-test-replace-np.float_-to-np.float64.patch b/pkgs/development/python-modules/mlxtend/0001-fix-test-replace-np.float_-to-np.float64.patch
deleted file mode 100644
index c196d2bb5035..000000000000
--- a/pkgs/development/python-modules/mlxtend/0001-fix-test-replace-np.float_-to-np.float64.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From 360cb75317aecaf6b9abcf24f0577afef75c464e Mon Sep 17 00:00:00 2001
-From: wxt <3264117476@qq.com>
-Date: Mon, 6 Jan 2025 20:41:27 +0800
-Subject: [PATCH] fix(test): replace np.float_ to np.float64
-
----
- mlxtend/_base/_regressor.py | 2 +-
- mlxtend/_base/tests/test_classifier.py | 2 +-
- mlxtend/_base/tests/test_cluster.py | 2 +-
- mlxtend/classifier/multilayerperceptron.py | 2 +-
- mlxtend/classifier/softmax_regression.py | 2 +-
- mlxtend/math/linalg.py | 2 +-
- mlxtend/plotting/tests/test_decision_regions.py | 2 +-
- 7 files changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/mlxtend/_base/_regressor.py b/mlxtend/_base/_regressor.py
-index e3d0a1d..1d3a5d6 100644
---- a/mlxtend/_base/_regressor.py
-+++ b/mlxtend/_base/_regressor.py
-@@ -16,7 +16,7 @@ class _Regressor(object):
- pass
-
- def _check_target_array(self, y, allowed=None):
-- if not isinstance(y[0], (float, np.float_)):
-+ if not isinstance(y[0], (float, np.float64)):
- raise AttributeError("y must be a float array.\nFound %s" % y.dtype)
-
- def fit(self, X, y, init_params=True):
-diff --git a/mlxtend/_base/tests/test_classifier.py b/mlxtend/_base/tests/test_classifier.py
-index f77f74d..1bbac6d 100644
---- a/mlxtend/_base/tests/test_classifier.py
-+++ b/mlxtend/_base/tests/test_classifier.py
-@@ -51,7 +51,7 @@ def test_check_labels_not_ok_1():
-
-
- def test_check_labels_integer_notok():
-- y = np.array([1.0, 2.0], dtype=np.float_)
-+ y = np.array([1.0, 2.0], dtype=np.float64)
- cl = BlankClassifier(print_progress=0, random_seed=1)
- with pytest.raises(AttributeError) as excinfo:
- cl._check_target_array(y)
-diff --git a/mlxtend/_base/tests/test_cluster.py b/mlxtend/_base/tests/test_cluster.py
-index 6da1a9d..54c2526 100644
---- a/mlxtend/_base/tests/test_cluster.py
-+++ b/mlxtend/_base/tests/test_cluster.py
-@@ -51,7 +51,7 @@ def test_check_labels_not_ok_1():
-
-
- def test_check_labels_integer_notok():
-- y = np.array([1.0, 2.0], dtype=np.float_)
-+ y = np.array([1.0, 2.0], dtype=np.float64)
- cl = BlankClassifier(print_progress=0, random_seed=1)
- with pytest.raises(AttributeError) as excinfo:
- cl._check_target_array(y)
-diff --git a/mlxtend/classifier/multilayerperceptron.py b/mlxtend/classifier/multilayerperceptron.py
-index 770dab9..05416c3 100644
---- a/mlxtend/classifier/multilayerperceptron.py
-+++ b/mlxtend/classifier/multilayerperceptron.py
-@@ -143,7 +143,7 @@ class MultiLayerPerceptron(
- prev_grad_b_out = np.zeros(shape=self.b_["out"].shape)
- prev_grad_w_out = np.zeros(shape=self.w_["out"].shape)
-
-- y_enc = self._one_hot(y=y, n_labels=self.n_classes, dtype=np.float_)
-+ y_enc = self._one_hot(y=y, n_labels=self.n_classes, dtype=np.float64)
-
- self.init_time_ = time()
-
-diff --git a/mlxtend/classifier/softmax_regression.py b/mlxtend/classifier/softmax_regression.py
-index 56444e5..173154e 100644
---- a/mlxtend/classifier/softmax_regression.py
-+++ b/mlxtend/classifier/softmax_regression.py
-@@ -141,7 +141,7 @@ class SoftmaxRegression(_BaseModel, _IterativeModel, _Classifier, _MultiClass):
- )
- self.cost_ = []
-
-- y_enc = self._one_hot(y=y, n_labels=self.n_classes, dtype=np.float_)
-+ y_enc = self._one_hot(y=y, n_labels=self.n_classes, dtype=np.float64)
-
- self.init_time_ = time()
- rgen = np.random.RandomState(self.random_seed)
-diff --git a/mlxtend/math/linalg.py b/mlxtend/math/linalg.py
-index 02600f1..ece4c3c 100644
---- a/mlxtend/math/linalg.py
-+++ b/mlxtend/math/linalg.py
-@@ -45,7 +45,7 @@ def vectorspace_orthonormalization(ary, eps=1e-13): # method='gram-schmidt',
- # 2c) Normalize if linearly independent,
- # and set to zero otherwise
-
-- arr = ary.astype(np.float_).copy()
-+ arr = ary.astype(np.float64).copy()
-
- for i in range(arr.shape[1]):
- for j in range(i):
-diff --git a/mlxtend/plotting/tests/test_decision_regions.py b/mlxtend/plotting/tests/test_decision_regions.py
-index fba2255..aad63ff 100644
---- a/mlxtend/plotting/tests/test_decision_regions.py
-+++ b/mlxtend/plotting/tests/test_decision_regions.py
-@@ -94,7 +94,7 @@ def test_y_int_ary():
- "Try passing the array as y.astype(np.int_)",
- plot_decision_regions,
- X[:, :2],
-- y.astype(np.float_),
-+ y.astype(np.float64),
- sr,
- )
-
---
-2.47.0
-
diff --git a/pkgs/development/python-modules/mlxtend/default.nix b/pkgs/development/python-modules/mlxtend/default.nix
index 87f82295d1e8..db5689580279 100644
--- a/pkgs/development/python-modules/mlxtend/default.nix
+++ b/pkgs/development/python-modules/mlxtend/default.nix
@@ -15,7 +15,7 @@
buildPythonPackage rec {
pname = "mlxtend";
- version = "0.23.3";
+ version = "0.23.4";
pyproject = true;
disabled = isPy27;
@@ -24,7 +24,7 @@ buildPythonPackage rec {
owner = "rasbt";
repo = "mlxtend";
tag = "v${version}";
- hash = "sha256-c6I0dwu4y/Td2G6m2WP/52W4noQUmQMDvpzXA9RZauo=";
+ hash = "sha256-xoAHYRmqN5SrEWlc18ntTZ6WAznBlVZdf+x5Yev3ysE=";
};
build-system = [ setuptools ];
@@ -39,8 +39,8 @@ buildPythonPackage rec {
];
patches = [
- # https://github.com/rasbt/mlxtend/pull/1119
- ./0001-fix-test-replace-np.float_-to-np.float64.patch
+ # https://github.com/rasbt/mlxtend/issues/1117
+ ./0001-StackingCVClassifier-fit-ensure-compatibility-with-s.patch
];
nativeCheckInputs = [ pytestCheckHook ];
@@ -59,6 +59,10 @@ buildPythonPackage rec {
"mlxtend/evaluate/tests/test_feature_importance.py" # urlopen error
"mlxtend/evaluate/tests/test_bias_variance_decomp.py" # keras.api._v2
"mlxtend/evaluate/tests/test_bootstrap_point632.py" # keras.api._v2
+ # Failing tests, most likely an upstream issue. See https://github.com/rasbt/mlxtend/issues/1117
+ "mlxtend/classifier/tests/test_ensemble_vote_classifier.py"
+ "mlxtend/classifier/tests/test_stacking_classifier.py"
+ "mlxtend/classifier/tests/test_stacking_cv_classifier.py"
];
meta = {