Skip to content

Commit 8ee5b68

Browse files
committed
[GR-25788] GraalPython allows to put multiple values for keyword argument.
PullRequest: graalpython/1249
2 parents 40deb71 + ad2a24e commit 8ee5b68

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1989
-1721
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_call.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -167,6 +167,8 @@ def f24(*args, a, b=5):
167167
def f25(*args, a, b=5, **kwds):
168168
pass
169169

170+
def f26(**kw):
171+
return kw
170172

171173
def assert_parses(call_expr):
172174
raised = False
@@ -234,8 +236,7 @@ def test_parse_args():
234236

235237
assert_parses("f11(a=1, b=2)")
236238
assert_parses("f11(a=1, b=2, c=3)")
237-
# TODO
238-
# assert_call_raises(SyntaxError, "f11(a=1, b=2, a=3)") # SyntaxError: keyword argument repeated
239+
assert_call_raises(SyntaxError, "f11(a=1, b=2, a=3)") # SyntaxError: keyword argument repeated
239240
assert_call_raises(TypeError, "f11(1, b=2, a=3)") # TypeError: f11() got multiple values for argument 'a'
240241

241242
assert_parses("f12(1,2)")
@@ -286,8 +287,7 @@ def test_parse_args():
286287
assert_parses("f20(a=1)")
287288
assert_parses("f20(a=1, b=2)")
288289
assert_parses("f20(a=1, b=2, c=3)")
289-
# TODO
290-
# assert_call_raises(SyntaxError, "f20(a=1, b=2, a=3)") # SyntaxError: keyword argument repeated
290+
assert_call_raises(SyntaxError, "f20(a=1, b=2, a=3)") # SyntaxError: keyword argument repeated
291291
assert_call_raises(TypeError, "f20(1, b=2)") # TypeError: f20() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
292292
assert_call_raises(TypeError, "f20(1)") # TypeError: f20() takes 0 positional arguments but 1 was given
293293

@@ -324,3 +324,41 @@ def test_parse_args():
324324
assert_call_raises(TypeError, "f25(1,2,3,c=6)") # TypeError: f25() missing 1 required keyword-only argument: 'a'
325325
assert_parses("f25(a=4,c=6)")
326326
assert_parses("f25(a=4)")
327+
328+
def test_multiple_values_for_keyword_argument():
329+
assert_call_raises(TypeError, "f26(a=1, **{'a' : 2})") # TypeError: f26() got multiple values for keyword argument 'a'
330+
assert_call_raises(TypeError, "f26(**{'a' : 4}, **{'a': 3})") # TypeError: f26() got multiple values for keyword argument 'a'
331+
332+
b = 1
333+
def test_argument_must_be_mapping():
334+
assert_call_raises(TypeError, "f26(a=1, **b)") # TypeError: f26() argument after ** must be a mapping, not int
335+
assert_call_raises(TypeError, "f26(**b)") # TypeError: f26() argument after ** must be a mapping, not int
336+
class MyDict(dict):
337+
pass
338+
d = MyDict()
339+
assert f26(**d) == {}
340+
341+
fooo = f26
342+
def test_multiple_values_with_callable_name():
343+
def assert_get_message(err, fn, *args, **kwargs):
344+
raised = False
345+
try:
346+
fn(*args, **kwargs)
347+
except err as ex:
348+
return str(ex)
349+
assert raised
350+
351+
def assert_call_raises_get_message(exception, call_expr):
352+
return assert_get_message(exception, eval, call_expr)
353+
354+
msg = assert_call_raises_get_message(TypeError, "fooo(a=1, **b)") # TypeError: f26() argument after ** must be a mapping, not int
355+
assert msg == "f26() argument after ** must be a mapping, not int"
356+
357+
msg = assert_call_raises_get_message(TypeError, "fooo(**{'a' : 4}, **{'a': 3})") # TypeError: f26() got multiple values for keyword argument 'a'
358+
assert msg == "f26() got multiple values for keyword argument 'a'"
359+
360+
def test_runtime_args():
361+
mydict = {'a':1, 'b':2, 'c':3}
362+
kw = f26(b = mydict.pop('b', 22), **mydict)
363+
assert 'b' in kw
364+
assert kw['b'] == 2

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call03.tast

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ ModuleRootNode Name: <module 'call03'> SourceSection: [0,12]`foo(arg = 1)`
88
PythonCallNodeGen SourceSection: [0,12]`foo(arg = 1)`
99
CallNodeGen SourceSection: None
1010
KeywordArgumentsNodeGen SourceSection: None
11-
KeywordLiteralNode SourceSection: None
12-
IntegerLiteralNode SourceSection: [10,11]`1`
13-
Value: 1
14-
CompactKeywordsNodeGen SourceSection: None
15-
ExecuteKeywordStarargsNodeGen SourceSection: None
16-
EmptyNode SourceSection: None
11+
ExecuteKeywordArgumentsNode SourceSection: None
12+
KeywordLiteralNode SourceSection: None
13+
IntegerLiteralNode SourceSection: [10,11]`1`
14+
Value: 1
15+
EmptyNode SourceSection: None
1716
ReadNameNodeGen SourceSection: [0,3]`foo`
1817
Identifier: foo
1918
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call06.tast

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ ModuleRootNode Name: <module 'call06'> SourceSection: [0,23]`foo(arg1 = 1, arg2
88
PythonCallNodeGen SourceSection: [0,23]`foo(arg1 = 1, arg2 =...`
99
CallNodeGen SourceSection: None
1010
KeywordArgumentsNodeGen SourceSection: None
11-
KeywordLiteralNode SourceSection: None
12-
IntegerLiteralNode SourceSection: [11,12]`1`
13-
Value: 1
14-
KeywordLiteralNode SourceSection: None
15-
IntegerLiteralNode SourceSection: [21,22]`2`
16-
Value: 2
17-
CompactKeywordsNodeGen SourceSection: None
18-
ExecuteKeywordStarargsNodeGen SourceSection: None
19-
EmptyNode SourceSection: None
11+
ExecuteKeywordArgumentsNode SourceSection: None
12+
KeywordLiteralNode SourceSection: None
13+
IntegerLiteralNode SourceSection: [11,12]`1`
14+
Value: 1
15+
KeywordLiteralNode SourceSection: None
16+
IntegerLiteralNode SourceSection: [21,22]`2`
17+
Value: 2
18+
EmptyNode SourceSection: None
2019
ReadNameNodeGen SourceSection: [0,3]`foo`
2120
Identifier: foo
2221
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call07.tast

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ ModuleRootNode Name: <module 'call07'> SourceSection: [0,31]`foo('ahoj', arg1 =
99
CallNodeGen SourceSection: None
1010
StringLiteralNode SourceSection: [4,10]`'ahoj'`
1111
KeywordArgumentsNodeGen SourceSection: None
12-
KeywordLiteralNode SourceSection: None
13-
IntegerLiteralNode SourceSection: [19,20]`1`
14-
Value: 1
15-
KeywordLiteralNode SourceSection: None
16-
IntegerLiteralNode SourceSection: [29,30]`2`
17-
Value: 2
18-
CompactKeywordsNodeGen SourceSection: None
19-
ExecuteKeywordStarargsNodeGen SourceSection: None
20-
EmptyNode SourceSection: None
12+
ExecuteKeywordArgumentsNode SourceSection: None
13+
KeywordLiteralNode SourceSection: None
14+
IntegerLiteralNode SourceSection: [19,20]`1`
15+
Value: 1
16+
KeywordLiteralNode SourceSection: None
17+
IntegerLiteralNode SourceSection: [29,30]`2`
18+
Value: 2
19+
EmptyNode SourceSection: None
2120
ReadNameNodeGen SourceSection: [0,3]`foo`
2221
Identifier: foo
2322
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call08.tast

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ ModuleRootNode Name: <module 'call08'> SourceSection: [0,31]`foo('ahoj', arg1 =
99
CallNodeGen SourceSection: None
1010
StringLiteralNode SourceSection: [4,10]`'ahoj'`
1111
KeywordArgumentsNodeGen SourceSection: None
12-
KeywordLiteralNode SourceSection: None
13-
IntegerLiteralNode SourceSection: [19,20]`1`
14-
Value: 1
15-
KeywordLiteralNode SourceSection: None
16-
IntegerLiteralNode SourceSection: [29,30]`2`
17-
Value: 2
18-
CompactKeywordsNodeGen SourceSection: None
19-
ExecuteKeywordStarargsNodeGen SourceSection: None
20-
EmptyNode SourceSection: None
12+
ExecuteKeywordArgumentsNode SourceSection: None
13+
KeywordLiteralNode SourceSection: None
14+
IntegerLiteralNode SourceSection: [19,20]`1`
15+
Value: 1
16+
KeywordLiteralNode SourceSection: None
17+
IntegerLiteralNode SourceSection: [29,30]`2`
18+
Value: 2
19+
EmptyNode SourceSection: None
2120
ReadNameNodeGen SourceSection: [0,3]`foo`
2221
Identifier: foo
2322
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call11.tast

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ ModuleRootNode Name: <module 'call11'> SourceSection: [0,13]`foo(**mydict)`
88
PythonCallNodeGen SourceSection: [0,13]`foo(**mydict)`
99
CallNodeGen SourceSection: None
1010
KeywordArgumentsNodeGen SourceSection: None
11-
CompactKeywordsNodeGen SourceSection: None
12-
ExecuteKeywordStarargsNodeGen SourceSection: None
13-
ReadNameNodeGen SourceSection: [6,12]`mydict`
14-
Identifier: mydict
15-
IsBuiltinClassProfile SourceSection: None
16-
CachedDispatchFirst SourceSection: None
11+
ExecuteKeywordArgumentsNode SourceSection: None
12+
ReadNameNodeGen SourceSection: [6,12]`mydict`
13+
Identifier: mydict
14+
IsBuiltinClassProfile SourceSection: None
15+
CachedDispatchFirst SourceSection: None
1716
ReadNameNodeGen SourceSection: [0,3]`foo`
1817
Identifier: foo
1918
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call12.tast

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@ ModuleRootNode Name: <module 'call12'> SourceSection: [0,25]`foo(**mydict1, **my
88
PythonCallNodeGen SourceSection: [0,25]`foo(**mydict1, **myd...`
99
CallNodeGen SourceSection: None
1010
KeywordArgumentsNodeGen SourceSection: None
11-
CompactKeywordsNodeGen SourceSection: None
12-
ExecuteKeywordStarargsNodeGen SourceSection: None
13-
DictConcatNodeGen SourceSection: None
14-
ReadNameNodeGen SourceSection: [6,13]`mydict1`
15-
Identifier: mydict1
16-
IsBuiltinClassProfile SourceSection: None
17-
CachedDispatchFirst SourceSection: None
18-
ReadNameNodeGen SourceSection: [17,24]`mydict2`
19-
Identifier: mydict2
20-
IsBuiltinClassProfile SourceSection: None
21-
CachedDispatchFirst SourceSection: None
11+
ExecuteKeywordArgumentsNode SourceSection: None
12+
ConcatKeywordsNodeGen SourceSection: None
13+
ReadNameNodeGen SourceSection: [6,13]`mydict1`
14+
Identifier: mydict1
15+
IsBuiltinClassProfile SourceSection: None
16+
CachedDispatchFirst SourceSection: None
17+
ReadNameNodeGen SourceSection: [17,24]`mydict2`
18+
Identifier: mydict2
19+
IsBuiltinClassProfile SourceSection: None
20+
CachedDispatchFirst SourceSection: None
2221
ReadNameNodeGen SourceSection: [0,3]`foo`
2322
Identifier: foo
2423
IsBuiltinClassProfile SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call17.tast

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ ModuleRootNode Name: <module 'call17'> SourceSection: [0,22]`def fn(): foo(arg =
3838
PythonCallNodeGen SourceSection: [10,22]`foo(arg = 1)`
3939
CallNodeGen SourceSection: None
4040
KeywordArgumentsNodeGen SourceSection: None
41-
KeywordLiteralNode SourceSection: None
42-
IntegerLiteralNode SourceSection: [20,21]`1`
43-
Value: 1
44-
CompactKeywordsNodeGen SourceSection: None
45-
ExecuteKeywordStarargsNodeGen SourceSection: None
46-
EmptyNode SourceSection: None
41+
ExecuteKeywordArgumentsNode SourceSection: None
42+
KeywordLiteralNode SourceSection: None
43+
IntegerLiteralNode SourceSection: [20,21]`1`
44+
Value: 1
45+
EmptyNode SourceSection: None
4746
ReadGlobalOrBuiltinNodeGen SourceSection: [10,13]`foo`
4847
Identifier: foo
4948
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call18.tast

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,13 @@ ModuleRootNode Name: <module 'call18'> SourceSection: [0,35]`def fn(arg = [1,2])
5151
PythonCallNodeGen SourceSection: [21,35]`foo(arg = [1])`
5252
CallNodeGen SourceSection: None
5353
KeywordArgumentsNodeGen SourceSection: None
54-
KeywordLiteralNode SourceSection: None
55-
ListLiteralNode SourceSection: [31,34]`[1]`
56-
IntegerLiteralNode SourceSection: [32,33]`1`
57-
Value: 1
58-
PythonObjectFactoryNodeGen SourceSection: None
59-
CompactKeywordsNodeGen SourceSection: None
60-
ExecuteKeywordStarargsNodeGen SourceSection: None
61-
EmptyNode SourceSection: None
54+
ExecuteKeywordArgumentsNode SourceSection: None
55+
KeywordLiteralNode SourceSection: None
56+
ListLiteralNode SourceSection: [31,34]`[1]`
57+
IntegerLiteralNode SourceSection: [32,33]`1`
58+
Value: 1
59+
PythonObjectFactoryNodeGen SourceSection: None
60+
EmptyNode SourceSection: None
6261
ReadGlobalOrBuiltinNodeGen SourceSection: [21,24]`foo`
6362
Identifier: foo
6463
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/call19.tast

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,10 @@ ModuleRootNode Name: <module 'call19'> SourceSection: [0,33]`def fn(): "in".form
3838
PythonCallNodeGen SourceSection: [10,33]`"in".format(name="Ba...`
3939
CallNodeGen SourceSection: None
4040
KeywordArgumentsNodeGen SourceSection: None
41-
KeywordLiteralNode SourceSection: None
42-
StringLiteralNode SourceSection: [27,32]`"Baf"`
43-
CompactKeywordsNodeGen SourceSection: None
44-
ExecuteKeywordStarargsNodeGen SourceSection: None
45-
EmptyNode SourceSection: None
41+
ExecuteKeywordArgumentsNode SourceSection: None
42+
KeywordLiteralNode SourceSection: None
43+
StringLiteralNode SourceSection: [27,32]`"Baf"`
44+
EmptyNode SourceSection: None
4645
GetCallAttributeNodeGen SourceSection: None
4746
StringLiteralNode SourceSection: [10,14]`"in"`
4847
Return Expresssion: ReadLocalVariableNode SourceSection: None

0 commit comments

Comments
 (0)