1
- # Copyright (c) 2018, 2019 , Oracle and/or its affiliates. All rights reserved.
1
+ # Copyright (c) 2018, 2020 , Oracle and/or its affiliates. All rights reserved.
2
2
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
3
#
4
4
# The Universal Permissive License (UPL), Version 1.0
@@ -62,6 +62,52 @@ def _reference_fetch(args):
62
62
return sys .exc_info ()[0 ]
63
63
64
64
65
+ def compare_tracebacks (tb1 , tb2 ):
66
+ while tb1 and tb2 :
67
+ if tb1 .tb_frame .f_code != tb2 .tb_frame .f_code :
68
+ print (f"\n tb_next: { tb1 .tb_frame .f_code } != { tb2 .tb_frame .f_code } \n " )
69
+ return False
70
+ tb1 = tb1 .tb_next
71
+ tb2 = tb2 .tb_next
72
+ return tb1 is None and tb2 is None
73
+
74
+
75
+ def compare_frame_f_back_chain (f1 , f2 ):
76
+ while f1 and f2 :
77
+ if f1 .f_code != f2 .f_code :
78
+ print (f"\n frame: { f1 .f_code } != { f2 .f_code } \n " )
79
+ return False
80
+ f1 = f1 .f_back
81
+ f2 = f2 .f_back
82
+ return f1 is None and f2 is None
83
+
84
+
85
+ def _reference_fetch_tb_from_python (args ):
86
+ try :
87
+ args [0 ]()
88
+ except :
89
+ tb = sys .exc_info ()[2 ]
90
+ return tb .tb_next # PyErr_Fetch doesn't contain the current frame
91
+
92
+
93
+ def _reference_fetch_tb_f_back (args ):
94
+ try :
95
+ args [0 ]()
96
+ except :
97
+ return sys .exc_info ()[2 ].tb_frame .f_back
98
+
99
+
100
+ def _raise_exception ():
101
+ def inner ():
102
+ raise OSError
103
+ def reraise (e ):
104
+ raise e
105
+ try :
106
+ inner ()
107
+ except Exception as e :
108
+ reraise (e )
109
+
110
+
65
111
def _is_exception_class (exc ):
66
112
return isinstance (exc , type ) and issubclass (exc , BaseException )
67
113
@@ -89,11 +135,11 @@ class Dummy:
89
135
pass
90
136
91
137
92
- class TestPyNumber (CPyExtTestCase ):
138
+ class TestPyErr (CPyExtTestCase ):
93
139
94
140
def compile_module (self , name ):
95
141
type (self ).mro ()[1 ].__dict__ ["test_%s" % name ].create_module (name )
96
- super (TestPyNumber , self ).compile_module (name )
142
+ super (TestPyErr , self ).compile_module (name )
97
143
98
144
test_PyErr_SetString = CPyExtFunctionVoid (
99
145
_reference_setstring ,
@@ -312,7 +358,6 @@ def compile_module(self, name):
312
358
PyObject* typ = NULL;
313
359
PyObject* val = NULL;
314
360
PyObject* tb = NULL;
315
- Py_ssize_t size = 3;
316
361
PyErr_SetNone(exception_type);
317
362
PyErr_Fetch(&typ, &val, &tb);
318
363
return typ;
@@ -324,3 +369,65 @@ def compile_module(self, name):
324
369
callfunction = "wrap_PyErr_Fetch" ,
325
370
cmpfunc = unhandled_error_compare
326
371
)
372
+
373
+ test_PyErr_Fetch_tb_from_c = CPyExtFunctionVoid (
374
+ lambda args : None ,
375
+ lambda : [(1 ,)],
376
+ code = """PyObject* wrap_PyErr_Fetch_tb_from_c() {
377
+ PyErr_SetString(PyExc_ArithmeticError, "test");
378
+ PyObject* typ = NULL;
379
+ PyObject* val = NULL;
380
+ PyObject* tb = NULL;
381
+ PyErr_Fetch(&typ, &val, &tb);
382
+ return tb == NULL? Py_None: tb;
383
+ }
384
+ """ ,
385
+ resultspec = "O" ,
386
+ callfunction = "wrap_PyErr_Fetch_tb_from_c" ,
387
+ cmpfunc = compare_tracebacks ,
388
+ )
389
+
390
+ test_PyErr_Fetch_tb_from_python = CPyExtFunction (
391
+ _reference_fetch_tb_from_python ,
392
+ lambda : (
393
+ (lambda : 1 / 0 ,),
394
+ (_raise_exception ,),
395
+ ),
396
+ code = """PyObject* wrap_PyErr_Fetch_tb_from_python(PyObject* fn) {
397
+ PyObject_CallFunction(fn, NULL);
398
+ PyObject* typ = NULL;
399
+ PyObject* val = NULL;
400
+ PyObject* tb = NULL;
401
+ PyErr_Fetch(&typ, &val, &tb);
402
+ return tb;
403
+ }
404
+ """ ,
405
+ resultspec = "O" ,
406
+ argspec = 'O' ,
407
+ arguments = ["PyObject* fn" ],
408
+ callfunction = "wrap_PyErr_Fetch_tb_from_python" ,
409
+ cmpfunc = compare_tracebacks ,
410
+ )
411
+
412
+ # GR-22089
413
+ # test_PyErr_Fetch_tb_f_back = CPyExtFunction(
414
+ # _reference_fetch_tb_f_back,
415
+ # lambda: (
416
+ # (lambda: 1 / 0,),
417
+ # (_raise_exception,),
418
+ # ),
419
+ # code="""PyObject* wrap_PyErr_Fetch_tb_f_back(PyObject* fn) {
420
+ # PyObject_CallFunction(fn, NULL);
421
+ # PyObject* typ = NULL;
422
+ # PyObject* val = NULL;
423
+ # PyObject* tb = NULL;
424
+ # PyErr_Fetch(&typ, &val, &tb);
425
+ # return PyObject_GetAttrString(PyObject_GetAttrString(tb, "tb_frame"), "f_back");
426
+ # }
427
+ # """,
428
+ # resultspec="O",
429
+ # argspec='O',
430
+ # arguments=["PyObject* fn"],
431
+ # callfunction="wrap_PyErr_Fetch_tb_f_back",
432
+ # cmpfunc=compare_frame_f_back_chain,
433
+ # )
0 commit comments