microsoft / pyright

Static Type Checker for Python
Other
12.7k stars 1.35k forks source link

Dataclass ConfigDict `frozen` doesn't work as expected #8308

Closed gregbrowndev closed 1 week ago

gregbrowndev commented 1 week ago

Describe the bug

There are two apparent ways to make a dataclass frozen. Coming from using ordinary class-based Pydantic models to dataclass-based ones, I found myself providing ConfigDict(frozen=True) to the dataclass decorator. However, this doesn't work with dataclasses, instead you have to provide this argument to the decorator.

This could be made clearer in the docs, one of the arguments could be removed (pref the ConfigDict one), or the dataclass could default to either of which is set (would be a problem if both were set to opposite values).

Cheers!

Code or Screenshots

Throws error:

from pydantic import ConfigDict
from pydantic.dataclasses import dataclass

@dataclass(config=ConfigDict(frozen=True))
class Location:
    latitude: float
    longitude: float

location = Location(latitude=0, longitude=0)
hash(location)
# TypeError: unhashable type: 'Location'

Works:

from pydantic.dataclasses import dataclass

@dataclass(frozen=True)
class Location:
    latitude: float
    longitude: float

location = Location(latitude=0, longitude=0)
hash(location)
# -8458139203682520985
erictraut commented 1 week ago

Pyright has no knowledge of pydantic or any other behaviors specific to third-party libraries. The ConfigDict behavior is specific to pydantic, and it is a non-standard behavior (i.e. it deviates from the mechanisms used in the stdlib dataclass library). Standards-compliant type checkers like pyright therefore do not support this behavior. If you're interested in documentation for the behavior that pyright supports, refer to the dataclass section of the Python typing spec.

gregbrowndev commented 1 week ago

Sorry, I submitted this in completely the wrong place 🤦🏻