@@ -18,107 +18,130 @@ namespace Python.Runtime {
1818
1919 public class PythonException : System . Exception {
2020
21- private IntPtr excType = IntPtr . Zero ;
22- private IntPtr excValue = IntPtr . Zero ;
23- private IntPtr excTb = IntPtr . Zero ;
24- private bool disposed = false ;
25-
26- public PythonException ( ) : base ( ) {
27- Runtime . PyErr_Fetch ( ref excType , ref excValue , ref excTb ) ;
28- Runtime . Incref ( excType ) ;
29- Runtime . Incref ( excValue ) ;
30- Runtime . Incref ( excTb ) ;
31-
32- }
33-
34- // Ensure that encapsulated Python objects are decref'ed appropriately
35- // when the managed exception wrapper is garbage-collected.
36-
37- ~ PythonException ( ) {
38- Dispose ( ) ;
39- }
40-
41-
42- /// <summary>
43- /// Type Property
44- /// </summary>
45- ///
46- /// <remarks>
47- /// Returns the exception type as a Python object.
48- /// </remarks>
49-
50- public IntPtr Type {
51- get {
52- return excType ;
53- }
54- }
55-
56- /// <summary>
57- /// Value Property
58- /// </summary>
59- ///
60- /// <remarks>
61- /// Returns the exception value as a Python object.
62- /// </remarks>
63-
64- public IntPtr Value {
65- get {
66- return excValue ;
67- }
68- }
69-
70- /// <summary>
71- /// Traceback Property
72- /// </summary>
73- ///
74- /// <remarks>
75- /// Returns the exception traceback as a Python object.
76- /// </remarks>
77-
78- public IntPtr Traceback {
79- get {
80- return excTb ;
81- }
82- }
83-
84-
85- /// <summary>
86- /// Dispose Method
87- /// </summary>
88- ///
89- /// <remarks>
90- /// The Dispose method provides a way to explicitly release the
91- /// Python objects represented by a PythonException.
92- /// </remarks>
93-
94- public void Dispose ( ) {
95- if ( ! disposed ) {
96- if ( Runtime . Py_IsInitialized ( ) > 0 ) {
97- IntPtr gs = PythonEngine . AcquireLock ( ) ;
98- Runtime . Decref ( excType ) ;
99- Runtime . Decref ( excValue ) ;
100- Runtime . Decref ( excTb ) ;
101- PythonEngine . ReleaseLock ( gs ) ;
102- }
103- GC . SuppressFinalize ( this ) ;
104- disposed = true ;
105- }
106- }
107-
108- /// <summary>
109- /// Matches Method
110- /// </summary>
111- ///
112- /// <remarks>
113- /// Returns true if the Python exception type represented by the
114- /// PythonException instance matches the given exception type.
115- /// </remarks>
116-
117- public static bool Matches ( IntPtr ob ) {
118- return Runtime . PyErr_ExceptionMatches ( ob ) != 0 ;
119- }
21+ private IntPtr _pyType = IntPtr . Zero ;
22+ private IntPtr _pyValue = IntPtr . Zero ;
23+ private IntPtr _pyTB = IntPtr . Zero ;
24+ private string _tb = "" ;
25+ private string _message = "" ;
26+ private bool disposed = false ;
27+
28+ public PythonException ( ) : base ( )
29+ {
30+ Runtime . PyErr_Fetch ( ref _pyType , ref _pyValue , ref _pyTB ) ;
31+ Runtime . Incref ( _pyType ) ;
32+ Runtime . Incref ( _pyValue ) ;
33+ Runtime . Incref ( _pyTB ) ;
34+ IntPtr gs = PythonEngine . AcquireLock ( ) ;
35+ if ( ( _pyType != IntPtr . Zero ) && ( _pyValue != IntPtr . Zero ) )
36+ {
37+ string type = new PyObject ( _pyType ) . ToString ( ) ;
38+ string message = Runtime . GetManagedString ( _pyValue ) ;
39+ _message = type + " : " + message ;
40+ }
41+ if ( _pyTB != IntPtr . Zero )
42+ {
43+ PyObject tb_module = PythonEngine . ImportModule ( "traceback" ) ;
44+ _tb = tb_module . InvokeMethod ( "format_tb" , new PyObject ( _pyTB ) ) . ToString ( ) ;
45+ }
46+ PythonEngine . ReleaseLock ( gs ) ;
47+ }
48+
49+ // Ensure that encapsulated Python objects are decref'ed appropriately
50+ // when the managed exception wrapper is garbage-collected.
51+
52+ ~ PythonException ( ) {
53+ Dispose ( ) ;
54+ }
12055
121- }
12256
57+ /// <summary>
58+ /// PyType Property
59+ /// </summary>
60+ ///
61+ /// <remarks>
62+ /// Returns the exception type as a Python object.
63+ /// </remarks>
64+
65+ public IntPtr PyType
66+ {
67+ get { return _pyType ; }
68+ }
69+
70+ /// <summary>
71+ /// PyValue Property
72+ /// </summary>
73+ ///
74+ /// <remarks>
75+ /// Returns the exception value as a Python object.
76+ /// </remarks>
12377
78+ public IntPtr PyValue
79+ {
80+ get { return _pyValue ; }
81+ }
82+
83+ /// <summary>
84+ /// Message Property
85+ /// </summary>
86+ ///
87+ /// <remarks>
88+ /// A string representing the python exception message.
89+ /// </remarks>
90+
91+ public override string Message
92+ {
93+ get { return _message ; }
94+ }
95+
96+ /// <summary>
97+ /// StackTrace Property
98+ /// </summary>
99+ ///
100+ /// <remarks>
101+ /// A string representing the python exception stack trace.
102+ /// </remarks>
103+
104+ public override string StackTrace
105+ {
106+ get { return _tb ; }
107+ }
108+
109+
110+ /// <summary>
111+ /// Dispose Method
112+ /// </summary>
113+ ///
114+ /// <remarks>
115+ /// The Dispose method provides a way to explicitly release the
116+ /// Python objects represented by a PythonException.
117+ /// </remarks>
118+
119+ public void Dispose ( ) {
120+ if ( ! disposed ) {
121+ if ( Runtime . Py_IsInitialized ( ) > 0 ) {
122+ IntPtr gs = PythonEngine . AcquireLock ( ) ;
123+ Runtime . Decref ( _pyType ) ;
124+ Runtime . Decref ( _pyValue ) ;
125+ Runtime . Decref ( _pyTB ) ;
126+ PythonEngine . ReleaseLock ( gs ) ;
127+ }
128+ GC . SuppressFinalize ( this ) ;
129+ disposed = true ;
130+ }
131+ }
132+
133+ /// <summary>
134+ /// Matches Method
135+ /// </summary>
136+ ///
137+ /// <remarks>
138+ /// Returns true if the Python exception type represented by the
139+ /// PythonException instance matches the given exception type.
140+ /// </remarks>
141+
142+ public static bool Matches ( IntPtr ob ) {
143+ return Runtime . PyErr_ExceptionMatches ( ob ) != 0 ;
144+ }
145+
146+ }
124147}
0 commit comments