Talip7/scikit-learn-issues-multilabel huggingface dataset:
Enabling array API dispatch causes pipelines to reject dataframe inputs

### Describe the bug

Enabling the array API dispatch has a negative side effect on code that usually accepts non-array inputs such as pandas dataframes:

### Steps/Code to Reproduce

```python
# %%
import os
os.environ["SCIPY_ARRAY_API"] = "1"

# %%
import sklearn
from sklearn.datasets import fetch_openml
from sklearn.preprocessing import OneHotEncoder


adult = fetch_openml(name="adult", version=2, as_frame=True)
X, y = adult.data, adult.target

with sklearn.config_context(array_api_dispatch=True):
    OneHotEncoder().fit(
        X.select_dtypes(include=["category", "object"])
    )
```

### Expected Results

The enabling of array API should not affect the estimator behavior on dataframe inputs.

### Actual Results

```python
Traceback (most recent call last):

  Cell In[11], [line 11](vscode-notebook-cell:?execution_count=11&line=11)
    OneHotEncoder().fit(

  File ~/code/scikit-learn/sklearn/base.py:1336 in wrapper
    return fit_method(estimator, *args, **kwargs)

  File ~/code/scikit-learn/sklearn/preprocessing/_encoders.py:999 in fit
    self._fit(

  File ~/code/scikit-learn/sklearn/preprocessing/_encoders.py:86 in _fit
    X_list, n_samples, n_features = self._check_X(

  File ~/code/scikit-learn/sklearn/preprocessing/_encoders.py:69 in _check_X
    Xi = check_array(

  File ~/code/scikit-learn/sklearn/utils/validation.py:858 in check_array
    xp, is_array_api_compliant = get_namespace(array)

  File ~/code/scikit-learn/sklearn/utils/_array_api.py:404 in get_namespace
    namespace, is_array_api_compliant = array_api_compat.get_namespace(*arrays), True

  File ~/code/scikit-learn/sklearn/externals/array_api_compat/common/_helpers.py:643 in array_namespace
    raise TypeError(f"{type(x).__name__} is not a supported array type")

TypeError: Series is not a supported array type
```

### Versions

```shell
System:
    python: 3.13.7 | packaged by conda-forge | (main, Sep  3 2025, 14:24:46) [Clang 19.1.7 ]
executable: /Users/ogrisel/miniforge3/envs/dev/bin/python
   machine: macOS-15.6.1-arm64-arm-64bit-Mach-O

Python dependencies:
      sklearn: 1.9.dev0
          pip: 25.2
   setuptools: 80.9.0
        numpy: 2.3.3
        scipy: 1.16.3
       Cython: 3.1.4
       pandas: 3.0.0.dev0+2566.g2bb3fef887
   matplotlib: 3.10.6
       joblib: 1.5.2
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 10
         prefix: libopenblas
       filepath: /Users/ogrisel/miniforge3/envs/dev/lib/libopenblas.0.dylib
        version: 0.3.30
threading_layer: openmp
   architecture: VORTEX

       user_api: openmp
   internal_api: openmp
    num_threads: 10
         prefix: libomp
       filepath: /Users/ogrisel/miniforge3/envs/dev/lib/libomp.dylib
        version: None
```

COMMENT:
`#RHJITDD` aka Release Highlights Just-In-Time Driven Development 😉

Labels: Bug, Array API
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
By what do you want to replace the repeated `<style></style>` blocks? We still need to add those CSS to the DOM. In a jupyter notebook, the DOM is incrementally built when adding new cells. We don't know ahead of time that the user will import `sklearn` and display estimators in his/her notebook. So we cannot tell ahead of time jupyterlab or VS Code to include a static CSS file in the headers section of the page.

I see no alternative to inline style blocks, given the dynamic nature of notebooks in interactive programming environments.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
> I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know.

I am not sure I understand what changed. Can you open a draft PR so that we can see the diff?

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
I mean that we could add the `<style></style>` blocks only once with `estimator.py`. I didn't mean in the header section. My main point was that I fail to see the purpose of the dynamic selectors on `estimator.css`. If that isn't needed, the file can be loaded only once if we use a cache. 

I'll open a draft PR, it will be easier.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
> I mean that we could add the <style></style> blocks only once with estimator.py.

But how does scikit-learn can know that a previous call to `estimator_html_repr` has already been included in a user facing DOM tree or not?

There might be a single Python program that executes several notebook files (e.g. `nbconvert`) and it's hard to know whether individual calls to `estimator_html_repr` are redundant or not.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
The fundamental problem is that `estimator_html_repr` does not have access to inspect the to target HTML document: it cannot know if other estimators HTML snippets have already been included in the target HTML doc or not.

EDIT: furthermore, when we run interactive Python code with Jupyter notebooks or VS Code, the Python code is executed within an ipykernel process. As far as I know, this Python process has no awareness on whether its output will be included in an HTML document object tree or not and if several consecutive cell executions stem from the same HTML document object tree or from several independent documents. I think the designers of the Jupyter kernel protocol decided to make the kernel execution completely decoupled from the rendering of the previously executed cells by design. I think this is a fundamental limitation of the jupyter protocol.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
OK, but if the css rules don't change for each estimator, maybe we don't need a dynamic selector. At least getting rid of the Template and substitution may improve a bit? Opened a draft PR.

For the rest - the repeated <style></style> I was overlooking stuff. I was thinking that I could use `lru_cache` for example, not reading from HTML. But I guess not.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
Just to be clear: I do understand the need of several styling blocks. 
My PR only touches CSS logic.

Labels: RFC
RFC: Potential improvement of HTML Display's css logic

I propose to remove repetition of CSS styling in `sklearn/utils/_repr_html/estimator.py`.

Every time that a cell in a jupyter notebook (or similar) uses the HTML display method, a new CSS block is added to the DOM. This happens in [`estimator_html_repr`](https://github.com/scikit-learn/scikit-learn/blob/4a10d0ed8d85e6ed24a647bd28a65c0c64b101ef/sklearn/utils/_repr_html/estimator.py#L448C5-L472C66).

But CSS is static and the styling rules don't change between estimators. That means that the `#$` in the css file [`estimator.css`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_repr_html/estimator.css) is not needed I think.  ~~And we could cache the css file so it's loaded and added to the DOM only once.~~

This way we improve performance by avoiding:

~~- DOM bloat with many duplicate CSS rules.~~
~~- Browser memory waste.~~
~~- Less parsing overhead by the browser (browser processing several times identical styles).~~
- Repeated template substitution through string processing in `estimator.py`.

~~The same thing happens with the javascript script, it is added to the DOM with each cell that uses a HTML display. But the script could be added just once at the bottom of the DOM.~~

Note: the container id in `estimator.py` is still needed as it is used by javascript - It's used to construct the fully qualified name of parameters. But I would add a new class name (to this file) because we still need a CSS selector in `estimator.css`.

I have done local tests that seem to work. If I am missing something about the purpose of multiple CSS blocks, I would love to know. 

WDYT?
@Charlie-XIAO @glemaitre (or anybody) 

Edit: crossing out points above, but keeping the last one. 

<details>
<summary> Screenshot showing issue</summary>
One can see that for each estimator, there is styling and a script.
<img width="1344" height="964" alt="Image" src="https://github.com/user-attachments/assets/ea30c328-42c2-4679-9d72-74a925dd0434"/>
</details>

COMMENT:
Hi, I’ve gone through the discussion and my understanding is that the main concern is repeated <style> and JS blocks being injected by estimator_html_repr for every estimator display, which could cause DOM bloat and repeated parsing. The CSS is static, so it could be injected only once, but the container ID is still needed for JS functionality. 

I would like to help, could you clarify what kind of change or solution you’re looking for?

Labels: RFC