Repository: pandas-dev/pandas-stubs (language: python)

Issue:
read_excel/index_col: string not accepted
Either the documentation or the type hint for index_col in pandas.read_excel is wrong.

The documentation says a string may be used.

The type hint forbids that

Documentation:
index_col     int, **str**, list of int, default None

Type hints:
`index_col: int | Sequence[int] | None = ...,`
read_excel/index_col: string not accepted
Either the documentation or the type hint for index_col in pandas.read_excel is wrong.

The documentation says a string may be used.

The type hint forbids that

Documentation:
index_col     int, **str**, list of int, default None

Type hints:
`index_col: int | Sequence[int] | None = ...,`


Discussion / hints:
Looking internally at the pandas source, I think the docs may be wrong.  Inside of pandas, `index_col` is typed without allowing `str` as an arg type.

If you can produce an example where `read_excel()` accepts a string (and maybe a list of strings??) as an argument for `index_col`, then updates should be made to the internal pandas source and the type hints.

Conversely, if a string doesn't work as the argument, then an issue should be raised in the pandas repo.

Can you provide an appropriate test (either way)?

```python
from pandas import read_excel
print(read_excel("Book1.xlsx"))
print(read_excel("Book1.xlsx", index_col="bar"))
```

Output:
```
   foo  bar
0    1    2
1    3    4
     foo
bar     
2      1
4      3
```

[Book1.xlsx](https://github.com/pandas-dev/pandas-stubs/files/13264037/Book1.xlsx)
Thanks for the example. I created an issue for the pandas source to fix the typing there. 

In the meantime, a fix here would be welcome, along with appropriate tests.
Looking internally at the pandas source, I think the docs may be wrong.  Inside of pandas, `index_col` is typed without allowing `str` as an arg type.

If you can produce an example where `read_excel()` accepts a string (and maybe a list of strings??) as an argument for `index_col`, then updates should be made to the internal pandas source and the type hints.

Conversely, if a string doesn't work as the argument, then an issue should be raised in the pandas repo.

Can you provide an appropriate test (either way)?

```python
from pandas import read_excel
print(read_excel("Book1.xlsx"))
print(read_excel("Book1.xlsx", index_col="bar"))
```

Output:
```
   foo  bar
0    1    2
1    3    4
     foo
bar     
2      1
4      3
```

[Book1.xlsx](https://github.com/pandas-dev/pandas-stubs/files/13264037/Book1.xlsx)
Thanks for the example. I created an issue for the pandas source to fix the typing there. 

In the meantime, a fix here would be welcome, along with appropriate tests.

Fix patch:
diff --git a/pandas-stubs/io/excel/_base.pyi b/pandas-stubs/io/excel/_base.pyi
index a3368d2e..5937fa5f 100644
--- a/pandas-stubs/io/excel/_base.pyi
+++ b/pandas-stubs/io/excel/_base.pyi
@@ -49,7 +49,7 @@ def read_excel(
     *,
     header: int | Sequence[int] | None = ...,
     names: ListLikeHashable | None = ...,
-    index_col: int | Sequence[int] | None = ...,
+    index_col: int | Sequence[int] | str | None = ...,
     usecols: str | UsecolsArgType = ...,
     dtype: str | Dtype | Mapping[str, str | Dtype] | None = ...,
     engine: ExcelReadEngine | None = ...,
@@ -91,7 +91,7 @@ def read_excel(
     *,
     header: int | Sequence[int] | None = ...,
     names: ListLikeHashable | None = ...,
-    index_col: int | Sequence[int] | None = ...,
+    index_col: int | Sequence[int] | str | None = ...,
     usecols: str | UsecolsArgType = ...,
     dtype: str | Dtype | Mapping[str, str | Dtype] | None = ...,
     engine: ExcelReadEngine | None = ...,
@@ -134,7 +134,7 @@ def read_excel(  # type: ignore[misc]
     *,
     header: int | Sequence[int] | None = ...,
     names: ListLikeHashable | None = ...,
-    index_col: int | Sequence[int] | None = ...,
+    index_col: int | Sequence[int] | str | None = ...,
     usecols: str | UsecolsArgType = ...,
     dtype: str | Dtype | Mapping[str, str | Dtype] | None = ...,
     engine: ExcelReadEngine | None = ...,
@@ -176,7 +176,7 @@ def read_excel(
     *,
     header: int | Sequence[int] | None = ...,
     names: ListLikeHashable | None = ...,
-    index_col: int | Sequence[int] | None = ...,
+    index_col: int | Sequence[int] | str | None = ...,
     usecols: str | UsecolsArgType = ...,
     dtype: str | Dtype | Mapping[str, str | Dtype] | None = ...,
     engine: ExcelReadEngine | None = ...,


Test patch:
diff --git a/tests/test_io.py b/tests/test_io.py
index df2b8480..b0301718 100644
--- a/tests/test_io.py
+++ b/tests/test_io.py
@@ -1558,3 +1558,21 @@ def test_added_date_format() -> None:
             ),
             pd.DataFrame,
         )
+
+
+def test_read_excel_index_col() -> None:
+    with ensure_clean(".xlsx") as path:
+        pd.DataFrame(
+            data={
+                "foo": [1, 3],
+                "bar": [2, 4],
+            }
+        ).to_excel(path)
+
+        check(
+            assert_type(
+                pd.read_excel(path, index_col="bar"),
+                pd.DataFrame,
+            ),
+            pd.DataFrame,
+        )