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

Issue:
Empty Series is considered `TimestampSeries`
**Describe the bug**

Instantiating an empty `Series` object creates a `TimestamptSeries`, should probably be `Series[Any]`.

**To Reproduce**

```python
from pandas import Series
baz = Series([])
reveal_type(baz)  # pandas.core.series.TimestampSeries
```


**Please complete the following information:**
- pandas                        1.5.3
- pandas-stubs                  1.5.3.230304
Empty Series is considered `TimestampSeries`
**Describe the bug**

Instantiating an empty `Series` object creates a `TimestamptSeries`, should probably be `Series[Any]`.

**To Reproduce**

```python
from pandas import Series
baz = Series([])
reveal_type(baz)  # pandas.core.series.TimestampSeries
```


**Please complete the following information:**
- pandas                        1.5.3
- pandas-stubs                  1.5.3.230304


Discussion / hints:
I'm not sure that this is something that can be fixed.  There is not a way for a type checker to differentiate between an empty list that has no type information, and a list/sequence containing specific types.

@Dr-Irv  Right, but then it should fall back to the most general type `Series[Any]` instead of a highly specialized type `TimestampSeries`.

I think one could fix this by carefully changing the order of the overloads. The problem is that [the first overload of `Series.__new__`](https://github.com/pandas-dev/pandas-stubs/blob/main/pandas-stubs/core/series.pyi) matches an empty Series and returns `TimestampSeries`. If I read https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads correctly, then if the first overload was e.g. of the form `data: Sequence[Scalar] -> Series[Scalar]`, then mypy would correctly impute `Any`.


> I think one could fix this by carefully changing the order of the overloads. The problem is that [the first overload of `Series.__new__`](https://github.com/pandas-dev/pandas-stubs/blob/main/pandas-stubs/core/series.pyi) matches an empty Series and returns `TimestampSeries`. If I read https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads correctly, then if the first overload was e.g. of the form `data: Sequence[Scalar] -> Series[Scalar]`, then mypy would correctly impute `Any`.

The problem with that solution is that we want to have a `Sequence[Timestamp]` match to create `TimestampSeries`, (and similar with the `Timedelta` related types), so we have to use a proper subset of `S1` that doesn't include the other types we want to match inside of sequences.

This might be possible if we split `S1` into two groups, with one group including the types that we don't want to explicitly match.  Not sure - some investigation would be required to get this right.

Empty Sequence can be handled by `Sequence[Never]` in pyright, currently it seems unsupported in mypy: https://github.com/python/mypy/issues/15763

So, one might have to wait for newer version of mypy.
I'm not sure that this is something that can be fixed.  There is not a way for a type checker to differentiate between an empty list that has no type information, and a list/sequence containing specific types.

@Dr-Irv  Right, but then it should fall back to the most general type `Series[Any]` instead of a highly specialized type `TimestampSeries`.

I think one could fix this by carefully changing the order of the overloads. The problem is that [the first overload of `Series.__new__`](https://github.com/pandas-dev/pandas-stubs/blob/main/pandas-stubs/core/series.pyi) matches an empty Series and returns `TimestampSeries`. If I read https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads correctly, then if the first overload was e.g. of the form `data: Sequence[Scalar] -> Series[Scalar]`, then mypy would correctly impute `Any`.


> I think one could fix this by carefully changing the order of the overloads. The problem is that [the first overload of `Series.__new__`](https://github.com/pandas-dev/pandas-stubs/blob/main/pandas-stubs/core/series.pyi) matches an empty Series and returns `TimestampSeries`. If I read https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads correctly, then if the first overload was e.g. of the form `data: Sequence[Scalar] -> Series[Scalar]`, then mypy would correctly impute `Any`.

The problem with that solution is that we want to have a `Sequence[Timestamp]` match to create `TimestampSeries`, (and similar with the `Timedelta` related types), so we have to use a proper subset of `S1` that doesn't include the other types we want to match inside of sequences.

This might be possible if we split `S1` into two groups, with one group including the types that we don't want to explicitly match.  Not sure - some investigation would be required to get this right.

Empty Sequence can be handled by `Sequence[Never]` in pyright, currently it seems unsupported in mypy: https://github.com/python/mypy/issues/15763

So, one might have to wait for newer version of mypy.

Fix patch:
diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi
index 080c6a82..1729d324 100644
--- a/pandas-stubs/core/series.pyi
+++ b/pandas-stubs/core/series.pyi
@@ -241,6 +241,16 @@ class Series(IndexOpsMixin[S1], NDFrame):
         copy: bool = ...,
     ) -> Series[float]: ...
     @overload
+    def __new__(  # type: ignore[overload-overlap]
+        cls,
+        data: Sequence[Never],
+        index: Axes | None = ...,
+        *,
+        dtype: Dtype = ...,
+        name: Hashable = ...,
+        copy: bool = ...,
+    ) -> Series[Any]: ...
+    @overload
     def __new__(
         cls,
         data: (


Test patch:
diff --git a/tests/test_frame.py b/tests/test_frame.py
index bee41a20..5edd0901 100644
--- a/tests/test_frame.py
+++ b/tests/test_frame.py
@@ -7,6 +7,7 @@
     Iterator,
     Mapping,
     MutableMapping,
+    Sequence,
 )
 import csv
 import datetime
@@ -38,6 +39,7 @@
 from pandas.core.series import Series
 import pytest
 from typing_extensions import (
+    Never,
     TypeAlias,
     assert_never,
     assert_type,
@@ -3556,3 +3558,12 @@ class MyDict(TypedDict):
     my_dict = MyDict(a="", b="")
     sr = pd.Series(my_dict)
     check(assert_type(sr, pd.Series), pd.Series)
+
+
+def test_series_empty_dtype() -> None:
+    """Test for the creation of a Series from an empty list GH571 to map to a Series[Any]."""
+    new_tab: Sequence[Never] = []  # need to be typehinted to please mypy
+    check(assert_type(pd.Series(new_tab), "pd.Series[Any]"), pd.Series)
+    check(assert_type(pd.Series([]), "pd.Series[Any]"), pd.Series)
+    # ensure that an empty string does not get matched to Sequence[Never]
+    check(assert_type(pd.Series(""), "pd.Series[str]"), pd.Series)