Skip to content

Commit a6a57fa

Browse files
committed
Fix named only arguments
Fixes robotframework#111
1 parent 9315f4f commit a6a57fa

8 files changed

+58
-16
lines changed

atest/DynamicTypesAnnotationsLibrary.py

+16
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,19 @@ def keyword_optional_with_none(self, arg: Optional[str] = None):
156156
@keyword
157157
def keyword_union_with_none(self, arg: Union[None, Dict, str] = None):
158158
return f"arg: {arg}, type: {type(arg)}"
159+
160+
@keyword
161+
def kw_with_named_arguments(self, *, arg):
162+
print(arg)
163+
return f"arg: {arg}, type: {type(arg)}"
164+
165+
@keyword
166+
def kw_with_many_named_arguments(self, *, arg1, arg2):
167+
print(arg1)
168+
print(arg2)
169+
return f"arg1: {arg1}, type: {type(arg1)}, arg2: {arg2}, type: {type(arg2)}"
170+
171+
@keyword
172+
def kw_with_named_arguments_and_variable_number_args(self, *varargs, arg):
173+
print(arg)
174+
return f"arg: {arg}, type: {type(arg)}"

atest/Python310Library.py

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from robotlibcore import DynamicCore, keyword
44

5+
56
class Python310Library(DynamicCore):
67

78
def __init__(self):

atest/tests.robot

+12-12
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ ${LIBRARY} DynamicLibrary
77

88

99
*** Test Cases ***
10-
Keyword names
11-
Keyword in main
10+
Keyword Names
11+
Keyword In Main
1212
Function
1313
FUNCTION
1414
Method
15-
Custom name
16-
Cust omna me
17-
IF $LIBRARY == "ExtendExistingLibrary" Keyword in extending library
15+
Custom Name
16+
Cust Omna Me
17+
IF $LIBRARY == "ExtendExistingLibrary" Keyword In Extending Library
1818

1919
Method without @keyword are not keyowrds
2020
[Documentation] FAIL GLOB: No keyword with name 'Not keyword' found.*
@@ -27,27 +27,27 @@ Arguments
2727
'foo', 2, 3 Defaults foo ${2}
2828
'a', 'b', 'c' Defaults a b c
2929

30-
Named arguments
30+
Named Arguments
3131
[Template] Return value should be
3232
'foo', 'bar' Mandatory foo arg2=bar
3333
'1', 2 Mandatory arg2=${2} arg1=1
3434
'x', 'default', 'y' Defaults x arg3=y
3535

36-
Varargs and kwargs
36+
Varargs And Kwargs
3737
[Template] Return value should be
3838
${EMPTY} Varargs and kwargs
3939
'a', 'b', 'c' Varargs and kwargs a b c
4040
a\='1', b\=2 Varargs and kwargs a=1 b=${2}
4141
'a', 'b\=b', c\='c' Varargs and kwargs a b\=b c=c
4242

43-
Embedded arguments
44-
[Documentation] FAIL Work but this fails
45-
Embedded arguments "work"
46-
embeDded ArgumeNtS "Work but this fails"
43+
Embedded Arguments
44+
[Documentation] FAIL Work But This Fails
45+
Embedded Arguments "work"
46+
EmbeDded ArgumeNtS "Work But This Fails"
4747

4848

4949
*** Keywords ***
50-
Return value should be
50+
Return Value Should Be
5151
[Arguments] ${expected} ${keyword} @{args} &{kwargs}
5252
${result} Run Keyword ${keyword} @{args} &{kwargs}
5353
Should Be Equal ${result} ${expected}

atest/tests_types.robot

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Keyword Only Arguments Without VarArg
5252
${return} = DynamicTypesAnnotationsLibrary.Keyword Only Arguments No Vararg other=tidii
5353
Should Match ${return} tidii: <class 'str'>
5454

55-
Varargs and KeywordArgs With Typing Hints
55+
Varargs And KeywordArgs With Typing Hints
5656
${return} = DynamicTypesAnnotationsLibrary.Keyword Self And Keyword Only Types
5757
... this_is_mandatory # mandatory argument
5858
... 1 2 3 4 # varargs
@@ -112,6 +112,9 @@ Python 3.10 New Type Hints
112112
Should Be Equal ${types} arg: {"key": 1}, type: <class 'str'>
113113
END
114114

115+
Keyword With Named Only Arguments
116+
Kw With Named Arguments arg=1
117+
115118

116119
*** Keywords ***
117120
Import DynamicTypesAnnotationsLibrary In Python 3.10 Only

src/robotlibcore.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -229,18 +229,22 @@ def _drop_self_from_args(cls, function, arg_spec):
229229
@classmethod
230230
def _get_var_args(cls, arg_spec):
231231
if arg_spec.varargs:
232-
return ["*%s" % arg_spec.varargs]
232+
return [f"*{arg_spec.varargs}"]
233233
return []
234234

235235
@classmethod
236236
def _get_kwargs(cls, arg_spec):
237-
return ["**%s" % arg_spec.varkw] if arg_spec.varkw else []
237+
return [f"**{arg_spec.varkw}"] if arg_spec.varkw else []
238238

239239
@classmethod
240240
def _get_kw_only(cls, arg_spec):
241241
kw_only_args = []
242+
kw_only_defaults = arg_spec.kwonlydefaults if arg_spec.kwonlydefaults else []
242243
for arg in arg_spec.kwonlyargs:
243-
if not arg_spec.kwonlydefaults or arg not in arg_spec.kwonlydefaults:
244+
if not arg_spec.varargs and arg not in kw_only_defaults and not kw_only_args:
245+
kw_only_args.append("*")
246+
kw_only_args.append(arg)
247+
elif arg not in kw_only_defaults:
244248
kw_only_args.append(arg)
245249
else:
246250
value = arg_spec.kwonlydefaults.get(arg, "")

tasks.py

+6
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ def lint(ctx):
132132
print(f"Lint Robot files {'in ci' if in_ci else ''}")
133133
command = [
134134
"robotidy",
135+
"--transform",
136+
"RenameKeywords",
137+
"--transform",
138+
"RenameTestCases",
139+
"-c",
140+
"RenameTestCases:capitalize_each_word=True",
135141
"--lineseparator",
136142
"unix",
137143
"atest/",

utest/test_get_keyword_types.py

+5
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,8 @@ def test_keyword_optional_with_none(lib_types):
192192
def test_keyword_union_with_none(lib_types):
193193
types = lib_types.get_keyword_types("keyword_union_with_none")
194194
assert types == {"arg": typing.Union[type(None), typing.Dict, str]}
195+
196+
197+
def test_kw_with_named_arguments(lib_types: DynamicTypesAnnotationsLibrary):
198+
types = lib_types.get_keyword_types("kw_with_named_arguments")
199+
assert types == {}

utest/test_robotlibcore.py

+7
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ def test_keyword_only_arguments_for_get_keyword_arguments():
132132
assert args("keyword_with_deco_and_signature") == [("arg1", False), ("arg2", False)]
133133

134134

135+
def test_named_only_argumens():
136+
args = DynamicTypesAnnotationsLibrary(1).get_keyword_arguments
137+
assert args("kw_with_named_arguments") == ["*", "arg"]
138+
assert args("kw_with_many_named_arguments") == ["*", "arg1", "arg2"]
139+
assert args("kw_with_named_arguments_and_variable_number_args") == ["*varargs", "arg"]
140+
141+
135142
def test_get_keyword_documentation():
136143
doc = DynamicLibrary().get_keyword_documentation
137144
assert doc("function") == ""

0 commit comments

Comments
 (0)