Rubem Pacelli
Rubem Pacelli

Reputation: 201

`mypy` doesn't allow unpacking

Consider the following

from datetime import datetime

def tle_request(date_time: list[int]) -> datetime:
    # Attempting to create a datetime object using unpacking
    general_date: datetime = datetime(*date_time[:3])  # This causes a mypy error
    return general_date

# Example usage
my_time = tle_request([2023, 9, 27])
print(f"Hello {my_time}")

Although it works:

❯ python main.py
Hello 2023-09-27 00:00:00

mypy is prompting the following error:

❯ mypy main.py
main.py:5: error: Argument 1 to "datetime" has incompatible type "*list[int]"; expected "tzinfo | None"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

That is very weird because if I change datetime(*date_time[:3]) with datetime(date_time[0], date_time[1], date_time[2]). I works:

❯ mypy main.py
Success: no issues found in 1 source file

Why? Unpacking is really necessary and I see no reason for mypy to complain about it.

Upvotes: 2

Views: 228

Answers (1)

dROOOze
dROOOze

Reputation: 3608

Have a look at the signature of datetime.datetime.__new__:

    def __new__(
        cls,
        year: SupportsIndex,
        month: SupportsIndex,
        day: SupportsIndex,
        hour: SupportsIndex = ...,
        minute: SupportsIndex = ...,
        second: SupportsIndex = ...,
        microsecond: SupportsIndex = ...,
        tzinfo: _TzInfo | None = ...,  # Expected "tzinfo | None"
        *,
        fold: int = ...,
    ) -> Self: ...

mypy does not know the size of your list[int], so the best guess it does in this situation is to fill all the arguments to __new__ with int. The last positional parameter of __new__ is not allowed to be an int, which is what mypy is warning you of.

Using list[int] with an unpacking operation here simply won't work for static typing purposes - if you want to use unpacking, use a tuple:

def tle_request(date_time: tuple[int, int, int]) -> datetime: ...

Upvotes: 4

Related Questions