|
5 | 5 | from collections import OrderedDict
|
6 | 6 | from typing import (
|
7 | 7 | Any, TypeVar, Dict, List, Tuple, cast, Generic, Set, Sequence, Optional, Union, Iterable,
|
8 |
| - NamedTuple, |
| 8 | + NamedTuple, Callable, |
9 | 9 | )
|
10 | 10 |
|
11 | 11 | import mypy.nodes
|
@@ -1500,109 +1500,78 @@ def keywords_str(self, a: Iterable[Tuple[str, Type]]) -> str:
|
1500 | 1500 | ])
|
1501 | 1501 |
|
1502 | 1502 |
|
1503 |
| -# These constants define the method used by TypeQuery to combine multiple |
1504 |
| -# query results, e.g. for tuple types. The strategy is not used for empty |
1505 |
| -# result lists; in that case the default value takes precedence. |
1506 |
| -ANY_TYPE_STRATEGY = 0 # Return True if any of the results are True. |
1507 |
| -ALL_TYPES_STRATEGY = 1 # Return True if all of the results are True. |
| 1503 | +class TypeQuery(Generic[T], TypeVisitor[T]): |
| 1504 | + """Visitor for performing queries of types. |
1508 | 1505 |
|
| 1506 | + strategy is used to combine results for a series of types |
1509 | 1507 |
|
1510 |
| -class TypeQuery(TypeVisitor[bool]): |
1511 |
| - """Visitor for performing simple boolean queries of types. |
1512 |
| -
|
1513 |
| - This class allows defining the default value for leafs to simplify the |
1514 |
| - implementation of many queries. |
| 1508 | + Common use cases involve a boolean query using `any` or `all` |
1515 | 1509 | """
|
1516 | 1510 |
|
1517 |
| - default = False # Default result |
1518 |
| - strategy = 0 # Strategy for combining multiple values (ANY_TYPE_STRATEGY or ALL_TYPES_...). |
1519 |
| - |
1520 |
| - def __init__(self, default: bool, strategy: int) -> None: |
1521 |
| - """Construct a query visitor. |
1522 |
| -
|
1523 |
| - Use the given default result and strategy for combining |
1524 |
| - multiple results. The strategy must be either |
1525 |
| - ANY_TYPE_STRATEGY or ALL_TYPES_STRATEGY. |
1526 |
| - """ |
1527 |
| - self.default = default |
| 1511 | + def __init__(self, strategy: Callable[[Iterable[T]], T]) -> None: |
1528 | 1512 | self.strategy = strategy
|
1529 | 1513 |
|
1530 |
| - def visit_unbound_type(self, t: UnboundType) -> bool: |
1531 |
| - return self.default |
| 1514 | + def visit_unbound_type(self, t: UnboundType) -> T: |
| 1515 | + return self.query_types(t.args) |
1532 | 1516 |
|
1533 |
| - def visit_type_list(self, t: TypeList) -> bool: |
1534 |
| - return self.default |
| 1517 | + def visit_type_list(self, t: TypeList) -> T: |
| 1518 | + return self.query_types(t.items) |
1535 | 1519 |
|
1536 |
| - def visit_any(self, t: AnyType) -> bool: |
1537 |
| - return self.default |
| 1520 | + def visit_any(self, t: AnyType) -> T: |
| 1521 | + return self.strategy([]) |
1538 | 1522 |
|
1539 |
| - def visit_uninhabited_type(self, t: UninhabitedType) -> bool: |
1540 |
| - return self.default |
| 1523 | + def visit_uninhabited_type(self, t: UninhabitedType) -> T: |
| 1524 | + return self.strategy([]) |
1541 | 1525 |
|
1542 |
| - def visit_none_type(self, t: NoneTyp) -> bool: |
1543 |
| - return self.default |
| 1526 | + def visit_none_type(self, t: NoneTyp) -> T: |
| 1527 | + return self.strategy([]) |
1544 | 1528 |
|
1545 |
| - def visit_erased_type(self, t: ErasedType) -> bool: |
1546 |
| - return self.default |
| 1529 | + def visit_erased_type(self, t: ErasedType) -> T: |
| 1530 | + return self.strategy([]) |
1547 | 1531 |
|
1548 |
| - def visit_deleted_type(self, t: DeletedType) -> bool: |
1549 |
| - return self.default |
| 1532 | + def visit_deleted_type(self, t: DeletedType) -> T: |
| 1533 | + return self.strategy([]) |
1550 | 1534 |
|
1551 |
| - def visit_type_var(self, t: TypeVarType) -> bool: |
1552 |
| - return self.default |
| 1535 | + def visit_type_var(self, t: TypeVarType) -> T: |
| 1536 | + return self.strategy([]) |
1553 | 1537 |
|
1554 |
| - def visit_partial_type(self, t: PartialType) -> bool: |
1555 |
| - return self.default |
| 1538 | + def visit_partial_type(self, t: PartialType) -> T: |
| 1539 | + return self.query_types(t.inner_types) |
1556 | 1540 |
|
1557 |
| - def visit_instance(self, t: Instance) -> bool: |
| 1541 | + def visit_instance(self, t: Instance) -> T: |
1558 | 1542 | return self.query_types(t.args)
|
1559 | 1543 |
|
1560 |
| - def visit_callable_type(self, t: CallableType) -> bool: |
| 1544 | + def visit_callable_type(self, t: CallableType) -> T: |
1561 | 1545 | # FIX generics
|
1562 | 1546 | return self.query_types(t.arg_types + [t.ret_type])
|
1563 | 1547 |
|
1564 |
| - def visit_tuple_type(self, t: TupleType) -> bool: |
| 1548 | + def visit_tuple_type(self, t: TupleType) -> T: |
1565 | 1549 | return self.query_types(t.items)
|
1566 | 1550 |
|
1567 |
| - def visit_typeddict_type(self, t: TypedDictType) -> bool: |
| 1551 | + def visit_typeddict_type(self, t: TypedDictType) -> T: |
1568 | 1552 | return self.query_types(t.items.values())
|
1569 | 1553 |
|
1570 |
| - def visit_star_type(self, t: StarType) -> bool: |
| 1554 | + def visit_star_type(self, t: StarType) -> T: |
1571 | 1555 | return t.type.accept(self)
|
1572 | 1556 |
|
1573 |
| - def visit_union_type(self, t: UnionType) -> bool: |
| 1557 | + def visit_union_type(self, t: UnionType) -> T: |
1574 | 1558 | return self.query_types(t.items)
|
1575 | 1559 |
|
1576 |
| - def visit_overloaded(self, t: Overloaded) -> bool: |
| 1560 | + def visit_overloaded(self, t: Overloaded) -> T: |
1577 | 1561 | return self.query_types(t.items())
|
1578 | 1562 |
|
1579 |
| - def visit_type_type(self, t: TypeType) -> bool: |
| 1563 | + def visit_type_type(self, t: TypeType) -> T: |
1580 | 1564 | return t.item.accept(self)
|
1581 | 1565 |
|
1582 |
| - def query_types(self, types: Iterable[Type]) -> bool: |
| 1566 | + def visit_ellipsis_type(self, t: EllipsisType) -> T: |
| 1567 | + return self.strategy([]) |
| 1568 | + |
| 1569 | + def query_types(self, types: Iterable[Type]) -> T: |
1583 | 1570 | """Perform a query for a list of types.
|
1584 | 1571 |
|
1585 |
| - Use the strategy constant to combine the results. |
| 1572 | + Use the strategy to combine the results. |
1586 | 1573 | """
|
1587 |
| - if not types: |
1588 |
| - # Use default result for empty list. |
1589 |
| - return self.default |
1590 |
| - if self.strategy == ANY_TYPE_STRATEGY: |
1591 |
| - # Return True if at least one component is true. |
1592 |
| - res = False |
1593 |
| - for t in types: |
1594 |
| - res = res or t.accept(self) |
1595 |
| - if res: |
1596 |
| - break |
1597 |
| - return res |
1598 |
| - else: |
1599 |
| - # Return True if all components are true. |
1600 |
| - res = True |
1601 |
| - for t in types: |
1602 |
| - res = res and t.accept(self) |
1603 |
| - if not res: |
1604 |
| - break |
1605 |
| - return res |
| 1574 | + return self.strategy(t.accept(self) for t in types) |
1606 | 1575 |
|
1607 | 1576 |
|
1608 | 1577 | def strip_type(typ: Type) -> Type:
|
|
0 commit comments