Skip to content

Commit 696a0f7

Browse files
committed
Builtin exceptions: allow deletion of builtin attributes as well
1 parent fb229ba commit 696a0f7

13 files changed

+189
-107
lines changed

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

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,41 @@ default Object[] create() {
6666
}
6767
}
6868

69+
public final Object get(PBaseException self, int index, StorageFactory factory) {
70+
return execute(self, PNone.NO_VALUE, index, factory);
71+
}
72+
73+
public final int getInt(PBaseException self, int index, StorageFactory factory) {
74+
final Object val = execute(self, PNone.NO_VALUE, index, factory);
75+
assert val instanceof Integer : "expected PBaseException attribute to be an integer";
76+
return (int) val;
77+
}
78+
79+
public final Object set(PBaseException self, Object value, int index, StorageFactory factory) {
80+
return execute(self, value, index, factory);
81+
}
82+
6983
public abstract Object execute(PBaseException self, Object value, int index, StorageFactory factory);
7084

7185
protected static boolean withAttributes(PBaseException self) {
7286
return self.getExceptionAttributes() != null;
7387
}
7488

89+
private Object[] ensureAttrStorage(PBaseException self, StorageFactory factory, SequenceStorageNodes.GetInternalObjectArrayNode getArrayNode, PythonObjectFactory objectFactory) {
90+
Object[] attributes = self.getExceptionAttributes();
91+
if (attributes == null) {
92+
// TODO: cbasca should we raise in case getArgs() is null (due to lazy init of args)?
93+
Object[] args = PythonUtils.EMPTY_OBJECT_ARRAY;
94+
if (self.getArgs() != null) {
95+
args = getArrayNode.execute(self.getArgs().getSequenceStorage());
96+
}
97+
attributes = factory.create(args, objectFactory);
98+
self.setExceptionAttributes(attributes);
99+
}
100+
return attributes;
101+
}
102+
103+
// GET
75104
@Specialization(guards = {"isNoValue(none)", "withAttributes(self)"})
76105
public Object getAttrWithStorage(PBaseException self, @SuppressWarnings("unused") PNone none, int index, @SuppressWarnings("unused") StorageFactory factory) {
77106
Object[] attributes = self.getExceptionAttributes();
@@ -84,42 +113,44 @@ public Object getAttrWithStorage(PBaseException self, @SuppressWarnings("unused"
84113
public Object getAttrNoStorage(PBaseException self, @SuppressWarnings("unused") PNone none, int index, StorageFactory factory,
85114
@Cached SequenceStorageNodes.GetInternalObjectArrayNode getArrayNode,
86115
@Cached PythonObjectFactory objectFactory) {
87-
Object[] attributes = self.getExceptionAttributes();
88-
if (attributes == null) {
89-
// TODO: cbasca should we raise in cast getArgs() is null (lazy init)?
90-
Object[] args = PythonUtils.EMPTY_OBJECT_ARRAY;
91-
if (self.getArgs() != null) {
92-
args = getArrayNode.execute(self.getArgs().getSequenceStorage());
93-
}
94-
attributes = factory.create(args, objectFactory);
95-
self.setExceptionAttributes(attributes);
96-
}
116+
Object[] attributes = ensureAttrStorage(self, factory, getArrayNode, objectFactory);
97117
assert attributes != null : "PBaseException attributes field is null";
98118
return getAttrWithStorage(self, none, index, factory);
99119
}
100120

101-
@Specialization(guards = {"!isNoValue(value)", "withAttributes(self)"})
121+
// SET
122+
@Specialization(guards = {"!isNoValue(value)", "!isDeleteMarker(value)", "withAttributes(self)"})
102123
public Object setAttrWithStorage(PBaseException self, Object value, int index, @SuppressWarnings("unused") StorageFactory factory) {
103124
Object[] attributes = self.getExceptionAttributes();
104125
assert index >= 0 && index < attributes.length : "PBaseException attribute index is out of range";
105126
attributes[index] = value;
106127
return PNone.NONE;
107128
}
108129

109-
@Specialization(guards = {"!isNoValue(value)", "!withAttributes(self)"})
130+
@Specialization(guards = {"!isNoValue(value)", "!isDeleteMarker(value)", "!withAttributes(self)"})
110131
public Object setAttrNoStorage(PBaseException self, Object value, int index, StorageFactory factory,
111132
@Cached SequenceStorageNodes.GetInternalObjectArrayNode getArrayNode,
112133
@Cached PythonObjectFactory objectFactory) {
113-
Object[] attributes = self.getExceptionAttributes();
114-
if (attributes == null) {
115-
// TODO: cbasca should we raise in cast getArgs() is null (lazy init)?
116-
Object[] args = PythonUtils.EMPTY_OBJECT_ARRAY;
117-
if (self.getArgs() != null) {
118-
args = getArrayNode.execute(self.getArgs().getSequenceStorage());
119-
}
120-
attributes = factory.create(args, objectFactory);
121-
self.setExceptionAttributes(attributes);
122-
}
134+
Object[] attributes = ensureAttrStorage(self, factory, getArrayNode, objectFactory);
135+
assert attributes != null : "PBaseException attributes field is null";
123136
return setAttrWithStorage(self, value, index, factory);
124137
}
138+
139+
// DEL
140+
@Specialization(guards = {"!isNoValue(value)", "isDeleteMarker(value)", "withAttributes(self)"})
141+
public Object delAttrWithStorage(PBaseException self, @SuppressWarnings("unused") Object value, int index, @SuppressWarnings("unused") StorageFactory factory) {
142+
Object[] attributes = self.getExceptionAttributes();
143+
assert index >= 0 && index < attributes.length : "PBaseException attribute index is out of range";
144+
attributes[index] = null;
145+
return PNone.NONE;
146+
}
147+
148+
@Specialization(guards = {"!isNoValue(value)", "isDeleteMarker(value)", "!withAttributes(self)"})
149+
public Object delAttrNoStorage(PBaseException self, Object value, int index, StorageFactory factory,
150+
@Cached SequenceStorageNodes.GetInternalObjectArrayNode getArrayNode,
151+
@Cached PythonObjectFactory objectFactory) {
152+
Object[] attributes = ensureAttrStorage(self, factory, getArrayNode, objectFactory);
153+
assert attributes != null : "PBaseException attributes field is null";
154+
return delAttrWithStorage(self, value, index, factory);
155+
}
125156
}

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ Object init(PBaseException self, Object[] args, PKeyword[] kwargs,
117117
}
118118
}
119119

120-
@Builtin(name = "msg", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "exception message")
120+
@Builtin(name = "msg", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "exception message")
121121
@GenerateNodeFactory
122122
public abstract static class ImportErrorMsgNode extends PythonBuiltinNode {
123123
@Specialization
@@ -127,7 +127,7 @@ Object generic(PBaseException self, Object value,
127127
}
128128
}
129129

130-
@Builtin(name = "name", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "module name")
130+
@Builtin(name = "name", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "module name")
131131
@GenerateNodeFactory
132132
public abstract static class ImportErrorNameNode extends PythonBuiltinNode {
133133
@Specialization
@@ -137,7 +137,7 @@ Object generic(PBaseException self, Object value,
137137
}
138138
}
139139

140-
@Builtin(name = "path", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "module path")
140+
@Builtin(name = "path", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "module path")
141141
@GenerateNodeFactory
142142
public abstract static class ImportErrorPathNode extends PythonBuiltinNode {
143143
@Specialization
@@ -150,11 +150,10 @@ Object generic(PBaseException self, Object value,
150150
@Builtin(name = __REDUCE__, minNumOfPositionalArgs = 1)
151151
@GenerateNodeFactory
152152
public abstract static class ImportErrorReduceNode extends PythonUnaryBuiltinNode {
153-
private Object getState(PBaseException self, GetDictIfExistsNode getDictIfExistsNode, HashingStorageLibrary hashlib) {
154-
assert self.getExceptionAttributes() != null;
153+
private Object getState(PBaseException self, GetDictIfExistsNode getDictIfExistsNode, HashingStorageLibrary hashlib, BaseExceptionAttrNode attrNode) {
155154
PDict dict = getDictIfExistsNode.execute(self);
156-
final Object name = self.getExceptionAttribute(IDX_NAME);
157-
final Object path = self.getExceptionAttribute(IDX_PATH);
155+
final Object name = attrNode.get(self, IDX_NAME, IMPORT_ERROR_ATTR_FACTORY);
156+
final Object path = attrNode.get(self, IDX_PATH, IMPORT_ERROR_ATTR_FACTORY);
158157
if (name != null || path != null) {
159158
HashingStorage storage = (dict != null) ? hashlib.copy(dict.getDictStorage()) : EmptyStorage.INSTANCE;
160159
if (name != null) {
@@ -173,13 +172,14 @@ private Object getState(PBaseException self, GetDictIfExistsNode getDictIfExists
173172

174173
@Specialization
175174
Object reduce(VirtualFrame frame, PBaseException self,
175+
@Cached BaseExceptionAttrNode attrNode,
176176
@Cached GetClassNode getClassNode,
177177
@Cached GetDictIfExistsNode getDictIfExistsNode,
178178
@Cached BaseExceptionBuiltins.ArgsNode argsNode,
179179
@CachedLibrary(limit = "getCallSiteInlineCacheMaxDepth()") HashingStorageLibrary hashlib) {
180180
Object clazz = getClassNode.execute(self);
181181
Object args = argsNode.executeObject(frame, self, PNone.NO_VALUE);
182-
Object state = getState(self, getDictIfExistsNode, hashlib);
182+
Object state = getState(self, getDictIfExistsNode, hashlib, attrNode);
183183
if (state == PNone.NONE) {
184184
return factory().createTuple(new Object[]{clazz, args});
185185
}
@@ -192,10 +192,11 @@ Object reduce(VirtualFrame frame, PBaseException self,
192192
public abstract static class ImportErrorStrNode extends PythonUnaryBuiltinNode {
193193
@Specialization
194194
Object str(VirtualFrame frame, PBaseException self,
195+
@Cached BaseExceptionAttrNode attrNode,
195196
@Cached BaseExceptionBuiltins.StrNode exStrNode,
196197
@Cached PyUnicodeCheckExactNode unicodeCheckExactNode) {
197198
assert self.getExceptionAttributes() != null;
198-
final Object msg = self.getExceptionAttribute(IDX_MSG);
199+
final Object msg = attrNode.get(self, IDX_MSG, IMPORT_ERROR_ATTR_FACTORY);
199200
if (msg != null && unicodeCheckExactNode.execute(msg)) {
200201
return msg;
201202
} else {

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

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ public static OSErrorInitNode create() {
324324
}
325325
}
326326

327-
@Builtin(name = "errno", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "POSIX exception code")
327+
@Builtin(name = "errno", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "POSIX exception code")
328328
@GenerateNodeFactory
329329
public abstract static class OSErrorErrnoNode extends PythonBuiltinNode {
330330
@Specialization
@@ -334,7 +334,7 @@ Object generic(PBaseException self, Object value,
334334
}
335335
}
336336

337-
@Builtin(name = "strerror", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "exception strerror")
337+
@Builtin(name = "strerror", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "exception strerror")
338338
@GenerateNodeFactory
339339
public abstract static class OSErrorStrerrorNode extends PythonBuiltinNode {
340340
@Specialization
@@ -344,7 +344,7 @@ Object generic(PBaseException self, Object value,
344344
}
345345
}
346346

347-
@Builtin(name = "filename", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "exception filename")
347+
@Builtin(name = "filename", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "exception filename")
348348
@GenerateNodeFactory
349349
public abstract static class OSErrorFilenameNode extends PythonBuiltinNode {
350350
@Specialization
@@ -354,7 +354,7 @@ Object generic(PBaseException self, Object value,
354354
}
355355
}
356356

357-
@Builtin(name = "filename2", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "exception filename2")
357+
@Builtin(name = "filename2", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "exception filename2")
358358
@GenerateNodeFactory
359359
public abstract static class OSErrorFilename2Node extends PythonBuiltinNode {
360360
@Specialization
@@ -364,7 +364,7 @@ Object generic(PBaseException self, Object value,
364364
}
365365
}
366366

367-
@Builtin(name = "winerror", os = PythonOS.PLATFORM_WIN32, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "Win32 exception code")
367+
@Builtin(name = "winerror", os = PythonOS.PLATFORM_WIN32, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "Win32 exception code")
368368
@GenerateNodeFactory
369369
public abstract static class OSErrorWinerrorNode extends PythonBuiltinNode {
370370
@Specialization
@@ -374,7 +374,7 @@ Object generic(PBaseException self, Object value,
374374
}
375375
}
376376

377-
@Builtin(name = "characters_written", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "exception characters written")
377+
@Builtin(name = "characters_written", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "exception characters written")
378378
@GenerateNodeFactory
379379
public abstract static class OSErrorCharsWrittenNode extends PythonBuiltinNode {
380380
protected boolean isInvalid(PBaseException self) {
@@ -383,14 +383,20 @@ protected boolean isInvalid(PBaseException self) {
383383
}
384384

385385
@Specialization(guards = "isInvalid(self)")
386+
@SuppressWarnings("unused")
386387
Object generic(PBaseException self, Object value) {
387388
throw raise(PythonBuiltinClassType.AttributeError, "characters_written");
388389
}
389390

390391
@Specialization(guards = "!isInvalid(self)")
391392
Object generic(PBaseException self, Object value,
392393
@Cached BaseExceptionAttrNode attrNode) {
393-
return attrNode.execute(self, value, IDX_WRITTEN, OS_ERROR_ATTR_FACTORY);
394+
final Object retVal = attrNode.execute(self, value, IDX_WRITTEN, OS_ERROR_ATTR_FACTORY);
395+
if (PGuards.isDeleteMarker(value)) {
396+
// reset the internal state
397+
self.getExceptionAttributes()[IDX_WRITTEN] = -1;
398+
}
399+
return retVal;
394400
}
395401
}
396402

@@ -399,15 +405,16 @@ Object generic(PBaseException self, Object value,
399405
public abstract static class OSErrorStrNode extends PythonUnaryBuiltinNode {
400406
@Specialization
401407
Object str(VirtualFrame frame, PBaseException self,
408+
@Cached BaseExceptionAttrNode attrNode,
402409
@Cached BaseExceptionBuiltins.StrNode baseStrNode,
403410
@Cached PyObjectReprAsJavaStringNode reprNode) {
404411
// TODO: missing windows code
405-
final Object filename = self.getExceptionAttribute(IDX_FILENAME);
406-
final Object filename2 = self.getExceptionAttribute(IDX_FILENAME2);
407-
final Object errno = self.getExceptionAttribute(IDX_ERRNO);
408-
final Object strerror = self.getExceptionAttribute(IDX_STRERROR);
409-
if (filename != null && filename != PNone.NONE) {
410-
if (filename2 != null && filename2 != PNone.NONE) {
412+
final Object filename = attrNode.get(self, IDX_FILENAME, OS_ERROR_ATTR_FACTORY);
413+
final Object filename2 = attrNode.get(self, IDX_FILENAME2, OS_ERROR_ATTR_FACTORY);
414+
final Object errno = attrNode.get(self, IDX_ERRNO, OS_ERROR_ATTR_FACTORY);
415+
final Object strerror = attrNode.get(self, IDX_STRERROR, OS_ERROR_ATTR_FACTORY);
416+
if (filename != PNone.NONE) {
417+
if (filename2 != PNone.NONE) {
411418
return PythonUtils.format("[Errno %s] %s: %s -> %s",
412419
errno != null ? errno : PNone.NONE,
413420
strerror != null ? strerror : PNone.NONE,
@@ -420,7 +427,7 @@ Object str(VirtualFrame frame, PBaseException self,
420427
reprNode.execute(frame, filename));
421428
}
422429
}
423-
if (errno != null && strerror != null) {
430+
if (errno != PNone.NONE && strerror != PNone.NONE) {
424431
return PythonUtils.format("[Errno %s] %s", errno, strerror);
425432
}
426433
return baseStrNode.execute(frame, self);
@@ -432,13 +439,14 @@ Object str(VirtualFrame frame, PBaseException self,
432439
public abstract static class OSErrorReduceNode extends PythonUnaryBuiltinNode {
433440
@Specialization
434441
Object reduce(VirtualFrame frame, PBaseException self,
442+
@Cached BaseExceptionAttrNode attrNode,
435443
@Cached GetClassNode getClassNode,
436444
@Cached GetDictIfExistsNode getDictNode,
437445
@Cached SequenceStorageNodes.GetItemNode getItemNode,
438446
@Cached SequenceStorageNodes.LenNode lenNode) {
439447
PTuple args = self.getArgs();
440-
final Object filename = self.getExceptionAttribute(IDX_FILENAME);
441-
final Object filename2 = self.getExceptionAttribute(IDX_FILENAME2);
448+
final Object filename = attrNode.get(self, IDX_FILENAME, OS_ERROR_ATTR_FACTORY);
449+
final Object filename2 = attrNode.get(self, IDX_FILENAME2, OS_ERROR_ATTR_FACTORY);
442450
if (lenNode.execute(args.getSequenceStorage()) == 2 && filename != null) {
443451
Object[] argData = new Object[filename2 != null ? 5 : 3];
444452
argData[0] = getItemNode.execute(frame, args.getSequenceStorage(), 0);

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,6 @@ public Object getExceptionAttribute(int idx) {
126126
return exceptionAttributes[idx];
127127
}
128128

129-
public int getExceptionIntAttribute(int idx) {
130-
final Object val = getExceptionAttribute(idx);
131-
assert val instanceof Integer : "expected PBaseException attribute to be an integer";
132-
return (int) val;
133-
}
134-
135129
public Object[] getExceptionAttributes() {
136130
return exceptionAttributes;
137131
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Object init(PBaseException self, Object[] args,
7878
}
7979
}
8080

81-
@Builtin(name = "value", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, doc = "generator return value")
81+
@Builtin(name = "value", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "generator return value")
8282
@GenerateNodeFactory
8383
public abstract static class StopIterationValueNode extends PythonBuiltinNode {
8484
@Specialization

0 commit comments

Comments
 (0)