Beispiel #1
0
        private static Type GetBaseTypeFromUserType(PythonType curBasePythonType, IList <Type> baseInterfaces, Type curTypeToExtend)
        {
            Queue <PythonType> processing = new Queue <PythonType>();

            processing.Enqueue(curBasePythonType);

            do
            {
                PythonType walking = processing.Dequeue();
                foreach (PythonType dt in walking.BaseTypes)
                {
                    if (dt.ExtensionType == curTypeToExtend || curTypeToExtend.IsSubclassOf(dt.ExtensionType))
                    {
                        continue;
                    }

                    if (dt.ExtensionType.IsInterface)
                    {
                        baseInterfaces.Add(dt.ExtensionType);
                    }
                    else if (NewTypeMaker.IsInstanceType(dt.ExtensionType))
                    {
                        processing.Enqueue(dt);
                    }
                    else if (!dt.IsOldClass)
                    {
                        curTypeToExtend = null;
                        break;
                    }
                }
            } while (processing.Count > 0);
            return(curTypeToExtend);
        }
Beispiel #2
0
        public override Type GetTypesToExtend(out IList <Type> interfacesToExtend)
        {
            interfacesToExtend = new List <Type>();
            foreach (object b in bases)
            {
                if (b is OldClass)
                {
                    continue;
                }

                PythonType   baseType = b as PythonType;
                IList <Type> baseTypeInterfaces;
                baseType.GetTypesToExtend(out baseTypeInterfaces);
                foreach (Type baseTypeInterface in baseTypeInterfaces)
                {
                    interfacesToExtend.Add(baseTypeInterface);
                }
            }
            // We dont use type.GetInterfaces() as it contains all the interfaces that are added by NewTypeMaker,
            // as well as all the interfaces implemented by type.BaseType. Instead, we only want the new set of
            // interfaces that need to be implemented by the new instance type.
            Debug.Assert(interfacesToExtend.Count < type.GetInterfaces().Length);

            // "type" is the instance type used for instances of this type. This will be a type created by NewTypeMaker.
            Debug.Assert(NewTypeMaker.IsInstanceType(type));
            // Its BaseType will the CLI type that needs to be inherited by instance types used by other UserTypes inheriting
            // from the current UserType. For pure Python types, this will be System.Object.
            Debug.Assert(!NewTypeMaker.IsInstanceType(type.BaseType));

            return(type.BaseType);
        }
        /// <summary>
        /// Gets a builtin function for the given declaring type and member infos.
        ///
        /// Given the same inputs this always returns the same object ensuring there's only 1 builtinfunction
        /// for each .NET method.
        ///
        /// This method takes both a cacheName and a pythonName.  The cache name is the real method name.  The pythonName
        /// is the name of the method as exposed to Python.
        /// </summary>
        internal static BuiltinFunction /*!*/ GetBuiltinFunction(Type /*!*/ type, string /*!*/ cacheName, string /*!*/ pythonName, FunctionType?funcType, params MemberInfo /*!*/[] /*!*/ mems)
        {
            BuiltinFunction res = null;

            if (mems.Length != 0)
            {
                FunctionType ft = funcType ?? GetMethodFunctionType(type, mems);
                type = GetBaseDeclaringType(type, mems);

                BuiltinFunctionKey cache = new BuiltinFunctionKey(type, new ReflectionCache.MethodBaseCache(cacheName, GetNonBaseHelperMethodInfos(mems)), ft);

                lock (_functions) {
                    if (!_functions.TryGetValue(cache, out res))
                    {
                        if (PythonTypeOps.GetFinalSystemType(type) == type)
                        {
                            IList <MethodInfo> overriddenMethods = NewTypeMaker.GetOverriddenMethods(type, cacheName);

                            if (overriddenMethods.Count > 0)
                            {
                                List <MemberInfo> newMems = new List <MemberInfo>(mems);

                                foreach (MethodInfo mi in overriddenMethods)
                                {
                                    newMems.Add(mi);
                                }

                                mems = newMems.ToArray();
                            }
                        }

                        _functions[cache] = res = BuiltinFunction.MakeMethod(pythonName, ReflectionUtils.GetMethodInfos(mems), type, ft);
                    }
                }
            }

            return(res);
        }
Beispiel #4
0
        /// <summary>
        /// clr.CompileSubclassTypes(assemblyName, *typeDescription)
        ///
        /// Provides a helper for creating an assembly which contains pre-generated .NET
        /// base types for new-style types.
        ///
        /// This assembly can then be AddReferenced or put sys.prefix\DLLs and the cached
        /// types will be used instead of generating the types at runtime.
        ///
        /// This function takes the name of the assembly to save to and then an arbitrary
        /// number of parameters describing the types to be created.  Each of those
        /// parameter can either be a plain type or a sequence of base types.
        ///
        /// clr.CompileSubclassTypes(object) -> create a base type for object
        /// clr.CompileSubclassTypes(object, str, System.Collections.ArrayList) -> create
        ///     base  types for both object and ArrayList.
        ///
        /// clr.CompileSubclassTypes(object, (object, IComparable)) -> create base types for
        ///     object and an object which implements IComparable.
        ///
        /// </summary>
        public static void CompileSubclassTypes(string /*!*/ assemblyName, params object[] newTypes)
        {
            if (assemblyName == null)
            {
                throw PythonOps.TypeError("CompileTypes expected str for assemblyName, got NoneType");
            }

            var typesToCreate = new List <PythonTuple>();

            foreach (object o in newTypes)
            {
                if (o is PythonType)
                {
                    typesToCreate.Add(PythonTuple.MakeTuple(o));
                }
                else
                {
                    typesToCreate.Add(PythonTuple.Make(o));
                }
            }

            NewTypeMaker.SaveNewTypes(assemblyName, typesToCreate);
        }
Beispiel #5
0
        protected UserType(string name, Tuple bases, IDictionary <object, object> dict)
            : base(NewTypeMaker.GetNewType(name, bases, dict))
        {
            List <MethodInfo> ctors = new List <MethodInfo>();

            foreach (MethodInfo mi in type.GetMethods())
            {
                if (mi.Name == ReflectedType.MakeNewName)
                {
                    ctors.Add(mi);
                }
            }

            if (ctors.Count == 0)
            {
                throw new NotImplementedException("no MakeNew found");
            }

            ctor = BuiltinFunction.Make(name, ctors.ToArray(), ctors.ToArray(), FunctionType.Function);

            IAttributesDictionary fastDict = (IAttributesDictionary)dict;

            this.__name__   = name;
            this.__module__ = fastDict[SymbolTable.Module];   // should always be present...

            if (!fastDict.ContainsKey(SymbolTable.Doc))
            {
                fastDict[SymbolTable.Doc] = null;
            }

            InitializeUserType(bases, false);

            this.dict = CreateNamespaceDictionary(dict);

            AddProtocolWrappers();
        }
        internal static ReflectedGetterSetter GetReflectedProperty(PropertyTracker pt, MemberGroup allProperties, bool privateBinding)
        {
            ReflectedGetterSetter rp;

            lock (_propertyCache) {
                if (_propertyCache.TryGetValue(pt, out rp))
                {
                    return(rp);
                }

                NameType   nt     = NameType.PythonProperty;
                MethodInfo getter = FilterProtectedGetterOrSetter(pt.GetGetMethod(true), privateBinding);
                MethodInfo setter = FilterProtectedGetterOrSetter(pt.GetSetMethod(true), privateBinding);

                if ((getter != null && PythonHiddenAttribute.IsHidden(getter, true)) ||
                    (setter != null && PythonHiddenAttribute.IsHidden(setter, true)))
                {
                    nt = NameType.Property;
                }

                ExtensionPropertyTracker ept = pt as ExtensionPropertyTracker;
                if (ept == null)
                {
                    ReflectedPropertyTracker rpt = pt as ReflectedPropertyTracker;
                    Debug.Assert(rpt != null);

                    if (PythonBinder.IsExtendedType(pt.DeclaringType) ||
                        PythonHiddenAttribute.IsHidden(rpt.Property, true))
                    {
                        nt = NameType.Property;
                    }

                    if (pt.GetIndexParameters().Length == 0)
                    {
                        List <MethodInfo> getters = new List <MethodInfo>();
                        List <MethodInfo> setters = new List <MethodInfo>();

                        IList <ExtensionPropertyTracker> overriddenProperties = NewTypeMaker.GetOverriddenProperties((getter ?? setter).DeclaringType, pt.Name);
                        foreach (ExtensionPropertyTracker tracker in overriddenProperties)
                        {
                            MethodInfo method = tracker.GetGetMethod(privateBinding);
                            if (method != null)
                            {
                                getters.Add(method);
                            }

                            method = tracker.GetSetMethod(privateBinding);
                            if (method != null)
                            {
                                setters.Add(method);
                            }
                        }

                        foreach (PropertyTracker propTracker in allProperties)
                        {
                            MethodInfo method = propTracker.GetGetMethod(privateBinding);
                            if (method != null)
                            {
                                getters.Add(method);
                            }

                            method = propTracker.GetSetMethod(privateBinding);
                            if (method != null)
                            {
                                setters.Add(method);
                            }
                        }
                        rp = new ReflectedProperty(rpt.Property, getters.ToArray(), setters.ToArray(), nt);
                    }
                    else
                    {
                        rp = new ReflectedIndexer(((ReflectedPropertyTracker)pt).Property, NameType.Property, privateBinding);
                    }
                }
                else
                {
                    rp = new ReflectedExtensionProperty(new ExtensionPropertyInfo(pt.DeclaringType, getter ?? setter), nt);
                }

                _propertyCache[pt] = rp;

                return(rp);
            }
        }
Beispiel #7
0
        /// <summary>
        /// "bases" contains a set of PythonTypes. These can include types defined in Python (say cpy1, cpy2),
        /// CLI types (say cCLI1, cCLI2), and CLI interfaces (say iCLI1, iCLI2). Here are some
        /// examples of how this works:
        ///
        /// (bases)                      => baseType,        {interfaceTypes}
        ///
        /// (cpy1)                       => System.Object,   {}
        /// (cpy1, cpy2)                 => System.Object,   {}
        /// (cpy1, cCLI1, iCLI1, iCLI2)  => cCLI1,           {iCLI1, iCLI2}
        /// [some type that satisfies the line above] =>
        ///                                 cCLI1,           {iCLI1, iCLI2}
        /// (cCLI1, cCLI2)               => error
        /// </summary>
        public static NewTypeInfo GetTypeInfo(string typeName, PythonTuple bases)
        {
            List <Type> interfaceTypes = new List <Type>();
            Type        baseCLIType    = typeof(object); // Pure Python object instances inherit from System.Object
            PythonType  basePythonType = null;

            foreach (PythonType curBasePythonType in GetPythonTypes(typeName, bases))
            {
                // discover the initial base/interfaces
                IList <Type> baseInterfaces  = ReflectionUtils.EmptyTypes;
                Type         curTypeToExtend = curBasePythonType.ExtensionType;

                if (curBasePythonType.ExtensionType.IsInterface)
                {
                    baseInterfaces  = new Type[] { curTypeToExtend };
                    curTypeToExtend = typeof(object);
                }
                else if (NewTypeMaker.IsInstanceType(curTypeToExtend))
                {
                    baseInterfaces  = new List <Type>();
                    curTypeToExtend = GetBaseTypeFromUserType(curBasePythonType, baseInterfaces, curTypeToExtend.BaseType);
                }

                if (curTypeToExtend == null || typeof(BuiltinFunction).IsAssignableFrom(curTypeToExtend) || typeof(PythonFunction).IsAssignableFrom(curTypeToExtend))
                {
                    throw PythonOps.TypeError(typeName + ": {0} is not an acceptable base type", curBasePythonType.Name);
                }
                if (curTypeToExtend.ContainsGenericParameters)
                {
                    throw PythonOps.TypeError(typeName + ": cannot inhert from open generic instantiation {0}. Only closed instantiations are supported.", curBasePythonType);
                }

                foreach (Type interfaceType in baseInterfaces)
                {
                    if (interfaceType.ContainsGenericParameters)
                    {
                        throw PythonOps.TypeError(typeName + ": cannot inhert from open generic instantiation {0}. Only closed instantiations are supported.", interfaceType);
                    }

                    // collecting all the interfaces because we override them all.
                    interfaceTypes.Add(interfaceType);
                }

                // if we're not extending something already in our existing base classes type hierarchy
                // then we better be in some esoteric __slots__ situation
                if (!baseCLIType.IsSubclassOf(curTypeToExtend))
                {
                    if (baseCLIType != typeof(object) && baseCLIType != curTypeToExtend &&
                        (!baseCLIType.IsDefined(typeof(DynamicBaseTypeAttribute), false) && !curTypeToExtend.IsSubclassOf(baseCLIType)))
                    {
                        throw PythonOps.TypeError(
                                  typeName + ": can only extend one CLI or builtin type, not both {0} (for {1}) and {2} (for {3})",
                                  baseCLIType.FullName,
                                  basePythonType,
                                  curTypeToExtend.FullName,
                                  curBasePythonType);
                    }

                    // we have a new base type
                    baseCLIType    = curTypeToExtend;
                    basePythonType = curBasePythonType;
                }
            }
            return(new NewTypeInfo(baseCLIType, interfaceTypes.Count == 0 ? ReflectionUtils.EmptyTypes : interfaceTypes.ToArray()));
        }