PyErr_Restore() private method

private PyErr_Restore ( IntPtr ob, IntPtr val, IntPtr tb ) : void
ob IntPtr
val IntPtr
tb IntPtr
return void
Exemplo n.º 1
0
        /// <summary>
        /// SetError Method
        /// </summary>
        /// <remarks>
        /// Sets the current Python exception given a CLR exception
        /// object. The CLR exception instance is wrapped as a Python
        /// object, allowing it to be handled naturally from Python.
        /// </remarks>
        public static void SetError(Exception e)
        {
            // Because delegates allow arbitrary nesting of Python calling
            // managed calling Python calling... etc. it is possible that we
            // might get a managed exception raised that is a wrapper for a
            // Python exception. In that case we'd rather have the real thing.

            var pe = e as PythonException;

            if (pe != null)
            {
                Runtime.XIncref(pe.PyType);
                Runtime.XIncref(pe.PyValue);
                Runtime.XIncref(pe.PyTB);
                Runtime.PyErr_Restore(pe.PyType, pe.PyValue, pe.PyTB);
                return;
            }

            IntPtr op    = CLRObject.GetInstHandle(e);
            IntPtr etype = Runtime.PyObject_GetAttr(op, PyIdentifier.__class__);

            Runtime.PyErr_SetObject(new BorrowedReference(etype), new BorrowedReference(op));
            Runtime.XDecref(etype);
            Runtime.XDecref(op);
        }
Exemplo n.º 2
0
        private void DisposeAll()
        {
            BeforeCollect?.Invoke(this, new CollectArgs()
            {
                ObjectCount = _objQueue.Count
            });
#if FINALIZER_CHECK
            lock (_queueLock)
#endif
            {
#if FINALIZER_CHECK
                ValidateRefCount();
#endif
                IntPtr obj;
                Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback);

                try
                {
                    while (!_objQueue.IsEmpty)
                    {
                        if (!_objQueue.TryDequeue(out obj))
                        {
                            continue;
                        }

                        Runtime.XDecref(obj);
                        try
                        {
                            Runtime.CheckExceptionOccurred();
                        }
                        catch (Exception e)
                        {
                            var errorArgs = new ErrorArgs
                            {
                                Error = e,
                            };

                            ErrorHandler?.Invoke(this, errorArgs);

                            if (!errorArgs.Handled)
                            {
                                throw new FinalizationException(
                                          "Python object finalization failed",
                                          disposable: obj, innerException: e);
                            }
                        }
                    }
                }
                finally
                {
                    // Python requires finalizers to preserve exception:
                    // https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation
                    Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), traceback.StealNullable());
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Restores python error.
        /// </summary>
        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);
        }
Exemplo n.º 4
0
        private void DisposeAll()
        {
#if DEBUG
            // only used for testing
            CollectOnce?.Invoke(this, new CollectArgs()
            {
                ObjectCount = _objQueue.Count
            });
#endif
#if FINALIZER_CHECK
            lock (_queueLock)
#endif
            {
#if FINALIZER_CHECK
                ValidateRefCount();
#endif
                IntPtr obj;
                Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback);

                try
                {
                    while (_objQueue.TryDequeue(out obj))
                    {
                        Runtime.XDecref(obj);
                        try
                        {
                            Runtime.CheckExceptionOccurred();
                        }
                        catch (Exception e)
                        {
                            var handler = ErrorHandler;
                            if (handler is null)
                            {
                                throw new FinalizationException(
                                          "Python object finalization failed",
                                          disposable: obj, innerException: e);
                            }

                            handler.Invoke(this, new ErrorArgs()
                            {
                                Error = e
                            });
                        }
                    }
                }
                finally
                {
                    // Python requires finalizers to preserve exception:
                    // https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation
                    Runtime.PyErr_Restore(errType, errVal, traceback);
                }
            }
        }
Exemplo n.º 5
0
        private static void SetConversionError(IntPtr value, Type target)
        {
            // PyObject_Repr might clear the error
            Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace);

            IntPtr ob  = Runtime.PyObject_Repr(value);
            string src = Runtime.GetManagedString(ob);

            Runtime.XDecref(ob);

            Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable());
            Exceptions.RaiseTypeError($"Cannot convert {src} to {target}");
        }
Exemplo n.º 6
0
        internal static Exception?PeekCurrentOrNull(out ExceptionDispatchInfo?dispatchInfo)
        {
            using var _ = new Py.GILState();

            Runtime.PyErr_Fetch(out var type, out var value, out var traceback);
            Runtime.PyErr_Restore(
                new NewReference(type, canBeNull: true).StealNullable(),
                new NewReference(value, canBeNull: true).StealNullable(),
                new NewReference(traceback, canBeNull: true).StealNullable());

            var err = FetchCurrentOrNull(out dispatchInfo);

            Runtime.PyErr_Restore(type.StealNullable(), value.StealNullable(), traceback.StealNullable());

            return(err);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Dispose Method
        /// </summary>
        /// <remarks>
        /// The Dispose method provides a way to explicitly release the
        /// Python object represented by a PyObject instance. It is a good
        /// idea to call Dispose on PyObjects that wrap resources that are
        /// limited or need strict lifetime control. Otherwise, references
        /// to Python objects will not be released until a managed garbage
        /// collection occurs.
        /// </remarks>
        protected virtual void Dispose(bool disposing)
        {
            if (this.obj == IntPtr.Zero)
            {
                return;
            }

            if (Runtime.Py_IsInitialized() == 0)
            {
                throw new InvalidOperationException("Python runtime must be initialized");
            }

            if (!Runtime.IsFinalizing)
            {
                long refcount = Runtime.Refcount(this.obj);
                Debug.Assert(refcount > 0, "Object refcount is 0 or less");

                if (refcount == 1)
                {
                    Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback);

                    try
                    {
                        Runtime.XDecref(this.obj);
                        Runtime.CheckExceptionOccurred();
                    }
                    finally
                    {
                        // Python requires finalizers to preserve exception:
                        // https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation
                        Runtime.PyErr_Restore(errType, errVal, traceback);
                    }
                }
                else
                {
                    Runtime.XDecref(this.obj);
                }
            }
            else
            {
                throw new InvalidOperationException("Runtime is already finalizing");
            }
            this.obj = IntPtr.Zero;
        }
Exemplo n.º 8
0
        private static void SetConversionError(BorrowedReference value, Type target)
        {
            // PyObject_Repr might clear the error
            Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace);

            var    ob  = Runtime.PyObject_Repr(value);
            string src = "'object has no repr'";

            if (ob.IsNull())
            {
                Exceptions.Clear();
            }
            else
            {
                src = Runtime.GetManagedString(ob.Borrow()) ?? src;
            }
            ob.Dispose();

            Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable());
            Exceptions.RaiseTypeError($"Cannot convert {src} to {target}");
        }
Exemplo n.º 9
0
        internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // No valid methods, nothing to bind.
            if (GetMethods().Length == 0)
            {
                var msg = new StringBuilder("The underlying C# method(s) have been deleted");
                if (list.Count > 0 && list[0].Name != null)
                {
                    msg.Append($": {list[0]}");
                }
                return(Exceptions.RaiseTypeError(msg.ToString()));
            }

            Binding binding = Bind(inst, args, kw, info, methodinfo);
            object  result;
            IntPtr  ts = IntPtr.Zero;

            if (binding == null)
            {
                var value = new StringBuilder("No method matches given arguments");
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    value.Append($" for {methodinfo[0].Name}");
                }
                else if (list.Count > 0 && list[0].Valid)
                {
                    value.Append($" for {list[0].Value.Name}");
                }

                value.Append(": ");
                Runtime.PyErr_Fetch(out var errType, out var errVal, out var errTrace);
                AppendArgumentTypes(to: value, args);
                Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), errTrace.StealNullable());
                Exceptions.RaiseTypeError(value.ToString());
                return(IntPtr.Zero);
            }

            if (allow_threads)
            {
                ts = PythonEngine.BeginAllowThreads();
            }

            try
            {
                result = binding.info.Invoke(binding.inst, BindingFlags.Default, null, binding.args, null);
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                if (allow_threads)
                {
                    PythonEngine.EndAllowThreads(ts);
                }
                Exceptions.SetError(e);
                return(IntPtr.Zero);
            }

            if (allow_threads)
            {
                PythonEngine.EndAllowThreads(ts);
            }

            // If there are out parameters, we return a tuple containing
            // the result, if any, followed by the out parameters. If there is only
            // one out parameter and the return type of the method is void,
            // we return the out parameter as the result to Python (for
            // code compatibility with ironpython).

            var mi = (MethodInfo)binding.info;

            if (binding.outs > 0)
            {
                ParameterInfo[] pi = mi.GetParameters();
                int             c  = pi.Length;
                var             n  = 0;

                bool   isVoid    = mi.ReturnType == typeof(void);
                int    tupleSize = binding.outs + (isVoid ? 0 : 1);
                IntPtr t         = Runtime.PyTuple_New(tupleSize);
                if (!isVoid)
                {
                    IntPtr v = Converter.ToPython(result, mi.ReturnType);
                    Runtime.PyTuple_SetItem(t, n, v);
                    n++;
                }

                for (var i = 0; i < c; i++)
                {
                    Type pt = pi[i].ParameterType;
                    if (pt.IsByRef)
                    {
                        IntPtr v = Converter.ToPython(binding.args[i], pt.GetElementType());
                        Runtime.PyTuple_SetItem(t, n, v);
                        n++;
                    }
                }

                if (binding.outs == 1 && mi.ReturnType == typeof(void))
                {
                    IntPtr v = Runtime.PyTuple_GetItem(t, 0);
                    Runtime.XIncref(v);
                    Runtime.XDecref(t);
                    return(v);
                }

                return(t);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Allows ctor selection to be limited to a single attempt at a
        /// match by providing the MethodBase to use instead of searching
        /// the entire MethodBinder.list (generic ArrayList)
        /// </summary>
        /// <param name="inst"> (possibly null) instance </param>
        /// <param name="args"> PyObject* to the arg tuple </param>
        /// <param name="kw"> PyObject* to the keyword args dict </param>
        /// <param name="info"> The sole ContructorInfo to use or null </param>
        /// <returns> The result of the constructor call with converted params </returns>
        /// <remarks>
        /// 2010-07-24 BC: I added the info parameter to the call to Bind()
        /// Binding binding = this.Bind(inst, args, kw, info);
        /// to take advantage of Bind()'s ability to use a single MethodBase (CI or MI).
        /// </remarks>
        internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info)
        {
            if (!_containingType.Valid)
            {
                return(Exceptions.RaiseTypeError(_containingType.DeletedMessage));
            }
            object result;
            Type   tp = _containingType.Value;

            if (tp.IsValueType && !tp.IsPrimitive &&
                !tp.IsEnum && tp != typeof(decimal) &&
                Runtime.PyTuple_Size(args) == 0)
            {
                // If you are trying to construct an instance of a struct by
                // calling its default constructor, that ConstructorInfo
                // instance will not appear in reflection and the object must
                // instead be constructed via a call to
                // Activator.CreateInstance().
                try
                {
                    result = Activator.CreateInstance(tp);
                }
                catch (Exception e)
                {
                    if (e.InnerException != null)
                    {
                        e = e.InnerException;
                    }
                    Exceptions.SetError(e);
                    return(null);
                }
                return(result);
            }

            Binding binding = Bind(inst, args, kw, info);

            if (binding == null)
            {
                // It is possible for __new__ to be invoked on construction
                // of a Python subclass of a managed class, so args may
                // reflect more args than are required to instantiate the
                // class. So if we cant find a ctor that matches, we'll see
                // if there is a default constructor and, if so, assume that
                // any extra args are intended for the subclass' __init__.

                IntPtr eargs = Runtime.PyTuple_New(0);
                binding = Bind(inst, eargs, IntPtr.Zero);
                Runtime.XDecref(eargs);

                if (binding == null)
                {
                    var errorMessage = new StringBuilder("No constructor matches given arguments");
                    if (info != null && info.IsConstructor && info.DeclaringType != null)
                    {
                        errorMessage.Append(" for ").Append(info.DeclaringType.Name);
                    }

                    errorMessage.Append(": ");
                    Runtime.PyErr_Fetch(out var errType, out var errVal, out var errTrace);
                    AppendArgumentTypes(to: errorMessage, args);
                    Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), errTrace.StealNullable());
                    Exceptions.RaiseTypeError(errorMessage.ToString());
                    return(null);
                }
            }

            // Fire the selected ctor and catch errors...
            var ci = (ConstructorInfo)binding.info;

            // Object construction is presumed to be non-blocking and fast
            // enough that we shouldn't really need to release the GIL.
            try
            {
                result = ci.Invoke(binding.args);
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                Exceptions.SetError(e);
                return(null);
            }
            return(result);
        }