[Zope-CVS] CVS: PythonNet/src/runtime - Indexer.cs:1.1 ClassBase.cs:1.2 ClassManager.cs:1.2 TypeManager.cs:1.2 IndexerObject.cs:NONE makefile:NONE

Brian Lloyd brian@zope.com
Thu, 24 Jul 2003 19:55:38 -0400


Update of /cvs-repository/PythonNet/src/runtime
In directory cvs.zope.org:/tmp/cvs-serv24649/src/runtime

Modified Files:
	ClassBase.cs ClassManager.cs TypeManager.cs 
Added Files:
	Indexer.cs 
Removed Files:
	IndexerObject.cs makefile 
Log Message:
commit refactorings

=== Added File PythonNet/src/runtime/Indexer.cs ===
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.

using System;
using System.Collections;
using System.Reflection;
using System.Security.Permissions;

namespace Python.Runtime {

    //========================================================================
    // Bundles the information required to support an indexer property.
    //========================================================================

    internal class Indexer {

	public MethodBinder GetterBinder;
	public MethodBinder SetterBinder;

	public Indexer() {
	    GetterBinder = new MethodBinder();
	    SetterBinder = new MethodBinder();
	}

	public void AddProperty(PropertyInfo pi) {
	    MethodInfo getter = pi.GetGetMethod(true);
	    MethodInfo setter = pi.GetSetMethod(true);
	    if (getter != null) {
		GetterBinder.AddMethod(getter);
	    }
	    if (setter != null) {
		SetterBinder.AddMethod(setter);
	    }
	}

    }


}


=== PythonNet/src/runtime/ClassBase.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ClassBase.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ClassBase.cs	Thu Jul 24 19:55:00 2003
@@ -12,6 +12,7 @@
 using System;
 using System.Collections;
 using System.Reflection;
+using System.Security;
 using System.Runtime.InteropServices;
 
 namespace Python.Runtime {
@@ -27,142 +28,18 @@
 
     internal class ClassBase : ManagedType {
 
+	internal Indexer indexer;
 	internal Type type;
 
 	internal ClassBase(Type tp) : base() {
-	    tpHandle = TypeManager.GetTypeHandle(this, tp);
+	    indexer = null;
+	    //tpHandle = TypeManager.GetTypeHandle(this, tp);
 	    type = tp;
-	    InitializeClass();
+	    //InitializeClass();
 	}
 
 	internal virtual bool CanSubclass() {
 	    return (!this.type.IsEnum);
-	}
-
-	//====================================================================
-	// Reflected type initialization. This uses reflection to populate the
-	// __dict__ of the Python type object with descriptors that reflect
-	// the attributes of the reflected type.
-	//====================================================================
-
-	protected void InitializeClass() {
-	    // todo: name discrimination!
-	    Hashtable methods = new Hashtable();
-	    IntPtr pp = Runtime._PyObject_GetDictPtr(this.tpHandle);
-	    IntPtr op = Marshal.ReadIntPtr(pp);
-	    IntPtr dict = op;
-
-	    Type type = this.type;
-	    ArrayList list;
-	    MethodInfo mInfo;
-	    String name;
-	    Object item;
-	    Type tp;
-
-	    ManagedType mt;
-	    // may want to use DeclaredOnly here to match Python inheritance.
-
-	    BindingFlags flags = BindingFlags.Static | 
-		                 BindingFlags.Instance | 
-	                         BindingFlags.Public | 
-                                 BindingFlags.NonPublic;
-
-	    MemberInfo[] info = type.GetMembers(flags);
-
-	    int ilen = info.Length;
-	    for (int i=0; i < ilen; i++) {
-
-		MemberInfo mi = info[i];
-
-
-		switch(mi.MemberType) {
-
-	        case MemberTypes.Method:
-		    mInfo = (MethodInfo) mi;
-		    if (!(mInfo.IsPublic || mInfo.IsFamily || 
-			  mInfo.IsFamilyOrAssembly))
-			continue;
-		    name = mInfo.Name;
-		    item = methods[name];
-		    if (item == null) {
-			item = methods[name] = new ArrayList();
-		    }
-		    list = (ArrayList) item;
-		    list.Add(mInfo);
-		    continue;
-
-	        case MemberTypes.Property:
-		    PropertyInfo pi = (PropertyInfo) mi;
-
-		    MethodInfo mm = null;
-		    try {
-			mm = pi.GetGetMethod(true);
-			if (mm == null) {
-			    mm = pi.GetSetMethod(true);
-			}
-		    }
-		    catch (System.Security.SecurityException) {
-			// GetGetMethod may try to get a method protected by
-			// StrongNameIdentityPermission - effectively private.
-			continue;
-		    }
-
-		    if (mm == null) {
-			continue;
-		    }
-
-		    if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly))
-			continue;
-		    mt = new PropertyObject((PropertyInfo) mi);
-
-		    Runtime.PyDict_SetItemString(dict, mi.Name, mt.Handle);
-		    continue;
-
-	        case MemberTypes.Field:
-		    FieldInfo fi = (FieldInfo) mi;
-		    if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly))
-			continue;
-		    mt = new FieldObject((FieldInfo) mi);
-		    Runtime.PyDict_SetItemString(dict, mi.Name, mt.Handle);
-		    continue;
-
-	        case MemberTypes.Event:
-		    mt = new EventObject((EventInfo) mi);
-		    Runtime.PyDict_SetItemString(dict, mi.Name, mt.Handle);
-		    continue;
-
-	        case MemberTypes.NestedType:
-		    tp = (Type) mi;
-		    if (!(tp.IsNestedPublic || tp.IsNestedFamily || 
-			  tp.IsNestedFamORAssem))
-			continue;
-		    mt = ClassManager.GetClass(tp);
-		    Runtime.PyDict_SetItemString(dict, mi.Name, mt.Handle);
-		    continue;
-
-	        case MemberTypes.TypeInfo:
-		    continue;
-
-	        case MemberTypes.Constructor:
-		    continue;
-
-	        case MemberTypes.Custom:
-		    continue;
-		}
-	    }
-
-	    IDictionaryEnumerator dictIter = methods.GetEnumerator();
-
-	    while(dictIter.MoveNext()) {
-		name = (string) dictIter.Key;
-		list = (ArrayList) dictIter.Value;
-
-		MethodInfo[] mlist = (MethodInfo[])list.ToArray(typeof(MethodInfo));
-
-		mt = new MethodObject(name, mlist);
-		Runtime.PyDict_SetItemString(dict, name, mt.Handle);
-
-	    }
 	}
 
 


=== PythonNet/src/runtime/ClassManager.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ClassManager.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ClassManager.cs	Thu Jul 24 19:55:00 2003
@@ -13,13 +13,18 @@
 using System.Runtime.InteropServices;
 using System.Collections;
 using System.Reflection;
+using System.Security;
 
 namespace Python.Runtime {
 
     /// <summary>
-    /// The ClassManager is responsible for creating and managing Python
-    /// types that reflect managed classes, structs, interfaces, enums
-    /// and delegates.
+    /// The ClassManager is responsible for creating and managing instances
+    /// that implement the Python type objects that reflect managed classes.
+    ///
+    /// Each managed type reflected to Python is represented by an instance
+    /// of a concrete subclass of ClassBase. Each instance is associated with
+    /// a generated Python type object, whose slots point to static methods 
+    /// of the managed instance's class. 
     /// </summary>
 
     internal class ClassManager {
@@ -34,14 +39,10 @@
 	    dtype = typeof(System.Delegate);
 	}
 
-	/// <summary>
-	/// GetClass Method
-	/// </summary>
-	///
-	/// <remarks>
-	/// Return a ClassObject that reflects the given CLR type, or null
-	/// if the ClassObject cannot be created. Ref behavior??
-	/// </remarks>
+	//====================================================================
+	// Return the ClassBase-derived instance that implements a particular 
+	// reflected managed type, creating it if it doesn't yet exist.
+	//====================================================================
 
 	internal static ClassBase GetClass(Type type) {
 	    Object ob = cache[type];
@@ -53,23 +54,216 @@
 	    return (ClassBase) ob;
 	}
 
+
+	//====================================================================
+	// Create a new ClassBase-derived instance that implements a reflected
+	// managed type. The new object will be associated with a generated
+	// Python type object.
+	//====================================================================
+
 	private static ClassBase CreateClass(Type type) {
+
+	    // First, we introspect the managed type and build some class
+	    // information, including generating the member descriptors 
+	    // that we'll be putting in the Python class __dict__.
+
+	    ClassInfo info = GetClassInfo(type);
+
+	    // Next, select the appropriate managed implementation class.
+	    // Different kinds of types, such as array types or interface
+	    // types, want to vary certain implementation details to make
+	    // sure that the type semantics are consistent in Python.
+
+	    ClassBase impl;
+
 	    if (type.IsSubclassOf(dtype)) {
-		return new DelegateObject(type);
+		impl = new DelegateObject(type);
 	    }
 
-	    if (type.IsArray) {
-		return new ArrayObject(type);
+	    else if (type.IsArray) {
+		impl = new ArrayObject(type);
 	    }
 
-	    if (type.IsInterface) {
-		return new InterfaceObject(type);
+	    else if (type.IsInterface) {
+		impl = new InterfaceObject(type);
 	    }
 
-	    return new ClassObject(type);
+	    else {
+		impl = new ClassObject(type);
+	    }
+
+	    impl.indexer = info.indexer;
+
+	    // Now we allocate the Python type object to reflect the given
+	    // managed type, filling the Python type slots with thunks that
+	    // point to the managed methods providing the implementation.
+
+	    impl.tpHandle = TypeManager.GetTypeHandle(impl, type);
+
+
+	    // Finally, initialize the class __dict__ and return the object.
 
+	    IntPtr pp = Runtime._PyObject_GetDictPtr(impl.tpHandle);
+	    IntPtr dict = Marshal.ReadIntPtr(pp);
+	    IDictionaryEnumerator iter;
+	    ManagedType item;
+	    string name;
+
+	    iter = info.members.GetEnumerator();
+	    while(iter.MoveNext()) {
+		item = (ManagedType)iter.Value;
+		name = (string)iter.Key;
+		Runtime.PyDict_SetItemString(dict, name, item.Handle);
+	    }
+
+	    return impl;
 	}
 
+
+
+
+	private static ClassInfo GetClassInfo(Type type) {
+	    ClassInfo ci = new ClassInfo(type);
+	    Hashtable methods = new Hashtable();
+	    ArrayList list;
+	    MethodInfo meth;
+	    ManagedType ob;
+	    String name;
+	    Object item;
+	    Type tp;
+
+
+	    BindingFlags flags = BindingFlags.DeclaredOnly | 
+		                 BindingFlags.Static | 
+		                 BindingFlags.Instance | 
+	                         BindingFlags.Public | 
+                                 BindingFlags.NonPublic;
+
+	    MemberInfo[] info = type.GetMembers(flags);
+
+	    for (int i = 0; i < info.Length; i++) {
+
+		MemberInfo mi = info[i];
+
+		switch(mi.MemberType) {
+
+	        case MemberTypes.Method:
+		    meth = (MethodInfo) mi;
+		    if (!(meth.IsPublic || meth.IsFamily || 
+			  meth.IsFamilyOrAssembly))
+			continue;
+		    name = meth.Name;
+		    item = methods[name];
+		    if (item == null) {
+			item = methods[name] = new ArrayList();
+		    }
+		    list = (ArrayList) item;
+		    list.Add(meth);
+		    continue;
+
+	        case MemberTypes.Property:
+		    PropertyInfo pi = (PropertyInfo) mi;
+
+		    MethodInfo mm = null;
+		    try {
+			mm = pi.GetGetMethod(true);
+			if (mm == null) {
+			    mm = pi.GetSetMethod(true);
+			}
+		    }
+		    catch (SecurityException) {
+			// GetGetMethod may try to get a method protected by
+			// StrongNameIdentityPermission - effectively private.
+			continue;
+		    }
+
+		    if (mm == null) {
+			continue;
+		    }
+
+		    if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly))
+			continue;
+
+		    // Check for indexer
+		    ParameterInfo[] args = pi.GetIndexParameters();
+		    if (args.GetLength(0) > 0) {
+			Indexer idx = ci.indexer;
+			if (idx == null) {
+			    ci.indexer = new Indexer();
+			    idx = ci.indexer;
+			}
+			idx.AddProperty(pi);
+			continue;
+		    }
+
+		    ob = new PropertyObject((PropertyInfo) mi);
+		    ci.members[mi.Name] = ob;
+		    continue;
+
+	        case MemberTypes.Field:
+		    FieldInfo fi = (FieldInfo) mi;
+		    if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly))
+			continue;
+		    ob = new FieldObject((FieldInfo) mi);
+		    ci.members[mi.Name] = ob;
+		    continue;
+
+	        case MemberTypes.Event:
+		    ob = new EventObject((EventInfo) mi);
+		    ci.members[mi.Name] = ob;
+		    continue;
+
+	        case MemberTypes.NestedType:
+		    tp = (Type) mi;
+		    if (!(tp.IsNestedPublic || tp.IsNestedFamily || 
+			  tp.IsNestedFamORAssem))
+			continue;
+		    ob = ClassManager.GetClass(tp);
+		    ci.members[mi.Name] = ob;
+		    continue;
+
+		}
+	    }
+
+	    IDictionaryEnumerator iter = methods.GetEnumerator();
+
+	    while(iter.MoveNext()) {
+		name = (string) iter.Key;
+		list = (ArrayList) iter.Value;
+
+		MethodInfo[] mlist = (MethodInfo[])list.ToArray(
+						   typeof(MethodInfo)
+						   );
+
+		ob = new MethodObject(name, mlist);
+		ci.members[name] = ob;
+	    }
+
+	    return ci;
+
+	}
+
+
+
+
+
     }	
+
+
+
+
+
+    internal class ClassInfo {
+
+	internal ClassInfo(Type t) {
+	    members = new Hashtable();
+	    indexer = null;
+	}
+
+	public Hashtable members;
+	public Indexer indexer;
+    }
+
+
 
 }


=== PythonNet/src/runtime/TypeManager.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/TypeManager.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/TypeManager.cs	Thu Jul 24 19:55:00 2003
@@ -205,6 +205,11 @@
 	    PyTypeObject pyTypeObj = new PyTypeObject();
 	    pyTypeObj.tp_name = Marshal.StringToHGlobalAnsi(name);
 
+	    if (clrType.BaseType != null) {
+		ClassBase bc = ClassManager.GetClass(clrType.BaseType);
+		pyTypeObj.tp_base = bc.tpHandle;
+	    }
+
 	    pyTypeObj.ob_type = Runtime.PyCLRMetaType;
 	    obj.tpHandle = pyTypeObj.ob_type;
 	    obj.gcHandle = GCHandle.Alloc(obj);

=== Removed File PythonNet/src/runtime/IndexerObject.cs ===

=== Removed File PythonNet/src/runtime/makefile ===