Skip to content

Commit e76baa0

Browse files
committed
[GR-23226] Make test_exceptions.testAttributes pass
PullRequest: graalpython/1004
2 parents e4b01a8 + 28bb81e commit e76baa0

File tree

9 files changed

+180
-29
lines changed

9 files changed

+180
-29
lines changed

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import static com.oracle.graal.python.runtime.exception.PythonErrorType.UnicodeDecodeError;
4646
import static com.oracle.graal.python.runtime.exception.PythonErrorType.UnicodeEncodeError;
4747

48+
import java.nio.BufferUnderflowException;
4849
import java.nio.ByteBuffer;
4950
import java.nio.CharBuffer;
5051
import java.nio.charset.CharacterCodingException;
@@ -311,7 +312,7 @@ Object encode(VirtualFrame frame, Object bytes, @SuppressWarnings("unused") Stri
311312

312313
@TruffleBoundary
313314
private static String strFromBytes(byte[] execute) {
314-
return new String(execute);
315+
return new String(execute, StandardCharsets.ISO_8859_1);
315316
}
316317
}
317318

@@ -423,7 +424,8 @@ private Object[] encodeString(String self, String errors) {
423424
try {
424425
ByteBuffer encoded = UTF32.newEncoder().onMalformedInput(errorAction).onUnmappableCharacter(errorAction).encode(CharBuffer.wrap(self));
425426
int n = encoded.remaining();
426-
ByteBuffer buf = ByteBuffer.allocate(n);
427+
// Worst case is 6 bytes ("\\uXXXX") for every java char
428+
ByteBuffer buf = ByteBuffer.allocate(self.length() * 6);
427429
assert n % Integer.BYTES == 0;
428430
int codePoints = n / Integer.BYTES;
429431

@@ -432,9 +434,7 @@ private Object[] encodeString(String self, String errors) {
432434
if (codePoint <= 0xFF) {
433435
buf.put((byte) codePoint);
434436
} else {
435-
buf.put((byte) '\\');
436-
buf.put((byte) 'u');
437-
String hexString = Integer.toHexString(codePoint);
437+
String hexString = String.format((codePoint <= 0xFFFF ? "\\u%04x" : "\\U%08x"), codePoint);
438438
for (int i = 0; i < hexString.length(); i++) {
439439
assert hexString.charAt(i) < 128;
440440
buf.put((byte) hexString.charAt(i));
@@ -587,28 +587,32 @@ String decodeBytes(ByteBuffer bytes, String errors) {
587587
CodingErrorAction errorAction = convertCodingErrorAction(errors);
588588
try {
589589
ByteBuffer buf = ByteBuffer.allocate(bytes.remaining() * Integer.BYTES);
590+
byte[] hexString = new byte[8];
590591
while (bytes.hasRemaining()) {
591592
int val;
592593
byte b = bytes.get();
593594
if (b == (byte) '\\') {
594595
byte b1 = bytes.get();
595596
if (b1 == (byte) 'u') {
596-
// read 2 bytes as integer
597-
val = bytes.getShort();
597+
bytes.get(hexString, 0, 4);
598+
val = Integer.parseInt(new String(hexString, 0, 4), 16);
598599
} else if (b1 == (byte) 'U') {
599-
val = bytes.getInt();
600+
bytes.get(hexString, 0, 8);
601+
val = Integer.parseInt(new String(hexString, 0, 8), 16);
600602
} else {
601603
throw new CharacterCodingException();
602604
}
603605
} else {
604-
val = b;
606+
// Bytes that are not an escape sequence are latin-1, which maps to unicode
607+
// codepoints directly
608+
val = b & 0xFF;
605609
}
606610
buf.putInt(val);
607611
}
608612
buf.flip();
609613
CharBuffer decoded = UTF32.newDecoder().onMalformedInput(errorAction).onUnmappableCharacter(errorAction).decode(buf);
610614
return String.valueOf(decoded);
611-
} catch (CharacterCodingException e) {
615+
} catch (CharacterCodingException | NumberFormatException | BufferUnderflowException e) {
612616
throw raise(UnicodeDecodeError, e);
613617
}
614618
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.builtins.modules;
2727

28+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.EOFError;
2829
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
2930
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
3031

@@ -565,7 +566,11 @@ public void reset() {
565566
}
566567

567568
private int readByte() {
568-
return data[index++];
569+
if (index < data.length) {
570+
return data[index++];
571+
} else {
572+
throw raise(EOFError, "EOF read where not expected");
573+
}
569574
}
570575

571576
private int readInt() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesBuiltins.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -444,33 +444,51 @@ public abstract static class RMulNode extends MulNode {
444444
@GenerateNodeFactory
445445
public abstract static class ReprNode extends PythonUnaryBuiltinNode {
446446
@TruffleBoundary
447-
private static final StringBuilder newStringBuilder() {
448-
return new StringBuilder("b'");
447+
private static StringBuilder newStringBuilder() {
448+
return new StringBuilder();
449449
}
450450

451451
@TruffleBoundary
452-
private static final String sbFinishAndToString(StringBuilder sb) {
453-
sb.append("'");
452+
private static String sbToString(StringBuilder sb) {
454453
return sb.toString();
455454
}
456455

456+
@TruffleBoundary
457+
private static void sbAppend(StringBuilder sb, String s) {
458+
sb.append(s);
459+
}
460+
457461
@Specialization
458462
public Object repr(VirtualFrame frame, PBytes self,
459463
@Cached SequenceStorageNodes.LenNode lenNode,
460464
@Cached SequenceStorageNodes.GetItemNode getItemNode) {
461465
SequenceStorage store = self.getSequenceStorage();
462466
int len = lenNode.execute(store);
463467
StringBuilder sb = newStringBuilder();
468+
sbAppend(sb, "b'");
464469
for (int i = 0; i < len; i++) {
465470
BytesUtils.byteRepr(sb, (byte) getItemNode.executeInt(frame, store, i));
466471
}
467-
return sbFinishAndToString(sb);
472+
sbAppend(sb, "'");
473+
return sbToString(sb);
468474
}
469475

470476
@Specialization
471-
public Object repr(PByteArray self, @Cached("create()") TypeNodes.GetNameNode getNameNode) {
477+
public Object repr(VirtualFrame frame, PByteArray self,
478+
@Cached("create()") TypeNodes.GetNameNode getNameNode,
479+
@Cached SequenceStorageNodes.LenNode lenNode,
480+
@Cached SequenceStorageNodes.GetItemNode getItemNode) {
472481
String typeName = getNameNode.execute(self.getLazyPythonClass());
473-
return self.formatByteArray(typeName);
482+
SequenceStorage store = self.getSequenceStorage();
483+
int len = lenNode.execute(store);
484+
StringBuilder sb = newStringBuilder();
485+
sb.append(typeName);
486+
sb.append("(b'");
487+
for (int i = 0; i < len; i++) {
488+
BytesUtils.byteRepr(sb, (byte) getItemNode.executeInt(frame, store, i));
489+
}
490+
sb.append("')");
491+
return sbToString(sb);
474492
}
475493
}
476494

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/BaseExceptionBuiltins.java

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
2929
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CAUSE__;
3030
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CONTEXT__;
31+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
3132
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SUPPRESS_CONTEXT__;
3233
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__TRACEBACK__;
3334
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT__;
35+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REDUCE__;
3436

3537
import java.util.IllegalFormatException;
3638
import java.util.List;
@@ -40,16 +42,21 @@
4042
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4143
import com.oracle.graal.python.builtins.PythonBuiltins;
4244
import com.oracle.graal.python.builtins.objects.PNone;
45+
import com.oracle.graal.python.builtins.objects.common.PHashingCollection;
4346
import com.oracle.graal.python.builtins.objects.list.PList;
47+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
4448
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
4549
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
50+
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
4651
import com.oracle.graal.python.nodes.ErrorMessages;
4752
import com.oracle.graal.python.nodes.PGuards;
4853
import com.oracle.graal.python.nodes.PRaiseNode;
54+
import com.oracle.graal.python.nodes.argument.ReadArgumentNode;
4955
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
5056
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5157
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
5258
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
59+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
5360
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
5461
import com.oracle.graal.python.nodes.util.CannotCastException;
5562
import com.oracle.graal.python.nodes.util.CastToJavaBooleanNode;
@@ -64,6 +71,8 @@
6471
import com.oracle.truffle.api.dsl.NodeFactory;
6572
import com.oracle.truffle.api.dsl.Specialization;
6673
import com.oracle.truffle.api.frame.VirtualFrame;
74+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
75+
import com.oracle.truffle.api.library.CachedLibrary;
6776
import com.oracle.truffle.api.profiles.ConditionProfile;
6877

6978
@CoreFunctions(extendClasses = PythonBuiltinClassType.PBaseException)
@@ -147,7 +156,11 @@ public Object args(VirtualFrame frame, PBaseException self, Object value,
147156
return PNone.NONE;
148157
}
149158

150-
public abstract Object executeObject(VirtualFrame frame, Object excObj);
159+
public abstract Object executeObject(VirtualFrame frame, Object excObj, Object value);
160+
161+
public static ArgsNode create() {
162+
return BaseExceptionBuiltinsFactory.ArgsNodeFactory.create(new ReadArgumentNode[]{});
163+
}
151164
}
152165

153166
@Builtin(name = __CAUSE__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
@@ -226,7 +239,7 @@ public Object setSuppressContext(PBaseException self, Object value,
226239
try {
227240
self.setSuppressContext(castToJavaBooleanNode.execute(value));
228241
} catch (CannotCastException e) {
229-
raise(TypeError, ErrorMessages.ATTR_VALUE_MUST_BE_BOOL);
242+
throw raise(TypeError, ErrorMessages.ATTR_VALUE_MUST_BE_BOOL);
230243
}
231244
return PNone.NONE;
232245
}
@@ -277,4 +290,50 @@ PBaseException doSetTraceback(PBaseException self, PTraceback tb) {
277290
return self;
278291
}
279292
}
293+
294+
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
295+
@GenerateNodeFactory
296+
abstract static class DictNode extends PythonBinaryBuiltinNode {
297+
@Specialization(limit = "1")
298+
PNone dict(PBaseException self, PHashingCollection mapping,
299+
@CachedLibrary("self") PythonObjectLibrary lib) {
300+
try {
301+
lib.setDict(self, mapping);
302+
} catch (UnsupportedMessageException e) {
303+
CompilerDirectives.transferToInterpreterAndInvalidate();
304+
throw new IllegalStateException(e);
305+
}
306+
return PNone.NONE;
307+
}
308+
309+
@Specialization(guards = "isNoValue(mapping)", limit = "1")
310+
Object dict(PBaseException self, @SuppressWarnings("unused") PNone mapping,
311+
@CachedLibrary("self") PythonObjectLibrary lib) {
312+
PHashingCollection dict = lib.getDict(self);
313+
if (dict == null) {
314+
dict = factory().createDictFixedStorage(self);
315+
try {
316+
lib.setDict(self, dict);
317+
} catch (UnsupportedMessageException e) {
318+
CompilerDirectives.transferToInterpreterAndInvalidate();
319+
throw new IllegalStateException(e);
320+
}
321+
}
322+
return dict;
323+
}
324+
}
325+
326+
@Builtin(name = __REDUCE__, minNumOfPositionalArgs = 1)
327+
@GenerateNodeFactory
328+
public abstract static class ReduceNode extends PythonUnaryBuiltinNode {
329+
@Specialization(limit = "1")
330+
Object reduce(VirtualFrame frame, PBaseException self,
331+
@CachedLibrary("self") PythonObjectLibrary lib,
332+
@Cached ArgsNode argsNode) {
333+
LazyPythonClass clazz = lib.getLazyPythonClass(self);
334+
Object args = argsNode.executeObject(frame, self, PNone.NO_VALUE);
335+
Object dict = lib.lookupAttribute(self, __DICT__);
336+
return factory().createTuple(new Object[]{clazz, args, dict});
337+
}
338+
}
280339
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ protected boolean isInBuiltinFunctionRoot() {
216216
protected ReadLocalVariableNode createRead(VirtualFrame frame) {
217217
FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(SpecialAttributeNames.__CLASS__);
218218
if (slot == null) {
219-
throw raise(PythonErrorType.RuntimeError, ErrorMessages.EMPTY_CLASS_CELL);
219+
throw raise(PythonErrorType.RuntimeError, ErrorMessages.SUPER_NO_CLASS);
220220
}
221221
return ReadLocalVariableNode.create(slot);
222222
}
@@ -238,7 +238,7 @@ PNone initInPlace(VirtualFrame frame, SuperObject self, @SuppressWarnings("unuse
238238
cls = getGetRefNode().execute((PCell) cls);
239239
}
240240
if (cls == PNone.NONE) {
241-
throw raise(PythonErrorType.RuntimeError, ErrorMessages.EMPTY_CLASS_CELL, "super()");
241+
throw raise(PythonErrorType.RuntimeError, ErrorMessages.SUPER_NO_CLASS);
242242
}
243243
return init(frame, self, cls, obj);
244244
}
@@ -276,7 +276,7 @@ private Object getClassFromTarget(VirtualFrame frame, PFrame target, HashingStor
276276
if (cls instanceof PCell) {
277277
cls = getGetRefNode().execute((PCell) cls);
278278
if (cls == null) {
279-
throw raise(PythonErrorType.RuntimeError, ErrorMessages.EMPTY_CLASS_CELL, "super()");
279+
throw raise(PythonErrorType.RuntimeError, ErrorMessages.SUPER_NO_CLASS);
280280
}
281281
}
282282
return cls != null ? cls : PNone.NONE;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public abstract class ErrorMessages {
167167
public static final String DICT_UPDATE_SEQ_ELEM_HAS_LENGTH_2_REQUIRED = "dictionary update sequence element #%d has length %d; 2 is required";
168168
public static final String DIVISION_BY_ZERO = "division by zero";
169169
public static final String S_DIVISION_BY_ZERO = "%s division by zero";
170-
public static final String EMPTY_CLASS_CELL = "%s: empty __class__ cell";
170+
public static final String SUPER_NO_CLASS = "super(): no arguments";
171171
public static final String EMPTY_SEPARATOR = "empty separator";
172172
public static final String EMPTY_STR_FOR_COMPLEX = "empty string for complex()";
173173
public static final String END_MUST_BE_NONE_OR_STRING = "end must be None or a string, not %p";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
408408
ft.format(((PString) arg).getCharSequence());
409409
} else {
410410
// It couldn't be converted, raise the error here
411-
throw core.raise(TypeError, ErrorMessages.REQUIRES_INT_OR_CHAR);
411+
throw core.raise(TypeError, ErrorMessages.REQUIRES_INT_OR_CHAR, spec.type);
412412
}
413413

414414
break;

0 commit comments

Comments
 (0)