def test_optional_pep604(self):
        # New PEP 604 union syntax in Python 3.10+
        self.assertTrue(typing_utils.is_optional_type(str | None))
        self.assertTrue(typing_utils.is_optional_type(None | str))

        self.assertEqual(typing_utils.get_optional_type(str | None), str)
        self.assertEqual(typing_utils.get_optional_type(None | str), str)

        self.assertFalse(typing_utils.is_optional_type(int | str))
def get_type_info(tp: type) -> TypeInfo:
    """
    Reduce iterable and optional types to their 'base' types.
    """
    is_final = typing_utils.is_final_type(tp)
    if is_final:
        tp = typing_utils.get_final_type(tp)
        if tp is typing.Any:
            # This used to be supported, but Python 3.10 raises in get_type_hints() if it encounters a plain Final hint.
            raise TypeError(
                'Plain typing.Final is not valid as a type argument.')

    is_nullable = typing_utils.is_optional_type(tp)
    if is_nullable:
        tp = typing_utils.get_optional_type(tp)

    is_mapping = typing_utils.is_mapping_type(tp)
    is_many = typing_utils.is_iterable_type(tp)

    if is_mapping:
        tp = typing_utils.get_mapping_value_type(tp)
    elif is_many:  # This must be elif (instead of if), as otherwise we'd reduce mappings twice as they're also iterable
        tp = typing_utils.get_iterable_element_type(tp)

    if typing_utils.is_type_variable(tp):
        tp = typing_utils.get_variable_type_substitute(tp)

    if tp is typing.Any:
        tp = None

    return TypeInfo(is_many, is_mapping, is_final, is_nullable, tp)
Exemplo n.º 3
0
def get_type_info(
        tp: type,
        default_value_type: typing.Optional[type] = None) -> TypeInfo:
    """
    Reduce iterable and optional types to their 'base' types.
    """
    is_final = typing_utils.is_final_type(tp)
    if is_final:
        tp = typing_utils.get_final_type(tp)
        if tp is typing.Any and default_value_type is not None:
            tp = default_value_type

    is_optional = typing_utils.is_optional_type(tp)
    if is_optional:
        tp = typing_utils.get_optional_type(tp)

    is_mapping = typing_utils.is_mapping_type(tp)
    is_many = typing_utils.is_iterable_type(tp)

    if is_mapping:
        tp = typing_utils.get_mapping_value_type(tp)
    elif is_many:  # This must be elif (instead of if), as otherwise we'd reduce mappings twice as they're also iterable
        tp = typing_utils.get_iterable_element_type(tp)

    if typing_utils.is_type_variable(tp):
        tp = typing_utils.get_variable_type_substitute(tp)

    if tp is typing.Any:
        tp = None

    return TypeInfo(is_many, is_mapping, is_final, is_optional, tp)
    def test_optional(self):
        self.assertTrue(typing_utils.is_optional_type(typing.Optional[str]))
        self.assertTrue(typing_utils.is_optional_type(typing.Union[str, None]))
        self.assertTrue(
            typing_utils.is_optional_type(typing.Union[str,
                                                       typing.Optional[str]]))
        self.assertTrue(
            typing_utils.is_optional_type(typing.Union[str,
                                                       typing.Union[str,
                                                                    None]]))
        self.assertFalse(typing_utils.is_optional_type(str))
        self.assertFalse(typing_utils.is_optional_type(int))
        self.assertFalse(typing_utils.is_optional_type(TypingTest))

        self.assertEqual(typing_utils.get_optional_type(typing.Optional[str]),
                         str)
        self.assertEqual(
            typing_utils.get_optional_type(typing.Union[str, None]), str)
        self.assertEqual(
            typing_utils.get_optional_type(typing.Union[None, str]), str)
        self.assertEqual(
            typing_utils.get_optional_type(typing.Union[str,
                                                        typing.Optional[str]]),
            str)
        self.assertEqual(
            typing_utils.get_optional_type(typing.Union[str,
                                                        typing.Union[str,
                                                                     None]]),
            str)

        with self.assertRaises(ValueError):
            typing_utils.get_optional_type(str)
Exemplo n.º 5
0
    def test_literal(self):
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b']))
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b', None]))
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b', types.Literal['c', 'd']]))
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b', types.Literal['c', 'd', None]]))
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b', types.Literal[1, 2]]))
        self.assertTrue(typing_utils.is_literal_type(types.Literal['a', 'b', types.Literal[1, 2, None]]))

        self.assertFalse(typing_utils.is_optional_type(types.Literal['a', 'b']))
        self.assertTrue(typing_utils.is_optional_type(types.Literal['a', 'b', None]))
        self.assertFalse(typing_utils.is_optional_type(types.Literal['a', 'b', types.Literal['c', 'd']]))
        self.assertTrue(typing_utils.is_optional_type(types.Literal['a', 'b', types.Literal['c', 'd', None]]))
        self.assertFalse(typing_utils.is_optional_type(types.Literal['a', 'b', types.Literal[1, 2]]))
        self.assertTrue(typing_utils.is_optional_type(types.Literal['a', 'b', types.Literal[1, 2, None]]))

        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b']), ['a', 'b'])
        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b', None]), ['a', 'b', None])
        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b', types.Literal['c', 'd']]),
                             ['a', 'b', 'c', 'd'])
        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b', types.Literal['c', 'd', None]]),
                             ['a', 'b', 'c', 'd', None])
        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b', types.Literal[1, 2]]),
                             ['a', 'b', 1, 2])
        self.assertListEqual(typing_utils.get_literal_choices(types.Literal['a', 'b', types.Literal[1, 2, None]]),
                             ['a', 'b', 1, 2, None])

        with self.assertRaises(ValueError):
            typing_utils.get_literal_choices(str)
Exemplo n.º 6
0
def get_type_info(tp: type) -> TypeInfo:
    """
    Reduce iterable and optional types to their 'base' types.
    """
    is_optional = typing_utils.is_optional_type(tp)
    if is_optional:
        tp = typing_utils.get_optional_type(tp)

    is_mapping = typing_utils.is_mapping_type(tp)
    is_many = typing_utils.is_iterable_type(tp)

    if is_mapping:
        tp = typing_utils.get_mapping_value_type(tp)
    elif is_many:  # This must be elif (instead of if), as otherwise we'd reduce mappings twice
        tp = typing_utils.get_iterable_element_type(tp)

    return TypeInfo(is_many, is_mapping, is_optional, tp)