SetError() public static method

SetError Method
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.
public static SetError ( Exception e ) : void
e System.Exception
return void
Example #1
0
        //====================================================================
        // Implements __call__ for reflected generic types.
        //====================================================================

        public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw)
        {
            Exceptions.SetError(Exceptions.TypeError,
                                "object is not callable");
            return(IntPtr.Zero);
        }
Example #2
0
        //====================================================================
        // MethodBinding  __call__ implementation.
        //====================================================================

        public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw)
        {
            MethodBinding self = (MethodBinding)GetManagedObject(ob);

            // This works around a situation where the wrong generic method is picked,
            // for example this method in the tests: string Overloaded<T>(int arg1, int arg2, string arg3)
            if (self.info != null)
            {
                if (self.info.IsGenericMethod)
                {
                    int    len   = Runtime.PyTuple_Size(args);
                    Type[] sigTp = Runtime.PythonArgsToTypeArray(args, true);
                    if (sigTp != null)
                    {
                        Type[]     genericTp   = self.info.GetGenericArguments();
                        MethodInfo betterMatch = MethodBinder.MatchSignatureAndParameters(self.m.info, genericTp, sigTp);
                        if (betterMatch != null)
                        {
                            self.info = betterMatch;
                        }
                    }
                }
            }

            // This supports calling a method 'unbound', passing the instance
            // as the first argument. Note that this is not supported if any
            // of the overloads are static since we can't know if the intent
            // was to call the static method or the unbound instance method.
            List <IntPtr> disposeList = new List <IntPtr>();

            try
            {
                IntPtr target = self.target;

                if ((target == IntPtr.Zero) && (!self.m.IsStatic()))
                {
                    int len = Runtime.PyTuple_Size(args);
                    if (len < 1)
                    {
                        Exceptions.SetError(Exceptions.TypeError, "not enough arguments");
                        return(IntPtr.Zero);
                    }
                    target = Runtime.PyTuple_GetItem(args, 0);
                    Runtime.Incref(target);
                    disposeList.Add(target);

                    args = Runtime.PyTuple_GetSlice(args, 1, len);
                    disposeList.Add(args);
                }

                // if the class is a IPythonDerivedClass and target is not the same as self.targetType
                // (eg if calling the base class method) then call the original base class method instead
                // of the target method.
                IntPtr superType = IntPtr.Zero;
                if (Runtime.PyObject_TYPE(target) != self.targetType)
                {
                    CLRObject inst = CLRObject.GetManagedObject(target) as CLRObject;
                    if (inst != null && (inst.inst as IPythonDerivedType) != null)
                    {
                        ClassBase baseType = GetManagedObject(self.targetType) as ClassBase;
                        if (baseType != null)
                        {
                            string baseMethodName = "_" + baseType.type.Name + "__" + self.m.name;
                            IntPtr baseMethod     = Runtime.PyObject_GetAttrString(target, baseMethodName);
                            if (baseMethod != null)
                            {
                                MethodBinding baseSelf = GetManagedObject(baseMethod) as MethodBinding;
                                if (baseSelf != null)
                                {
                                    self = baseSelf;
                                }
                            }
                            Runtime.Decref(baseMethod);
                        }
                    }
                }

                return(self.m.Invoke(target, args, kw, self.info));
            }
            finally
            {
                foreach (IntPtr ptr in disposeList)
                {
                    Runtime.Decref(ptr);
                }
            }
        }
Example #3
0
        internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            Binding binding = Bind(inst, args, kw, info, methodinfo);
            object  result;
            IntPtr  ts = IntPtr.Zero;

            if (binding == null)
            {
                var value = "No method matches given arguments";
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    value += (" for " + methodinfo[0].Name + "");
                }
                Exceptions.SetError(Exceptions.TypeError, value);
                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 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 == 1 && mi.ReturnType == typeof(void))
            {
            }

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

                IntPtr t = Runtime.PyTuple_New(binding.outs + 1);
                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 (pi[i].IsOut || pt.IsByRef)
                    {
                        v = Converter.ToPython(binding.args[i], pt);
                        Runtime.PyTuple_SetItem(t, n, v);
                        n++;
                    }
                }

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

                return(t);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }
Example #4
0
        /// <summary>
        /// Implements __new__ for reflected classes and value types.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = GetManagedObject(tp) as ClassObject;

            // Sanity check: this ensures a graceful error if someone does
            // something intentially wrong like use the managed metatype for
            // a class that is not really derived from a managed class.
            if (self == null)
            {
                return(Exceptions.RaiseTypeError("invalid object"));
            }

            if (!self.type.Valid)
            {
                return(Exceptions.RaiseTypeError(self.type.DeletedMessage));
            }
            Type type = self.type.Value;

            // Primitive types do not have constructors, but they look like
            // they do from Python. If the ClassObject represents one of the
            // convertible primitive types, just convert the arg directly.
            if (type.IsPrimitive || type == typeof(string))
            {
                if (Runtime.PyTuple_Size(args) != 1)
                {
                    Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments");
                    return(IntPtr.Zero);
                }

                IntPtr op = Runtime.PyTuple_GetItem(args, 0);
                object result;

                if (!Converter.ToManaged(op, type, out result, true))
                {
                    return(IntPtr.Zero);
                }

                return(CLRObject.GetInstHandle(result, tp));
            }

            if (type.IsAbstract)
            {
                Exceptions.SetError(Exceptions.TypeError, "cannot instantiate abstract class");
                return(IntPtr.Zero);
            }

            if (type.IsEnum)
            {
                Exceptions.SetError(Exceptions.TypeError, "cannot instantiate enumeration");
                return(IntPtr.Zero);
            }

            object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw);

            if (obj == null)
            {
                return(IntPtr.Zero);
            }

            return(CLRObject.GetInstHandle(obj, tp));
        }
        /// <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)
        {
            object result;

            if (_containingType.IsValueType && !_containingType.IsPrimitive &&
                !_containingType.IsEnum && _containingType != 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(_containingType);
                }
                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, kw);
                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(": ");
                    AppendArgumentTypes(to: errorMessage, args);
                    Exceptions.SetError(Exceptions.TypeError, 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);
        }
Example #6
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            IntPtr   overflow = Exceptions.OverflowError;
            TypeCode tc       = Type.GetTypeCode(obType);

            result = null;
            IntPtr op;
            int    ival;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
                // Trickery to support 64-bit platforms.
                if (Runtime.IsPython2 && Runtime.Is32Bit)
                {
                    op = Runtime.PyNumber_Int(value);

                    // As of Python 2.3, large ints magically convert :(
                    if (Runtime.PyLong_Check(op))
                    {
                        Runtime.XDecref(op);
                        goto overflow;
                    }

                    if (op == IntPtr.Zero)
                    {
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    ival = (int)Runtime.PyInt_AsLong(op);
                    Runtime.XDecref(op);
                    result = ival;
                    return(true);
                }
                else     // Python3 always use PyLong API
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        Exceptions.Clear();
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    long ll = (long)Runtime.PyLong_AsLongLong(op);
                    Runtime.XDecref(op);
                    if (ll == -1 && Exceptions.ErrorOccurred())
                    {
                        goto overflow;
                    }
                    if (ll > Int32.MaxValue || ll < Int32.MinValue)
                    {
                        goto overflow;
                    }
                    result = (int)ll;
                    return(true);
                }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > Byte.MaxValue || ival < Byte.MinValue)
                {
                    goto overflow;
                }
                byte b = (byte)ival;
                result = b;
                return(true);

            case TypeCode.SByte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (sbyte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > SByte.MaxValue || ival < SByte.MinValue)
                {
                    goto overflow;
                }
                sbyte sb = (sbyte)ival;
                result = sb;
                return(true);

            case TypeCode.Char:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (char)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                ival = Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Char.MaxValue || ival < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)ival;
                return(true);

            case TypeCode.Int16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Int16.MaxValue || ival < Int16.MinValue)
                {
                    goto overflow;
                }
                short s = (short)ival;
                result = s;
                return(true);

            case TypeCode.Int64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long l = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.XDecref(op);
                if ((l == -1) && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = l;
                return(true);

            case TypeCode.UInt16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
                {
                    goto overflow;
                }
                ushort us = (ushort)ival;
                result = us;
                return(true);

            case TypeCode.UInt32:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Runtime.XDecref(op);
                    goto overflow;
                }

                IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
                int    err   = Runtime.PyObject_Compare(check, op);
                Runtime.XDecref(check);
                Runtime.XDecref(op);
                if (0 != err || Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }

                result = ui;
                return(true);

            case TypeCode.UInt64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
                Runtime.XDecref(op);
                if (Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = ul;
                return(true);


            case TypeCode.Single:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                double dd = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                if (dd > Single.MaxValue || dd < Single.MinValue)
                {
                    if (!double.IsInfinity(dd))
                    {
                        goto overflow;
                    }
                }
                result = (float)dd;
                return(true);

            case TypeCode.Double:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                double d = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                result = d;
                return(true);
            }


type_error:

            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }

            return(false);

overflow:

            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }

            return(false);
        }
Example #7
0
        //====================================================================
        // Internal helper methods for common error handling scenarios.
        //====================================================================

        internal static IntPtr RaiseTypeError(string message)
        {
            Exceptions.SetError(Exceptions.TypeError, message);
            return(IntPtr.Zero);
        }
Example #8
0
        /// <summary>
        /// The actual import hook that ties Python to the managed world.
        /// </summary>
        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // Replacement for the builtin __import__. The original import
            // hook is saved as this.py_import. This version handles CLR
            // import and defers to the normal builtin for everything else.

            var num_args = Runtime.PyTuple_Size(args);

            if (num_args < 1)
            {
                return(Exceptions.RaiseTypeError("__import__() takes at least 1 argument (0 given)"));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if (py_mod_name == IntPtr.Zero ||
                !Runtime.IsStringType(py_mod_name))
            {
                return(Exceptions.RaiseTypeError("string expected"));
            }

            // Check whether the import is of the form 'from x import y'.
            // This determines whether we return the head or tail module.

            IntPtr fromList = IntPtr.Zero;
            var    fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if (fromList != IntPtr.Zero &&
                    Runtime.PyObject_IsTrue(fromList) == 1)
                {
                    fromlist = true;
                }
            }

            string mod_name = Runtime.GetManagedString(py_mod_name);

            // Check these BEFORE the built-in import runs; may as well
            // do the Incref()ed return here, since we've already found
            // the module.
            if (mod_name == "clr")
            {
                IntPtr clr_module = GetCLRModule(fromList);
                if (clr_module != IntPtr.Zero)
                {
                    IntPtr sys_modules = Runtime.PyImport_GetModuleDict();
                    if (sys_modules != IntPtr.Zero)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module);
            }
            if (mod_name == "CLR")
            {
                Exceptions.deprecation("The CLR module is deprecated. Please use 'clr'.");
                IntPtr clr_module = GetCLRModule(fromList);
                if (clr_module != IntPtr.Zero)
                {
                    IntPtr sys_modules = Runtime.PyImport_GetModuleDict();
                    if (sys_modules != IntPtr.Zero)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module);
            }
            string realname   = mod_name;
            string clr_prefix = null;

            if (mod_name.StartsWith("CLR."))
            {
                clr_prefix = "CLR."; // prepend when adding the module to sys.modules
                realname   = mod_name.Substring(4);
                string msg = $"Importing from the CLR.* namespace is deprecated. Please import '{realname}' directly.";
                Exceptions.deprecation(msg);
            }
            else
            {
                // 2010-08-15: Always seemed smart to let python try first...
                // This shaves off a few tenths of a second on test_module.py
                // and works around a quirk where 'sys' is found by the
                // LoadImplicit() deprecation logic.
                // Turns out that the AssemblyManager.ResolveHandler() checks to see if any
                // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very
                // little sense to me.
                IntPtr res = Runtime.PyObject_Call(py_import, args, kw);
                if (res != IntPtr.Zero)
                {
                    // There was no error.
                    if (fromlist && IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(res) as ModuleObject;
                        mod?.LoadNames();
                    }
                    return(res);
                }
                // There was an error
                if (!Exceptions.ExceptionMatches(Exceptions.ImportError))
                {
                    // and it was NOT an ImportError; bail out here.
                    return(IntPtr.Zero);
                }

                if (mod_name == string.Empty)
                {
                    // Most likely a missing relative import.
                    // For example site-packages\bs4\builder\__init__.py uses it to check if a package exists:
                    //     from . import _html5lib
                    // We don't support them anyway
                    return(IntPtr.Zero);
                }
                // Otherwise,  just clear the it.
                Exceptions.Clear();
            }

            string[] names = realname.Split('.');

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                if (!AssemblyManager.LoadImplicit(realname))
                {
                    // May be called when a module being imported imports a module.
                    // In particular, I've seen decimal import copy import org.python.core
                    return(Runtime.PyObject_Call(py_import, args, kw));
                }
            }

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the existing module.
            IntPtr modules = Runtime.PyImport_GetModuleDict();
            IntPtr module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    if (IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(module) as ModuleObject;
                        mod?.LoadNames();
                    }
                    Runtime.XIncref(module);
                    return(module);
                }
                if (clr_prefix != null)
                {
                    return(GetCLRModule(fromList));
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.XIncref(module);
                return(module);
            }
            Exceptions.Clear();

            // Traverse the qualified module name to get the named module
            // and place references in sys.modules as we go. Note that if
            // we are running in interactive mode we pre-load the names in
            // each module, which is often useful for introspection. If we
            // are not interactive, we stick to just-in-time creation of
            // objects at lookup time, which is much more efficient.
            // NEW: The clr got a new module variable preload. You can
            // enable preloading in a non-interactive python processing by
            // setting clr.preload = True

            ModuleObject head = mod_name == realname ? null : root;
            ModuleObject tail = root;

            root.InitializePreload();

            foreach (string name in names)
            {
                ManagedType mt = tail.GetAttribute(name, true);
                if (!(mt is ModuleObject))
                {
                    Exceptions.SetError(Exceptions.ImportError, $"No module named {name}");
                    return(IntPtr.Zero);
                }
                if (head == null)
                {
                    head = (ModuleObject)mt;
                }
                tail = (ModuleObject)mt;
                if (CLRModule.preload)
                {
                    tail.LoadNames();
                }

                // Add the module to sys.modules
                Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.pyHandle);

                // If imported from CLR add CLR.<modulename> to sys.modules as well
                if (clr_prefix != null)
                {
                    Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.pyHandle);
                }
            }

            {
                var mod = fromlist ? tail : head;

                if (fromlist && IsLoadAll(fromList))
                {
                    mod.LoadNames();
                }

                Runtime.XIncref(mod.pyHandle);
                return(mod.pyHandle);
            }
        }
Example #9
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out object result, bool setError)
        {
            if (obType == typeof(PyObject))
            {
                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            if (mt != null)
            {
                if (mt is CLRObject)
                {
                    object tmp = ((CLRObject)mt).inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    Exceptions.SetError(Exceptions.TypeError, $"value cannot be converted to {obType}");
                    return(false);
                }
                if (mt is ClassBase)
                {
                    result = ((ClassBase)mt).type;
                    return(true);
                }
                // shouldn't happen
                return(false);
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (value == Runtime.PyNone)
                {
                    result = null;
                    return(true);
                }
                // Set type to underlying type
                obType = obType.GetGenericArguments()[0];
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            if (obType.IsEnum)
            {
                return(ToEnum(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable default
            // conversions (Python string -> managed string, Python int -> Int32 etc.).
            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result, setError));
                }

                if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                if (Runtime.PyInt_Check(value))
                {
                    return(ToPrimitive(value, int32Type, out result, setError));
                }

                if (Runtime.PyLong_Check(value))
                {
                    return(ToPrimitive(value, int64Type, out result, setError));
                }

                if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                if (Runtime.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result, setError));
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object");
                }

                return(false);
            }

            // Conversion to 'Type' is done using the same mappings as above for objects.
            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                if (value == Runtime.PyIntType)
                {
                    result = int32Type;
                    return(true);
                }

                if (value == Runtime.PyLongType)
                {
                    result = int64Type;
                    return(true);
                }

                if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                if (value == Runtime.PyListType || value == Runtime.PyTupleType)
                {
                    result = typeof(object[]);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type");
                }

                return(false);
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
Example #10
0
 /// <summary>
 /// Default __set__ implementation - this prevents descriptor instances
 /// being silently replaced in a type __dict__ by default __setattr__.
 /// </summary>
 public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
 {
     Exceptions.SetError(Exceptions.AttributeError, "attribute is read-only");
     return(-1);
 }
Example #11
0
        /// <summary>
        /// Descriptor __set__ implementation. This method sets the value of
        /// a property based on the given Python value. The Python value must
        /// be convertible to the type of the property.
        /// </summary>
        public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
        {
            var        self   = (PropertyObject)GetManagedObject(ds);
            MethodInfo setter = self.setter;
            object     newval;

            if (val == IntPtr.Zero)
            {
                Exceptions.RaiseTypeError("cannot delete property");
                return(-1);
            }

            if (setter == null)
            {
                Exceptions.RaiseTypeError("property is read-only");
                return(-1);
            }


            if (!Converter.ToManaged(val, self.info.PropertyType, out newval, true))
            {
                return(-1);
            }

            bool is_static = setter.IsStatic;

            if (ob == IntPtr.Zero || ob == Runtime.PyNone)
            {
                if (!is_static)
                {
                    Exceptions.RaiseTypeError("instance property must be set on an instance");
                    return(-1);
                }
            }

            try
            {
                if (!is_static)
                {
                    var co = GetManagedObject(ob) as CLRObject;
                    if (co == null)
                    {
                        Exceptions.RaiseTypeError("invalid target");
                        return(-1);
                    }
                    self.info.SetValue(co.inst, newval, null);
                }
                else
                {
                    self.info.SetValue(null, newval, null);
                }
                return(0);
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                Exceptions.SetError(e);
                return(-1);
            }
        }
Example #12
0
        /// <summary>
        /// Implements __setitem__ for reflected classes and value types.
        /// </summary>
        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            IntPtr tp  = Runtime.PyObject_TYPE(ob);
            var    cls = (ClassBase)GetManagedObject(tp);

            if (cls.indexer == null || !cls.indexer.CanSet)
            {
                Exceptions.SetError(Exceptions.TypeError, "object doesn't support item assignment");
                return(-1);
            }

            // Arg may be a tuple in the case of an indexer with multiple
            // parameters. If so, use it directly, else make a new tuple
            // with the index arg (method binders expect arg tuples).
            IntPtr args = idx;
            var    free = false;

            if (!Runtime.PyTuple_Check(idx))
            {
                args = Runtime.PyTuple_New(1);
                Runtime.XIncref(idx);
                Runtime.PyTuple_SetItem(args, 0, idx);
                free = true;
            }

            // Get the args passed in.
            var    i                = Runtime.PyTuple_Size(args);
            IntPtr defaultArgs      = cls.indexer.GetDefaultArgs(args);
            var    numOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs);
            var    temp             = i + numOfDefaultArgs;
            IntPtr real             = Runtime.PyTuple_New(temp + 1);

            for (var n = 0; n < i; n++)
            {
                IntPtr item = Runtime.PyTuple_GetItem(args, n);
                Runtime.XIncref(item);
                Runtime.PyTuple_SetItem(real, n, item);
            }

            // Add Default Args if needed
            for (var n = 0; n < numOfDefaultArgs; n++)
            {
                IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n);
                Runtime.XIncref(item);
                Runtime.PyTuple_SetItem(real, n + i, item);
            }
            // no longer need defaultArgs
            Runtime.XDecref(defaultArgs);
            i = temp;

            // Add value to argument list
            Runtime.XIncref(v);
            Runtime.PyTuple_SetItem(real, i, v);

            try
            {
                cls.indexer.SetItem(ob, real);
            }
            finally
            {
                Runtime.XDecref(real);

                if (free)
                {
                    Runtime.XDecref(args);
                }
            }

            if (Exceptions.ErrorOccurred())
            {
                return(-1);
            }

            return(0);
        }
Example #13
0
        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // Replacement for the builtin __import__. The original import
            // hook is saved as this.py_import. This version handles CLR
            // import and defers to the normal builtin for everything else.

            int num_args = Runtime.PyTuple_Size(args);

            if (num_args < 1)
            {
                return(Exceptions.RaiseTypeError(
                           "__import__() takes at least 1 argument (0 given)"
                           ));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if ((py_mod_name == IntPtr.Zero) ||
                (!Runtime.IsStringType(py_mod_name)))
            {
                return(Exceptions.RaiseTypeError("string expected"));
            }

            // Check whether the import is of the form 'from x import y'.
            // This determines whether we return the head or tail module.

            IntPtr fromList = IntPtr.Zero;
            bool   fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if ((fromList != IntPtr.Zero) &&
                    (Runtime.PyObject_IsTrue(fromList) == 1))
                {
                    fromlist = true;
                }
            }

            string mod_name = Runtime.GetManagedString(py_mod_name);

            if (mod_name == "CLR" || mod_name == "clr")
            {
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }

            string realname = mod_name;

            if (mod_name.StartsWith("CLR."))
            {
                realname = mod_name.Substring(4);
            }

            string[] names = realname.Split('.');

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            AssemblyManager.LoadImplicit(realname);
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                return(Runtime.PyObject_Call(py_import, args, kw));
            }

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the exising module.

            IntPtr modules = Runtime.PyImport_GetModuleDict();
            IntPtr module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    Runtime.Incref(module);
                    return(module);
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.Incref(module);
                return(module);
            }
            Exceptions.Clear();

            // Traverse the qualified module name to get the named module
            // and place references in sys.modules as we go. Note that if
            // we are running in interactive mode we pre-load the names in
            // each module, which is often useful for introspection. If we
            // are not interactive, we stick to just-in-time creation of
            // objects at lookup time, which is much more efficient.

            if (preload < 0)
            {
                if (Runtime.PySys_GetObject("ps1") != IntPtr.Zero)
                {
                    preload = 1;
                }
                else
                {
                    Exceptions.Clear();
                    preload = 0;
                }
            }

            ModuleObject head = (mod_name == realname) ? null : root;
            ModuleObject tail = root;

            for (int i = 0; i < names.Length; i++)
            {
                string      name = names[i];
                ManagedType mt   = tail.GetAttribute(name);
                if (!(mt is ModuleObject))
                {
                    string error = String.Format("No module named {0}", name);
                    Exceptions.SetError(Exceptions.ImportError, error);
                    return(IntPtr.Zero);
                }
                if (head == null)
                {
                    head = (ModuleObject)mt;
                }
                tail = (ModuleObject)mt;
                if (preload == 1)
                {
                    tail.LoadNames();
                }
                Runtime.PyDict_SetItemString(modules, tail.moduleName,
                                             tail.pyHandle
                                             );
            }

            ModuleObject mod = fromlist ? tail : head;

            if (fromlist && Runtime.PySequence_Size(fromList) == 1)
            {
                IntPtr fp = Runtime.PySequence_GetItem(fromList, 0);
                if ((preload < 1) && Runtime.GetManagedString(fp) == "*")
                {
                    mod.LoadNames();
                }
                Runtime.Decref(fp);
            }

            Runtime.Incref(mod.pyHandle);
            return(mod.pyHandle);
        }
Example #14
0
        /// <summary>
        /// Convert a Python value to a correctly typed managed array instance.
        /// The Python value must support the Python iterator protocol or and the
        /// items in the sequence must be convertible to the target array type.
        /// </summary>
        private static bool ToArray(IntPtr value, Type obType, out object result, bool setError)
        {
            Type elementType = obType.GetElementType();

            result = null;

            IntPtr IterObject = Runtime.PyObject_GetIter(value);

            if (IterObject == IntPtr.Zero)
            {
                if (setError)
                {
                    SetConversionError(value, obType);
                }
                else
                {
                    // PyObject_GetIter will have set an error
                    Exceptions.Clear();
                }
                return(false);
            }

            IList list;

            try
            {
                // MakeGenericType can throw because elementType may not be a valid generic argument even though elementType[] is a valid array type.
                // For example, if elementType is a pointer type.
                // See https://docs.microsoft.com/en-us/dotnet/api/system.type.makegenerictype#System_Type_MakeGenericType_System_Type
                var  constructedListType = typeof(List <>).MakeGenericType(elementType);
                bool IsSeqObj            = Runtime.PySequence_Check(value);
                if (IsSeqObj)
                {
                    var len = Runtime.PySequence_Size(value);
                    list = (IList)Activator.CreateInstance(constructedListType, new Object[] { (int)len });
                }
                else
                {
                    // CreateInstance can throw even if MakeGenericType succeeded.
                    // See https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance#System_Activator_CreateInstance_System_Type_
                    list = (IList)Activator.CreateInstance(constructedListType);
                }
            }
            catch (Exception e)
            {
                if (setError)
                {
                    Exceptions.SetError(e);
                    SetConversionError(value, obType);
                }
                return(false);
            }

            IntPtr item;

            while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero)
            {
                object obj;

                if (!Converter.ToManaged(item, elementType, out obj, setError))
                {
                    Runtime.XDecref(item);
                    return(false);
                }

                list.Add(obj);
                Runtime.XDecref(item);
            }
            Runtime.XDecref(IterObject);

            Array items = Array.CreateInstance(elementType, list.Count);

            list.CopyTo(items, 0);

            result = items;
            return(true);
        }
Example #15
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            result = null;
            if (obType.IsEnum)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "since Python.NET 3.0 int can not be converted to Enum implicitly. Use Enum(int_value)");
                }
                return(false);
            }

            TypeCode tc = Type.GetTypeCode(obType);
            IntPtr   op = IntPtr.Zero;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                if (Runtime.Is32Bit)
                {
                    if (!Runtime.PyLong_Check(value))
                    {
                        goto type_error;
                    }
                    long num = Runtime.PyExplicitlyConvertToInt64(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = num;
                    return(true);
                }
                else
                {
                    nint num = Runtime.PyLong_AsSignedSize_t(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = (long)num;
                    return(true);
                }
            }

            case TypeCode.UInt16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                nuint num = Runtime.PyLong_AsUnsignedSize_t(value);
                if (num == unchecked ((nuint)(-1)) && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt32.MaxValue)
                {
                    goto overflow;
                }
                result = (uint)num;
                return(true);
            }

            case TypeCode.UInt64:
            {
                ulong num = Runtime.PyLong_AsUnsignedLongLong(value);
                if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            case TypeCode.Single:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            default:
                goto type_error;
            }

convert_error:
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }
Example #16
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out object result, bool setError)
        {
            if (obType == typeof(PyObject))
            {
                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            if (mt != null)
            {
                if (mt is CLRObject co)
                {
                    object tmp = co.inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    if (setError)
                    {
                        string typeString = tmp is null ? "null" : tmp.GetType().ToString();
                        Exceptions.SetError(Exceptions.TypeError, $"{typeString} value cannot be converted to {obType}");
                    }
                    return(false);
                }
                if (mt is ClassBase cb)
                {
                    if (!cb.type.Valid)
                    {
                        Exceptions.SetError(Exceptions.TypeError, cb.type.DeletedMessage);
                        return(false);
                    }
                    result = cb.type.Value;
                    return(true);
                }
                // shouldn't happen
                return(false);
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (value == Runtime.PyNone)
                {
                    result = null;
                    return(true);
                }
                // Set type to underlying type
                obType = obType.GetGenericArguments()[0];
            }

            if (obType.ContainsGenericParameters)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, $"Cannot create an instance of the open generic type {obType}");
                }
                return(false);
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable default
            // conversions (Python string -> managed string, Python int -> Int32 etc.).
            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result, setError));
                }

                if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                if (Runtime.PyInt_Check(value))
                {
                    return(ToPrimitive(value, int32Type, out result, setError));
                }

                if (Runtime.PyLong_Check(value))
                {
                    return(ToPrimitive(value, int64Type, out result, setError));
                }

                if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                // give custom codecs a chance to take over conversion of sequences
                IntPtr pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }

                if (Runtime.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result, setError));
                }

                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            // Conversion to 'Type' is done using the same mappings as above for objects.
            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                if (value == Runtime.PyIntType)
                {
                    result = int32Type;
                    return(true);
                }

                if (value == Runtime.PyLongType)
                {
                    result = int64Type;
                    return(true);
                }

                if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                if (value == Runtime.PyListType || value == Runtime.PyTupleType)
                {
                    result = typeof(object[]);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type");
                }

                return(false);
            }

            TypeCode typeCode = Type.GetTypeCode(obType);

            if (typeCode == TypeCode.Object || obType.IsEnum)
            {
                IntPtr pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }