|
2 | 2 |
|
3 | 3 | import itertools
|
4 | 4 | import fnmatch
|
5 |
| -import sys |
6 | 5 | from contextlib import contextmanager
|
7 | 6 |
|
8 | 7 | from typing import (
|
|
50 | 49 | from mypy.typeops import (
|
51 | 50 | map_type_from_supertype, bind_self, erase_to_bound, make_simplified_union,
|
52 | 51 | erase_def_to_union_or_bound, erase_to_union_or_bound,
|
53 |
| - true_only, false_only, function_type, |
| 52 | + true_only, false_only, function_type, is_singleton_type, |
| 53 | + try_expanding_enum_to_union, coerce_to_literal, |
54 | 54 | )
|
55 | 55 | from mypy import message_registry
|
56 | 56 | from mypy.subtypes import (
|
|
63 | 63 | from mypy.typevars import fill_typevars, has_no_typevars, fill_typevars_with_any
|
64 | 64 | from mypy.semanal import set_callable_name, refers_to_fullname
|
65 | 65 | from mypy.mro import calculate_mro
|
66 |
| -from mypy.erasetype import erase_typevars, remove_instance_last_known_values |
| 66 | +from mypy.erasetype import erase_typevars, remove_instance_transient_info |
67 | 67 | from mypy.expandtype import expand_type, expand_type_by_instance
|
68 | 68 | from mypy.visitor import NodeVisitor
|
69 | 69 | from mypy.join import join_types
|
@@ -2069,7 +2069,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
|
2069 | 2069 | if partial_types is not None:
|
2070 | 2070 | if not self.current_node_deferred:
|
2071 | 2071 | # Partial type can't be final, so strip any literal values.
|
2072 |
| - rvalue_type = remove_instance_last_known_values(rvalue_type) |
| 2072 | + rvalue_type = remove_instance_transient_info(rvalue_type) |
2073 | 2073 | inferred_type = make_simplified_union(
|
2074 | 2074 | [rvalue_type, NoneType()])
|
2075 | 2075 | self.set_inferred_type(var, lvalue, inferred_type)
|
@@ -2126,7 +2126,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
|
2126 | 2126 | if inferred:
|
2127 | 2127 | rvalue_type = self.expr_checker.accept(rvalue)
|
2128 | 2128 | if not inferred.is_final:
|
2129 |
| - rvalue_type = remove_instance_last_known_values(rvalue_type) |
| 2129 | + rvalue_type = remove_instance_transient_info(rvalue_type) |
2130 | 2130 | self.infer_variable_type(inferred, lvalue, rvalue_type, rvalue)
|
2131 | 2131 |
|
2132 | 2132 | def check_compatibility_all_supers(self, lvalue: RefExpr, lvalue_type: Optional[Type],
|
@@ -4753,97 +4753,6 @@ def is_private(node_name: str) -> bool:
|
4753 | 4753 | return node_name.startswith('__') and not node_name.endswith('__')
|
4754 | 4754 |
|
4755 | 4755 |
|
4756 |
| -def get_enum_values(typ: Instance) -> List[str]: |
4757 |
| - """Return the list of values for an Enum.""" |
4758 |
| - return [name for name, sym in typ.type.names.items() if isinstance(sym.node, Var)] |
4759 |
| - |
4760 |
| - |
4761 |
| -def is_singleton_type(typ: Type) -> bool: |
4762 |
| - """Returns 'true' if this type is a "singleton type" -- if there exists |
4763 |
| - exactly only one runtime value associated with this type. |
4764 |
| -
|
4765 |
| - That is, given two values 'a' and 'b' that have the same type 't', |
4766 |
| - 'is_singleton_type(t)' returns True if and only if the expression 'a is b' is |
4767 |
| - always true. |
4768 |
| -
|
4769 |
| - Currently, this returns True when given NoneTypes, enum LiteralTypes and |
4770 |
| - enum types with a single value. |
4771 |
| -
|
4772 |
| - Note that other kinds of LiteralTypes cannot count as singleton types. For |
4773 |
| - example, suppose we do 'a = 100000 + 1' and 'b = 100001'. It is not guaranteed |
4774 |
| - that 'a is b' will always be true -- some implementations of Python will end up |
4775 |
| - constructing two distinct instances of 100001. |
4776 |
| - """ |
4777 |
| - typ = get_proper_type(typ) |
4778 |
| - # TODO: Also make this return True if the type is a bool LiteralType. |
4779 |
| - # Also make this return True if the type corresponds to ... (ellipsis) or NotImplemented? |
4780 |
| - return ( |
4781 |
| - isinstance(typ, NoneType) or (isinstance(typ, LiteralType) and typ.is_enum_literal()) |
4782 |
| - or (isinstance(typ, Instance) and typ.type.is_enum and len(get_enum_values(typ)) == 1) |
4783 |
| - ) |
4784 |
| - |
4785 |
| - |
4786 |
| -def try_expanding_enum_to_union(typ: Type, target_fullname: str) -> ProperType: |
4787 |
| - """Attempts to recursively expand any enum Instances with the given target_fullname |
4788 |
| - into a Union of all of its component LiteralTypes. |
4789 |
| -
|
4790 |
| - For example, if we have: |
4791 |
| -
|
4792 |
| - class Color(Enum): |
4793 |
| - RED = 1 |
4794 |
| - BLUE = 2 |
4795 |
| - YELLOW = 3 |
4796 |
| -
|
4797 |
| - class Status(Enum): |
4798 |
| - SUCCESS = 1 |
4799 |
| - FAILURE = 2 |
4800 |
| - UNKNOWN = 3 |
4801 |
| -
|
4802 |
| - ...and if we call `try_expanding_enum_to_union(Union[Color, Status], 'module.Color')`, |
4803 |
| - this function will return Literal[Color.RED, Color.BLUE, Color.YELLOW, Status]. |
4804 |
| - """ |
4805 |
| - typ = get_proper_type(typ) |
4806 |
| - |
4807 |
| - if isinstance(typ, UnionType): |
4808 |
| - items = [try_expanding_enum_to_union(item, target_fullname) for item in typ.items] |
4809 |
| - return make_simplified_union(items) |
4810 |
| - elif isinstance(typ, Instance) and typ.type.is_enum and typ.type.fullname() == target_fullname: |
4811 |
| - new_items = [] |
4812 |
| - for name, symbol in typ.type.names.items(): |
4813 |
| - if not isinstance(symbol.node, Var): |
4814 |
| - continue |
4815 |
| - new_items.append(LiteralType(name, typ)) |
4816 |
| - # SymbolTables are really just dicts, and dicts are guaranteed to preserve |
4817 |
| - # insertion order only starting with Python 3.7. So, we sort these for older |
4818 |
| - # versions of Python to help make tests deterministic. |
4819 |
| - # |
4820 |
| - # We could probably skip the sort for Python 3.6 since people probably run mypy |
4821 |
| - # only using CPython, but we might as well for the sake of full correctness. |
4822 |
| - if sys.version_info < (3, 7): |
4823 |
| - new_items.sort(key=lambda lit: lit.value) |
4824 |
| - return make_simplified_union(new_items) |
4825 |
| - else: |
4826 |
| - return typ |
4827 |
| - |
4828 |
| - |
4829 |
| -def coerce_to_literal(typ: Type) -> ProperType: |
4830 |
| - """Recursively converts any Instances that have a last_known_value or are |
4831 |
| - instances of enum types with a single value into the corresponding LiteralType. |
4832 |
| - """ |
4833 |
| - typ = get_proper_type(typ) |
4834 |
| - if isinstance(typ, UnionType): |
4835 |
| - new_items = [coerce_to_literal(item) for item in typ.items] |
4836 |
| - return make_simplified_union(new_items) |
4837 |
| - elif isinstance(typ, Instance): |
4838 |
| - if typ.last_known_value: |
4839 |
| - return typ.last_known_value |
4840 |
| - elif typ.type.is_enum: |
4841 |
| - enum_values = get_enum_values(typ) |
4842 |
| - if len(enum_values) == 1: |
4843 |
| - return LiteralType(value=enum_values[0], fallback=typ) |
4844 |
| - return typ |
4845 |
| - |
4846 |
| - |
4847 | 4756 | def has_bool_item(typ: ProperType) -> bool:
|
4848 | 4757 | """Return True if type is 'bool' or a union with a 'bool' item."""
|
4849 | 4758 | if is_named_instance(typ, 'builtins.bool'):
|
|
0 commit comments