Example #1
0
def merged_type(t, s):
    # type: (AbstractType, AbstractType) -> Optional[AbstractType]
    """Return merged type if two items can be merged in to a different, more general type.

    Return None if merging is not possible.
    """
    if isinstance(t, TupleType) and isinstance(s, TupleType):
        if len(t.items) == len(s.items):
            return TupleType(
                [combine_types([ti, si]) for ti, si in zip(t.items, s.items)])
        all_items = t.items + s.items
        if all_items and all(item == all_items[0] for item in all_items[1:]):
            # Merge multiple compatible fixed-length tuples into a variable-length tuple type.
            return ClassType('Tuple', [all_items[0]])
    elif (isinstance(t, TupleType) and isinstance(s, ClassType)
          and s.name == 'Tuple' and len(s.args) == 1):
        if all(item == s.args[0] for item in t.items):
            # Merge fixed-length tuple and variable-length tuple.
            return s
    elif isinstance(s, TupleType) and isinstance(
            t, ClassType) and t.name == 'Tuple':
        return merged_type(s, t)
    elif isinstance(s, AnyType):
        # This seems to be usually desirable, since Anys tend to come from unknown types.
        return t
    elif isinstance(t, AnyType):
        # Similar to above.
        return s
    return None
Example #2
0
 def parse_type(self):
     # type: () -> AbstractType
     t = self.next()
     if not isinstance(t, DottedName):
         self.fail()
     if t.text == 'Any':
         return AnyType()
     elif t.text == 'Tuple':
         self.expect('[')
         args = self.parse_type_list()
         self.expect(']')
         return TupleType(args)
     elif t.text == 'Union':
         self.expect('[')
         items = self.parse_type_list()
         self.expect(']')
         if len(items) == 1:
             return items[0]
         elif len(items) == 0:
             self.fail()
         else:
             return UnionType(items)
     else:
         if self.lookup() == '[':
             self.expect('[')
             args = self.parse_type_list()
             self.expect(']')
             if t.text == 'Optional' and len(args) == 1:
                 return UnionType([args[0], ClassType('None')])
             return ClassType(t.text, args)
         else:
             return ClassType(t.text)
Example #3
0
 def test_simplify_multiple_empty_collections(self):
     # type: () -> None
     self.assert_infer(
         ['() -> Tuple[List, List[x]]', '() -> Tuple[List, List]'],
         ([],
          TupleType(
              [ClassType('List'),
               ClassType('List', [ClassType('x')])])))
Example #4
0
 def test_merge_tuples_with_different_lengths(self):
     # type: () -> None
     assert merge_items([
         TupleType([CT('str')]),
         TupleType([CT('str'), CT('str')])]) == [CT('Tuple', [CT('str')])]
     assert merge_items([
         TupleType([]),
         TupleType([CT('str')]),
         TupleType([CT('str'), CT('str')])]) == [CT('Tuple', [CT('str')])]
     # Don't merge if types aren't identical
     assert merge_items([
         TupleType([CT('str')]),
         TupleType([CT('str'), CT('int')])]) == [TupleType([CT('str')]),
                                                 TupleType([CT('str'), CT('int')])]
Example #5
0
 def test_merge_union_of_same_length_tuples(self):
     # type: () -> None
     assert merge_items([TupleType([CT('str')]),
                         TupleType([CT('int')])]) == [TupleType([UnionType([CT('str'),
                                                                            CT('int')])])]
     assert merge_items([TupleType([CT('str')]),
                         TupleType([CT('Text')])]) == [TupleType([CT('Text')])]
Example #6
0
def simplify_recursive(typ):
    # type: (AbstractType) -> AbstractType
    """Simplify all components of a type."""
    if isinstance(typ, UnionType):
        return combine_types(typ.items)
    elif isinstance(typ, ClassType):
        simplified = ClassType(typ.name, [simplify_recursive(arg) for arg in typ.args])
        args = simplified.args
        if (simplified.name == 'Dict' and len(args) == 2
                and isinstance(args[0], ClassType) and args[0].name in ('str', 'Text')
                and isinstance(args[1], UnionType) and not is_optional(args[1])):
            # Looks like a potential case for TypedDict, which we don't properly support yet.
            return ClassType('Dict', [args[0], AnyType()])
        return simplified
    elif isinstance(typ, TupleType):
        return TupleType([simplify_recursive(item) for item in typ.items])
    return typ
Example #7
0
 def test_tuple_type_str(self):
     # type: () -> None
     assert str(TupleType([ClassType('int')])) == 'Tuple[int]'
     assert str(TupleType([ClassType('int'),
                           ClassType('str')])) == 'Tuple[int, str]'
     assert str(TupleType([])) == 'Tuple[()]'
Example #8
0
def tuple_arg(items):
    # type: (List[AbstractType]) -> Argument
    return Argument(TupleType(items), ARG_POS)