Repository: scikit-learn/scikit-learn
File: sklearn/utils/estimator_checks.py (Python)

Code before:

            result_xp_np = _convert_to_numpy(result_xp, xp=xp)
            if check_values:
                assert_allclose(
                    result,
                    result_xp_np,
                    err_msg=f"{method} did not the return the same result",
                    atol=_atol_for_type(X.dtype),
                )
            elif hasattr(result, "shape"):
                assert result.shape == result_xp_np.shape
                assert result.dtype == result_xp_np.dtype

        if method_name == "transform" and hasattr(est, "inverse_transform"):
            inverse_result = est.inverse_transform(result)
            with config_context(array_api_dispatch=True):
                inverse_result_xp = est_xp.inverse_transform(result_xp)

            if expect_only_array_outputs:
                with config_context(array_api_dispatch=True):
                    inverse_result_ns = get_namespace(inverse_result_xp)[0].__name__
                assert inverse_result_ns == input_ns, (
                    "'inverse_transform' output is in wrong namespace, expected"
                    f" {input_ns}, got {inverse_result_ns}."
                )
                assert array_device(inverse_result_xp) == array_device(X_xp)

                inverse_result_xp_np = _convert_to_numpy(inverse_result_xp, xp=xp)
                if check_values:
                    assert_allclose(
                        inverse_result,
                        inverse_result_xp_np,
                        err_msg="inverse_transform did not the return the same result",
                        atol=_atol_for_type(X.dtype),
                    )
                elif hasattr(result, "shape"):
                    assert inverse_result.shape == inverse_result_xp_np.shape
                    assert inverse_result.dtype == inverse_result_xp_np.dtype


def check_array_api_input_and_values(
    name,
    estimator_orig,
    array_namespace,
    device=None,
    dtype_name="float64",
    check_sample_weight=False,
):
    return check_array_api_input(
        name,
        estimator_orig,

Review comment (suggestion):
I think you need a `config_context` here otherwise this assert statement will always pass, checking that None == None. This was noted some time ago by Stefanie in https://github.com/scikit-learn/scikit-learn/pull/31814.

Maybe we should do something about it because it's easy to fall into this trap. One potential idea was to add an `assert_same_device` that uses `array_api_compat.device` and does not depend on `config_context(array_api_dispatch=True)` (and a similar assert function like `assert_same_namespace`). Also maybe it would be nice to have a better name than device for our config_context-dependent device function since I find the clash with `array_api_compat.device` a tiny bit confusing.

```suggestion
                with config_context(array_api_dispatch=True):
                    assert array_device(result_xp) == array_device(X_xp)
```

Code after:
                assert array_device(result_xp) == array_device(X_xp)

            result_xp_np = _convert_to_numpy(result_xp, xp=xp)
            if check_values:
                assert_allclose(
                    result,
                    result_xp_np,
                    err_msg=f"{method} did not the return the same result",
                    atol=_atol_for_type(X.dtype),
                )
            elif hasattr(result, "shape"):
                assert result.shape == result_xp_np.shape
                assert result.dtype == result_xp_np.dtype

        if method_name == "transform" and hasattr(est, "inverse_transform"):
            inverse_result = est.inverse_transform(result)
            with config_context(array_api_dispatch=True):
                inverse_result_xp = est_xp.inverse_transform(result_xp)

            if expect_only_array_outputs:
                with config_context(array_api_dispatch=True):
                    inverse_result_ns = get_namespace(inverse_result_xp)[0].__name__
                assert inverse_result_ns == input_ns, (
                    "'inverse_transform' output is in wrong namespace, expected"
                    f" {input_ns}, got {inverse_result_ns}."
                )
                with config_context(array_api_dispatch=True):
                    assert array_device(result_xp) == array_device(X_xp)

                inverse_result_xp_np = _convert_to_numpy(inverse_result_xp, xp=xp)
                if check_values:
                    assert_allclose(
                        inverse_result,
                        inverse_result_xp_np,
                        err_msg="inverse_transform did not the return the same result",
                        atol=_atol_for_type(X.dtype),
                    )
                elif hasattr(result, "shape"):
                    assert inverse_result.shape == inverse_result_xp_np.shape
                    assert inverse_result.dtype == inverse_result_xp_np.dtype


def check_array_api_input_and_values(
    name,
    estimator_orig,
    array_namespace,
    device=None,
    dtype_name="float64",
    check_sample_weight=False,
):
    return check_array_api_input(