8000 Wrong type annotation for `pydantic_core.TzInfo(0)` · Issue #1605 · pydantic/pydantic-core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Wrong type annotation for pydantic_core.TzInfo(0) #1605
Closed
@barisione

Description

@barisione

This code (only the first part is relevant to the bug, the second part with MyTzInfo shows why this happens):

import datetime

import pydantic_core


# Mypy complains:
#   Too many arguments for "TzInfo"  [call-arg]
# But running the code works and prints "UTC".
print(pydantic_core.TzInfo(0))

# Mypy is happy with this, but running the code results in:
#   TypeError: TzInfo.__new__() missing 1 required positional argument: 'seconds'
try:
    print(pydantic_core.TzInfo())
except TypeError as exc:
    print(f"Got error as expected: {exc}")
else:
    raise AssertionError("Expected TypeError")


class MyTzInfo(datetime.tzinfo):
    def tzname(self, dt: datetime.datetime | None) -> str:
        return "Fake timezone"

    def utcoffset(self, dt: datetime.datetime | None) -> datetime.timedelta:
        return datetime.timedelta(seconds=42)

    def dst(self, dt: datetime.datetime | None) -> datetime.timedelta:
        return datetime.timedelta(seconds=0)

    def __repr__(self) -> str:
        return f"MyTzInfo: {self.tzname(None)}"


# Mypy compains with this as well, but running the code works as `datetime.tzinfo` ignores its
# arguments.
print(MyTzInfo())
print(MyTzInfo(0))
print(MyTzInfo(0, "foo", 42))

Produces this output:

UTC
Got error as expected: TzInfo.__new__() missing 1 required positional argument: 'seconds'
MyTzInfo: Fake timezone
MyTzInfo: Fake timezone
MyTzInfo: Fake timezone

The problem is that datetime.tzinfo ignores any argument passed to it, but it's annotated in typeshed as not accepting any argument.

In pydantic_core, the interface for TzInfo is defined as a final class TzInfo(datetime.tzinfo) which doesn't have an __init__, so mypy assumes it doesn't accept arguments. On the other hand, the implementation requires the number of seconds.

I'm using the most recent version of pydantic and mypy from PyPi:

$ pip show mypy
Name: mypy
Version: 1.14.1
Summary: Optional static typing for Python
Home-page:
Author:
Author-email: Jukka Lehtosalo <jukka.lehtosalo@iki.fi>
License: MIT
Location: /Users/bari/.pyenv/versions/3.10.1/envs/tmp3.10/lib/python3.10/site-packages
Requires: typing_extensions, mypy_extensions, tomli
Required-by:

$ pip show pydantic_core
Name: pydantic_core
Version: 2.27.2
Summary: Core functionality for Pydantic validation and serialization
Home-page: https://github.com/pydantic/pydantic-core
Author:
Author-email: Samuel Colvin <s@muelcolvin.com>
License: MIT
Location: /Users/bari/.pyenv/versions/3.10.1/envs/tmp3.10/lib/python3.10/site-packages
Requires: typing-extensions
Required-by: pydantic

Note that, in practice, I don't need to use pydantic.TzInfo in my production code. I'm only using it in some unit tests as my code previously tripped up when dealing with pydantic converting Python's native datetime.timezone.utc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0