PyTuple_Size() private method

private PyTuple_Size ( IntPtr pointer ) : int
pointer IntPtr
return int
Ejemplo n.º 1
0
        /// <summary>
        /// DelegateObject __new__ implementation. The result of this is a new
        /// PyObject whose type is DelegateObject and whose ob_data is a handle
        /// to an actual delegate instance. The method wrapped by the actual
        /// delegate instance belongs to an object generated to relay the call
        /// to the Python callable passed in.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = (DelegateObject)GetManagedObject(tp);

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

            if (Runtime.PyTuple_Size(args) != 1)
            {
                return(Exceptions.RaiseTypeError("class takes exactly one argument"));
            }

            IntPtr method = Runtime.PyTuple_GetItem(args, 0);

            if (Runtime.PyCallable_Check(method) != 1)
            {
                return(Exceptions.RaiseTypeError("argument must be callable"));
            }

            Delegate d = PythonEngine.DelegateManager.GetDelegate(type, method);

            return(CLRObject.GetInstHandle(d, self.pyHandle));
        }
Ejemplo n.º 2
0
        internal bool NeedsDefaultArgs(IntPtr args)
        {
            var methods = SetterBinder.GetMethods();

            if (methods.Count == 0)
            {
                return(false);
            }
            int pynargs = Runtime.PyTuple_Size(args);

            var pi = methods[0].ParameterInfo;
            // need to subtract one for the value
            int clrnargs = pi.Length - 1;

            if (pynargs == clrnargs || pynargs > clrnargs)
            {
                return(false);
            }

            for (int v = pynargs; v < clrnargs; v++)
            {
                if (pi[v].DefaultValue == DBNull.Value)
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// This will return default arguments a new instance of a tuple. The size
        /// of the tuple will indicate the number of default arguments.
        /// </summary>
        /// <param name="args">This is pointing to the tuple args passed in</param>
        /// <returns>a new instance of the tuple containing the default args</returns>
        internal IntPtr GetDefaultArgs(IntPtr args)
        {
            // if we don't need default args return empty tuple
            if (!NeedsDefaultArgs(args))
            {
                return(Runtime.PyTuple_New(0));
            }
            var pynargs = Runtime.PyTuple_Size(args);

            // Get the default arg tuple
            MethodBase[] methods = SetterBinder.GetMethods();
            MethodBase   mi      = methods[0];

            ParameterInfo[] pi          = mi.GetParameters();
            int             clrnargs    = pi.Length - 1;
            IntPtr          defaultArgs = Runtime.PyTuple_New(clrnargs - pynargs);

            for (var i = 0; i < clrnargs - pynargs; i++)
            {
                if (pi[i + pynargs].DefaultValue == DBNull.Value)
                {
                    continue;
                }
                IntPtr arg = Converter.ToPython(pi[i + pynargs].DefaultValue, pi[i + pynargs].ParameterType);
                Runtime.PyTuple_SetItem(defaultArgs, i, arg);
            }
            return(defaultArgs);
        }
Ejemplo n.º 4
0
        //====================================================================
        // Implements __setitem__ for reflected classes and value types.
        //====================================================================

        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            //ManagedType self = GetManagedObject(ob);
            IntPtr    tp  = Runtime.PyObject_TYPE(ob);
            ClassBase 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;
            bool   free = false;

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

            int    i    = Runtime.PyTuple_Size(args);
            IntPtr real = Runtime.PyTuple_New(i + 1);

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

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

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

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

            return(0);
        }
Ejemplo n.º 5
0
        public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw)
        {
            MethodBinding self = (MethodBinding)GetManagedObject(ob);

            // 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.

            if ((self.target == IntPtr.Zero) && (!self.m.IsStatic()))
            {
                if (Runtime.PyTuple_Size(args) < 1)
                {
                    Exceptions.SetError(Exceptions.TypeError,
                                        "not enough arguments"
                                        );
                    return(IntPtr.Zero);
                }
                int    len   = Runtime.PyTuple_Size(args);
                IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len);
                IntPtr inst  = Runtime.PyTuple_GetItem(args, 0);
                Runtime.Incref(inst);
                IntPtr r = self.m.Invoke(inst, uargs, kw, self.info);
                Runtime.Decref(inst);
                Runtime.Decref(uargs);
                return(r);
            }

            return(self.m.Invoke(self.target, args, kw, self.info));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// DelegateObject __new__ implementation. The result of this is a new
        /// PyObject whose type is DelegateObject and whose ob_data is a handle
        /// to an actual delegate instance. The method wrapped by the actual
        /// delegate instance belongs to an object generated to relay the call
        /// to the Python callable passed in.
        /// </summary>
        public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
        {
            var self = (DelegateObject)GetManagedObject(tp) !;

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

            if (Runtime.PyTuple_Size(args) != 1)
            {
                return(Exceptions.RaiseTypeError("class takes exactly one argument"));
            }

            BorrowedReference method = Runtime.PyTuple_GetItem(args, 0);

            if (Runtime.PyCallable_Check(method) != 1)
            {
                return(Exceptions.RaiseTypeError("argument must be callable"));
            }

            Delegate d = PythonEngine.DelegateManager.GetDelegate(type, new PyObject(method));

            return(CLRObject.GetReference(d, ClassManager.GetClass(type)));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// This will return default arguments a new instance of a tuple. The size
        /// of the tuple will indicate the number of default arguments.
        /// </summary>
        /// <param name="args">This is pointing to the tuple args passed in</param>
        /// <returns>a new instance of the tuple containing the default args</returns>
        internal NewReference GetDefaultArgs(BorrowedReference args)
        {
            // if we don't need default args return empty tuple
            if (!NeedsDefaultArgs(args))
            {
                return(Runtime.PyTuple_New(0));
            }
            var pynargs = Runtime.PyTuple_Size(args);

            // Get the default arg tuple
            var        methods = SetterBinder.GetMethods();
            MethodBase mi      = methods[0].MethodBase;

            ParameterInfo[] pi          = mi.GetParameters();
            int             clrnargs    = pi.Length - 1;
            var             defaultArgs = Runtime.PyTuple_New(clrnargs - pynargs);

            for (var i = 0; i < clrnargs - pynargs; i++)
            {
                if (pi[i + pynargs].DefaultValue == DBNull.Value)
                {
                    continue;
                }
                using var arg = Converter.ToPython(pi[i + pynargs].DefaultValue, pi[i + pynargs].ParameterType);
                Runtime.PyTuple_SetItem(defaultArgs.Borrow(), i, arg.Steal());
            }
            return(defaultArgs);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Implements __new__ for reflected classes and value types.
        /// </summary>
        static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
        {
            // 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 (GetManagedObject(tp) is not ClassObject self)
            {
                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(default);
Ejemplo n.º 9
0
        internal bool NeedsDefaultArgs(IntPtr args)
        {
            var pynargs = Runtime.PyTuple_Size(args);

            MethodBase[] methods = SetterBinder.GetMethods();
            if (methods.Length == 0)
            {
                return(false);
            }

            MethodBase mi = methods[0];

            ParameterInfo[] pi = mi.GetParameters();
            // need to subtract one for the value
            int clrnargs = pi.Length - 1;

            if (pynargs == clrnargs || pynargs > clrnargs)
            {
                return(false);
            }

            for (var v = pynargs; v < clrnargs; v++)
            {
                if (pi[v].DefaultValue == DBNull.Value)
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 10
0
        //====================================================================
        // Metatype __new__ implementation. This is called to create a new
        // class / type when a reflected class is subclassed.
        //====================================================================

        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            int len = Runtime.PyTuple_Size(args);

            if (len < 3)
            {
                return(Exceptions.RaiseTypeError("invalid argument list"));
            }

            IntPtr name  = Runtime.PyTuple_GetItem(args, 0);
            IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
            IntPtr dict  = Runtime.PyTuple_GetItem(args, 2);

            // We do not support multiple inheritance, so the bases argument
            // should be a 1-item tuple containing the type we are subtyping.
            // That type must itself have a managed implementation. We check
            // that by making sure its metatype is the CLR metatype.

            if (Runtime.PyTuple_Size(bases) != 1)
            {
                return(Exceptions.RaiseTypeError(
                           "cannot use multiple inheritance with managed classes"
                           ));
            }

            IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0);
            IntPtr mt        = Runtime.PyObject_TYPE(base_type);

            if (!((mt == PyCLRMetaType) || (mt == Runtime.PyTypeType)))
            {
                return(Exceptions.RaiseTypeError("invalid metatype"));
            }

            // Ensure that the reflected type is appropriate for subclassing,
            // disallowing subclassing of delegates, enums and array types.

            ClassBase cb = GetManagedObject(base_type) as ClassBase;

            if (cb != null)
            {
                if (!cb.CanSubclass())
                {
                    return(Exceptions.RaiseTypeError(
                               "delegates, enums and array types cannot be subclassed"
                               ));
                }
            }

            IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");

            if (slots != IntPtr.Zero)
            {
                return(Exceptions.RaiseTypeError(
                           "subclasses of managed classes do not support __slots__"
                           ));
            }

            return(TypeManager.CreateSubType(name, base_type, dict));
        }
Ejemplo n.º 11
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"));
            }

            Type type = self.type;

            // 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));
        }
Ejemplo n.º 12
0
        public static IntPtr tp_new(IntPtr tpRaw, IntPtr args, IntPtr kw)
        {
            if (kw != IntPtr.Zero)
            {
                return(Exceptions.RaiseTypeError("array constructor takes no keyword arguments"));
            }

            var tp = new BorrowedReference(tpRaw);

            var self = GetManagedObject(tp) as ArrayObject;

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

            long[] dimensions = new long[Runtime.PyTuple_Size(args)];
            if (dimensions.Length == 0)
            {
                return(Exceptions.RaiseTypeError("array constructor requires at least one integer argument or an object convertible to array"));
            }
            if (dimensions.Length != 1)
            {
                return(CreateMultidimensional(arrType.GetElementType(), dimensions,
                                              shapeTuple: new BorrowedReference(args),
                                              pyType: tp)
                       .DangerousMoveToPointerOrNull());
            }

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

            // create single dimensional array
            if (Runtime.PyInt_Check(op))
            {
                dimensions[0] = Runtime.PyLong_AsSignedSize_t(op);
                if (dimensions[0] == -1 && Exceptions.ErrorOccurred())
                {
                    Exceptions.Clear();
                }
                else
                {
                    return(NewInstance(arrType.GetElementType(), tp, dimensions)
                           .DangerousMoveToPointerOrNull());
                }
            }
            object result;

            // this implements casting to Array[T]
            if (!Converter.ToManaged(op, arrType, out result, true))
            {
                return(IntPtr.Zero);
            }
            return(CLRObject.GetInstHandle(result, tp)
                   .DangerousGetAddress());
        }
Ejemplo n.º 13
0
        private static NewReference NewEnum(Type type, BorrowedReference args, BorrowedReference tp)
        {
            nint argCount       = Runtime.PyTuple_Size(args);
            bool allowUnchecked = false;

            if (argCount == 2)
            {
                var allow = Runtime.PyTuple_GetItem(args, 1);
                if (!Converter.ToManaged(allow, typeof(bool), out var allowObj, true) || allowObj is null)
                {
                    Exceptions.RaiseTypeError("second argument to enum constructor must be a boolean");
                    return(default);
Ejemplo n.º 14
0
        public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
        {
            if (kw != null)
            {
                return(Exceptions.RaiseTypeError("array constructor takes no keyword arguments"));
            }

            var self = (ArrayObject)GetManagedObject(tp) !;

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

            long[] dimensions = new long[Runtime.PyTuple_Size(args)];
            if (dimensions.Length == 0)
            {
                return(Exceptions.RaiseTypeError("array constructor requires at least one integer argument or an object convertible to array"));
            }
            if (dimensions.Length != 1)
            {
                return(CreateMultidimensional(arrType.GetElementType(), dimensions,
                                              shapeTuple: args,
                                              pyType: tp));
            }

            BorrowedReference op = Runtime.PyTuple_GetItem(args, 0);

            // create single dimensional array
            if (Runtime.PyInt_Check(op))
            {
                dimensions[0] = Runtime.PyLong_AsSignedSize_t(op);
                if (dimensions[0] == -1 && Exceptions.ErrorOccurred())
                {
                    Exceptions.Clear();
                }
                else
                {
                    return(NewInstance(arrType.GetElementType(), tp, dimensions));
                }
            }

            // this implements casting to Array[T]
            if (Converter.ToManaged(op, arrType, out object?result, true))
            {
                return(CLRObject.GetReference(result !, tp));
            }
            else
            {
                return(default);
Ejemplo n.º 15
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.

            if ((self.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);
                }
                IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len);
                IntPtr inst  = Runtime.PyTuple_GetItem(args, 0);
                Runtime.Incref(inst);
                IntPtr r = self.m.Invoke(inst, uargs, kw, self.info);
                Runtime.Decref(inst);
                Runtime.Decref(uargs);
                return(r);
            }

            return(self.m.Invoke(self.target, args, kw, self.info));
        }
Ejemplo n.º 16
0
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = GetManagedObject(tp) as ArrayObject;

            if (Runtime.PyTuple_Size(args) != 1)
            {
                return(Exceptions.RaiseTypeError("array expects 1 argument"));
            }
            IntPtr op = Runtime.PyTuple_GetItem(args, 0);
            object result;

            if (!Converter.ToManaged(op, self.type, out result, true))
            {
                return(IntPtr.Zero);
            }
            return(CLRObject.GetInstHandle(result, tp));
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Implements __new__ for reflected interface types.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = (InterfaceObject)GetManagedObject(tp);

            if (!self.type.Valid)
            {
                return(Exceptions.RaiseTypeError(self.type.DeletedMessage));
            }
            var    nargs = Runtime.PyTuple_Size(args);
            Type   type  = self.type.Value;
            object obj;

            if (nargs == 1)
            {
                IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
                var    co   = GetManagedObject(inst) as CLRObject;

                if (co == null || !type.IsInstanceOfType(co.inst))
                {
                    Exceptions.SetError(Exceptions.TypeError, $"object does not implement {type.Name}");
                    return(IntPtr.Zero);
                }

                obj = co.inst;
            }

            else if (nargs == 0 && self.ctor != null)
            {
                obj = self.ctor.Invoke(null);

                if (obj == null || !type.IsInstanceOfType(obj))
                {
                    Exceptions.SetError(Exceptions.TypeError, "CoClass default constructor failed");
                    return(IntPtr.Zero);
                }
            }

            else
            {
                Exceptions.SetError(Exceptions.TypeError, "interface takes exactly one argument");
                return(IntPtr.Zero);
            }

            return(self.WrapObject(obj));
        }
Ejemplo n.º 18
0
        //====================================================================
        // Implements __new__ for reflected interface types.
        //====================================================================

        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            InterfaceObject self  = (InterfaceObject)GetManagedObject(tp);
            int             nargs = Runtime.PyTuple_Size(args);
            Type            type  = self.type;
            Object          obj;

            if (nargs == 1)
            {
                IntPtr    inst = Runtime.PyTuple_GetItem(args, 0);
                CLRObject co   = GetManagedObject(inst) as CLRObject;

                if ((co == null) || (!type.IsInstanceOfType(co.inst)))
                {
                    string msg = "object does not implement " + type.Name;
                    Exceptions.SetError(Exceptions.TypeError, msg);
                    return(IntPtr.Zero);
                }

                obj = co.inst;
            }

            else if ((nargs == 0) && (self.ctor != null))
            {
                obj = self.ctor.Invoke(null);

                if (obj == null || !type.IsInstanceOfType(obj))
                {
                    Exceptions.SetError(Exceptions.TypeError,
                                        "CoClass default constructor failed"
                                        );
                    return(IntPtr.Zero);
                }
            }

            else
            {
                Exceptions.SetError(Exceptions.TypeError,
                                    "interface takes exactly one argument"
                                    );
                return(IntPtr.Zero);
            }

            return(CLRObject.GetInstHandle(obj, self.pyHandle));
        }
Ejemplo n.º 19
0
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            DelegateObject self = (DelegateObject)GetManagedObject(tp);

            if (Runtime.PyTuple_Size(args) != 1)
            {
                string message = "class takes exactly one argument";
                return(Exceptions.RaiseTypeError(message));
            }

            IntPtr method = Runtime.PyTuple_GetItem(args, 0);

            if (Runtime.PyCallable_Check(method) != 1)
            {
                return(Exceptions.RaiseTypeError("argument must be callable"));
            }

            Delegate d = DelegateManager.GetDelegate(self.type, method);

            return(CLRObject.GetInstHandle(d, self.pyHandle));
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Implements __new__ for reflected interface types.
        /// </summary>
        public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
        {
            var self = (InterfaceObject)GetManagedObject(tp) !;

            if (!self.type.Valid)
            {
                return(Exceptions.RaiseTypeError(self.type.DeletedMessage));
            }
            var    nargs = Runtime.PyTuple_Size(args);
            Type   type  = self.type.Value;
            object obj;

            if (nargs == 1)
            {
                BorrowedReference inst = Runtime.PyTuple_GetItem(args, 0);
                var co = GetManagedObject(inst) as CLRObject;

                if (co == null || !type.IsInstanceOfType(co.inst))
                {
                    Exceptions.SetError(Exceptions.TypeError, $"object does not implement {type.Name}");
                    return(default);
Ejemplo n.º 21
0
        internal static IntPtr GenerateExceptionClass(IntPtr real)
        {
            if (real == ns_exc)
            {
                return(os_exc);
            }

            IntPtr nbases = Runtime.PyObject_GetAttrString(real, "__bases__");

            if (Runtime.PyTuple_Size(nbases) != 1)
            {
                throw new SystemException("Invalid __bases__");
            }
            IntPtr nsbase = Runtime.PyTuple_GetItem(nbases, 0);

            Runtime.Decref(nbases);

            IntPtr osbase   = GetExceptionClassWrapper(nsbase);
            IntPtr baselist = Runtime.PyTuple_New(1);

            Runtime.Incref(osbase);
            Runtime.PyTuple_SetItem(baselist, 0, osbase);
            IntPtr name = Runtime.PyObject_GetAttrString(real, "__name__");

            IntPtr dict = Runtime.PyDict_New();
            IntPtr mod  = Runtime.PyObject_GetAttrString(real, "__module__");

            Runtime.PyDict_SetItemString(dict, "__module__", mod);
            Runtime.Decref(mod);

            IntPtr subc = Runtime.PyClass_New(baselist, dict, name);

            Runtime.Decref(baselist);
            Runtime.Decref(dict);
            Runtime.Decref(name);

            Runtime.PyObject_SetAttrString(subc, "_class", real);
            return(subc);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Implements __new__ for reflected generic types.
        /// </summary>
        public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
        {
            var self = (GenericType)GetManagedObject(tp) !;

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

            if (type.IsInterface && !type.IsConstructedGenericType)
            {
                var nargs = Runtime.PyTuple_Size(args);
                if (nargs == 1)
                {
                    var instance = Runtime.PyTuple_GetItem(args, 0);
                    return(AsGenericInterface(instance, type));
                }
            }

            Exceptions.SetError(Exceptions.TypeError, "cannot instantiate an open generic type");

            return(default);
Ejemplo n.º 23
0
        protected static void AppendArgumentTypes(StringBuilder to, IntPtr args)
        {
            long argCount = Runtime.PyTuple_Size(args);

            to.Append("(");
            for (long argIndex = 0; argIndex < argCount; argIndex++)
            {
                var arg = Runtime.PyTuple_GetItem(args, argIndex);
                if (arg != IntPtr.Zero)
                {
                    var type = Runtime.PyObject_Type(arg);
                    if (type != IntPtr.Zero)
                    {
                        try
                        {
                            var description = Runtime.PyObject_Str(type);
                            if (description != IntPtr.Zero)
                            {
                                to.Append(Runtime.GetManagedString(description));
                                Runtime.XDecref(description);
                            }
                        }
                        finally
                        {
                            Runtime.XDecref(type);
                        }
                    }
                }

                if (argIndex + 1 < argCount)
                {
                    to.Append(", ");
                }
            }
            to.Append(')');
        }
Ejemplo n.º 24
0
        /// <summary>
        /// The actual import hook that ties Python to the managed world.
        /// </summary>
        public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
        {
            var args = new BorrowedReference(argsRaw);

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

            BorrowedReference py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if (py_mod_name.IsNull ||
                !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.

            BorrowedReference fromList = default;
            var fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if (fromList != null &&
                    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")
            {
                NewReference clr_module = GetCLRModule(fromList);
                if (!clr_module.IsNull())
                {
                    BorrowedReference sys_modules = Runtime.PyImport_GetModuleDict();
                    if (!sys_modules.IsNull)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module.DangerousMoveToPointerOrNull());
            }

            string realname = mod_name;

            // 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.DangerousGetAddress(), 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);
            }
            // Save the exception
            var originalException = new PythonException();

            // Otherwise,  just clear the it.
            Exceptions.Clear();

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

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

            if (module != null)
            {
                if (fromlist)
                {
                    if (IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(module) as ModuleObject;
                        mod?.LoadNames();
                    }
                    return(new NewReference(module).DangerousMoveToPointer());
                }

                module = Runtime.PyDict_GetItemString(modules, names[0]);
                return(new NewReference(module, canBeNull: true).DangerousMoveToPointer());
            }
            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))
                {
                    originalException.Restore();
                    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.ObjectReference);
            }

            {
                var mod = fromlist ? tail : head;

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

                Runtime.XIncref(mod.pyHandle);
                return(mod.pyHandle);
            }
        }
Ejemplo n.º 25
0
        //===================================================================
        // The actual import hook that ties Python to the managed world.
        //===================================================================

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

            // 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")
            {
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }
            if (mod_name == "CLR")
            {
                Exceptions.deprecation("The CLR module is deprecated. " +
                                       "Please use 'clr'.");
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }
            string realname = mod_name;

            if (mod_name.StartsWith("CLR."))
            {
                realname = mod_name.Substring(4);
                string msg = String.Format("Importing from the CLR.* namespace " +
                                           "is deprecated. Please import '{0}' directly.", realname);
                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.
                    return(res);
                }
                // There was an error
                if (!Exceptions.ExceptionMatches(Exceptions.ImportError))
                {
                    // and it was NOT an ImportError; bail out here.
                    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))
            {
                bool fromFile = false;
                if (AssemblyManager.LoadImplicit(realname, out fromFile))
                {
                    if (true == fromFile)
                    {
                        string deprWarning = String.Format("\nThe module was found, but not in a referenced namespace.\n" +
                                                           "Implicit loading is deprecated. Please use clr.AddReference(\"{0}\").", realname);
                        Exceptions.deprecation(deprWarning);
                    }
                }
                else
                {
                    // 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 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.
            // 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();

            for (int i = 0; i < names.Length; i++)
            {
                string      name = names[i];
                ManagedType mt   = tail.GetAttribute(name, true);
                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 (CLRModule.preload)
                {
                    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 ((!CLRModule.preload) && Runtime.GetManagedString(fp) == "*")
                {
                    mod.LoadNames();
                }
                Runtime.Decref(fp);
            }

            Runtime.Incref(mod.pyHandle);
            return(mod.pyHandle);
        }
Ejemplo n.º 26
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);
        }
Ejemplo n.º 27
0
        internal List <Binding> Bind(IntPtr inst, IntPtr args, IntPtr kw, Type type, MethodBase info, MethodInfo[] methodinfo)
        {
            #region COM Binding

            List <Binding> bindings = new List <Binding>();

            #endregion


            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods  = null;
            var          pynargs   = (int)Runtime.PyTuple_Size(args);
            var          isGeneric = false;
            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                #region COM Binding

                try
                {
                    // Enforcable return types
                    if (type != null)
                    {
                        if (!(type.IsSubclassOf(((MethodInfo)mi).ReturnType) ||
                              type.Equals(((MethodInfo)mi).ReturnType)))
                        {
                            continue;
                        }
                    }
                }
                catch (InvalidCastException ex) { }

                #endregion

                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;

                if (!MatchesArgumentCount(pynargs, pi, out paramsArray, out defaultArgList))
                {
                    continue;
                }
                var outs  = 0;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList,
                                                needsResolution: _methods.Length > 1,
                                                outs: out outs);

                if (margs == null)
                {
                    continue;
                }

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        return(new List <Binding>());
                    }
                    target = co.inst;
                }

                #region COM Binding

                bindings.Add(new Binding(mi, target, margs, outs));
                //return new Binding(mi, target, margs, outs);

                #endregion
            }

            #region COM Binding

            if (bindings.Count > 0)
            {
                /*Binding item = bindings.Where<Binding>(x => x.info.Name.EndsWith("_Item")).FirstOrDefault<Binding>();
                 * if (item != null)
                 *  return item;
                 *
                 * Binding def = bindings.Where<Binding>(x => x.info.Name.EndsWith("_Default")).FirstOrDefault<Binding>();
                 * if (def != null)
                 *  return def;
                 *
                 * return bindings.First<Binding>();*/

                return(bindings.OrderBy(x => x.info.Name).ToList <Binding>());
            }

            #endregion

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, type, mi, null));
            }
            return(new List <Binding>());
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Bind the given Python instance and arguments to a particular method
        /// overload in <see cref="list"/> and return a structure that contains the converted Python
        /// instance, converted arguments and the correct method to call.
        /// If unsuccessful, may set a Python error.
        /// </summary>
        /// <param name="inst">The Python target of the method invocation.</param>
        /// <param name="args">The Python arguments.</param>
        /// <param name="kw">The Python keyword arguments.</param>
        /// <param name="info">If not null, only bind to that method.</param>
        /// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param>
        /// <returns>A Binding if successful.  Otherwise null.</returns>
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or w/o error
            MethodBase[] _methods = null;

            var kwargDict = new Dictionary <string, IntPtr>();

            if (kw != IntPtr.Zero)
            {
                var    pynkwargs = (int)Runtime.PyDict_Size(kw);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            var pynargs   = (int)Runtime.PyTuple_Size(args);
            var isGeneric = false;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            var argMatchedMethods = new List <MatchedMethod>(_methods.Length);
            var mismatchedMethods = new List <MismatchedMethod>();

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;
                int             kwargsMatched;
                int             defaultsNeeded;
                bool            isOperator = OperatorMethod.IsOperatorMethod(mi);
                // Binary operator methods will have 2 CLR args but only one Python arg
                // (unary operators will have 1 less each), since Python operator methods are bound.
                isOperator = isOperator && pynargs == pi.Length - 1;
                bool isReverse = isOperator && OperatorMethod.IsReverse((MethodInfo)mi);  // Only cast if isOperator.
                if (isReverse && OperatorMethod.IsComparisonOp((MethodInfo)mi))
                {
                    continue;  // Comparison operators in Python have no reverse mode.
                }
                if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList, out kwargsMatched, out defaultsNeeded) && !isOperator)
                {
                    continue;
                }
                // Preprocessing pi to remove either the first or second argument.
                if (isOperator && !isReverse)
                {
                    // The first Python arg is the right operand, while the bound instance is the left.
                    // We need to skip the first (left operand) CLR argument.
                    pi = pi.Skip(1).ToArray();
                }
                else if (isOperator && isReverse)
                {
                    // The first Python arg is the left operand.
                    // We need to take the first CLR argument.
                    pi = pi.Take(1).ToArray();
                }
                int outs;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList, outs: out outs);
                if (margs == null)
                {
                    var mismatchCause = PythonException.FetchCurrent();
                    mismatchedMethods.Add(new MismatchedMethod(mismatchCause, mi));
                    continue;
                }
                if (isOperator)
                {
                    if (inst != IntPtr.Zero)
                    {
                        if (ManagedType.GetManagedObject(inst) is CLRObject co)
                        {
                            bool isUnary = pynargs == 0;
                            // Postprocessing to extend margs.
                            var margsTemp = isUnary ? new object[1] : new object[2];
                            // If reverse, the bound instance is the right operand.
                            int boundOperandIndex = isReverse ? 1 : 0;
                            // If reverse, the passed instance is the left operand.
                            int passedOperandIndex = isReverse ? 0 : 1;
                            margsTemp[boundOperandIndex] = co.inst;
                            if (!isUnary)
                            {
                                margsTemp[passedOperandIndex] = margs[0];
                            }
                            margs = margsTemp;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }


                var matchedMethod = new MatchedMethod(kwargsMatched, defaultsNeeded, margs, outs, mi);
                argMatchedMethods.Add(matchedMethod);
            }
            if (argMatchedMethods.Count > 0)
            {
                var bestKwargMatchCount    = argMatchedMethods.Max(x => x.KwargsMatched);
                var fewestDefaultsRequired = argMatchedMethods.Where(x => x.KwargsMatched == bestKwargMatchCount).Min(x => x.DefaultsNeeded);

                int bestCount      = 0;
                int bestMatchIndex = -1;

                for (int index = 0; index < argMatchedMethods.Count; index++)
                {
                    var testMatch = argMatchedMethods[index];
                    if (testMatch.DefaultsNeeded == fewestDefaultsRequired && testMatch.KwargsMatched == bestKwargMatchCount)
                    {
                        bestCount++;
                        if (bestMatchIndex == -1)
                        {
                            bestMatchIndex = index;
                        }
                    }
                }

                if (bestCount > 1 && fewestDefaultsRequired > 0)
                {
                    // Best effort for determining method to match on gives multiple possible
                    // matches and we need at least one default argument - bail from this point
                    StringBuilder stringBuilder = new StringBuilder("Not enough arguments provided to disambiguate the method.  Found:");
                    foreach (var matchedMethod in argMatchedMethods)
                    {
                        stringBuilder.AppendLine();
                        stringBuilder.Append(matchedMethod.Method.ToString());
                    }
                    Exceptions.SetError(Exceptions.TypeError, stringBuilder.ToString());
                    return(null);
                }

                // If we're here either:
                //      (a) There is only one best match
                //      (b) There are multiple best matches but none of them require
                //          default arguments
                // in the case of (a) we're done by default. For (b) regardless of which
                // method we choose, all arguments are specified _and_ can be converted
                // from python to C# so picking any will suffice
                MatchedMethod bestMatch = argMatchedMethods[bestMatchIndex];
                var           margs     = bestMatch.ManagedArgs;
                var           outs      = bestMatch.Outs;
                var           mi        = bestMatch.Method;

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        Exceptions.SetError(Exceptions.TypeError, "Invoked a non-static method with an invalid instance");
                        return(null);
                    }
                    target = co.inst;
                }

                return(new Binding(mi, target, margs, outs));
            }
            else if (isGeneric && info == null && methodinfo != null)
            {
                // We weren't able to find a matching method but at least one
                // is a generic method and info is null. That happens when a generic
                // method was not called using the [] syntax. Let's introspect the
                // type of the arguments and use it to construct the correct method.
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                if (mi != null)
                {
                    return(Bind(inst, args, kw, mi, null));
                }
            }
            if (mismatchedMethods.Count > 0)
            {
                var aggregateException = GetAggregateException(mismatchedMethods);
                Exceptions.SetError(aggregateException);
            }
            return(null);
        }
Ejemplo n.º 29
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;

            var kwargDict = new Dictionary <string, IntPtr>();

            if (kw != IntPtr.Zero)
            {
                var    pynkwargs = (int)Runtime.PyDict_Size(kw);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            var pynargs   = (int)Runtime.PyTuple_Size(args);
            var isGeneric = false;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;

                if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList))
                {
                    continue;
                }
                var outs  = 0;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList,
                                                needsResolution: _methods.Length > 1,
                                                outs: out outs);

                if (margs == null)
                {
                    continue;
                }

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        return(null);
                    }
                    target = co.inst;
                }

                return(new Binding(mi, target, margs, outs));
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
Ejemplo n.º 30
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 = new StringBuilder("No method matches given arguments");
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    value.Append($" for {methodinfo[0].Name}");
                }

                long argCount = Runtime.PyTuple_Size(args);
                value.Append(": (");
                for (long argIndex = 0; argIndex < argCount; argIndex++)
                {
                    var arg = Runtime.PyTuple_GetItem(args, argIndex);
                    if (arg != IntPtr.Zero)
                    {
                        var type = Runtime.PyObject_Type(arg);
                        if (type != IntPtr.Zero)
                        {
                            try {
                                var description = Runtime.PyObject_Unicode(type);
                                if (description != IntPtr.Zero)
                                {
                                    value.Append(Runtime.GetManagedString(description));
                                    Runtime.XDecref(description);
                                }
                            } finally {
                                Runtime.XDecref(type);
                            }
                        }
                    }

                    if (argIndex + 1 < argCount)
                    {
                        value.Append(", ");
                    }
                }
                value.Append(')');
                Exceptions.SetError(Exceptions.TypeError, value.ToString());
                return(IntPtr.Zero);
            }

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

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

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

            // If there are out parameters, we return a tuple containing
            // the result 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));
        }