@@ -1526,13 +1526,16 @@ Other types cause conversion failures.
15261526Specifying multiple possible types
15271527''''''''''''''''''''''''''''''''''
15281528
1529- Starting from Robot Framework 4.0, it is possible to specify that an argument
1530- has multiple possible types. In this situation argument conversion is attempted
1531- based on each type and the whole conversion fails if none of these conversions
1532- succeed.
1529+ It is possible to specify that an argument has multiple possible types. In this
1530+ situation argument conversion is attempted based on each type, from left to right,
1531+ and the value of the first succeeding conversion is used. If none of these conversions
1532+ succeeds, the whole conversion fails.
1533+
1534+ Union syntax
1535+ ````````````
15331536
15341537When using function annotations, the natural syntax to specify that an argument
1535- has multiple possible types is usingUnion _:
1538+ has multiple possible types is usinga Union _:
15361539
15371540..sourcecode ::python
15381541
@@ -1542,23 +1545,29 @@ has multiple possible types is using Union_:
15421545 def example(length: Union[int, float], padding: Union[int, str, None] = None):
15431546 ...
15441547
1545- When using Python 3.10 or newer, it is possible to use the native` type1 | type2 `__
1546- syntax instead:
1548+ When using Python 3.10 or newer, it is possible to use the` nativeunion syntax `__
1549+ like ` int | float ` instead:
15471550
15481551..sourcecode ::python
15491552
15501553 def example(length: int | float, padding: int | str | None = None):
15511554 ...
15521555
15531556Robot Framework 7.0 enhanced the support for the union syntax so that also
1554- "stringly typed" unions like `'type1 |type2' ` work. This syntax works also
1557+ "stringly typed" unions like `"int |float" ` work. This syntax works also
15551558with older Python versions:
15561559
15571560..sourcecode ::python
15581561
1559- def example(length:' int | float' , padding:' int | str | None' = None):
1562+ def example(length:" int | float" , padding:" int | str | None" = None):
15601563 ...
15611564
1565+ __ https://peps.python.org/pep-0604/
1566+ .. _Union :https://docs.python.org/3/library/typing.html#typing.Union
1567+
1568+ Using tuples
1569+ ````````````
1570+
15621571An alternative is specifying types as a tuple. It is not recommended with annotations,
15631572because that syntax is not supported by other tools, but it works well with
15641573the `@keyword ` decorator:
@@ -1576,11 +1585,15 @@ With the above examples the `length` argument would first be converted to an
15761585integer and if that fails then to a float. The `padding ` would be first
15771586converted to an integer, then to a string, and finally to `None `.
15781587
1588+ When argument matches one of the types
1589+ ``````````````````````````````````````
1590+
15791591If the given argument has one of the accepted types, then no conversion is done
1580- and the argument is used as-is. For example, if the `length ` argument gets
1581- value `1.5 ` as a float, it would not be converted to an integer. Notice that
1582- using non-string values like floats as an argument requires using variables as
1583- these examples giving different values to the `length ` argument demonstrate:
1592+ and the argument is used as-is. For example, if the `length ` argument typed
1593+ like `length: int | float ` is used with a floating point number `1.5 `, it is not
1594+ converted to an integer. Notice that using non-string values like floats as an
1595+ argument requires using variables as these examples giving different values to
1596+ the `length ` argument demonstrate:
15841597
15851598..sourcecode ::robotframework
15861599
@@ -1591,10 +1604,10 @@ these examples giving different values to the `length` argument demonstrate:
15911604 Example ${10} # Argument is an integer. Accepted as-is.
15921605 Example ${1.5} # Argument is a float. Accepted as-is.
15931606
1594- If one of the accepted types is string, then no conversion is done if the given
1595- argument is a string. As thefollowing examples giving different values to the
1596- `padding ` argument demonstrate, also in these cases passing other types is
1597- possible using variables:
1607+ If one of the accepted types is string like in ` padding: int | str | None `,
1608+ then no conversion is done if thegiven argument is a string. As the following
1609+ examples giving different values to the `padding ` argument demonstrate, also in
1610+ these cases passing other types is possible using variables:
15981611
15991612..sourcecode ::robotframework
16001613
@@ -1607,9 +1620,7 @@ possible using variables:
16071620 Example 1 ${1.5} # Argument is a float. Converted to an integer.
16081621
16091622If the given argument does not have any of the accepted types, conversion is
1610- attempted in the order types are specified. If any conversion succeeds, the
1611- resulting value is used without attempting remaining conversions. If no individual
1612- conversion succeeds, the whole conversion fails.
1623+ attempted in the order types are specified.
16131624
16141625..note ::The order of types changes the conversion result in cases where the used
16151626 value does not match any of the types, but conversion to multiple types
@@ -1626,9 +1637,43 @@ conversion succeeds, the whole conversion fails.
16261637 the value is already an integer or a float either, because there is no
16271638 need for conversion in such cases.
16281639
1629- If a specified type is not recognized by Robot Framework, then the original argument
1630- value is used as-is. For example, with this keyword conversion would first be attempted
1631- to an integer, but if that fails the keyword would get the original argument:
1640+ Handling `Any ` and `object `
1641+ ```````````````````````````
1642+
1643+ If `Any ` or `object ` is used as a type hint on its own like `arg: Any ` or `arg: object `,
1644+ any value is accepted without conversion. How they work when used in an union differs,
1645+ though.
1646+
1647+ If `Any ` is used in a union like `arg: int | Any `, any value is accepted without
1648+ conversion. This allows using `Any ` as an escape hatch that disables argument conversion
1649+ altogether.
1650+
1651+ On the other hand, if `object ` is used in an union like `arg: int | object `,
1652+ conversion is attempted to types before `object `. This allows attempting conversion
1653+ to certain type or types, but getting the original value if conversions fail.
1654+
1655+ ..note ::Although this subtle difference in behavior may be useful, it is also
1656+ somewhat confusing and the plan is to change it in Robot Framework 8.0
1657+ so that `Any ` behaves like `object `. See the issue `#5571 `__ for more
1658+ information and comment the issue if you do not think the planned change
1659+ is a good idea.
1660+
1661+ __ https://github.com/robotframework/robotframework/issues/5571
1662+
1663+ Handling unrecognized types
1664+ ```````````````````````````
1665+
1666+ If types that are not recognized by Robot Framework are used in an union, they are
1667+ handled like this:
1668+
1669+ - If a used value matches any of the types, including unrecognized types, the value
1670+ is used as-is without conversion.
1671+ - Otherwise conversion is attempted to recognized types from left to right.
1672+ - If any conversion succeeds, the converted value is returned.
1673+ - If no conversion succeeds, the original value is returned.
1674+
1675+ For example, with the following keyword string `"7" ` would be converted to an integer,
1676+ but string `"something" ` would be used as-is:
16321677
16331678..sourcecode ::python
16341679
@@ -1641,9 +1686,6 @@ Also in this case `int` conversion is attempted, and the argument id passed as-i
16411686if it fails. With earlier Robot Framework versions, `int ` conversion would not be
16421687attempted at all.
16431688
1644- __ https://peps.python.org/pep-0604/
1645- .. _Union :https://docs.python.org/3/library/typing.html#typing.Union
1646-
16471689Parameterized types
16481690'''''''''''''''''''
16491691