Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit afb7645

Browse files
committed
Support overloads in type converters
1 parent d1febc5 commit afb7645

File tree

7 files changed

+93
-6
lines changed

7 files changed

+93
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*** Settings ***
2+
Suite Setup Run Tests ${EMPTY} keywords/type_conversion/overloads.robot
3+
Resource atest_resource.robot
4+
5+
*** Test Cases ***
6+
Annotated
7+
Check Test Case ${TESTNAME}
8+
9+
Unannotated
10+
Check Test Case ${TESTNAME}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from typing import Union
2+
3+
from typing_extensions import overload
4+
5+
6+
@overload
7+
def foo(argument: int, expected: object): ...
8+
9+
10+
@overload
11+
def foo(argument: None, expected: object): ...
12+
13+
14+
def foo(argument: Union[int, None], expected: object):
15+
assert argument == expected
16+
17+
18+
@overload
19+
def bar(argument: int, expected: object): ...
20+
21+
22+
@overload
23+
def bar(argument: None, expected: object): ...
24+
25+
26+
def bar(argument, expected):
27+
assert argument == expected
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
*** Settings ***
2+
Library overloads.py
3+
Resource conversion.resource
4+
5+
*** Test Cases ***
6+
Annotated
7+
foo 1 ${1}
8+
foo None ${None}
9+
TRY
10+
foo a a
11+
EXCEPT ValueError: Couldn't convert to any overload:\n \ Argument 'argument' got value 'a' that cannot be converted to integer.\n \ Argument 'argument' got value 'a' that cannot be converted to None.
12+
No Operation
13+
END
14+
15+
16+
Unannotated
17+
bar 1 ${1}
18+
bar None ${None}
19+
TRY
20+
foo a a
21+
EXCEPT ValueError: Couldn't convert to any overload:\n \ Argument 'argument' got value 'a' that cannot be converted to integer.\n \ Argument 'argument' got value 'a' that cannot be converted to None.
22+
No Operation
23+
END

src/robot/running/arguments/argumentparser.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
from robot.variables import is_assign, is_scalar_assign
2222

2323
from .argumentspec import ArgumentSpec
24+
try:
25+
from typing import get_overloads
26+
except ImportError:
27+
try:
28+
from typing_extensions import get_overloads
29+
except ImportError:
30+
get_overloads = None
2431

2532

2633
class _ArgumentParser:
@@ -41,8 +48,16 @@ def _report_error(self, error):
4148

4249
class PythonArgumentParser(_ArgumentParser):
4350

44-
def parse(self, handler, name=None):
45-
spec = ArgumentSpec(name, self._type)
51+
def parse(self, handler, name=None, parse_overloads=True):
52+
try:
53+
overloads = get_overloads(handler)
54+
except Exception: # < 3.10 doesn't work with `functools.partial` objects
55+
overloads = []
56+
spec_overloads = (
57+
tuple(self.parse(overload, name, False) for overload in overloads)
58+
if get_overloads and parse_overloads else ()
59+
)
60+
spec = ArgumentSpec(name, self._type, overloads=spec_overloads)
4661
self._set_args(spec, handler)
4762
self._set_types(spec, handler)
4863
return spec

src/robot/running/arguments/argumentspec.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ArgumentSpec:
2828

2929
def __init__(self, name=None, type='Keyword', positional_only=None,
3030
positional_or_named=None, var_positional=None, named_only=None,
31-
var_named=None, defaults=None, types=None):
31+
var_named=None, defaults=None, types=None, overloads=()):
3232
self.name = name
3333
self.type = type
3434
self.positional_only = positional_only or []
@@ -38,6 +38,7 @@ def __init__(self, name=None, type='Keyword', positional_only=None,
3838
self.var_named = var_named
3939
self.defaults = defaults or {}
4040
self.types = types
41+
self.overloads = overloads
4142

4243
@setter
4344
def types(self, types):

src/robot/running/handlers.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,19 @@ def _get_initial_handler(self, library, name, method):
8383
return None
8484

8585
def resolve_arguments(self, args, variables=None, languages=None):
86-
return self.arguments.resolve(args, variables, self.library.converters,
87-
languages=languages)
86+
if not self.arguments.overloads:
87+
return self.arguments.resolve(args, variables, self.library.converters,
88+
languages=languages)
89+
errors = []
90+
for spec in self.arguments.overloads:
91+
try:
92+
return spec.resolve(args, variables, self.library.converters,
93+
languages=languages)
94+
except ValueError as e:
95+
errors.append(str(e))
96+
message = '\n '.join(errors)
97+
raise ValueError(f"Couldn't convert to any overload:\n {message}")
98+
8899

89100
@property
90101
def doc(self):

utest/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# External Python modules required by unit tests.
22
docutils >= 0.10
33
jsonschema
4-
typing_extensions; python_version <= '3.8'
4+
typing_extensions # needed for backported overloads

0 commit comments

Comments
 (0)