Skip to content

Commit c5314bd

Browse files
committed
[GR-23252] Make test_positional_only_arg pass.
PullRequest: graalpython/1221
2 parents 30114f2 + 99196ed commit c5314bd

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_positional_only_arg.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_annotations
2+
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_annotations_constant_fold
3+
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_async
24
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_change_default_pos_only
35
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_closures
46
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_generator
@@ -19,6 +21,8 @@
1921
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_positional_only_with_optional_invalid_calls
2022
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_posonly_methods
2123
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_same_keyword_as_positional_with_kwargs
24+
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_serialization
2225
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_super
2326
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_syntax_for_many_positional_only
2427
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_too_many_arguments
28+
*graalpython.lib-python.3.test.test_positional_only_arg.PositionalOnlyTestCase.test_use_positional_as_keyword

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/CreateArgumentsNode.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@
8181
import com.oracle.truffle.api.nodes.ExplodeLoop;
8282
import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
8383
import com.oracle.truffle.api.nodes.Node;
84+
import com.oracle.truffle.api.profiles.BranchProfile;
8485
import com.oracle.truffle.api.profiles.ConditionProfile;
86+
import java.util.ArrayList;
87+
import java.util.List;
8588

8689
@ImportStatic({PythonOptions.class, PGuards.class})
8790
@GenerateUncached
@@ -473,6 +476,7 @@ Object[] applyCached(Object callee, @SuppressWarnings("unused") Signature callee
473476
@Cached(value = "cachedSignature.getParameterIds()", dimensions = 1) String[] parameters,
474477
@Cached("parameters.length") int positionalParamNum,
475478
@Cached(value = "cachedSignature.getKeywordNames()", dimensions = 1) String[] kwNames,
479+
@Cached BranchProfile posArgOnlyPassedAsKeywordProfile,
476480
@Exclusive @Cached SearchNamedParameterNode searchParamNode,
477481
@Exclusive @Cached SearchNamedParameterNode searchKwNode) {
478482
PKeyword[] unusedKeywords = takesVarKwds ? new PKeyword[kwLen] : null;
@@ -481,6 +485,7 @@ Object[] applyCached(Object callee, @SuppressWarnings("unused") Signature callee
481485
int additionalKwds = 0;
482486
String lastWrongKeyword = null;
483487
int positionalOnlyArgIndex = calleeSignature.getPositionalOnlyArgIndex();
488+
List<String> posArgOnlyPassedAsKeywordNames = null;
484489
for (int i = 0; i < kwLen; i++) {
485490
PKeyword kwArg = keywords[i];
486491
String name = kwArg.getName();
@@ -497,7 +502,8 @@ Object[] applyCached(Object callee, @SuppressWarnings("unused") Signature callee
497502
if (unusedKeywords != null) {
498503
unusedKeywords[k++] = kwArg;
499504
} else {
500-
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.GOT_SOME_POS_ONLY_ARGS_PASSED_AS_KEYWORD, CreateArgumentsNode.getName(callee), name);
505+
posArgOnlyPassedAsKeywordProfile.enter();
506+
posArgOnlyPassedAsKeywordNames = addPosArgOnlyPassedAsKeyword(posArgOnlyPassedAsKeywordNames, name);
501507
}
502508
} else {
503509
if (PArguments.getArgument(arguments, kwIdx) != null) {
@@ -512,13 +518,14 @@ Object[] applyCached(Object callee, @SuppressWarnings("unused") Signature callee
512518
lastWrongKeyword = name;
513519
}
514520
}
515-
storeKeywordsOrRaise(callee, arguments, unusedKeywords, k, additionalKwds, lastWrongKeyword, raise);
521+
storeKeywordsOrRaise(callee, arguments, unusedKeywords, k, additionalKwds, lastWrongKeyword, posArgOnlyPassedAsKeywordNames, posArgOnlyPassedAsKeywordProfile, raise);
516522
return arguments;
517523
}
518524

519525
@Specialization(replaces = "applyCached")
520526
Object[] applyUncached(Object callee, Signature calleeSignature, Object[] arguments, PKeyword[] keywords,
521527
@Cached PRaiseNode raise,
528+
@Cached BranchProfile posArgOnlyPassedAsKeywordProfile,
522529
@Exclusive @Cached SearchNamedParameterNode searchParamNode,
523530
@Exclusive @Cached SearchNamedParameterNode searchKwNode) {
524531
String[] parameters = calleeSignature.getParameterIds();
@@ -531,6 +538,7 @@ Object[] applyUncached(Object callee, Signature calleeSignature, Object[] argume
531538
int additionalKwds = 0;
532539
String lastWrongKeyword = null;
533540
int positionalOnlyArgIndex = calleeSignature.getPositionalOnlyArgIndex();
541+
List<String> posArgOnlyPassedAsKeywordNames = null;
534542
for (int i = 0; i < kwLen; i++) {
535543
PKeyword kwArg = keywords[i];
536544
String name = kwArg.getName();
@@ -547,7 +555,8 @@ Object[] applyUncached(Object callee, Signature calleeSignature, Object[] argume
547555
if (unusedKeywords != null) {
548556
unusedKeywords[k++] = kwArg;
549557
} else {
550-
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.GOT_SOME_POS_ONLY_ARGS_PASSED_AS_KEYWORD, CreateArgumentsNode.getName(callee), name);
558+
posArgOnlyPassedAsKeywordProfile.enter();
559+
posArgOnlyPassedAsKeywordNames = addPosArgOnlyPassedAsKeyword(posArgOnlyPassedAsKeywordNames, name);
551560
}
552561
} else {
553562
if (PArguments.getArgument(arguments, kwIdx) != null) {
@@ -562,20 +571,41 @@ Object[] applyUncached(Object callee, Signature calleeSignature, Object[] argume
562571
lastWrongKeyword = name;
563572
}
564573
}
565-
storeKeywordsOrRaise(callee, arguments, unusedKeywords, k, additionalKwds, lastWrongKeyword, raise);
574+
storeKeywordsOrRaise(callee, arguments, unusedKeywords, k, additionalKwds, lastWrongKeyword, posArgOnlyPassedAsKeywordNames, posArgOnlyPassedAsKeywordProfile, raise);
566575
return arguments;
567576
}
568577

569-
private static void storeKeywordsOrRaise(Object callee, Object[] arguments, PKeyword[] unusedKeywords, int unusedKeywordCount, int tooManyKeywords, String lastWrongKeyword, PRaiseNode raise) {
578+
@TruffleBoundary
579+
private static List<String> addPosArgOnlyPassedAsKeyword(List<String> names, String name) {
580+
if (names == null) {
581+
List<String> newList = new ArrayList<>();
582+
newList.add(name);
583+
return newList;
584+
}
585+
names.add(name);
586+
return names;
587+
}
588+
589+
private static void storeKeywordsOrRaise(Object callee, Object[] arguments, PKeyword[] unusedKeywords, int unusedKeywordCount, int tooManyKeywords, String lastWrongKeyword,
590+
List<String> posArgOnlyPassedAsKeywordNames, BranchProfile posArgOnlyPassedAsKeywordProfile, PRaiseNode raise) {
570591
if (tooManyKeywords == 1) {
571592
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.GOT_UNEXPECTED_KEYWORD_ARG, CreateArgumentsNode.getName(callee), lastWrongKeyword);
572593
} else if (tooManyKeywords > 1) {
573594
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.GOT_UNEXPECTED_KEYWORD_ARG, CreateArgumentsNode.getName(callee), tooManyKeywords);
595+
} else if (posArgOnlyPassedAsKeywordNames != null) {
596+
posArgOnlyPassedAsKeywordProfile.enter();
597+
String names = joinNames(posArgOnlyPassedAsKeywordNames);
598+
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.GOT_SOME_POS_ONLY_ARGS_PASSED_AS_KEYWORD, CreateArgumentsNode.getName(callee), names);
574599
} else if (unusedKeywords != null) {
575600
PArguments.setKeywordArguments(arguments, Arrays.copyOf(unusedKeywords, unusedKeywordCount));
576601
}
577602
}
578603

604+
@TruffleBoundary
605+
private static String joinNames(List<String> names) {
606+
return String.join(", ", names);
607+
}
608+
579609
@GenerateUncached
580610
protected abstract static class SearchNamedParameterNode extends Node {
581611
public abstract int execute(String[] parameters, String name);

graalpython/lib-python/3/test/test_positional_only_arg.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import dis
44
import pickle
55
import unittest
6-
6+
from test import support
77
from test.support import check_syntax_error
88

99

@@ -365,6 +365,7 @@ def test_serialization(self):
365365
with self.assertRaisesRegex(TypeError, expected):
366366
unpickled_defaults(a=1,b=2)
367367

368+
@support.impl_detail("async support", graalvm=False)
368369
def test_async(self):
369370

370371
async def f(a=1, /, b=2):
@@ -420,6 +421,7 @@ def method(self, /):
420421
def test_annotations(self):
421422
assert global_inner_has_pos_only().__annotations__ == {'x': int}
422423

424+
@support.impl_detail("bytecode, compiler instructions", graalvm=False)
423425
def test_annotations_constant_fold(self):
424426
def g():
425427
def f(x: not (int is int), /): ...

0 commit comments

Comments
 (0)