Skip to content

Commit

Permalink
Support generics in type conversion. #4433
Browse files Browse the repository at this point in the history
  • Loading branch information
pekkaklarck committed Sep 28, 2022
1 parent a56d052 commit 60d6f0e
Show file tree
Hide file tree
Showing 21 changed files with 581 additions and 120 deletions.
49 changes: 41 additions & 8 deletions atest/robot/keywords/type_conversion/annotations_with_typing.robot
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
*** Settings ***
Suite Setup Run Tests ${EMPTY} keywords/type_conversion/annotations_with_typing.robot
Resource atest_resource.robot
Suite Setup Run Tests ${EMPTY} keywords/type_conversion/annotations_with_typing.robot
Resource atest_resource.robot

*** Test Cases ***
List
Check Test Case ${TESTNAME}

List with params
List with types
Check Test Case ${TESTNAME}

List with incompatible types
Check Test Case ${TESTNAME}

Invalid list
Check Test Case ${TESTNAME}

Tuple
Check Test Case ${TESTNAME}

Tuple with types
Check Test Case ${TESTNAME}

Tuple with homogenous types
Check Test Case ${TESTNAME}

Tuple with incompatible types
Check Test Case ${TESTNAME}

Tuple with wrong number of values
Check Test Case ${TESTNAME}

Invalid tuple
Check Test Case ${TESTNAME}

Sequence
Check Test Case ${TESTNAME}

Sequence with params
Sequence with types
Check Test Case ${TESTNAME}

Invalid Sequence
Sequence with incompatible types
Check Test Case ${TESTNAME}

Invalid sequence
Check Test Case ${TESTNAME}

Dict
Check Test Case ${TESTNAME}

Dict with params
Dict with types
Check Test Case ${TESTNAME}

Dict with incompatible types
Check Test Case ${TESTNAME}

TypedDict
Expand All @@ -36,7 +63,10 @@ Invalid dictionary
Mapping
Check Test Case ${TESTNAME}

Mapping with params
Mapping with types
Check Test Case ${TESTNAME}

Mapping with incompatible types
Check Test Case ${TESTNAME}

Invalid mapping
Expand All @@ -45,7 +75,10 @@ Invalid mapping
Set
Check Test Case ${TESTNAME}

Set with params
Set with types
Check Test Case ${TESTNAME}

Set with incompatible types
Check Test Case ${TESTNAME}

Invalid Set
Expand Down
3 changes: 3 additions & 0 deletions atest/robot/keywords/type_conversion/custom_converters.robot
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Custom in Union
Accept subscripted generics
Check Test Case ${TESTNAME}

With generics
Check Test Case ${TESTNAME}

Failing conversion
Check Test Case ${TESTNAME}

Expand Down
44 changes: 44 additions & 0 deletions atest/robot/keywords/type_conversion/standard_generics.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
*** Settings ***
Suite Setup Run Tests ${EMPTY} keywords/type_conversion/standard_generics.robot
Force Tags require-py3.9
Resource atest_resource.robot

*** Test Cases ***
List
Check Test Case ${TESTNAME}

Incompatible list
Check Test Case ${TESTNAME}

Tuple
Check Test Case ${TESTNAME}

Homogenous tuple
Check Test Case ${TESTNAME}

Incompatible tuple
Check Test Case ${TESTNAME}

Dict
Check Test Case ${TESTNAME}

Incompatible dict
Check Test Case ${TESTNAME}

Set
Check Test Case ${TESTNAME}

Incompatible set
Check Test Case ${TESTNAME}

Invalid list
Check Test Case ${TESTNAME}

Invalid tuple
Check Test Case ${TESTNAME}

Invalid dict
Check Test Case ${TESTNAME}

Invalid set
Check Test Case ${TESTNAME}
1 change: 0 additions & 1 deletion atest/robot/libdoc/datatypes_json-xml.robot
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ Custom
... <p>Class doc is used when converter method has no doc.</p>

Accepted types

Accepted Types Should Be 1 Standard boolean
... string integer float None
Accepted Types Should Be 2 Custom CustomType
Expand Down
21 changes: 17 additions & 4 deletions atest/robot/libdoc/datatypes_py-json.robot
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ Standard types
${MODEL}[typedocs][1][name] boolean
${MODEL}[typedocs][1][doc] <p>Strings <code>TRUE</code>, <code>YES</code>, start=True

Standard types with generics
${MODEL}[typedocs][4][type] Standard
${MODEL}[typedocs][4][name] Dict[str, int]
${MODEL}[typedocs][4][doc] <p>Strings must be Python <a start=True
${MODEL}[typedocs][8][type] Standard
${MODEL}[typedocs][8][name] List[Any]
${MODEL}[typedocs][8][doc] <p>Strings must be Python <a start=True
${MODEL}[typedocs][9][type] Standard
${MODEL}[typedocs][9][name] List[str]
${MODEL}[typedocs][9][doc] <p>Strings must be Python <a start=True

Accepted types
${MODEL}[typedocs][1][type] Standard
${MODEL}[typedocs][1][accepts] ['string', 'integer', 'float', 'None']
Expand All @@ -113,18 +124,20 @@ Accepted types
${MODEL}[typedocs][6][accepts] ['string']
${MODEL}[typedocs][0][type] Enum
${MODEL}[typedocs][0][accepts] ['string']
${MODEL}[typedocs][10][type] Enum
${MODEL}[typedocs][10][accepts] ['string', 'integer']
${MODEL}[typedocs][11][type] Enum
${MODEL}[typedocs][11][accepts] ['string', 'integer']

Usages
${MODEL}[typedocs][1][type] Standard
${MODEL}[typedocs][1][usages] ['Funny Unions']
${MODEL}[typedocs][4][type] Standard
${MODEL}[typedocs][4][usages] ['Typing Types']
${MODEL}[typedocs][2][type] Custom
${MODEL}[typedocs][2][usages] ['Custom']
${MODEL}[typedocs][6][type] TypedDict
${MODEL}[typedocs][6][usages] ['Funny Unions', 'Set Location']
${MODEL}[typedocs][10][type] Enum
${MODEL}[typedocs][10][usages] ['__init__', 'Funny Unions']
${MODEL}[typedocs][11][type] Enum
${MODEL}[typedocs][11][usages] ['__init__', 'Funny Unions']

Typedoc links in arguments
${MODEL}[keywords][0][args][1][typedocs] {'AssertionOperator': 'AssertionOperator', 'None': 'None'}
Expand Down
17 changes: 15 additions & 2 deletions atest/robot/libdoc/datatypes_py-xml.robot
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ Standard
... boolean
... Strings ``TRUE``, ``YES``, ``ON`` and ``1`` are converted to Boolean ``True``,

Standard with generics
DataType Standard Should Be 1
... Dict[str, int]
... Strings must be Python [[]https://docs.python.org/library/stdtypes.html#dict|dictionary]
DataType Standard Should Be 4
... List[Any]
... Strings must be Python [[]https://docs.python.org/library/stdtypes.html#list|list]
DataType Standard Should Be 5
... List[str]
... Strings must be Python [[]https://docs.python.org/library/stdtypes.html#list|list]

Accepted types
Accepted Types Should Be 1 Standard boolean
... string integer float None
Expand All @@ -65,17 +76,19 @@ Accepted types
... string
Accepted Types Should Be 0 Enum AssertionOperator
... string
Accepted Types Should Be 10 Enum Small
Accepted Types Should Be 11 Enum Small
... string integer

Usages
Usages Should Be 1 Standard boolean
... Funny Unions
Usages Should Be 4 Standard Dict[str, int]
... Typing Types
Usages Should Be 2 Custom CustomType
... Custom
Usages Should be 6 TypedDict GeoLocation
... Funny Unions Set Location
Usages Should Be 10 Enum Small
Usages Should Be 11 Enum Small
... __init__ Funny Unions

Typedoc links in arguments
Expand Down
2 changes: 1 addition & 1 deletion atest/robot/libdoc/type_annotations.robot
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Varargs and kwargs
Keyword Arguments Should Be 4 *varargs: int **kwargs: bool

Unknown types
Keyword Arguments Should Be 5 unknown: UnknownType unrecognized: Ellipsis
Keyword Arguments Should Be 5 unknown: UnknownType unrecognized: ...

Non-type annotations
Keyword Arguments Should Be 6 arg: One of the usages in PEP-3107
Expand Down
2 changes: 1 addition & 1 deletion atest/robot/libdoc/types_via_keyword_decorator.robot
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Varargs and kwargs
Keyword Arguments Should Be 2 *varargs: int **kwargs: bool

Unknown types
Keyword Arguments Should Be 3 unknown: UnknownType unrecognized: Ellipsis
Keyword Arguments Should Be 3 unknown: UnknownType unrecognized: ...

Non-type annotations
Keyword Arguments Should Be 4 arg: One of the usages in PEP-3107
Expand Down
41 changes: 26 additions & 15 deletions atest/testdata/keywords/type_conversion/AnnotationsWithTyping.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import (List, Sequence, MutableSequence,
Dict, Mapping, MutableMapping,
Set, MutableSet)
from typing import (Dict, List, Mapping, MutableMapping, MutableSet, MutableSequence,
Set, Sequence, Tuple, Union)
try:
from typing import TypedDict
except ImportError:
Expand All @@ -25,31 +24,43 @@ def list_(argument: List, expected=None):
_validate_type(argument, expected)


def list_with_params(argument: List[int], expected=None):
def list_with_types(argument: List[int], expected=None):
_validate_type(argument, expected)


def tuple_(argument: Tuple, expected=None):
_validate_type(argument, expected)


def tuple_with_types(argument: Tuple[bool, int], expected=None):
_validate_type(argument, expected)


def homogenous_tuple(argument: Tuple[int, ...], expected=None):
_validate_type(argument, expected)


def sequence(argument: Sequence, expected=None):
_validate_type(argument, expected)


def sequence_with_params(argument: Sequence[bool], expected=None):
def sequence_with_types(argument: Sequence[Union[int, float]], expected=None):
_validate_type(argument, expected)


def mutable_sequence(argument: MutableSequence, expected=None):
_validate_type(argument, expected)


def mutable_sequence_with_params(argument: MutableSequence[bool], expected=None):
def mutable_sequence_with_types(argument: MutableSequence[int], expected=None):
_validate_type(argument, expected)


def dict_(argument: Dict, expected=None):
_validate_type(argument, expected)


def dict_with_params(argument: Dict[str, int], expected=None):
def dict_with_types(argument: Dict[int, float], expected=None):
_validate_type(argument, expected)


Expand All @@ -61,31 +72,31 @@ def mapping(argument: Mapping, expected=None):
_validate_type(argument, expected)


def mapping_with_params(argument: Mapping[bool, int], expected=None):
def mapping_with_types(argument: Mapping[int, float], expected=None):
_validate_type(argument, expected)


def mutable_mapping(argument: MutableMapping, expected=None):
_validate_type(argument, expected)


def mutable_mapping_with_params(argument: MutableMapping[bool, int], expected=None):
def mutable_mapping_with_types(argument: MutableMapping[int, float], expected=None):
_validate_type(argument, expected)


def set_(argument: Set, expected=None):
_validate_type(argument, expected)


def set_with_params(argument: Set[bool], expected=None):
def set_with_types(argument: Set[int], expected=None):
_validate_type(argument, expected)


def mutable_set(argument: MutableSet, expected=None):
_validate_type(argument, expected)


def mutable_set_with_params(argument: MutableSet[bool], expected=None):
def mutable_set_with_types(argument: MutableSet[float], expected=None):
_validate_type(argument, expected)


Expand All @@ -97,7 +108,7 @@ def forward_reference(argument: 'List', expected=None):
_validate_type(argument, expected)


def forward_ref_with_params(argument: 'List[int]', expected=None):
def forward_ref_with_types(argument: 'List[int]', expected=None):
_validate_type(argument, expected)


Expand All @@ -109,6 +120,6 @@ def _validate_type(argument, expected):
if isinstance(expected, str):
expected = eval(expected)
if argument != expected or type(argument) != type(expected):
raise AssertionError('%r (%s) != %r (%s)'
% (argument, type(argument).__name__,
expected, type(expected).__name__))
atype = type(argument).__name__
etype = type(expected).__name__
raise AssertionError(f'{argument!r} ({atype}) != {expected!r} ({etype})')
10 changes: 9 additions & 1 deletion atest/testdata/keywords/type_conversion/CustomConverters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import date, datetime
from typing import List, Union
from typing import Dict, List, Set, Tuple, Union


class Number:
Expand Down Expand Up @@ -130,6 +130,14 @@ def accept_subscripted_generics(argument: AcceptSubscriptedGenerics, expected):
assert argument.sum == expected


def with_generics(a: List[Number], b: Tuple[FiDate, UsDate], c: Dict[Number, FiDate], d: Set[Number]):
expected_date = date(2022, 9, 28)
assert a == [1, 2, 3], a
assert b == (expected_date, expected_date), b
assert c == {1: expected_date}, c
assert d == {1, 2, 3}, d


def number_or_int(number: Union[Number, int]):
assert number == 1

Expand Down

0 comments on commit 60d6f0e

Please sign in to comment.