Add more precise inference for enum attributes (#6867)
This pull request makes two changes to enum attributes.
First, this PR refines type inference for expressions like `MyEnum.FOO`
and `MyEnum.FOO.name`. Those two expressions will continue to evaluate to
`MyEnum` and `str` respectively under normal conditions, but will
evaluate to `Literal[MyEnum.FOO]` and `Literal["FOO"]` respectively
when used in Literal contexts.
Second, the type of `MyEnum.FOO.value` will be more precise when
possible: mypy will evaluate that expression to the type of whatever
FOO was assigned in the enum definition, falling back to `Any` as a
default.
Somewhat relatedly, this diff adds a few tests confirming we handle
enum.auto() correctly.
Two additional notes:
1. The changes I made to the `name` and `value` fields up above are
strictly speaking unsafe. While those files are normally read-only
(doing `MyEnum.FOO.name = blah` is a runtime error), it's actually
possible to change those fields anyway by altering the `_name_` and
`_value_` fields which are *not* protected.
But I think this use case is probably rare -- I'm planning on
investigating the feasibility of just having mypy just disallow
modifying these attributes altogether after I investigate how enums
are used in some internal codebases in a little more detail.
2. I would have liked to make `MyEnum.FOO.value` also return an even
more precise type when used in literal contexts similar to
`MyEnum.FOO.name`, but I think our plugin system needs to be a bit
more flexible first.