Skip to content

Commit edd411d

Browse files
authored
None and bool type should not return type hints when used as defaults in RF31. (robotframework#58)
Made returning defaults for bool and NoneType work differently for RF31 and RF32. Fixes robotframework#60
1 parent 2de7bc2 commit edd411d

File tree

4 files changed

+73
-33
lines changed

4 files changed

+73
-33
lines changed

atest/DynamicTypesAnnotationsLibrary.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def keyword_with_webdriver(self, arg: CustomObject):
5555
return arg
5656

5757
@keyword
58-
def keyword_default_and_annotation(self: 'DynamicTypesAnnotationsLibrary', arg1: int, arg2=False) -> str:
58+
def keyword_default_and_annotation(self: 'DynamicTypesAnnotationsLibrary', arg1: int, arg2: Union[bool, str] = False) -> str:
5959
return '%s: %s, %s: %s' % (arg1, type(arg1), arg2, type(arg2))
6060

6161
@keyword(types={'arg': str})
@@ -67,7 +67,7 @@ def keyword_robot_types_disabled_and_annotations(self, arg: int):
6767
return '%s: %s' % (arg, type(arg))
6868

6969
@keyword(types={'arg1': str})
70-
def keyword_robot_types_and_bool_defaults(self, arg1, arg2=False):
70+
def keyword_robot_types_and_bool_hint(self, arg1, arg2: bool):
7171
return '%s: %s, %s: %s' % (arg1, type(arg1), arg2, type(arg2))
7272

7373
@keyword
@@ -87,7 +87,9 @@ def keyword_only_arguments_no_vararg(self, *, other):
8787
return f'{other}: {type(other)}'
8888

8989
@keyword
90-
def keyword_only_arguments_many_positional_and_default(self: 'DynamicTypesAnnotationsLibrary', *varargs, one, two, three, four=True, five=None, six=False):
90+
def keyword_only_arguments_many_positional_and_default(self: 'DynamicTypesAnnotationsLibrary', *varargs, one, two,
91+
three, four: Union[int, str] = 1, five=None,
92+
six: Union[bool, str] = False):
9193
return f'{varargs}, {one}, {two}, {three}, {four}, {five}, {six}'
9294

9395
@keyword
@@ -99,7 +101,7 @@ def keyword_only_arguments_many(self, *varargs, some='value', other=None):
99101
return f'{some}: {type(some)}, {other}: {type(other)}, {varargs}: {type(varargs)}'
100102

101103
@keyword
102-
def keyword_mandatory_and_keyword_only_arguments(self, arg: int, *vararg, some=True):
104+
def keyword_mandatory_and_keyword_only_arguments(self, arg: int, *vararg, some: bool):
103105
return f'{arg}, {vararg}, {some}'
104106

105107
@keyword

atest/tests_types.robot

+3-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Keyword Default Argument As Abject None Default Value
1313

1414
Keyword Default Argument As String None
1515
${return} = DynamicTypesLibrary.Keyword None None
16-
Should Match Regexp ${return} None: <(class|type) 'NoneType'>
16+
Should Match Regexp ${return} None: <(class|type) '(unicode|str|NoneType)'>
1717

1818
Keyword Default As Booleans With Defaults
1919
${return} DynamicTypesLibrary.Keyword Booleans
@@ -35,23 +35,18 @@ Keyword Annonations And Bool Defaults Using Default
3535
Keyword Annonations And Bool Defaults Defining All Arguments
3636
[Tags] py3
3737
${return} = DynamicTypesAnnotationsLibrary.Keyword Default And Annotation 1 true
38-
Should Match Regexp ${return} 1: <(class|type) 'int'>, True: <(class|type) 'bool'>
38+
Should Match Regexp ${return} 1: <(class|type) 'int'>, true: <(class|type) 'str'>
3939

4040
Keyword Annonations And Bool Defaults Defining All Arguments And With Number
4141
[Tags] py3
4242
${return} = DynamicTypesAnnotationsLibrary.Keyword Default And Annotation ${1} true
43-
Should Match Regexp ${return} 1: <(class|type) 'int'>, True: <(class|type) 'bool'>
43+
Should Match Regexp ${return} 1: <(class|type) 'int'>, true: <(class|type) 'str'>
4444

4545
Keyword Annonations And Robot Types Disbales Argument Conversion
4646
[Tags] py3
4747
${return} = DynamicTypesAnnotationsLibrary.Keyword Robot Types Disabled And Annotations 111
4848
Should Match Regexp ${return} 111: <(class|type) 'str'>
4949

50-
Keyword Annonations And Robot Types Defined
51-
[Tags] py3
52-
${return} = DynamicTypesAnnotationsLibrary.Keyword Robot Types And Bool Defaults tidii 111
53-
Should Match Regexp ${return} tidii: <(class|type) 'str'>, 111: <(class|type) 'str'>
54-
5550
Keyword Annonations And Keyword Only Arguments
5651
[Tags] py3
5752
${return} = DynamicTypesAnnotationsLibrary.Keyword Only Arguments 1 ${1} some=222

src/robotlibcore.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ def get_keyword_types(self, keyword_name):
124124
return types
125125
if not types:
126126
types = self.__get_typing_hints(method)
127-
types = self.__join_defaults_with_types(method, types)
127+
if RF31:
128+
types = self.__join_defaults_with_types(method, types)
129+
else:
130+
types.pop('return', None)
128131
return types
129132

130133
def __get_keyword(self, keyword_name):

utest/test_get_keyword_types.py

+60-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pytest
22

33

4-
from robotlibcore import PY2
4+
from robotlibcore import PY2, RF31
55

66
if not PY2:
77
from typing import List, Union, Dict
@@ -31,11 +31,18 @@ def test_types_disabled(lib):
3131
assert types is None
3232

3333

34-
def test_keyword_types_and_bool_default(lib):
34+
@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
35+
def test_keyword_types_and_bool_default_rf31(lib):
3536
types = lib.get_keyword_types('keyword_robot_types_and_bool_default')
3637
assert types == {'arg1': str, 'arg2': bool}
3738

3839

40+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
41+
def test_keyword_types_and_bool_default_rf32(lib):
42+
types = lib.get_keyword_types('keyword_robot_types_and_bool_default')
43+
assert types == {'arg1': str}
44+
45+
3946
def test_one_keyword_type_defined(lib):
4047
types = lib.get_keyword_types('keyword_with_one_type')
4148
assert types == {'arg1': str}
@@ -51,12 +58,26 @@ def test_not_keyword(lib):
5158
lib.get_keyword_types('not_keyword')
5259

5360

54-
def test_keyword_booleans(lib):
61+
@pytest.mark.skipif(not RF31, reason='Only for RF3.2+')
62+
def test_keyword_booleans_rf31(lib):
5563
types = lib.get_keyword_types('keyword_booleans')
5664
assert types == {'arg1': bool, 'arg2': bool}
5765

5866

59-
def test_keyword_none(lib):
67+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
68+
def test_keyword_booleans_rf32(lib):
69+
types = lib.get_keyword_types('keyword_booleans')
70+
assert types == {}
71+
72+
73+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
74+
def test_keyword_none_rf32(lib):
75+
types = lib.get_keyword_types('keyword_none')
76+
assert types == {}
77+
78+
79+
@pytest.mark.skipif(not RF31, reason='Only for RF3.2+')
80+
def test_keyword_none_rf31(lib):
6081
types = lib.get_keyword_types('keyword_none')
6182
assert types == {'arg': type(None)}
6283

@@ -79,11 +100,6 @@ def test_multiple_types(lib_types):
79100
assert types == {'arg': Union[List, None]}
80101

81102

82-
def test_keyword_with_default_type(lib):
83-
types = lib.get_keyword_types('keyword_default_types')
84-
assert types == {'arg': type(None)}
85-
86-
87103
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
88104
def test_keyword_new_type(lib_types):
89105
types = lib_types.get_keyword_types('keyword_new_type')
@@ -123,7 +139,7 @@ def test_keyword_with_annotation_external_class(lib_types):
123139
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
124140
def test_keyword_with_annotation_and_default(lib_types):
125141
types = lib_types.get_keyword_types('keyword_default_and_annotation')
126-
assert types == {'arg1': int, 'arg2': bool}
142+
assert types == {'arg1': int, 'arg2': Union[bool, str]}
127143

128144

129145
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
@@ -140,13 +156,13 @@ def test_keyword_with_robot_types_disbaled_and_annotations(lib_types):
140156

141157
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
142158
def test_keyword_with_robot_types_and_bool_annotations(lib_types):
143-
types = lib_types.get_keyword_types('keyword_robot_types_and_bool_defaults')
144-
assert types == {'arg1': str, 'arg2': bool}
145-
159+
types = lib_types.get_keyword_types('keyword_robot_types_and_bool_hint')
160+
assert types == {'arg1': str}
146161

147-
def test_init_args(lib):
148-
types = lib.get_keyword_types('__init__')
149-
assert types == {'arg': bool}
162+
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
163+
def test_init_args(lib_types):
164+
types = lib_types.get_keyword_types('__init__')
165+
assert types == {'arg': str}
150166

151167

152168
def test_dummy_magic_method(lib):
@@ -177,26 +193,50 @@ def test_keyword_only_arguments(lib_types):
177193
assert types == {}
178194

179195

196+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
180197
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
181198
def test_keyword_only_arguments_many(lib_types):
182199
types = lib_types.get_keyword_types('keyword_only_arguments_many')
183-
assert types == {'other': type(None)}
200+
assert types == {}
184201

185202

203+
@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
186204
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
187205
def test_keyword_only_arguments_many(lib_types):
206+
types = lib_types.get_keyword_types('keyword_only_arguments_many')
207+
assert types == {'other': type(None)}
208+
209+
210+
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
211+
def test_keyword_mandatory_and_keyword_only_arguments(lib_types):
188212
types = lib_types.get_keyword_types('keyword_mandatory_and_keyword_only_arguments')
189213
assert types == {'arg': int, 'some': bool}
190214

191215

216+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
192217
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
193-
def test_keyword_only_arguments_many(lib_types):
218+
def test_keyword_only_arguments_many_positional_and_default_rf32(lib_types):
194219
types = lib_types.get_keyword_types('keyword_only_arguments_many_positional_and_default')
195-
assert types == {'four': bool, 'five': type(None), 'six': bool}
220+
assert types == {'four': Union[int, str], 'six': Union[bool, str]}
221+
222+
223+
@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
224+
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
225+
def test_keyword_only_arguments_many_positional_and_default_rf31(lib_types):
226+
types = lib_types.get_keyword_types('keyword_only_arguments_many_positional_and_default')
227+
assert types == {'four': Union[int, str], 'five': type(None), 'six': Union[bool, str]}
228+
229+
230+
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
231+
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
232+
def test_keyword_all_args_rf32(lib_types):
233+
types = lib_types.get_keyword_types('keyword_all_args')
234+
assert types == {}
196235

197236

237+
@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
198238
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
199-
def test_keyword_all_args(lib_types):
239+
def test_keyword_all_args_rf31(lib_types):
200240
types = lib_types.get_keyword_types('keyword_all_args')
201241
assert types == {'value': bool}
202242

0 commit comments

Comments
 (0)