pyright icon indicating copy to clipboard operation
pyright copied to clipboard

False-positive errors for attrs - wrong types for `default` argument?

Open olivercoleman-switchdin opened this issue 1 year ago • 2 comments

Not sure if this belongs here, but I'm getting erroneous type errors for the attrs module.

Field definitions like this:

from attrs import field, frozen, validators
@frozen
class Control:
    control_priority: int = field(validator=validators.instance_of(int), default=10)

Give errors like this:

control_definitions.py
  control_definitions.py:40:29 - error: No overloads for "field" match the provided arguments (reportGeneralTypeIssues)
  control_definitions.py:40:102 - error: Argument of type "Literal[10]" cannot be assigned to parameter "default" of type "None" in function "field"
    Type cannot be assigned to type "None" (reportGeneralTypeIssues)

Removing either the validator or the default argument to field make the error go away.

VS Code extension or command-line I get the same error running PyRight in:

  • VS Code via Pylance v2023.10.30 extension
  • Pants pyright backend running PyRight v1.1.332

olivercoleman-switchdin avatar Oct 20 '23 04:10 olivercoleman-switchdin

Thanks, I'm able to repro the problem and will investigate further. Here's a simplified example that doesn't rely on attrs.

from typing import Any, Callable, Generic, TypeVar

_T = TypeVar("_T")

class Attribute(Generic[_T]):
    pass

_ValidatorType = Callable[[Any, Attribute[_T], _T], Any]

def field(*, default: _T, validator: _ValidatorType[_T]) -> _T:
    ...

def instance_of(type: type[_T]) -> _ValidatorType[_T]:
    ...

field(validator=instance_of(int), default=10)

erictraut avatar Oct 20 '23 05:10 erictraut

Just encountered a similar issue, but with Literal and str. Maybe that helps with debugging.

from typing import Container, Generic, TypeVar, Callable, Any
_T = TypeVar("_T")

class Attribute(Generic[_T]): ...
_ValidatorType = Callable[[Any, Attribute[_T], _T], Any]

def field(default: _T, validator: _ValidatorType[_T]) -> _T: ...

def in_(options: Container[_T]) -> _ValidatorType[_T]: ...


s: list[str] = ["normal", "system"]
field("normal", in_(s))
  test.py:13:17 - error: Argument of type "(Any, Attribute[str], str) -> Any" cannot be assigned to parameter "validator" of type "_ValidatorType[_T@field]" in function "field"
    Type "(Any, Attribute[str], str) -> Any" is incompatible with type "_ValidatorType[_T@field]"
      Parameter 2: type "Attribute[_T@field]" is incompatible with type "Attribute[str]"
        "Attribute[Literal['normal']]" is incompatible with "Attribute[str]"
          Type parameter "_T@Attribute" is invariant, but "Literal['normal']" is not the same as "str" (reportArgumentType)

cdce8p avatar May 08 '24 10:05 cdce8p

I've fixed the bug associated with the original bug report. The other bug reported by @cdce8p is actually unrelated, so I've opened a separate issue (#8049) to track that one. The fix for the bug reported by @olivercoleman-switchdin will be included in the next release of pyright.

erictraut avatar Jun 02 '24 21:06 erictraut

This is addressed in pyright 1.1.366.

erictraut avatar Jun 05 '24 04:06 erictraut