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

Code before:
        Types to ignore in the arrays.

    Returns
    -------
    filtered_arrays : list
        List of arrays filtered as requested. An empty list is returned if no input
        passes the filters.
    """
    filtered_arrays = []
    remove_types = tuple(remove_types)
    for array in arrays:
        if remove_none and array is None:
            continue
        if isinstance(array, remove_types):
            continue
        if sp.issparse(array):
            continue
        filtered_arrays.append(array)

    return filtered_arrays


def _unwrap_memoryviewslices(*arrays):
    unwrapped = []
    for a in arrays:
        a_type = type(a)
        if (
            a_type.__module__ == "_cyutility"
            and a_type.__name__ == "_memoryviewslice"
            and hasattr(a, "base")
        ):
            a = a.base
        unwrapped.append(a)
    return unwrapped


def get_namespace(
    *arrays, remove_none=True, remove_types=REMOVE_TYPES_DEFAULT, xp=None
):
    """Get namespace of arrays.

    Introspect `arrays` arguments and return their common Array API compatible
    namespace object, if any.

    Note that sparse arrays are filtered by default.

    See: https://numpy.org/neps/nep-0047-array-api-standard.html

    If `arrays` are regular numpy arrays, `array_api_compat.numpy` is returned instead.

    Namespace support is not enabled by default. To enabled it call:

Review comment (refactor):
I think we could make the motivation behind this hackery a bit more explicit with an inline comment. Let's wait for the CI to complete before accepting this suggestion.

```suggestion
def _unwrap_memoryviewslices(*arrays):
    # Since _cyutility._memoryviewslice is an implementation detail of the
    # Cython runtime, we would rather not introduce a possibly brittle
    # import statement to run `isinstance`-based filtering, hence the
    # attribute-based type inspection.
```

Code after:
    remove_types : tuple or list, default=(str, list, tuple)
        Types to ignore in the arrays.

    Returns
    -------
    filtered_arrays : list
        List of arrays filtered as requested. An empty list is returned if no input
        passes the filters.
    """
    filtered_arrays = []
    remove_types = tuple(remove_types)
    for array in arrays:
        if remove_none and array is None:
            continue
        if isinstance(array, remove_types):
            continue
        if sp.issparse(array):
            continue
        if is_df_or_series(array):
            continue
        filtered_arrays.append(array)

    return filtered_arrays


def _unwrap_memoryviewslices(*arrays):
    # Since _cyutility._memoryviewslice is an implementation detail of the
    # Cython runtime, we would rather not introduce a possibly brittle
    # import statement to run `isinstance`-based filtering, hence the
    # attribute-based type inspection.
    unwrapped = []
    for a in arrays:
        a_type = type(a)
        if (
            a_type.__module__ == "_cyutility"
            and a_type.__name__ == "_memoryviewslice"
            and hasattr(a, "base")
        ):
            a = a.base
        unwrapped.append(a)
    return unwrapped


def get_namespace(
    *arrays, remove_none=True, remove_types=REMOVE_TYPES_DEFAULT, xp=None
):
    """Get namespace of arrays.

    Introspect `arrays` arguments and return their common Array API compatible
    namespace object, if any.