python-attrs / python-attrs/attrs

question about mypy error with optional() validator and non-None default

Open
#515 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Typing
Dominant language
Python
Stars
5.8k
Forks
480
Avg merge
2h 15m
Merged PRs (30d)
2

Description

With attrs 19.1.0/py 3.7.2, I have the following attrbug.py:

from typing import Optional

from attr import validators
import attr


@attr.s
class DoesntWorkWithMyPy:
    required_bool: bool = attr.ib(
        validator=validators.optional(validators.instance_of(bool)),
        default=False,
    )

    optional_bool: Optional[bool] = attr.ib(
        validator=validators.instance_of(bool),
        default=False,
    )


@attr.s
class DoesWorkWithMyPy:
    required_bool: bool = attr.ib(
        validator=validators.instance_of(bool),
        default=False,
    )


if __name__ == "__main__":
    # neither of these raises, because all attribs specify defaults
    DoesWorkWithMyPy()
    DoesntWorkWithMyPy()

Running mypy, I see thee following (I think wrong?) error:

$ mypy attrbug.py
attrbug.py:9: error: Argument "validator" has incompatible type "Callable[[Any, Attribute[Optional[bool]], Optional[bool]], Any]"; expected "Union[Callable[[Any, Attribute[bool], bool], Any], Sequence[Callable[[Any, Attribute[bool], bool], Any]], None]"

That's from the required_bool attribute of the DoesntWorkWithMyPy class. MyPy doesn't complain about any of the other invocations used here, as you can see, and I don't think it probably ought to complain about this one either.

I think what's going on is that I have said that the attribute is non-Optional on the class (because I specify a default value), but uses an "optional" validator. I had (originally) specified it there so that instances could be created without specifying a value for this parameter, assuming that the validators & converters happen before the default is applied; it seems however that the default applies before the validator, which is why both optional_bool and DoesWorkWithMyPy.required_bool work. Is this new understanding correct & reliable?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the diagnostic from the attrbug.py example with attrs 19.1.0 and Python 3.7.2. Read the typing around validators.optional and attr.ib, then check how defaults and validators are represented to mypy. Done means establishing whether the reported incompatibility is expected and identifying the relevant project behavior or typing change.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.