40
40
*/
41
41
package com .oracle .graal .python .builtins .modules ;
42
42
43
+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .AttributeError ;
44
+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .ImportError ;
43
45
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .RuntimeError ;
46
+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .RuntimeWarning ;
44
47
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
45
48
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .UnicodeEncodeError ;
46
49
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .ValueError ;
61
64
import static com .oracle .graal .python .builtins .objects .traceback .TracebackNodes .objectRepr ;
62
65
import static com .oracle .graal .python .builtins .objects .traceback .TracebackNodes .objectStr ;
63
66
import static com .oracle .graal .python .builtins .objects .traceback .TracebackNodes .tryCastToString ;
67
+ import static com .oracle .graal .python .nodes .BuiltinNames .BREAKPOINTHOOK ;
64
68
import static com .oracle .graal .python .nodes .BuiltinNames .BUILTINS ;
65
69
import static com .oracle .graal .python .nodes .BuiltinNames .DISPLAYHOOK ;
66
70
import static com .oracle .graal .python .nodes .BuiltinNames .EXCEPTHOOK ;
71
+ import static com .oracle .graal .python .nodes .BuiltinNames .PYTHONBREAKPOINT ;
67
72
import static com .oracle .graal .python .nodes .BuiltinNames .STDERR ;
68
73
import static com .oracle .graal .python .nodes .BuiltinNames .STDIN ;
69
74
import static com .oracle .graal .python .nodes .BuiltinNames .STDOUT ;
70
75
import static com .oracle .graal .python .nodes .BuiltinNames .UNRAISABLEHOOK ;
76
+ import static com .oracle .graal .python .nodes .BuiltinNames .__BREAKPOINTHOOK__ ;
71
77
import static com .oracle .graal .python .nodes .BuiltinNames .__DISPLAYHOOK__ ;
72
78
import static com .oracle .graal .python .nodes .BuiltinNames .__EXCEPTHOOK__ ;
73
79
import static com .oracle .graal .python .nodes .BuiltinNames .__STDERR__ ;
76
82
import static com .oracle .graal .python .nodes .BuiltinNames .__UNRAISABLEHOOK__ ;
77
83
import static com .oracle .graal .python .nodes .ErrorMessages .ARG_TYPE_MUST_BE ;
78
84
import static com .oracle .graal .python .nodes .ErrorMessages .LOST_S ;
85
+ import static com .oracle .graal .python .nodes .ErrorMessages .WARN_CANNOT_RUN_PDB_YET ;
86
+ import static com .oracle .graal .python .nodes .ErrorMessages .WARN_IGNORE_UNIMPORTABLE_BREAKPOINT_S ;
79
87
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__ ;
80
88
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__MODULE__ ;
81
89
import static com .oracle .graal .python .nodes .SpecialMethodNames .__SIZEOF__ ;
115
123
import com .oracle .graal .python .builtins .objects .frame .PFrame ;
116
124
import com .oracle .graal .python .builtins .objects .frame .PFrame .Reference ;
117
125
import com .oracle .graal .python .builtins .objects .function .PArguments ;
126
+ import com .oracle .graal .python .builtins .objects .function .PKeyword ;
118
127
import com .oracle .graal .python .builtins .objects .ints .PInt ;
119
128
import com .oracle .graal .python .builtins .objects .list .PList ;
120
129
import com .oracle .graal .python .builtins .objects .module .PythonModule ;
148
157
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
149
158
import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
150
159
import com .oracle .graal .python .nodes .function .builtins .PythonClinicBuiltinNode ;
160
+ import com .oracle .graal .python .nodes .function .builtins .PythonVarargsBuiltinNode ;
151
161
import com .oracle .graal .python .nodes .function .builtins .clinic .ArgumentClinicProvider ;
152
162
import com .oracle .graal .python .nodes .object .GetClassNode ;
153
163
import com .oracle .graal .python .nodes .object .IsBuiltinClassProfile ;
164
+ import com .oracle .graal .python .nodes .statement .ImportNode ;
154
165
import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
155
166
import com .oracle .graal .python .nodes .util .ExceptionStateNodes .GetCaughtExceptionNode ;
156
167
import com .oracle .graal .python .runtime .PosixSupportLibrary ;
@@ -543,6 +554,7 @@ public void postInitialize0(Python3Core core) {
543
554
sys .setAttribute (__EXCEPTHOOK__ , sys .getAttribute (EXCEPTHOOK ));
544
555
sys .setAttribute (__UNRAISABLEHOOK__ , sys .getAttribute (UNRAISABLEHOOK ));
545
556
sys .setAttribute (__DISPLAYHOOK__ , sys .getAttribute (DISPLAYHOOK ));
557
+ sys .setAttribute (__BREAKPOINTHOOK__ , sys .getAttribute (BREAKPOINTHOOK ));
546
558
}
547
559
548
560
@ Override
@@ -1089,12 +1101,12 @@ void printExceptionRecursive(MaterializedFrame frame, PythonModule sys, Object o
1089
1101
final PBaseException context = exc .getContext ();
1090
1102
1091
1103
if (cause != null ) {
1092
- if (! contains (seen , cause )) {
1104
+ if (notSeen (seen , cause )) {
1093
1105
printExceptionRecursive (frame , sys , out , cause , seen );
1094
1106
fileWriteString (frame , out , CAUSE_MESSAGE );
1095
1107
}
1096
1108
} else if (context != null && !exc .getSuppressContext ()) {
1097
- if (! contains (seen , context )) {
1109
+ if (notSeen (seen , context )) {
1098
1110
printExceptionRecursive (frame , sys , out , context , seen );
1099
1111
fileWriteString (frame , out , CONTEXT_MESSAGE );
1100
1112
}
@@ -1181,8 +1193,8 @@ static void add(Set<Object> set, Object value) {
1181
1193
}
1182
1194
1183
1195
@ TruffleBoundary
1184
- static boolean contains (Set <Object > set , Object value ) {
1185
- return set .contains (value );
1196
+ static boolean notSeen (Set <Object > set , Object value ) {
1197
+ return ! set .contains (value );
1186
1198
}
1187
1199
1188
1200
@ TruffleBoundary
@@ -1191,7 +1203,7 @@ static Set<Object> createSet() {
1191
1203
}
1192
1204
1193
1205
@ Specialization
1194
- Object doWithTb (VirtualFrame frame , PythonModule sys , @ SuppressWarnings ("unused" ) Object excType , Object value , PTraceback traceBack ) {
1206
+ Object doHookWithTb (VirtualFrame frame , PythonModule sys , @ SuppressWarnings ("unused" ) Object excType , Object value , PTraceback traceBack ) {
1195
1207
if (PGuards .isPBaseException (value )) {
1196
1208
final PBaseException exc = (PBaseException ) value ;
1197
1209
final PTraceback currTb = getExceptionTraceback (exc );
@@ -1209,7 +1221,7 @@ Object doWithTb(VirtualFrame frame, PythonModule sys, @SuppressWarnings("unused"
1209
1221
}
1210
1222
1211
1223
@ Specialization (guards = "!isPTraceback(traceBack)" )
1212
- Object doWithoutTb (VirtualFrame frame , PythonModule sys , @ SuppressWarnings ("unused" ) Object excType , Object value , @ SuppressWarnings ("unused" ) Object traceBack ) {
1224
+ Object doHookWithoutTb (VirtualFrame frame , PythonModule sys , @ SuppressWarnings ("unused" ) Object excType , Object value , @ SuppressWarnings ("unused" ) Object traceBack ) {
1213
1225
final MaterializedFrame materializedFrame = frame .materialize ();
1214
1226
Object stdErr = objectLookupAttr (materializedFrame , sys , STDERR );
1215
1227
printExceptionRecursive (materializedFrame , sys , stdErr , value , createSet ());
@@ -1224,12 +1236,12 @@ Object doWithoutTb(VirtualFrame frame, PythonModule sys, @SuppressWarnings("unus
1224
1236
"\n " +
1225
1237
"Print an object to sys.stdout and also save it in builtins._" )
1226
1238
@ GenerateNodeFactory
1227
- abstract static class DisplayHook extends PythonBuiltinNode {
1239
+ abstract static class DisplayHookNode extends PythonBuiltinNode {
1228
1240
private static final String ATTR_ENCODING = "encoding" ;
1229
1241
private static final String ATTR_BUFFER = "buffer" ;
1230
1242
1231
1243
@ Specialization
1232
- Object doit (VirtualFrame frame , PythonModule sys , Object obj ,
1244
+ Object doHook (VirtualFrame frame , PythonModule sys , Object obj ,
1233
1245
@ Cached PyObjectSetAttr setAttr ,
1234
1246
@ Cached IsBuiltinClassProfile unicodeEncodeErrorProfile ,
1235
1247
@ Cached PyObjectLookupAttr lookupAttr ,
@@ -1296,4 +1308,82 @@ Object doit(VirtualFrame frame, PythonModule sys, Object obj,
1296
1308
}
1297
1309
}
1298
1310
1311
+ @ Builtin (name = BREAKPOINTHOOK , takesVarKeywordArgs = true , takesVarArgs = true , doc = "breakpointhook(*args, **kws)\n " +
1312
+ "\n " +
1313
+ "This hook function is called by built-in breakpoint().\n " )
1314
+ @ GenerateNodeFactory
1315
+ abstract static class BreakpointHookNode extends PythonVarargsBuiltinNode {
1316
+ static final String VAL_PDB_SETTRACE = "pdb.set_trace" ;
1317
+
1318
+ @ Child private ImportNode .ImportExpression importNode ;
1319
+
1320
+ private ImportNode .ImportExpression ensureImportNode (String name ) {
1321
+ if (importNode == null ) {
1322
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
1323
+ importNode = insert (ImportNode .createAsExpression (name ));
1324
+ }
1325
+ return importNode ;
1326
+ }
1327
+
1328
+ @ TruffleBoundary
1329
+ private static Object getEnv (String name ) {
1330
+ return System .getenv (name );
1331
+ }
1332
+
1333
+ @ Specialization
1334
+ Object doHook (VirtualFrame frame , Object [] args , PKeyword [] keywords ,
1335
+ @ Cached CallNode callNode ,
1336
+ @ Cached PyObjectGetAttr getAttr ,
1337
+ @ Cached IsBuiltinClassProfile importErrorProfile ,
1338
+ @ Cached IsBuiltinClassProfile attrErrorProfile ,
1339
+ @ Cached CastToJavaStringNode castToJavaStringNode ,
1340
+ @ Cached WarningsModuleBuiltins .WarnNode warnNode ) {
1341
+ Object v = getEnv (PYTHONBREAKPOINT );
1342
+ final String hookName ;
1343
+ if (v == null ) {
1344
+ warnNode .warnFormat (frame , RuntimeWarning , WARN_CANNOT_RUN_PDB_YET );
1345
+ hookName = VAL_PDB_SETTRACE ;
1346
+ } else {
1347
+ hookName = castToString (v , castToJavaStringNode );
1348
+ }
1349
+
1350
+ if (hookName .length () == 1 && hookName .charAt (0 ) == '0' ) {
1351
+ // The breakpoint is explicitly no-op'd.
1352
+ return PNone .NONE ;
1353
+ }
1354
+
1355
+ final int lastDot = PythonUtils .lastIndexOf (hookName , '.' );
1356
+ final String modName ;
1357
+ final String attrName ;
1358
+ if (lastDot == -1 ) {
1359
+ // The breakpoint is a built-in, e.g. PYTHONBREAKPOINT=int
1360
+ modName = BUILTINS ;
1361
+ attrName = hookName ;
1362
+ } else {
1363
+ // Split on the last dot
1364
+ modName = PythonUtils .substring (hookName , 0 , lastDot );
1365
+ attrName = PythonUtils .substring (hookName , lastDot + 1 );
1366
+ }
1367
+
1368
+ final Object module ;
1369
+ try {
1370
+ module = ensureImportNode (modName ).execute (frame );
1371
+ } catch (PException pe ) {
1372
+ pe .expect (ImportError , importErrorProfile );
1373
+ warnNode .warnFormat (frame , RuntimeWarning , WARN_IGNORE_UNIMPORTABLE_BREAKPOINT_S , hookName );
1374
+ return PNone .NONE ;
1375
+ }
1376
+
1377
+ final Object hook ;
1378
+ try {
1379
+ hook = getAttr .execute (frame , module , attrName );
1380
+ } catch (PException pe ) {
1381
+ pe .expect (AttributeError , attrErrorProfile );
1382
+ warnNode .warnFormat (frame , RuntimeWarning , WARN_IGNORE_UNIMPORTABLE_BREAKPOINT_S , hookName );
1383
+ return PNone .NONE ;
1384
+ }
1385
+
1386
+ return callNode .execute (hook , args , keywords );
1387
+ }
1388
+ }
1299
1389
}
0 commit comments