Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

attr.Attributes incompatible with Literal #1207

Open
Why-not-now opened this issue Nov 25, 2023 · 3 comments
Open

attr.Attributes incompatible with Literal #1207

Why-not-now opened this issue Nov 25, 2023 · 3 comments
Assignees
Labels
Typing Typing/stub/Mypy/PyRight related bugs.

Comments

@Why-not-now
Copy link
Contributor

Because attr.Attributes causes the type it contains to be invariant, Literal types like Literal[1] to be incompatible with attr.Attributes[int]

from __future__ import annotations

from attr import Attribute
from attrs import define, field


def _check(self, attribute: Attribute[int], value: int):
    print(type(attribute))
    if value > 42:
        msg = "x must be smaller or equal to 42"
        raise ValueError(msg)


def trick_type_hinter() -> int:
    return 1

a = trick_type_hinter()

@define
class LiteralDefault:
    x: int = field(default=1, validator=_check)

@define
class LiteralFactory:
    x: int = field(factory=lambda: 1, validator=_check)

@define
class CustomDefault:
    x: int = field(default=a, validator=_check)

@define
class CustomFactory:
    x: int = field(factory=lambda: a, validator=_check)

LiteralDefault error:

  Type "(self: Unknown, attribute: Attribute[int], value: int) -> None" cannot be assigned to type "_ValidatorArgType[_T@field] | None"
    Type "(self: Unknown, attribute: Attribute[int], value: int) -> None" cannot be assigned to type "(Any, Attribute[_T@field], _T@field) -> Any"
      Parameter 2: type "Attribute[_T@field]" cannot be assigned to type "Attribute[int]"
        "Attribute[Literal[1]]" is incompatible with "Attribute[int]"
          Type parameter "_T@Attribute" is invariant, but "Literal[1]" is not the same as "int"
    "function" is incompatible with "Sequence[(Any, Attribute[_T@field], _T@field) -> Any]"
    Type cannot be assigned to type "None"

LiteralFactory error:

  Type "(self: Unknown, attribute: Attribute[int], value: int) -> None" cannot be assigned to type "_ValidatorArgType[_T@field] | None"
    Type "(self: Unknown, attribute: Attribute[int], value: int) -> None" cannot be assigned to type "(Any, Attribute[_T@field], _T@field) -> Any"
      Parameter 2: type "Attribute[_T@field]" cannot be assigned to type "Attribute[int]"
        "Attribute[Literal[1]]" is incompatible with "Attribute[int]"
          Type parameter "_T@Attribute" is invariant, but "Literal[1]" is not the same as "int"
    "function" is incompatible with "Sequence[(Any, Attribute[_T@field], _T@field) -> Any]"
    Type cannot be assigned to type "None"
@Why-not-now
Copy link
Contributor Author

While casting 1 to int using Typing.cast(int, 1) fixes it, I think this is not the behaviour I expected.

@Tinche
Copy link
Member

Tinche commented Nov 25, 2023

Hm yeah, something here should be covariant I guess?

@Tinche Tinche self-assigned this Nov 25, 2023
@Why-not-now
Copy link
Contributor Author

I think default and default factory should be covariant. (I may be wrong, covariance/contravariance breaks my head)

@hynek hynek added the Typing Typing/stub/Mypy/PyRight related bugs. label Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Typing Typing/stub/Mypy/PyRight related bugs.
Projects
None yet
Development

No branches or pull requests

3 participants