Skip to content

Commit 069179f

Browse files
committed
[GR-23238] [GR-21120] Accept buffer-like object in int() constructor
PullRequest: graalpython/1089
2 parents c416fba + 071e681 commit 069179f

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_base_bad_types
44
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_base_indexable
55
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_base_limits
6+
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_memoryview
67
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_subclass_with_index
78
*graalpython.lib-python.3.test.test_int.IntTestCases.test_int_subclass_with_int
89
*graalpython.lib-python.3.test.test_int.IntTestCases.test_intconversion
910
*graalpython.lib-python.3.test.test_int.IntTestCases.test_issue31619
1011
*graalpython.lib-python.3.test.test_int.IntTestCases.test_keyword_args
1112
*graalpython.lib-python.3.test.test_int.IntTestCases.test_no_args
13+
*graalpython.lib-python.3.test.test_int.IntTestCases.test_non_numeric_input_types
1214
*graalpython.lib-python.3.test.test_int.IntTestCases.test_small_ints
1315
*graalpython.lib-python.3.test.test_int.IntTestCases.test_string_float

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,7 @@ private HashingCollectionNodes.SetItemNode getSetItemNode() {
11401140
// int(x, base=10)
11411141
@Builtin(name = INT, minNumOfPositionalArgs = 1, parameterNames = {"cls", "x", "base"}, numOfPositionalOnlyArgs = 2, constructsClass = PythonBuiltinClassType.PInt)
11421142
@GenerateNodeFactory
1143+
@ReportPolymorphism
11431144
public abstract static class IntNode extends PythonTernaryBuiltinNode {
11441145

11451146
private final ConditionProfile invalidBase = ConditionProfile.createBinaryProfile();
@@ -1528,8 +1529,9 @@ Object fail(Object cls, Object arg, Object base) {
15281529
throw raise(TypeError, ErrorMessages.INT_CANT_CONVERT_STRING_WITH_EXPL_BASE);
15291530
}
15301531

1531-
@Specialization(guards = {"isNoValue(base)", "!isNoValue(obj)", "!isHandledType(obj)"})
1532-
Object createIntGeneric(VirtualFrame frame, Object cls, Object obj, @SuppressWarnings("unused") PNone base) {
1532+
@Specialization(guards = {"isNoValue(base)", "!isNoValue(obj)", "!isHandledType(obj)"}, limit = "2")
1533+
Object createIntGeneric(VirtualFrame frame, Object cls, Object obj, @SuppressWarnings("unused") PNone base,
1534+
@CachedLibrary("obj") PythonObjectLibrary lib) {
15331535
// This method (together with callInt and callIndex) reflects the logic of PyNumber_Long
15341536
// in CPython. We don't use PythonObjectLibrary here since the original CPython function
15351537
// does not use any of the conversion functions (such as _PyLong_AsInt or
@@ -1545,7 +1547,17 @@ Object createIntGeneric(VirtualFrame frame, Object cls, Object obj, @SuppressWar
15451547
if (result == PNone.NO_VALUE) {
15461548
Object truncResult = callTrunc(frame, obj);
15471549
if (truncResult == PNone.NO_VALUE) {
1548-
throw raise(TypeError, ErrorMessages.ARG_MUST_BE_STRING_OR_BYTELIKE_OR_NUMBER, "int()", obj);
1550+
if (lib.isBuffer(obj)) {
1551+
try {
1552+
byte[] bytes = lib.getBufferBytes(obj);
1553+
return stringToInt(frame, cls, toString(bytes), 10, obj);
1554+
} catch (UnsupportedMessageException e) {
1555+
CompilerDirectives.transferToInterpreterAndInvalidate();
1556+
throw new IllegalStateException("Object claims to be a buffer but does not support getBufferBytes()");
1557+
}
1558+
} else {
1559+
throw raise(TypeError, ErrorMessages.ARG_MUST_BE_STRING_OR_BYTELIKE_OR_NUMBER, "int()", obj);
1560+
}
15491561
}
15501562
if (isIntegerType(truncResult)) {
15511563
result = truncResult;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/PArray.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.array;
2727

28+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
29+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
2830
import com.oracle.graal.python.runtime.sequence.PMutableSequence;
2931
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
32+
import com.oracle.truffle.api.dsl.Cached;
33+
import com.oracle.truffle.api.library.ExportLibrary;
34+
import com.oracle.truffle.api.library.ExportMessage;
3035
import com.oracle.truffle.api.object.DynamicObject;
3136

37+
@ExportLibrary(PythonObjectLibrary.class)
3238
public class PArray extends PMutableSequence {
3339

3440
private SequenceStorage store;
@@ -55,4 +61,24 @@ public void setSequenceStorage(SequenceStorage store) {
5561
public int len() {
5662
return store.length();
5763
}
64+
65+
@ExportMessage
66+
boolean isBuffer() {
67+
return true;
68+
}
69+
70+
@ExportMessage
71+
byte[] getBufferBytes(
72+
@Cached SequenceStorageNodes.ToByteArrayNode toByteArrayNode) {
73+
// TODO Implement access to the actual bytes which represent the array in memory.
74+
// This implementation only works for ByteSequenceStorage.
75+
return toByteArrayNode.execute(store);
76+
}
77+
78+
@ExportMessage
79+
int getBufferLength(
80+
@Cached SequenceStorageNodes.LenNode lenNode) {
81+
// TODO This only works for ByteSequenceStorage since its itemsize is 1.
82+
return lenNode.execute(store);
83+
}
5884
}

mx.graalpython/native-image.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Requires = language:regex language:llvm
55

66
JavaArgs = -Xmx4G -Dpolyglot.image-build-time.PreinitializeContexts=python
77

8-
Args = -H:MaxRuntimeCompileMethods=8600 \
8+
Args = -H:MaxRuntimeCompileMethods=8700 \
99
-H:+AddAllCharsets \
1010
--initialize-at-build-time=com.oracle.graal.python,com.oracle.truffle.regex,org.antlr.v4,jline,org.fusesource \
1111
-H:SubstitutionResources=com/oracle/graal/python/aot/substitutions.json

0 commit comments

Comments
 (0)