Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
b93cdb56
Commit
b93cdb56
authored
Jul 29, 2018
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial (incomplete) attempt at supporting the Py3.7 exception state stack.
parent
bc487ccb
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
175 additions
and
77 deletions
+175
-77
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+3
-0
Cython/Utility/Coroutine.c
Cython/Utility/Coroutine.c
+85
-44
Cython/Utility/Exceptions.c
Cython/Utility/Exceptions.c
+63
-30
Cython/Utility/ModuleSetupCode.c
Cython/Utility/ModuleSetupCode.c
+7
-0
tests/run/test_exceptions.pyx
tests/run/test_exceptions.pyx
+17
-3
No files found.
Cython/Compiler/Nodes.py
View file @
b93cdb56
...
@@ -4256,7 +4256,10 @@ class GeneratorBodyDefNode(DefNode):
...
@@ -4256,7 +4256,10 @@ class GeneratorBodyDefNode(DefNode):
code
.
put_xgiveref
(
Naming
.
retval_cname
)
code
.
put_xgiveref
(
Naming
.
retval_cname
)
else
:
else
:
code
.
put_xdecref_clear
(
Naming
.
retval_cname
,
py_object_type
)
code
.
put_xdecref_clear
(
Naming
.
retval_cname
,
py_object_type
)
# For Py3.7, clearing is already done below.
code
.
putln
(
"#if !CYTHON_USE_EXC_INFO_STACK"
)
code
.
putln
(
"__Pyx_Coroutine_ResetAndClearException(%s);"
%
Naming
.
generator_cname
)
code
.
putln
(
"__Pyx_Coroutine_ResetAndClearException(%s);"
%
Naming
.
generator_cname
)
code
.
putln
(
"#endif"
)
code
.
putln
(
'%s->resume_label = -1;'
%
Naming
.
generator_cname
)
code
.
putln
(
'%s->resume_label = -1;'
%
Naming
.
generator_cname
)
# clean up as early as possible to help breaking any reference cycles
# clean up as early as possible to help breaking any reference cycles
code
.
putln
(
'__Pyx_Coroutine_clear((PyObject*)%s);'
%
Naming
.
generator_cname
)
code
.
putln
(
'__Pyx_Coroutine_clear((PyObject*)%s);'
%
Naming
.
generator_cname
)
...
...
Cython/Utility/Coroutine.c
View file @
b93cdb56
...
@@ -364,13 +364,23 @@ static void __Pyx_Generator_Replace_StopIteration(CYTHON_UNUSED int in_async_gen
...
@@ -364,13 +364,23 @@ static void __Pyx_Generator_Replace_StopIteration(CYTHON_UNUSED int in_async_gen
typedef
PyObject
*
(
*
__pyx_coroutine_body_t
)(
PyObject
*
,
PyThreadState
*
,
PyObject
*
);
typedef
PyObject
*
(
*
__pyx_coroutine_body_t
)(
PyObject
*
,
PyThreadState
*
,
PyObject
*
);
#if CYTHON_USE_EXC_INFO_STACK
// See https://bugs.python.org/issue25612
#define __Pyx_ExcInfoStruct _PyErr_StackItem
#else
// Minimal replacement struct for Py<3.7, without the Py3.7 exception state stack.
typedef
struct
{
typedef
struct
{
PyObject_HEAD
__pyx_coroutine_body_t
body
;
PyObject
*
closure
;
PyObject
*
exc_type
;
PyObject
*
exc_type
;
PyObject
*
exc_value
;
PyObject
*
exc_value
;
PyObject
*
exc_traceback
;
PyObject
*
exc_traceback
;
}
__Pyx_ExcInfoStruct
;
#endif
typedef
struct
{
PyObject_HEAD
__pyx_coroutine_body_t
body
;
PyObject
*
closure
;
__Pyx_ExcInfoStruct
gi_exc_state
;
PyObject
*
gi_weakreflist
;
PyObject
*
gi_weakreflist
;
PyObject
*
classobj
;
PyObject
*
classobj
;
PyObject
*
yieldfrom
;
PyObject
*
yieldfrom
;
...
@@ -391,20 +401,26 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
...
@@ -391,20 +401,26 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
__pyx_CoroutineObject
*
gen
,
__pyx_coroutine_body_t
body
,
PyObject
*
code
,
PyObject
*
closure
,
__pyx_CoroutineObject
*
gen
,
__pyx_coroutine_body_t
body
,
PyObject
*
code
,
PyObject
*
closure
,
PyObject
*
name
,
PyObject
*
qualname
,
PyObject
*
module_name
);
/*proto*/
PyObject
*
name
,
PyObject
*
qualname
,
PyObject
*
module_name
);
/*proto*/
static
CYTHON_INLINE
void
__Pyx_Coroutine_ExceptionClear
(
__Pyx_ExcInfoStruct
*
self
);
static
int
__Pyx_Coroutine_clear
(
PyObject
*
self
);
/*proto*/
static
int
__Pyx_Coroutine_clear
(
PyObject
*
self
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Send
(
PyObject
*
self
,
PyObject
*
value
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Send
(
PyObject
*
self
,
PyObject
*
value
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Close
(
PyObject
*
self
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Close
(
PyObject
*
self
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Throw
(
PyObject
*
gen
,
PyObject
*
args
);
/*proto*/
static
PyObject
*
__Pyx_Coroutine_Throw
(
PyObject
*
gen
,
PyObject
*
args
);
/*proto*/
// macros for exception state swapping instead of inline functions to make use of the local thread state context
// macros for exception state swapping instead of inline functions to make use of the local thread state context
#if CYTHON_USE_EXC_INFO_STACK
#define __Pyx_Coroutine_SwapException(self) __Pyx_Coroutine_ResetFrameBackpointer(self)
#define __Pyx_Coroutine_ResetAndClearException(self) __Pyx_Coroutine_ExceptionClear(&(self)->gi_exc_state)
#else
#define __Pyx_Coroutine_SwapException(self) { \
#define __Pyx_Coroutine_SwapException(self) { \
__Pyx_ExceptionSwap(&(self)->
exc_type, &(self)->exc_value, &(self)->
exc_traceback); \
__Pyx_ExceptionSwap(&(self)->
gi_exc_state.exc_type, &(self)->gi_exc_state.exc_value, &(self)->gi_exc_state.
exc_traceback); \
__Pyx_Coroutine_ResetFrameBackpointer(self); \
__Pyx_Coroutine_ResetFrameBackpointer(self); \
}
}
#define __Pyx_Coroutine_ResetAndClearException(self) { \
#define __Pyx_Coroutine_ResetAndClearException(self) { \
__Pyx_ExceptionReset((self)->
exc_type, (self)->exc_value, (self)->
exc_traceback); \
__Pyx_ExceptionReset((self)->
gi_exc_state.exc_type, (self)->gi_exc_state.exc_value, (self)->gi_exc_state.
exc_traceback); \
(self)->
exc_type = (self)->exc_value = (self)->
exc_traceback = NULL; \
(self)->
gi_exc_state.exc_type = (self)->gi_exc_state.exc_value = (self)->gi_exc_state.
exc_traceback = NULL; \
}
}
#endif
#if CYTHON_FAST_THREAD_STATE
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
...
@@ -573,18 +589,19 @@ static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *$lo
...
@@ -573,18 +589,19 @@ static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *$lo
}
}
static
CYTHON_INLINE
static
CYTHON_INLINE
void
__Pyx_Coroutine_ExceptionClear
(
__pyx_CoroutineObject
*
self
)
{
void
__Pyx_Coroutine_ExceptionClear
(
__Pyx_ExcInfoStruct
*
exc_state
)
{
PyObject
*
exc_type
=
self
->
exc_type
;
PyObject
*
t
,
*
v
,
*
tb
;
PyObject
*
exc_value
=
self
->
exc_value
;
t
=
exc_state
->
exc_type
;
PyObject
*
exc_traceback
=
self
->
exc_traceback
;
v
=
exc_state
->
exc_value
;
tb
=
exc_state
->
exc_traceback
;
self
->
exc_type
=
NULL
;
self
->
exc_value
=
NULL
;
exc_state
->
exc_type
=
NULL
;
self
->
exc_traceback
=
NULL
;
exc_state
->
exc_value
=
NULL
;
exc_state
->
exc_traceback
=
NULL
;
Py_XDECREF
(
exc_type
);
Py_XDECREF
(
exc_value
);
Py_XDECREF
(
t
);
Py_XDECREF
(
exc_traceback
);
Py_XDECREF
(
v
);
Py_XDECREF
(
tb
);
}
}
#define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL)
#define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL)
...
@@ -649,6 +666,7 @@ static
...
@@ -649,6 +666,7 @@ static
PyObject
*
__Pyx_Coroutine_SendEx
(
__pyx_CoroutineObject
*
self
,
PyObject
*
value
,
int
closing
)
{
PyObject
*
__Pyx_Coroutine_SendEx
(
__pyx_CoroutineObject
*
self
,
PyObject
*
value
,
int
closing
)
{
__Pyx_PyThreadState_declare
__Pyx_PyThreadState_declare
PyThreadState
*
tstate
;
PyThreadState
*
tstate
;
__Pyx_ExcInfoStruct
*
exc_state
;
PyObject
*
retval
;
PyObject
*
retval
;
assert
(
!
self
->
is_running
);
assert
(
!
self
->
is_running
);
...
@@ -671,42 +689,58 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
...
@@ -671,42 +689,58 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
#endif
#endif
// Traceback/Frame rules:
// Traceback/Frame rules:
// - on entry, save external exception state in self->
exc_*
, restore it on exit
// - on entry, save external exception state in self->
gi_exc_state
, restore it on exit
// - on exit, keep internally generated exceptions in self->
exc_*
, clear everything else
// - on exit, keep internally generated exceptions in self->
gi_exc_state
, clear everything else
// - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame
// - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame
// - on exit, clear "f_back" of internal exception traceback
// - on exit, clear "f_back" of internal exception traceback
// - do not touch external frames and tracebacks
// - do not touch external frames and tracebacks
if
(
self
->
exc_type
)
{
exc_state
=
&
self
->
gi_exc_state
;
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
if
(
exc_state
->
exc_type
)
{
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
// FIXME: what to do in PyPy?
// FIXME: what to do in PyPy?
#else
#else
// Generators always return to their most recent caller, not
// Generators always return to their most recent caller, not
// necessarily their creator.
// necessarily their creator.
if
(
self
->
exc_traceback
)
{
if
(
exc_state
->
exc_traceback
)
{
PyTracebackObject
*
tb
=
(
PyTracebackObject
*
)
self
->
exc_traceback
;
PyTracebackObject
*
tb
=
(
PyTracebackObject
*
)
exc_state
->
exc_traceback
;
PyFrameObject
*
f
=
tb
->
tb_frame
;
PyFrameObject
*
f
=
tb
->
tb_frame
;
Py_XINCREF
(
tstate
->
frame
);
Py_XINCREF
(
tstate
->
frame
);
assert
(
f
->
f_back
==
NULL
);
assert
(
f
->
f_back
==
NULL
);
f
->
f_back
=
tstate
->
frame
;
f
->
f_back
=
tstate
->
frame
;
}
}
#endif
#endif
}
#if CYTHON_USE_EXC_INFO_STACK
// See https://bugs.python.org/issue25612
exc_state
->
previous_item
=
tstate
->
exc_info
;
tstate
->
exc_info
=
exc_state
;
#else
if
(
exc_state
->
exc_type
)
{
// We were in an except handler when we left,
// We were in an except handler when we left,
// restore the exception state which was put aside.
// restore the exception state which was put aside.
__Pyx_ExceptionSwap
(
&
self
->
exc_type
,
&
self
->
exc_value
,
__Pyx_ExceptionSwap
(
&
exc_state
->
exc_type
,
&
exc_state
->
exc_value
,
&
exc_state
->
exc_traceback
);
&
self
->
exc_traceback
);
// self->exc_* now holds the exception state of the caller
// self->exc_* now holds the exception state of the caller
}
else
{
}
else
{
// save away the exception state of the caller
// save away the exception state of the caller
__Pyx_Coroutine_ExceptionClear
(
self
);
__Pyx_Coroutine_ExceptionClear
(
exc_state
);
__Pyx_ExceptionSave
(
&
self
->
exc_type
,
&
self
->
exc_value
,
&
self
->
exc_traceback
);
__Pyx_ExceptionSave
(
&
exc_state
->
exc_type
,
&
exc_state
->
exc_value
,
&
exc_state
->
exc_traceback
);
}
}
#endif
self
->
is_running
=
1
;
self
->
is_running
=
1
;
retval
=
self
->
body
((
PyObject
*
)
self
,
tstate
,
value
);
retval
=
self
->
body
((
PyObject
*
)
self
,
tstate
,
value
);
self
->
is_running
=
0
;
self
->
is_running
=
0
;
#if CYTHON_USE_EXC_INFO_STACK
// See https://bugs.python.org/issue25612
exc_state
=
&
self
->
gi_exc_state
;
tstate
->
exc_info
=
exc_state
->
previous_item
;
exc_state
->
previous_item
=
NULL
;
#endif
return
retval
;
return
retval
;
}
}
...
@@ -714,11 +748,13 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineO
...
@@ -714,11 +748,13 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineO
// Don't keep the reference to f_back any longer than necessary. It
// Don't keep the reference to f_back any longer than necessary. It
// may keep a chain of frames alive or it could create a reference
// may keep a chain of frames alive or it could create a reference
// cycle.
// cycle.
if
(
likely
(
self
->
exc_traceback
))
{
PyObject
*
tb
=
self
->
gi_exc_state
.
exc_traceback
;
if
(
likely
(
tb
))
{
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
// FIXME: what to do in PyPy?
// FIXME: what to do in PyPy?
#else
#else
PyTracebackObject
*
tb
=
(
PyTracebackObject
*
)
self
->
exc_traceback
;
PyTracebackObject
*
tb
=
(
PyTracebackObject
*
)
tb
;
PyFrameObject
*
f
=
tb
->
tb_frame
;
PyFrameObject
*
f
=
tb
->
tb_frame
;
Py_CLEAR
(
f
->
f_back
);
Py_CLEAR
(
f
->
f_back
);
#endif
#endif
...
@@ -1039,14 +1075,18 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
...
@@ -1039,14 +1075,18 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
return
__Pyx__Coroutine_Throw
(
self
,
typ
,
val
,
tb
,
args
,
1
);
return
__Pyx__Coroutine_Throw
(
self
,
typ
,
val
,
tb
,
args
,
1
);
}
}
static
CYTHON_INLINE
int
__Pyx_Coroutine_traverse_excstate
(
__Pyx_ExcInfoStruct
*
exc_state
,
visitproc
visit
,
void
*
arg
)
{
Py_VISIT
(
exc_state
->
exc_type
);
Py_VISIT
(
exc_state
->
exc_value
);
Py_VISIT
(
exc_state
->
exc_traceback
);
return
0
;
}
static
int
__Pyx_Coroutine_traverse
(
__pyx_CoroutineObject
*
gen
,
visitproc
visit
,
void
*
arg
)
{
static
int
__Pyx_Coroutine_traverse
(
__pyx_CoroutineObject
*
gen
,
visitproc
visit
,
void
*
arg
)
{
Py_VISIT
(
gen
->
closure
);
Py_VISIT
(
gen
->
closure
);
Py_VISIT
(
gen
->
classobj
);
Py_VISIT
(
gen
->
classobj
);
Py_VISIT
(
gen
->
yieldfrom
);
Py_VISIT
(
gen
->
yieldfrom
);
Py_VISIT
(
gen
->
exc_type
);
return
__Pyx_Coroutine_traverse_excstate
(
&
gen
->
gi_exc_state
,
visit
,
arg
);
Py_VISIT
(
gen
->
exc_value
);
Py_VISIT
(
gen
->
exc_traceback
);
return
0
;
}
}
static
int
__Pyx_Coroutine_clear
(
PyObject
*
self
)
{
static
int
__Pyx_Coroutine_clear
(
PyObject
*
self
)
{
...
@@ -1055,9 +1095,7 @@ static int __Pyx_Coroutine_clear(PyObject *self) {
...
@@ -1055,9 +1095,7 @@ static int __Pyx_Coroutine_clear(PyObject *self) {
Py_CLEAR
(
gen
->
closure
);
Py_CLEAR
(
gen
->
closure
);
Py_CLEAR
(
gen
->
classobj
);
Py_CLEAR
(
gen
->
classobj
);
Py_CLEAR
(
gen
->
yieldfrom
);
Py_CLEAR
(
gen
->
yieldfrom
);
Py_CLEAR
(
gen
->
exc_type
);
__Pyx_Coroutine_ExceptionClear
(
&
gen
->
gi_exc_state
);
Py_CLEAR
(
gen
->
exc_value
);
Py_CLEAR
(
gen
->
exc_traceback
);
#ifdef __Pyx_AsyncGen_USED
#ifdef __Pyx_AsyncGen_USED
if
(
__Pyx_AsyncGen_CheckExact
(
self
))
{
if
(
__Pyx_AsyncGen_CheckExact
(
self
))
{
Py_CLEAR
(((
__pyx_PyAsyncGenObject
*
)
gen
)
->
ag_finalizer
);
Py_CLEAR
(((
__pyx_PyAsyncGenObject
*
)
gen
)
->
ag_finalizer
);
...
@@ -1315,9 +1353,12 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
...
@@ -1315,9 +1353,12 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
gen
->
resume_label
=
0
;
gen
->
resume_label
=
0
;
gen
->
classobj
=
NULL
;
gen
->
classobj
=
NULL
;
gen
->
yieldfrom
=
NULL
;
gen
->
yieldfrom
=
NULL
;
gen
->
exc_type
=
NULL
;
gen
->
gi_exc_state
.
exc_type
=
NULL
;
gen
->
exc_value
=
NULL
;
gen
->
gi_exc_state
.
exc_value
=
NULL
;
gen
->
exc_traceback
=
NULL
;
gen
->
gi_exc_state
.
exc_traceback
=
NULL
;
#if CYTHON_USE_EXC_INFO_STACK
gen
->
gi_exc_state
.
previous_item
=
NULL
;
#endif
gen
->
gi_weakreflist
=
NULL
;
gen
->
gi_weakreflist
=
NULL
;
Py_XINCREF
(
qualname
);
Py_XINCREF
(
qualname
);
gen
->
gi_qualname
=
qualname
;
gen
->
gi_qualname
=
qualname
;
...
@@ -1862,8 +1903,8 @@ static void __Pyx__ReturnWithStopIteration(PyObject* value) {
...
@@ -1862,8 +1903,8 @@ static void __Pyx__ReturnWithStopIteration(PyObject* value) {
}
}
#if CYTHON_FAST_THREAD_STATE
#if CYTHON_FAST_THREAD_STATE
__Pyx_PyThreadState_assign
__Pyx_PyThreadState_assign
#if
PY_VERSION_HEX >= 0x030700A3
#if
CYTHON_USE_EXC_INFO_STACK
if
(
!
$
local_tstate_cname
->
exc_
state
.
exc_type
)
if
(
!
$
local_tstate_cname
->
exc_
info
->
exc_type
)
#else
#else
if
(
!
$
local_tstate_cname
->
exc_type
)
if
(
!
$
local_tstate_cname
->
exc_type
)
#endif
#endif
...
...
Cython/Utility/Exceptions.c
View file @
b93cdb56
...
@@ -307,6 +307,31 @@ bad:
...
@@ -307,6 +307,31 @@ bad:
}
}
#endif
#endif
/////////////// GetTopmostException.proto ///////////////
#if CYTHON_USE_EXC_INFO_STACK
static
_PyErr_StackItem
*
__Pyx_PyErr_GetTopmostException
(
PyThreadState
*
tstate
);
#endif
/////////////// GetTopmostException ///////////////
#if CYTHON_USE_EXC_INFO_STACK
// Copied from errors.c in CPython.
static
_PyErr_StackItem
*
__Pyx_PyErr_GetTopmostException
(
PyThreadState
*
tstate
)
{
_PyErr_StackItem
*
exc_info
=
tstate
->
exc_info
;
while
((
exc_info
->
exc_type
==
NULL
||
exc_info
->
exc_type
==
Py_None
)
&&
exc_info
->
previous_item
!=
NULL
)
{
exc_info
=
exc_info
->
previous_item
;
}
return
exc_info
;
}
#endif
/////////////// GetException.proto ///////////////
/////////////// GetException.proto ///////////////
//@substitute: naming
//@substitute: naming
//@requires: PyThreadStateGet
//@requires: PyThreadStateGet
...
@@ -360,13 +385,16 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
...
@@ -360,13 +385,16 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
*
value
=
local_value
;
*
value
=
local_value
;
*
tb
=
local_tb
;
*
tb
=
local_tb
;
#if CYTHON_FAST_THREAD_STATE
#if CYTHON_FAST_THREAD_STATE
#if PY_VERSION_HEX >= 0x030700A3
#if CYTHON_USE_EXC_INFO_STACK
tmp_type
=
tstate
->
exc_state
.
exc_type
;
{
tmp_value
=
tstate
->
exc_state
.
exc_value
;
_PyErr_StackItem
*
exc_info
=
tstate
->
exc_info
;
tmp_tb
=
tstate
->
exc_state
.
exc_traceback
;
tmp_type
=
exc_info
->
exc_type
;
tstate
->
exc_state
.
exc_type
=
local_type
;
tmp_value
=
exc_info
->
exc_value
;
tstate
->
exc_state
.
exc_value
=
local_value
;
tmp_tb
=
exc_info
->
exc_traceback
;
tstate
->
exc_state
.
exc_traceback
=
local_tb
;
exc_info
->
exc_type
=
local_type
;
exc_info
->
exc_value
=
local_value
;
exc_info
->
exc_traceback
=
local_tb
;
}
#else
#else
tmp_type
=
tstate
->
exc_type
;
tmp_type
=
tstate
->
exc_type
;
tmp_value
=
tstate
->
exc_value
;
tmp_value
=
tstate
->
exc_value
;
...
@@ -398,16 +426,18 @@ bad:
...
@@ -398,16 +426,18 @@ bad:
static
CYTHON_INLINE
void
__Pyx_ReraiseException
(
void
);
/*proto*/
static
CYTHON_INLINE
void
__Pyx_ReraiseException
(
void
);
/*proto*/
/////////////// ReRaiseException.proto ///////////////
/////////////// ReRaiseException ///////////////
//@requires: GetTopmostException
static
CYTHON_INLINE
void
__Pyx_ReraiseException
(
void
)
{
static
CYTHON_INLINE
void
__Pyx_ReraiseException
(
void
)
{
PyObject
*
type
=
NULL
,
*
value
=
NULL
,
*
tb
=
NULL
;
PyObject
*
type
=
NULL
,
*
value
=
NULL
,
*
tb
=
NULL
;
#if CYTHON_FAST_THREAD_STATE
#if CYTHON_FAST_THREAD_STATE
PyThreadState
*
tstate
=
PyThreadState_GET
();
PyThreadState
*
tstate
=
PyThreadState_GET
();
#if PY_VERSION_HEX >= 0x030700A3
#if CYTHON_USE_EXC_INFO_STACK
type
=
tstate
->
exc_state
.
exc_type
;
_PyErr_StackItem
*
exc_info
=
__Pyx_PyErr_GetTopmostException
(
tstate
);
value
=
tstate
->
exc_state
.
exc_value
;
type
=
exc_info
->
exc_type
;
tb
=
tstate
->
exc_state
.
exc_traceback
;
value
=
exc_info
->
exc_value
;
tb
=
exc_info
->
exc_traceback
;
#else
#else
type
=
tstate
->
exc_type
;
type
=
tstate
->
exc_type
;
value
=
tstate
->
exc_value
;
value
=
tstate
->
exc_value
;
...
@@ -456,10 +486,11 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
...
@@ -456,10 +486,11 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
#if CYTHON_FAST_THREAD_STATE
#if CYTHON_FAST_THREAD_STATE
static
CYTHON_INLINE
void
__Pyx__ExceptionSave
(
PyThreadState
*
tstate
,
PyObject
**
type
,
PyObject
**
value
,
PyObject
**
tb
)
{
static
CYTHON_INLINE
void
__Pyx__ExceptionSave
(
PyThreadState
*
tstate
,
PyObject
**
type
,
PyObject
**
value
,
PyObject
**
tb
)
{
#if PY_VERSION_HEX >= 0x030700A3
#if CYTHON_USE_EXC_INFO_STACK
*
type
=
tstate
->
exc_state
.
exc_type
;
_PyErr_StackItem
*
exc_info
=
__Pyx_PyErr_GetTopmostException
(
tstate
);
*
value
=
tstate
->
exc_state
.
exc_value
;
*
type
=
exc_info
->
exc_type
;
*
tb
=
tstate
->
exc_state
.
exc_traceback
;
*
value
=
exc_info
->
exc_value
;
*
tb
=
exc_info
->
exc_traceback
;
#else
#else
*
type
=
tstate
->
exc_type
;
*
type
=
tstate
->
exc_type
;
*
value
=
tstate
->
exc_value
;
*
value
=
tstate
->
exc_value
;
...
@@ -473,13 +504,14 @@ static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject *
...
@@ -473,13 +504,14 @@ static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject *
static
CYTHON_INLINE
void
__Pyx__ExceptionReset
(
PyThreadState
*
tstate
,
PyObject
*
type
,
PyObject
*
value
,
PyObject
*
tb
)
{
static
CYTHON_INLINE
void
__Pyx__ExceptionReset
(
PyThreadState
*
tstate
,
PyObject
*
type
,
PyObject
*
value
,
PyObject
*
tb
)
{
PyObject
*
tmp_type
,
*
tmp_value
,
*
tmp_tb
;
PyObject
*
tmp_type
,
*
tmp_value
,
*
tmp_tb
;
#if PY_VERSION_HEX >= 0x030700A3
#if CYTHON_USE_EXC_INFO_STACK
tmp_type
=
tstate
->
exc_state
.
exc_type
;
_PyErr_StackItem
*
exc_info
=
tstate
->
exc_info
;
tmp_value
=
tstate
->
exc_state
.
exc_value
;
tmp_type
=
exc_info
->
exc_type
;
tmp_tb
=
tstate
->
exc_state
.
exc_traceback
;
tmp_value
=
exc_info
->
exc_value
;
tstate
->
exc_state
.
exc_type
=
type
;
tmp_tb
=
exc_info
->
exc_traceback
;
tstate
->
exc_state
.
exc_value
=
value
;
exc_info
->
exc_type
=
type
;
tstate
->
exc_state
.
exc_traceback
=
tb
;
exc_info
->
exc_value
=
value
;
exc_info
->
exc_traceback
=
tb
;
#else
#else
tmp_type
=
tstate
->
exc_type
;
tmp_type
=
tstate
->
exc_type
;
tmp_value
=
tstate
->
exc_value
;
tmp_value
=
tstate
->
exc_value
;
...
@@ -511,14 +543,15 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
...
@@ -511,14 +543,15 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
static
CYTHON_INLINE
void
__Pyx__ExceptionSwap
(
PyThreadState
*
tstate
,
PyObject
**
type
,
PyObject
**
value
,
PyObject
**
tb
)
{
static
CYTHON_INLINE
void
__Pyx__ExceptionSwap
(
PyThreadState
*
tstate
,
PyObject
**
type
,
PyObject
**
value
,
PyObject
**
tb
)
{
PyObject
*
tmp_type
,
*
tmp_value
,
*
tmp_tb
;
PyObject
*
tmp_type
,
*
tmp_value
,
*
tmp_tb
;
#if PY_VERSION_HEX >= 0x030700A3
#if CYTHON_USE_EXC_INFO_STACK
tmp_type
=
tstate
->
exc_state
.
exc_type
;
_PyErr_StackItem
*
exc_info
=
tstate
->
exc_info
;
tmp_value
=
tstate
->
exc_state
.
exc_value
;
tmp_type
=
exc_info
->
exc_type
;
tmp_tb
=
tstate
->
exc_state
.
exc_traceback
;
tmp_value
=
exc_info
->
exc_value
;
tmp_tb
=
exc_info
->
exc_traceback
;
tstate
->
exc_state
.
exc_type
=
*
type
;
exc_info
->
exc_type
=
*
type
;
tstate
->
exc_state
.
exc_value
=
*
value
;
exc_info
->
exc_value
=
*
value
;
tstate
->
exc_state
.
exc_traceback
=
*
tb
;
exc_info
->
exc_traceback
=
*
tb
;
#else
#else
tmp_type
=
tstate
->
exc_type
;
tmp_type
=
tstate
->
exc_type
;
tmp_value
=
tstate
->
exc_value
;
tmp_value
=
tstate
->
exc_value
;
...
...
Cython/Utility/ModuleSetupCode.c
View file @
b93cdb56
...
@@ -81,6 +81,8 @@
...
@@ -81,6 +81,8 @@
#define CYTHON_USE_TP_FINALIZE 0
#define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS
#undef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS 0
#define CYTHON_USE_DICT_VERSIONS 0
#undef CYTHON_USE_EXC_INFO_STACK
#define CYTHON_USE_EXC_INFO_STACK 0
#elif defined(PYSTON_VERSION)
#elif defined(PYSTON_VERSION)
#define CYTHON_COMPILING_IN_PYPY 0
#define CYTHON_COMPILING_IN_PYPY 0
...
@@ -122,6 +124,8 @@
...
@@ -122,6 +124,8 @@
#define CYTHON_USE_TP_FINALIZE 0
#define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS
#undef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS 0
#define CYTHON_USE_DICT_VERSIONS 0
#undef CYTHON_USE_EXC_INFO_STACK
#define CYTHON_USE_EXC_INFO_STACK 0
#else
#else
#define CYTHON_COMPILING_IN_PYPY 0
#define CYTHON_COMPILING_IN_PYPY 0
...
@@ -186,6 +190,9 @@
...
@@ -186,6 +190,9 @@
#ifndef CYTHON_USE_DICT_VERSIONS
#ifndef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1)
#define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1)
#endif
#endif
#ifndef CYTHON_USE_EXC_INFO_STACK
#define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3)
#endif
#endif
#endif
#if !defined(CYTHON_FAST_PYCCALL)
#if !defined(CYTHON_FAST_PYCCALL)
...
...
tests/run/test_exceptions.pyx
View file @
b93cdb56
# Python test set -- part 5, built-in exceptions
# Python test set -- part 5, built-in exceptions
# Copied from CPython 3.7.
# cython: language_level=3
# mode: run
# tag: generator, exception, tryfinally, tryexcept
import
copy
import
copy
import
os
import
os
...
@@ -12,6 +17,12 @@ from test.support import (TESTFN, captured_stderr, check_impl_detail,
...
@@ -12,6 +17,12 @@ from test.support import (TESTFN, captured_stderr, check_impl_detail,
check_warnings
,
cpython_only
,
gc_collect
,
run_unittest
,
check_warnings
,
cpython_only
,
gc_collect
,
run_unittest
,
no_tracing
,
unlink
,
import_module
,
script_helper
,
no_tracing
,
unlink
,
import_module
,
script_helper
,
SuppressCrashReport
)
SuppressCrashReport
)
no_tracing
=
unittest
.
skip
(
"For nested functions, Cython generates a C call without recursion checks."
)
cpython_only
=
unittest
.
skip
(
"Tests for _testcapi make no sense here."
)
class
NaiveException
(
Exception
):
class
NaiveException
(
Exception
):
def
__init__
(
self
,
x
):
def
__init__
(
self
,
x
):
self
.
x
=
x
self
.
x
=
x
...
@@ -80,8 +91,8 @@ class ExceptionTests(unittest.TestCase):
...
@@ -80,8 +91,8 @@ class ExceptionTests(unittest.TestCase):
self
.
raise_catch
(
MemoryError
,
"MemoryError"
)
self
.
raise_catch
(
MemoryError
,
"MemoryError"
)
self
.
raise_catch
(
NameError
,
"NameError"
)
self
.
raise_catch
(
NameError
,
"NameError"
)
try
:
x
=
undefined_variable
#
try: x = undefined_variable
except
NameError
:
pass
#
except NameError: pass
self
.
raise_catch
(
OverflowError
,
"OverflowError"
)
self
.
raise_catch
(
OverflowError
,
"OverflowError"
)
x
=
1
x
=
1
...
@@ -649,16 +660,19 @@ class ExceptionTests(unittest.TestCase):
...
@@ -649,16 +660,19 @@ class ExceptionTests(unittest.TestCase):
obj
=
wr
()
obj
=
wr
()
self
.
assertIsNone
(
obj
)
self
.
assertIsNone
(
obj
)
'''
# This is currently a compile error in Cython-3, although it works in Cython-2 => could also work in Cy-3.
def test_exception_target_in_nested_scope(self):
def test_exception_target_in_nested_scope(self):
# issue 4617: This used to raise a SyntaxError
# issue 4617: This used to raise a SyntaxError
# "can not delete variable 'e' referenced in nested scope"
# "can not delete variable 'e' referenced in nested scope"
def print_error():
def print_error():
e
e
try:
try:
something
1/0
except Exception as e:
except Exception as e:
print_error()
print_error()
# implicit "del e" here
# implicit "del e" here
'''
def
test_generator_leaking
(
self
):
def
test_generator_leaking
(
self
):
# Test that generator exception state doesn't leak into the calling
# Test that generator exception state doesn't leak into the calling
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment