[Zope-CVS] CVS: PythonNet/src/runtime - ClassManager.cs:1.9 ClassObject.cs:1.11 Converter.cs:1.9 MetaType.cs:1.9 MethodBinder.cs:1.9 ModuleObject.cs:1.5 Python.cs:1.6 Runtime.cs:1.14 TypeManager.cs:1.11

Brian Lloyd brian at zope.com
Sat Jan 17 23:30:07 EST 2004


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

Modified Files:
	ClassManager.cs ClassObject.cs Converter.cs MetaType.cs 
	MethodBinder.cs ModuleObject.cs Python.cs Runtime.cs 
	TypeManager.cs 
Log Message:
Checkin miscellaneous stuff done since Nov.


=== PythonNet/src/runtime/ClassManager.cs 1.8 => 1.9 ===
--- PythonNet/src/runtime/ClassManager.cs:1.8	Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/ClassManager.cs	Sat Jan 17 23:29:36 2004
@@ -105,15 +105,20 @@
 	    // Finally, initialize the class __dict__ and return the object.
 	    IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);
 
-	    IDictionaryEnumerator iter;
-	    ManagedType item;
-	    string name;
-
-	    iter = info.members.GetEnumerator();
+	    IDictionaryEnumerator iter = info.members.GetEnumerator();
 	    while(iter.MoveNext()) {
-		item = (ManagedType)iter.Value;
-		name = (string)iter.Key;
+		ManagedType item = (ManagedType)iter.Value;
+		string name = (string)iter.Key;
 		Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
+	    }
+
+	    // If class has constructors, generate an __doc__ attribute.
+
+	    ClassObject co = impl as ClassObject;
+	    if (co != null) {
+		IntPtr doc = co.GetDocString();
+		Runtime.PyDict_SetItemString(dict, "__doc__", doc);
+		Runtime.Decref(doc);
 	    }
 
 	    return impl;


=== PythonNet/src/runtime/ClassObject.cs 1.10 => 1.11 ===
--- PythonNet/src/runtime/ClassObject.cs:1.10	Thu Nov  6 23:05:05 2003
+++ PythonNet/src/runtime/ClassObject.cs	Sat Jan 17 23:29:36 2004
@@ -37,6 +37,22 @@
 
 
 	//====================================================================
+	// Helper to get docstring from reflected constructor info.
+	//====================================================================
+
+	internal IntPtr GetDocString() {
+	    MethodBase[] methods = binder.GetMethods();
+	    string str = "";
+	    for (int i = 0; i < methods.Length; i++) {
+		if (str.Length > 0)
+		    str += Environment.NewLine;
+		str += methods[i].ToString();
+	    }
+	    return Runtime.PyString_FromString(str);
+	}
+
+
+	//====================================================================
 	// Implements __new__ for reflected classes and value types.
 	//====================================================================
 


=== PythonNet/src/runtime/Converter.cs 1.8 => 1.9 ===
--- PythonNet/src/runtime/Converter.cs:1.8	Mon Oct 27 23:00:45 2003
+++ PythonNet/src/runtime/Converter.cs	Sat Jan 17 23:29:36 2004
@@ -183,17 +183,17 @@
 		return false;
 	    }
 
+	    if (value == Runtime.PyNone && !obType.IsValueType) {
+		result = null;
+		return true;
+	    }
+
 	    if (obType.IsArray) {
 		return ToArray(value, obType, out result, setError);
 	    }
 
 	    if (obType.IsEnum) {
 		return ToEnum(value, obType, out result, setError);
-	    }
-
-	    if (value == Runtime.PyNone && !obType.IsValueType) {
-		result = null;
-		return true;
 	    }
 
 	    // Conversion to 'Object' is done based on some reasonable


=== PythonNet/src/runtime/MetaType.cs 1.8 => 1.9 ===
--- PythonNet/src/runtime/MetaType.cs:1.8	Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/MetaType.cs	Sat Jan 17 23:29:36 2004
@@ -99,36 +99,44 @@
 	    }
 
 	    // hack for now... fix for 1.0
-	    return TypeManager.CreateSubType(args);
+	    //return TypeManager.CreateSubType(args);
 
-	    // Now that we've done sanity checking to make sure that it is
-	    // appropriate to subclass the given class, 
 
-//  	    IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType,
-//  					     TypeOffset.tp_new);
-//  	    IntPtr type = NativeCall.Call_3(func, tp, args, kw);
-//  	    if (type == IntPtr.Zero) {
-//  		return IntPtr.Zero;
-//  	    }
-
-//  	    int flags = TypeFlags.Default;
-//  	    flags |= TypeFlags.Managed;
-//  	    flags |= TypeFlags.HeapType;
-//  	    flags |= TypeFlags.BaseType;
-//  	    flags |= TypeFlags.Subclass;
-//  	    flags |= TypeFlags.HaveGC;
-//  	    Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
-
-//  	    TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc);
-
-//  	    // for now, move up hidden handle...
-//  	    IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic());
-//  	    Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);
+	    // right way
 
-//  	    //DebugUtil.DumpType(base_type);
-//  	    //DebugUtil.DumpType(type);
+	    IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType,
+					     TypeOffset.tp_new);
+	    IntPtr type = NativeCall.Call_3(func, tp, args, kw);
+	    if (type == IntPtr.Zero) {
+		return IntPtr.Zero;
+	    }
+
+	    int flags = TypeFlags.Default;
+	    flags |= TypeFlags.Managed;
+	    flags |= TypeFlags.HeapType;
+	    flags |= TypeFlags.BaseType;
+	    flags |= TypeFlags.Subclass;
+	    flags |= TypeFlags.HaveGC;
+	    Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
+
+	    TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc);
+
+	    // Hmm - the standard subtype_traverse, clear look at ob_size to
+	    // do things, so to allow gc to work correctly we need to move
+	    // our hidden handle out of ob_size. Then, in theory we can 
+	    // comment this out and still not crash.
+	    TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse);
+	    TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear);
+
+
+	    // for now, move up hidden handle...
+	    IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic());
+	    Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);
 
-//  	    return type;
+	    //DebugUtil.DumpType(base_type);
+	    //DebugUtil.DumpType(type);
+
+	    return type;
 	}
 
 
@@ -230,7 +238,6 @@
 
 	[CallConvCdecl()]
 	public static void tp_dealloc(IntPtr tp) {
-
 	    // Fix this when we dont cheat on the handle for subclasses!
 
 	    int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);


=== PythonNet/src/runtime/MethodBinder.cs 1.8 => 1.9 ===
--- PythonNet/src/runtime/MethodBinder.cs:1.8	Mon Oct 27 23:00:45 2003
+++ PythonNet/src/runtime/MethodBinder.cs	Sat Jan 17 23:29:36 2004
@@ -130,7 +130,7 @@
 
 	    for (int i = 0; i < _methods.Length; i++) {
 		MethodBase mi = _methods[i];
-
+		//Console.WriteLine("trying: {0}", mi.ToString());
 		ParameterInfo[] pi = mi.GetParameters();
 
 		int count = pi.Length;
@@ -143,6 +143,8 @@
 			Type type = pi[n].ParameterType;
 			Object arg;
 			if (!Converter.ToManaged(op, type, out arg, false)) {
+			    //Console.WriteLine("failed on: {0}", type.ToString());
+			    //DebugUtil.Print("ob is: ", op);
 			    Exceptions.Clear();
 			    margs = null;
 			    break;


=== PythonNet/src/runtime/ModuleObject.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/ModuleObject.cs:1.4	Wed Oct 22 22:53:10 2003
+++ PythonNet/src/runtime/ModuleObject.cs	Sat Jan 17 23:29:36 2004
@@ -30,7 +30,7 @@
 	string moduleName;
 	string _namespace;
 	Hashtable cache;
-	bool hacked;
+	static bool hacked;
 	IntPtr dict;
 
 	public ModuleObject(string name) : base() {
@@ -41,6 +41,7 @@
 	    dict = Runtime.PyDict_New();
 	    IntPtr pyname = Runtime.PyString_FromString(moduleName);
 	    Runtime.PyDict_SetItemString(dict, "__name__", pyname);
+	    Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone);
 	    Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone);
 	    Runtime.Decref(pyname);
 


=== PythonNet/src/runtime/Python.cs 1.5 => 1.6 ===
--- PythonNet/src/runtime/Python.cs:1.5	Thu Nov  6 23:05:05 2003
+++ PythonNet/src/runtime/Python.cs	Sat Jan 17 23:29:36 2004
@@ -60,6 +60,132 @@
 
 	public static void InitExt() {
 	    Initialize();
+
+	    // Trickery - when the import hook is installed into an already
+	    // running Python, the standard import machinery is still in 
+	    // control for the duration of the import that caused bootstrap.
+	    // 
+	    // That is problematic because the std machinery tries to get
+	    // sub-names directly from the module __dict__ rather than going
+	    // through our module object's getattr hook. This workaround
+	    // replaces the __dict__ of the root module with a proxy that
+	    // delegates to the getattr of the root module. ;^/
+
+	    string code = 
+"import sys\n" + 
+
+"class module(type(sys)):\n" + 
+"  def __init__(self, real):\n" + 
+"    self.dict = self.proxy(real)\n" + 
+"    self.real = real\n" + 
+"\n" + 
+"  def __getattribute__(self, name):\n" + 
+"    print 'getattr: %s' % name\n" +
+"    if name in ('dict', 'real', 'proxy'):\n" +
+"      return super(type(self), self).__getattribute__(name)\n" +
+"    real = super(type(self), self).__getattribute__('real')\n" +
+"    return getattr(real, name)\n" + 
+"\n" + 
+"  class proxy(dict):\n" + 
+"    def __init__(self, real):\n" + 
+"      self.real = real\n" + 
+"    def __getitem__(self, name):\n" + 
+"      print 'getitem: %s' % name\n" +
+"      return getattr(self.real, name)\n" + 
+"    def __setitem__(self, name, val):\n" + 
+"      obj = self.real.__dict__\n" + 
+"      dict.__setitem__(obj, name, val)\n" + 
+"    def keys(self):\n" + 
+"      return self.real.__dict__.keys()\n" + 
+"\n" + 
+"clr = sys.modules['CLR']\n" + 
+"sys.modules['CLR'] = module(clr)\n" + 
+"dict = sys.modules['CLR'].dict\n";
+
+	    IntPtr globals = Runtime.PyEval_GetGlobals();
+	    IntPtr locals = Runtime.PyDict_New();
+	    IntPtr flag = (IntPtr)257; /* Py_file_input */
+	    IntPtr done = Runtime.PyRun_String(code, flag, globals, locals);
+
+	    IntPtr dict = Runtime.PyDict_GetItemString(locals, "dict");
+	    Runtime.Decref(globals);
+	    Runtime.Decref(locals);
+	    Runtime.Decref(done);
+
+	    IntPtr temp = Runtime.PyImport_GetModuleDict();
+	    IntPtr mod = Runtime.PyDict_GetItemString(temp, "CLR");
+	    Marshal.WriteIntPtr(mod, ObjectOffset.ob_dict, dict);
+	}
+
+
+	public static void OldInitExt() {
+	    Initialize();
+
+	    // Trickery - when the import hook is installed into an already
+	    // running Python, the standard import machinery is still in 
+	    // control for the duration of the import that caused bootstrap.
+	    // 
+	    // That is problematic because the std machinery tries to get
+	    // sub-names directly from the module __dict__ rather than going
+	    // through our module object's getattr hook. This workaround
+	    // replaces the __dict__ of the root module with a proxy that
+	    // delegates to the getattr of the root module. ;^/
+
+	    IntPtr temp = Runtime.PyImport_GetModuleDict();
+	    IntPtr mod = Runtime.PyDict_GetItemString(temp, "CLR");
+
+	    string code = "class faux(dict):\n" +
+		          "  def __init__(self, ob, dict):\n" +
+		          "    self.dict = dict\n" +
+		          "    self.ob = ob\n" +
+		          "  def __getitem__(self, key):\n" +
+		          "    print 'getitem called!'\n" +
+		          "    v = self.dict.get(key)\n" +
+		          "    if v is not None:\n" +
+		          "      return v\n" +
+		          "    return getattr(self.ob, key)\n"+
+		          "  def __setitem__(self, key, val):\n" +
+                          "    self.dict[key] = val\n\n" +
+
+		          "import pdb; pdb.set_trace()\n";
+
+
+
+	    IntPtr globals = Runtime.PyEval_GetGlobals();
+	    IntPtr locals = Runtime.PyDict_New();
+	    IntPtr flag = (IntPtr)257; /* Py_file_input */
+	    IntPtr cls = Runtime.PyRun_String(code, flag, globals, locals);
+
+	    Runtime.Decref(globals);
+	    Runtime.Decref(cls);
+
+	    cls = Runtime.PyDict_GetItemString(locals, "faux");
+	    Runtime.Decref(locals);
+
+	    IntPtr old = Marshal.ReadIntPtr(mod, ObjectOffset.ob_dict);
+	    IntPtr args = Runtime.PyTuple_New(2);
+	    Runtime.Incref(mod);
+	    Runtime.PyTuple_SetItem(args, 0, mod);
+	    Runtime.Incref(old);
+	    Runtime.PyTuple_SetItem(args, 1, old);
+
+	    IntPtr dict = Runtime.PyObject_CallObject(cls, args);
+	    Runtime.Decref(cls);
+	    Runtime.Decref(args);
+
+	    Marshal.WriteIntPtr(mod, ObjectOffset.ob_dict, dict);
+
+	    //Runtime.PyObject_SetAttrString(mod, "__dict__", dict);
+	    /*
+
+	      import sys
+	      clr = sys.modules['CLR']
+
+
+	     */
+	    Runtime.Decref(mod);
+
+
 	}
 
 
@@ -197,6 +323,7 @@
 	public static int RunSimpleString(string code) {
 	    return Runtime.PyRun_SimpleString(code);
 	}
+
 
 
 	/// <summary>


=== PythonNet/src/runtime/Runtime.cs 1.13 => 1.14 ===
--- PythonNet/src/runtime/Runtime.cs:1.13	Thu Nov  6 23:05:05 2003
+++ PythonNet/src/runtime/Runtime.cs	Sat Jan 17 23:29:36 2004
@@ -312,6 +312,17 @@
 
 	[DllImport("python23", CallingConvention=CallingConvention.Cdecl,
 		    ExactSpelling=true, CharSet=CharSet.Ansi)]
+	internal unsafe static extern IntPtr
+	PyEval_GetGlobals();
+
+	[DllImport("python23", CallingConvention=CallingConvention.Cdecl,
+		    ExactSpelling=true, CharSet=CharSet.Ansi)]
+	internal unsafe static extern IntPtr
+	PyEval_GetLocals();
+
+
+	[DllImport("python23", CallingConvention=CallingConvention.Cdecl,
+		    ExactSpelling=true, CharSet=CharSet.Ansi)]
         internal unsafe static extern string
         Py_GetProgramName();
 
@@ -359,6 +370,11 @@
 		    ExactSpelling=true, CharSet=CharSet.Ansi)]
         internal unsafe static extern int
         PyRun_SimpleString(string code);
+
+	[DllImport("python23", CallingConvention=CallingConvention.Cdecl,
+		    ExactSpelling=true, CharSet=CharSet.Ansi)]
+        internal unsafe static extern IntPtr
+        PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals);
 
 	[DllImport("python23", CallingConvention=CallingConvention.Cdecl,
 		    ExactSpelling=true, CharSet=CharSet.Ansi)]


=== PythonNet/src/runtime/TypeManager.cs 1.10 => 1.11 ===
--- PythonNet/src/runtime/TypeManager.cs:1.10	Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/TypeManager.cs	Sat Jan 17 23:29:36 2004
@@ -175,10 +175,11 @@
 	    impl.gcHandle = gc;
 	    impl.pyHandle = type;
 
+	    //DebugUtil.DumpType(type);
+
 	    return type;
 	}
 
-
 	internal static IntPtr CreateSubType(IntPtr args) {
 
 	    IntPtr py_name = Runtime.PyTuple_GetItem(args, 0);
@@ -231,7 +232,6 @@
 	}
 
 
-
 	internal static IntPtr CreateMetaType(Type impl) {
 
 	    // The managed metatype is functionally little different than the
@@ -274,6 +274,47 @@
 	    Runtime.PyDict_SetItemString(dict, "__module__", mod);
 
 	    //DebugUtil.DumpType(type);
+
+	    return type;
+	}
+
+
+	internal static IntPtr BasicSubType(string name, IntPtr base_,
+					    Type impl) {
+
+	    // Utility to create a subtype of a std Python type, but with
+	    // a managed type able to override implementation
+
+	    IntPtr type = AllocateTypeObject(name);
+	    //Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
+	    //Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero);
+
+	    //IntPtr offset = (IntPtr)ObjectOffset.ob_dict;
+	    //Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
+
+	    //IntPtr dc = Runtime.PyDict_Copy(dict);
+	    //Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc);
+
+	    Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_);
+	    Runtime.Incref(base_);
+
+	    int flags = TypeFlags.Default;
+	    flags |= TypeFlags.Managed;
+	    flags |= TypeFlags.HeapType;
+	    flags |= TypeFlags.HaveGC;
+	    Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
+
+	    CopySlot(base_, type, TypeOffset.tp_traverse);
+	    CopySlot(base_, type, TypeOffset.tp_clear);
+	    CopySlot(base_, type, TypeOffset.tp_is_gc);
+
+	    InitializeSlots(type, impl);
+
+	    Runtime.PyType_Ready(type);
+
+	    IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
+	    IntPtr mod = Runtime.PyString_FromString("CLR");
+	    Runtime.PyDict_SetItemString(tp_dict, "__module__", mod);
 
 	    return type;
 	}




More information about the Zope-CVS mailing list