[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 ===