[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/attackgithub/pythonnet/featured/src/runtime/pythonexception.cs [Back]  [Original]

using System;

namespace Python.Runtime
{
    /// 
    /// Provides a managed interface to exceptions thrown by the Python
    /// runtime.
    /// 
    public class PythonException : System.Exception
    {
        private readonly PyReferenceDecrementer _referenceDecrementer;
        private IntPtr _pyType = IntPtr.Zero;
        private IntPtr _pyValue = IntPtr.Zero;
        private IntPtr _pyTB = IntPtr.Zero;
        private string _tb = "";
        private string _message = "";
        private bool disposed = false;

        public PythonException()
        {
            _referenceDecrementer = PythonEngine.CurrentRefDecrementer;
            IntPtr gs = PythonEngine.AcquireLock();
            Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB);

            // Those references already owned by the caller
            ////Runtime.XIncref(_pyType);
            ////Runtime.XIncref(_pyValue);
            ////Runtime.XIncref(_pyTB);
            if (_pyType != IntPtr.Zero && _pyValue != IntPtr.Zero)
            {
                string type;
                string message;
                Runtime.XIncref(_pyType);
                using (var pyType = new PyObject(_pyType))
                using (PyObject pyTypeName = pyType.GetAttr("__name__"))
                {
                    type = pyTypeName.ToString();
                }

                Runtime.XIncref(_pyValue);
                using (var pyValue = new PyObject(_pyValue))
                {
                    message = pyValue.ToString();
                }
                _message = type + " : " + message;
            }
            if (_pyTB != IntPtr.Zero)
            {

                if (_tbModule == null)
                {
                    _tbModule = PythonEngine.ImportModule("traceback");
                }
                PyObject tb_module = _tbModule;

                Runtime.XIncref(_pyTB);
                using (var pyTB = new PyObject(_pyTB))
                {
                    _tb = tb_module.InvokeMethod("format_tb", pyTB).ToString();
                }
            }
            PythonEngine.ReleaseLock(gs);
        }

        private static PyObject _tbModule;

        // Ensure that encapsulated Python objects are decref'ed appropriately
        // when the managed exception wrapper is garbage-collected.

        ~PythonException()
        {

            Dispose(false);
        }

        /// 
        /// Restores python error.
        /// 
        public void Restore()
        {
            IntPtr gs = PythonEngine.AcquireLock();
            Runtime.PyErr_Restore(_pyType, _pyValue, _pyTB);
            _pyType = IntPtr.Zero;
            _pyValue = IntPtr.Zero;
            _pyTB = IntPtr.Zero;
            PythonEngine.ReleaseLock(gs);
        }

        /// 
        /// PyType Property
        /// 
        /// 
        /// Returns the exception type as a Python object.
        /// 
        public IntPtr PyType
        {
            get { return _pyType; }
        }

        /// 
        /// PyValue Property
        /// 
        /// 
        /// Returns the exception value as a Python object.
        /// 
        public IntPtr PyValue
        {
            get { return _pyValue; }
        }

        /// 
        /// PyTB Property
        /// 
        /// 
        /// Returns the TraceBack as a Python object.
        /// 
        public IntPtr PyTB
        {
            get { return _pyTB; }
        }

        /// 
        /// Message Property
        /// 
        /// 
        /// A string representing the python exception message.
        /// 
        public override string Message
        {
            get { return _message; }
        }

        /// 
        /// StackTrace Property
        /// 
        /// 
        /// A string representing the python exception stack trace.
        /// 
        public override string StackTrace
        {
            get { return _tb; }
        }


        /// 
        /// Dispose Method
        /// 
        /// 
        /// The Dispose method provides a way to explicitly release the
        /// Python objects represented by a PythonException.
        /// If object not properly disposed can cause AppDomain unload issue.
        /// See GH#397 and GH#400.
        /// 
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            Dispose(true);
        }

        protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                disposed = true;

                IntPtr pyTypeToDispose = _pyType;
                _pyType = IntPtr.Zero;

                IntPtr pyValueToDispose = _pyValue;
                _pyValue = IntPtr.Zero;

                IntPtr pyTBToDispose = _pyTB;
                _pyTB = IntPtr.Zero;

                if (disposing)
                {
                    if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing)
                    {
                        IntPtr gs = PythonEngine.AcquireLock();
                        try
                        {
                            Runtime.XDecref(pyTypeToDispose);
                            Runtime.XDecref(pyValueToDispose);
                            // XXX Do we ever get TraceBack? //
                            if (pyTBToDispose != IntPtr.Zero)
                            {
                                Runtime.XDecref(pyTBToDispose);
                            }
                        }
                        finally
                        {
                            PythonEngine.ReleaseLock(gs);
                        }
                    }
                }
                else
                {
                    if (pyTypeToDispose != IntPtr.Zero)
                    {
                        _referenceDecrementer?.ScheduleDecRef(pyTypeToDispose);
                    }

                    if (pyValueToDispose != IntPtr.Zero)
                    {
                        _referenceDecrementer?.ScheduleDecRef(pyValueToDispose);
                    }

                    if (pyTBToDispose != IntPtr.Zero)
                    {
                        _referenceDecrementer?.ScheduleDecRef(pyTBToDispose);
                    }
                }
            }
        }

        /// 
        /// Matches Method
        /// 
        /// 
        /// Returns true if the Python exception type represented by the
        /// PythonException instance matches the given exception type.
        /// 
        public static bool Matches(IntPtr ob)
        {
            return Runtime.PyErr_ExceptionMatches(ob) != 0;
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page