PySequence_Check() private method

private PySequence_Check ( IntPtr pointer ) : bool
pointer IntPtr
return bool
Esempio n. 1
0
        static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference)
        {
            isNewReference = false;
            IntPtr op;

            // for a params method, we may have a sequence or single/multiple items
            // here we look to see if the item at the paramIndex is there or not
            // and then if it is a sequence itself.
            if ((pyArgCount - arrayStart) == 1)
            {
                // we only have one argument left, so we need to check it
                // to see if it is a sequence or a single item
                IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart);
                if (!Runtime.PyString_Check(item) && Runtime.PySequence_Check(item))
                {
                    // it's a sequence (and not a string), so we use it as the op
                    op = item;
                }
                else
                {
                    isNewReference = true;
                    op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
                }
            }
            else
            {
                isNewReference = true;
                op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
            }
            return(op);
        }
Esempio n. 2
0
        static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference)
        {
            isNewReference = false;
            IntPtr op;

            // for a params method, we may have a sequence or single/multiple items
            // here we look to see if the item at the paramIndex is there or not
            // and then if it is a sequence itself.
            if ((pyArgCount - arrayStart) == 1)
            {
                // Ee only have one argument left, so we need to check to see if it is a sequence or a single item
                // We also need to check if this object is possibly a wrapped C# Enumerable Object
                IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart);
                if (!Runtime.PyString_Check(item) && (Runtime.PySequence_Check(item) || (ManagedType.GetManagedObject(item) as CLRObject)?.inst is IEnumerable))
                {
                    // it's a sequence (and not a string), so we use it as the op
                    op = item;
                }
                else
                {
                    // Its a single value that needs to be converted into the params array
                    isNewReference = true;
                    op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
                }
            }
            else
            {
                // Its a set of individual values, so we grab them as a tuple to be converted into the params array
                isNewReference = true;
                op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
            }
            return(op);
        }
Esempio n. 3
0
        /// <summary>
        /// Helper function for ToArray and ToList that creates a IList out of iterable objects
        /// </summary>
        /// <param name="value"></param>
        /// <param name="IterObject"></param>
        /// <param name="obType"></param>
        /// <param name="elementType"></param>
        /// <param name="setError"></param>
        /// <returns></returns>
        private static IList MakeList(IntPtr value, IntPtr IterObject, Type obType, Type elementType, bool setError)
        {
            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(null);
            }

            IntPtr item;
            var    usedImplicit = false;

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

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

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

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

            bool IsSeqObj = Runtime.PySequence_Check(value);
            var  len      = IsSeqObj ? Runtime.PySequence_Size(value) : -1;

            IntPtr IterObject = Runtime.PyObject_GetIter(value);

            if (IterObject == IntPtr.Zero)
            {
                if (setError)
                {
                    SetConversionError(value, obType);
                }
                return(false);
            }

            Array items;

            var   listType            = typeof(List <>);
            var   constructedListType = listType.MakeGenericType(elementType);
            IList list = IsSeqObj ? (IList)Activator.CreateInstance(constructedListType, new Object[] { (int)len }) :
                         (IList)Activator.CreateInstance(constructedListType);
            IntPtr item;

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

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

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

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

            result = items;
            return(true);
        }
Esempio n. 5
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)
                {
                    var cb = (ClassBase)mt;
                    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.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));
                }

                // 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)
            {
                IntPtr pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
        /// <summary>
        /// IsSequenceType Method
        /// </summary>
        ///
        /// <remarks>
        /// Returns true if the given object implements the sequence protocol.
        /// </remarks>

        public static bool IsSequenceType(PyObject value)
        {
            return(Runtime.PySequence_Check(value.obj));
        }
Esempio n. 7
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.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));
        }
Esempio n. 8
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out Object result, bool setError)
        {
            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            // XXX - hack to support objects wrapped in old-style classes
            // (such as exception objects).
            if (Runtime.wrap_exceptions)
            {
                if (mt == null)
                {
                    if (Runtime.PyObject_IsInstance(
                            value, Exceptions.Exception
                            ) > 0)
                    {
                        IntPtr p = Runtime.PyObject_GetAttrString(value, "_inner");
                        if (p != IntPtr.Zero)
                        {
                            // This is safe because we know that the __dict__ of
                            // value holds a reference to _inner.
                            value = p;
                            Runtime.Decref(p);
                            mt = ManagedType.GetManagedObject(value);
                        }
                    }
                    IntPtr c = Exceptions.UnwrapExceptionClass(value);
                    if ((c != IntPtr.Zero) && (c != value))
                    {
                        value = c;
                        Runtime.Decref(c);
                        mt = ManagedType.GetManagedObject(value);
                    }
                }
            }

            if (mt != null)
            {
                if (mt is CLRObject)
                {
                    object tmp = ((CLRObject)mt).inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    string err = "value cannot be converted to {0}";
                    err = String.Format(err, obType);
                    Exceptions.SetError(Exceptions.TypeError, err);
                    return(false);
                }
                if (mt is ClassBase)
                {
                    result = ((ClassBase)mt).type;
                    return(true);
                }
                // shouldnt happen
                return(false);
            }

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

            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));
                }

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

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

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

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

                else 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);
                }

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

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

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

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

                else 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));
        }
Esempio n. 9
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out object result, bool setError, out bool usedImplicit)
        {
            usedImplicit = false;
            if (obType == typeof(PyObject))
            {
                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            if (obType.IsGenericType && Runtime.PyObject_TYPE(value) == Runtime.PyListType)
            {
                var typeDefinition = obType.GetGenericTypeDefinition();
                if (typeDefinition == typeof(List <>))
                {
                    return(ToList(value, obType, out result, setError));
                }
            }

            // 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);
                    }
                    else
                    {
                        var type = tmp.GetType();
                        // check implicit conversions that receive tmp type and return obType
                        var conversionMethod = type.GetMethod("op_Implicit", new[] { type });
                        if (conversionMethod != null && conversionMethod.ReturnType == obType)
                        {
                            result       = conversionMethod.Invoke(null, new[] { tmp });
                            usedImplicit = true;
                            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));
            }

            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));
                }

                // 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);
            }

            var underlyingType = Nullable.GetUnderlyingType(obType);

            if (underlyingType != null)
            {
                return(ToManagedValue(value, underlyingType, out result, setError, out usedImplicit));
            }

            TypeCode typeCode = Type.GetTypeCode(obType);

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

            var opImplicit = obType.GetMethod("op_Implicit", new[] { obType });

            if (opImplicit != null)
            {
                if (ToManagedValue(value, opImplicit.ReturnType, out result, setError, out usedImplicit))
                {
                    opImplicit = obType.GetMethod("op_Implicit", new[] { result.GetType() });
                    if (opImplicit != null)
                    {
                        result = opImplicit.Invoke(null, new[] { result });
                    }
                    return(opImplicit != null);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
Esempio n. 10
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(BorrowedReference value, Type obType, out object?result, bool setError)
        {
            Type elementType = obType.GetElementType();

            result = null;

            using var IterObject = Runtime.PyObject_GetIter(value);
            if (IterObject.IsNull())
            {
                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);
                object[] constructorArgs     = Array.Empty <object>();
                if (IsSeqObj)
                {
                    var len = Runtime.PySequence_Size(value);
                    if (len >= 0)
                    {
                        if (len <= int.MaxValue)
                        {
                            constructorArgs = new object[] { (int)len };
                        }
                    }
                    else
                    {
                        // for the sequences, that explicitly deny calling __len__()
                        Exceptions.Clear();
                    }
                }
                // 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, args: constructorArgs);
            }
            catch (Exception e)
            {
                if (setError)
                {
                    Exceptions.SetError(e);
                    SetConversionError(value, obType);
                }
                return(false);
            }

            while (true)
            {
                using var item = Runtime.PyIter_Next(IterObject.Borrow());
                if (item.IsNull())
                {
                    break;
                }

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

                list.Add(obj);
            }

            if (Exceptions.ErrorOccurred())
            {
                if (!setError)
                {
                    Exceptions.Clear();
                }
                return(false);
            }

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

            list.CopyTo(items, 0);

            result = items;
            return(true);
        }
Esempio n. 11
0
        internal static bool ToManagedValue(BorrowedReference value, Type obType,
                                            out object?result, bool setError)
        {
            if (obType == typeof(PyObject))
            {
                result = new PyObject(value);
                return(true);
            }

            if (obType.IsSubclassOf(typeof(PyObject)) &&
                !obType.IsAbstract &&
                obType.GetConstructor(new[] { typeof(PyObject) }) is { } ctor)
            {
                var untyped = new PyObject(value);
                result = ToPyObjectSubclass(ctor, untyped, setError);
                return(result is not null);
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            result = null;
            switch (ManagedType.GetManagedObject(value))
            {
            case 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);

            case ClassBase cb:
                if (!cb.type.Valid)
                {
                    Exceptions.SetError(Exceptions.TypeError, cb.type.DeletedMessage);
                    return(false);
                }
                result = cb.type.Value;
                return(true);

            case null:
                break;

            default:
                throw new ArgumentException("We should never receive instances of other managed types");
            }

            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).
            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.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

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

                if (Runtime.PyInt_Check(value))
                {
                    result = new PyInt(value);
                    return(true);
                }

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

                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.PyLongType)
                {
                    result = typeof(PyInt);
                    return(true);
                }

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

                if (value == Runtime.PyListType)
                {
                    result = typeof(PyList);
                    return(true);
                }

                if (value == Runtime.PyTupleType)
                {
                    result = typeof(PyTuple);
                    return(true);
                }

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

                return(false);
            }

            if (DecodableByUser(obType))
            {
                BorrowedReference pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
Esempio n. 12
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);
        }