Esempio n. 1
0
        /// <summary>
        /// Remove the given Python object event handler.
        /// </summary>
        internal bool RemoveEventHandler(IntPtr target, IntPtr handler)
        {
            object obj = null;

            if (target != IntPtr.Zero)
            {
                var co = (CLRObject)GetManagedObject(target);
                obj = co.inst;
            }

            IntPtr hash = Runtime.PyObject_Hash(handler);

            if (Exceptions.ErrorOccurred() || reg == null)
            {
                Exceptions.SetError(Exceptions.ValueError, "unknown event handler");
                return(false);
            }

            object key  = obj ?? info.ReflectedType;
            var    list = reg[key] as ArrayList;

            if (list == null)
            {
                Exceptions.SetError(Exceptions.ValueError, "unknown event handler");
                return(false);
            }

            object[]   args = { null };
            MethodInfo mi   = info.GetRemoveMethod(true);

            for (var i = 0; i < list.Count; i++)
            {
                var item = (Handler)list[i];
                if (item.hash != hash)
                {
                    continue;
                }
                args[0] = item.del;
                try
                {
                    mi.Invoke(obj, BindingFlags.Default, null, args, null);
                }
                catch
                {
                    continue;
                }
                list.RemoveAt(i);
                return(true);
            }

            Exceptions.SetError(Exceptions.ValueError, "unknown event handler");
            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Equals Method
        /// </summary>
        /// <remarks>
        /// Return true if this object is equal to the given object. This
        /// method is based on Python equality semantics.
        /// </remarks>
        public override bool Equals(object o)
        {
            if (!(o is PyObject))
            {
                return(false);
            }
            if (obj == ((PyObject)o).obj)
            {
                return(true);
            }
            int r = Runtime.PyObject_Compare(obj, ((PyObject)o).obj);

            if (Exceptions.ErrorOccurred())
            {
                throw new PythonException();
            }
            return(r == 0);
        }
Esempio n. 3
0
        /// <summary>
        /// Implements __setitem__ for reflected classes and value types.
        /// </summary>
        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            //ManagedType self = GetManagedObject(ob);
            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);
        }
Esempio n. 4
0
        /// <summary>
        /// Implements __getitem__ for array types.
        /// </summary>
        public static IntPtr mp_subscript(IntPtr ob, IntPtr idx)
        {
            var    obj      = (CLRObject)GetManagedObject(ob);
            var    items    = obj.inst as Array;
            Type   itemType = obj.inst.GetType().GetElementType();
            int    rank     = items.Rank;
            int    index;
            object value;

            // Note that CLR 1.0 only supports int indexes - methods to
            // support long indices were introduced in 1.1. We could
            // support long indices automatically, but given that long
            // indices are not backward compatible and a relative edge
            // case, we won't bother for now.

            // Single-dimensional arrays are the most common case and are
            // cheaper to deal with than multi-dimensional, so check first.

            if (rank == 1)
            {
                index = Runtime.PyInt_AsLong(idx);

                if (Exceptions.ErrorOccurred())
                {
                    return(Exceptions.RaiseTypeError("invalid index value"));
                }

                if (index < 0)
                {
                    index = items.Length + index;
                }

                try {
                    value = items.GetValue(index);
                }
                catch (IndexOutOfRangeException) {
                    Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                    return(IntPtr.Zero);
                }

                return(Converter.ToPython(value, itemType));
            }

            // Multi-dimensional arrays can be indexed a la: list[1, 2, 3].

            if (!Runtime.PyTuple_Check(idx))
            {
                Exceptions.SetError(Exceptions.TypeError, "invalid index value");
                return(IntPtr.Zero);
            }

            var count = Runtime.PyTuple_Size(idx);

            var args = new int[count];

            for (var i = 0; i < count; i++)
            {
                IntPtr op = Runtime.PyTuple_GetItem(idx, i);
                index = Runtime.PyInt_AsLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    return(Exceptions.RaiseTypeError("invalid index value"));
                }

                if (index < 0)
                {
                    index = items.GetLength(i) + index;
                }

                args.SetValue(index, i);
            }

            try {
                value = items.GetValue(args);
            }
            catch (IndexOutOfRangeException) {
                Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                return(IntPtr.Zero);
            }

            return(Converter.ToPython(value, itemType));
        }
Esempio n. 5
0
        /// <summary>
        /// Implements __setitem__ for array types.
        /// </summary>
        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            var    obj      = (CLRObject)GetManagedObject(ob);
            var    items    = obj.inst as Array;
            Type   itemType = obj.inst.GetType().GetElementType();
            int    rank     = items.Rank;
            int    index;
            object value;

            if (items.IsReadOnly)
            {
                Exceptions.RaiseTypeError("array is read-only");
                return(-1);
            }

            if (!Converter.ToManaged(v, itemType, out value, true))
            {
                return(-1);
            }

            if (rank == 1)
            {
                index = Runtime.PyInt_AsLong(idx);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.Length + index;
                }

                try {
                    items.SetValue(value, index);
                }
                catch (IndexOutOfRangeException) {
                    Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                    return(-1);
                }

                return(0);
            }

            if (!Runtime.PyTuple_Check(idx))
            {
                Exceptions.RaiseTypeError("invalid index value");
                return(-1);
            }

            var count = Runtime.PyTuple_Size(idx);
            var args  = new int[count];

            for (var i = 0; i < count; i++)
            {
                IntPtr op = Runtime.PyTuple_GetItem(idx, i);
                index = Runtime.PyInt_AsLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.GetLength(i) + index;
                }

                args.SetValue(index, i);
            }

            try {
                items.SetValue(value, args);
            }
            catch (IndexOutOfRangeException) {
                Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                return(-1);
            }

            return(0);
        }
Esempio n. 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);
        }