From 69a17d51141bd2457142c8309f57494ab2d97562 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Tue, 20 Feb 2024 22:34:22 +0800 Subject: [PATCH] Fix with None input. (#10052) --- python-package/xgboost/core.py | 19 ++++++++++--------- python-package/xgboost/data.py | 4 ++-- tests/python-gpu/test_from_cupy.py | 5 ++++- tests/python/test_with_sklearn.py | 13 +++++++++++++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/python-package/xgboost/core.py b/python-package/xgboost/core.py index 27331d3de..f19078224 100644 --- a/python-package/xgboost/core.py +++ b/python-package/xgboost/core.py @@ -861,9 +861,9 @@ class DMatrix: # pylint: disable=too-many-instance-attributes,too-many-public-m self.nthread = nthread if nthread is not None else -1 self.silent = silent - # force into void_p, mac need to pass things in as void_p - if data is None: - self.handle: Optional[ctypes.c_void_p] = None + if isinstance(data, ctypes.c_void_p): + # Used for constructing DMatrix slice. + self.handle = data return from .data import _is_iter, dispatch_data_backend @@ -925,9 +925,10 @@ class DMatrix: # pylint: disable=too-many-instance-attributes,too-many-public-m self.handle = handle def __del__(self) -> None: - if hasattr(self, "handle") and self.handle: + if hasattr(self, "handle"): + assert self.handle is not None _check_call(_LIB.XGDMatrixFree(self.handle)) - self.handle = None + del self.handle @_deprecate_positional_args def set_info( @@ -1281,19 +1282,19 @@ class DMatrix: # pylint: disable=too-many-instance-attributes,too-many-public-m """ from .data import _maybe_np_slice - res = DMatrix(None) - res.handle = ctypes.c_void_p() + handle = ctypes.c_void_p() + rindex = _maybe_np_slice(rindex, dtype=np.int32) _check_call( _LIB.XGDMatrixSliceDMatrixEx( self.handle, c_array(ctypes.c_int, rindex), c_bst_ulong(len(rindex)), - ctypes.byref(res.handle), + ctypes.byref(handle), ctypes.c_int(1 if allow_groups else 0), ) ) - return res + return DMatrix(handle) @property def feature_names(self) -> Optional[FeatureNames]: diff --git a/python-package/xgboost/data.py b/python-package/xgboost/data.py index 49a0f43b7..07a08dc5f 100644 --- a/python-package/xgboost/data.py +++ b/python-package/xgboost/data.py @@ -1053,10 +1053,10 @@ def _is_dlpack(data: DataType) -> bool: def _transform_dlpack(data: DataType) -> bool: - from cupy import fromDlpack # pylint: disable=E0401 + from cupy import from_dlpack # pylint: disable=E0401 assert "used_dltensor" not in str(data) - data = fromDlpack(data) + data = from_dlpack(data) return data diff --git a/tests/python-gpu/test_from_cupy.py b/tests/python-gpu/test_from_cupy.py index 79814a1bb..85d54c78d 100644 --- a/tests/python-gpu/test_from_cupy.py +++ b/tests/python-gpu/test_from_cupy.py @@ -202,7 +202,10 @@ class TestFromCupy: n = 100 X = cp.random.random((n, 2)) m = xgb.QuantileDMatrix(X.toDlpack()) - with pytest.raises(xgb.core.XGBoostError): + + with pytest.raises( + xgb.core.XGBoostError, match="Slicing DMatrix is not supported" + ): m.slice(rindex=[0, 1, 2]) @pytest.mark.skipif(**tm.no_cupy()) diff --git a/tests/python/test_with_sklearn.py b/tests/python/test_with_sklearn.py index 344628e4f..ede70bb8b 100644 --- a/tests/python/test_with_sklearn.py +++ b/tests/python/test_with_sklearn.py @@ -1456,3 +1456,16 @@ def test_intercept() -> None: result = reg.intercept_ assert result.dtype == np.float32 assert result[0] < 0.5 + + +def test_fit_none() -> None: + with pytest.raises(TypeError, match="NoneType"): + xgb.XGBClassifier().fit(None, [0, 1]) + + X = rng.normal(size=4).reshape(2, 2) + + with pytest.raises(ValueError, match="Invalid classes"): + xgb.XGBClassifier().fit(X, None) + + with pytest.raises(ValueError, match="labels"): + xgb.XGBRegressor().fit(X, None)