|
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