[Zope-CVS] CVS: PythonNet/src/runtime - AssemblyManager.cs:1.4
ClassObject.cs:1.10 ConstructorBinder.cs:1.5
Exceptions.cs:1.7 ImportHook.cs:1.7 PropertyObject.cs:1.5
Python.cs:1.5 Runtime.cs:1.13
Brian Lloyd
cvs-admin at zope.org
Thu Nov 6 23:05:36 EST 2003
Update of /cvs-repository/PythonNet/src/runtime
In directory cvs.zope.org:/tmp/cvs-serv12322/src/runtime
Modified Files:
AssemblyManager.cs ClassObject.cs ConstructorBinder.cs
Exceptions.cs ImportHook.cs PropertyObject.cs Python.cs
Runtime.cs
Log Message:
Add assembly load from python path; fix bug in constructors; added some
better finalization on shutdown.
=== PythonNet/src/runtime/AssemblyManager.cs 1.3 => 1.4 ===
--- PythonNet/src/runtime/AssemblyManager.cs:1.3 Wed Nov 5 22:35:10 2003
+++ PythonNet/src/runtime/AssemblyManager.cs Thu Nov 6 23:05:05 2003
@@ -25,26 +25,33 @@
internal class AssemblyManager {
+ static AssemblyLoadEventHandler lh;
+ static ResolveEventHandler rh;
static Hashtable namespaces;
static ArrayList assemblies;
static Hashtable probed;
+ static int last;
private AssemblyManager() {}
- static AssemblyManager() {
+ //===================================================================
+ // Initialization performed on startup of the Python runtime.
+ //===================================================================
+
+ internal static void Initialize() {
+
namespaces = new Hashtable();
assemblies = new ArrayList();
probed = new Hashtable();
AppDomain domain = AppDomain.CurrentDomain;
- domain.AssemblyLoad += new AssemblyLoadEventHandler(
- AssemblyLoadHandler
- );
-
-// domain.AssemblyResolve += new ResolveEventHandler(
-// ResolveHandler
-// );
-
+
+ lh = new AssemblyLoadEventHandler(AssemblyLoadHandler);
+ domain.AssemblyLoad += lh;
+
+ rh = new ResolveEventHandler(ResolveHandler);
+ domain.AssemblyResolve += rh;
+
Assembly[] items = domain.GetAssemblies();
for (int i = 0; i < items.Length; i++) {
Assembly a = items[i];
@@ -55,6 +62,17 @@
//===================================================================
+ // Cleanup resources upon shutdown of the Python runtime.
+ //===================================================================
+
+ internal static void Finalize() {
+ AppDomain domain = AppDomain.CurrentDomain;
+ domain.AssemblyLoad -= lh;
+ domain.AssemblyResolve -= rh;
+ }
+
+
+ //===================================================================
// Event handler for assembly load events. At the time the Python
// runtime loads, we scan the app domain to map the assemblies that
// are loaded at the time. We also have to register this event handler
@@ -79,7 +97,6 @@
static Assembly ResolveHandler(Object ob, ResolveEventArgs args){
string name = args.Name.ToLower();
-
for (int i = 0; i < assemblies.Count; i++) {
Assembly a = (Assembly)assemblies[i];
string full = a.FullName.ToLower();
@@ -87,8 +104,11 @@
return a;
}
}
-
- return LoadAssembly(name);
+ IntPtr ts = PythonEngine.EnsureThread();
+ IntPtr cs = Runtime.PyThreadState_Swap(ts);
+ Assembly ao = LoadAssemblyPath(args.Name);
+ Runtime.PyThreadState_Swap(cs);
+ return ao;
}
@@ -98,20 +118,24 @@
// using standard load semantics (app base directory then GAC, etc.)
//===================================================================
- internal string FindAssembly(string name) {
- // TODO: finish
+ static string FindAssembly(string name) {
+ IntPtr list = Runtime.PySys_GetObject("path");
+ int count = Runtime.PyList_Size(list);
char sep = Path.DirectorySeparatorChar;
- string path = name;
- string[] list = {};
- int count = list.Length;
for (int i = 0; i < count; i++) {
- string temp = list[i] + sep + name;
+ IntPtr item = Runtime.PyList_GetItem(list, i);
+ string head = Runtime.GetManagedString(item);
+ string path = head + sep + name;
+ string temp = path + ".dll";
+ if (File.Exists(temp)) {
+ return temp;
+ }
+ temp = path + ".exe";
if (File.Exists(temp)) {
return temp;
}
}
-
return null;
}
@@ -133,6 +157,21 @@
//===================================================================
+ // Loads an assembly using an augmented search path (the python path).
+ //===================================================================
+
+ public static Assembly LoadAssemblyPath(string name) {
+ string path = FindAssembly(name);
+ Assembly assembly = null;
+ if (path != null) {
+ try { assembly = Assembly.LoadFrom(path); }
+ catch {}
+ }
+ return assembly;
+ }
+
+
+ //===================================================================
// Given a qualified name of the form A.B.C.D, attempt to load
// an assembly named after each of A.B.C.D, A.B.C, A.B, A. This
// will only actually probe for the assembly once for each unique
@@ -140,13 +179,26 @@
//===================================================================
public static bool LoadImplicit(string name) {
+ // We'd like to cache misses to improve import speed, but we also
+ // want to be able to have an import fail and then succeed later
+ // after adding something to sys.path. This lets us do both :)
+ IntPtr list = Runtime.PySys_GetObject("path");
+ int count = Runtime.PyList_Size(list);
+ if (count != last) {
+ last = count;
+ probed.Clear();
+ }
+
string[] names = name.Split('.');
bool loaded = false;
string s = "";
for (int i = 0; i < names.Length; i++) {
s = (i == 0) ? names[0] : s + "." + names[i];
if (probed[s] == null) {
- if (LoadAssembly(s) != null) {
+ if (LoadAssemblyPath(s) != null){
+ loaded = true;
+ }
+ else if (LoadAssembly(s) != null) {
loaded = true;
}
probed[s] = 1;
=== PythonNet/src/runtime/ClassObject.cs 1.9 => 1.10 ===
--- PythonNet/src/runtime/ClassObject.cs:1.9 Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/ClassObject.cs Thu Nov 6 23:05:05 2003
@@ -92,10 +92,8 @@
}
Object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw);
-
if (obj == null) {
- Runtime.Incref(Runtime.PyNone);
- return Runtime.PyNone;
+ return IntPtr.Zero;
}
return CLRObject.GetInstHandle(obj, tp);
=== PythonNet/src/runtime/ConstructorBinder.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/ConstructorBinder.cs:1.4 Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/ConstructorBinder.cs Thu Nov 6 23:05:05 2003
@@ -43,7 +43,7 @@
Exceptions.SetError(Exceptions.TypeError,
"no constructor matches given arguments"
);
- return IntPtr.Zero;
+ return null;
}
// Object construction is presumed to be non-blocking and fast
@@ -58,7 +58,7 @@
e = e.InnerException;
}
Exceptions.SetError(e);
- return IntPtr.Zero;
+ return null;
}
return result;
=== PythonNet/src/runtime/Exceptions.cs 1.6 => 1.7 ===
--- PythonNet/src/runtime/Exceptions.cs:1.6 Wed Oct 22 22:53:10 2003
+++ PythonNet/src/runtime/Exceptions.cs Thu Nov 6 23:05:05 2003
@@ -22,26 +22,38 @@
private Exceptions() {}
- // This is called when the Python runtime is intitialized. It
- // uses reflection to populate static fields that expose handles
- // to the standard Python exception types.
+ //===================================================================
+ // Initialization performed on startup of the Python runtime.
+ //===================================================================
internal static void Initialize() {
IntPtr module = Runtime.PyImport_ImportModule("exceptions");
Type type = typeof(Exceptions);
-
foreach (FieldInfo fi in type.GetFields(BindingFlags.Public |
BindingFlags.Static)) {
IntPtr op = Runtime.PyObject_GetAttrString(module, fi.Name);
if (op != IntPtr.Zero) {
-
- // Note we own a reference to each exception class.
fi.SetValue(type, op);
}
}
Runtime.Decref(module);
Runtime.PyErr_Clear();
}
+
+
+ //===================================================================
+ // Cleanup resources upon shutdown of the Python runtime.
+ //===================================================================
+
+ internal static void Finalize() {
+ Type type = typeof(Exceptions);
+ foreach (FieldInfo fi in type.GetFields(BindingFlags.Public |
+ BindingFlags.Static)) {
+ IntPtr op = (IntPtr)fi.GetValue(type);
+ Runtime.Decref(op);
+ }
+ }
+
/// <summary>
/// GetException Method
=== PythonNet/src/runtime/ImportHook.cs 1.6 => 1.7 ===
--- PythonNet/src/runtime/ImportHook.cs:1.6 Wed Oct 22 22:53:10 2003
+++ PythonNet/src/runtime/ImportHook.cs Thu Nov 6 23:05:05 2003
@@ -24,7 +24,11 @@
static ModuleObject root;
static StaticMethodWrapper hook;
- public static void Initialize() {
+ //===================================================================
+ // Initialization performed on startup of the Python runtime.
+ //===================================================================
+
+ internal static void Initialize() {
// Initialize the Python <--> CLR module hook. We replace the
// built-in Python __import__ with our own. This isn't ideal,
@@ -48,6 +52,20 @@
}
+ //===================================================================
+ // Cleanup resources upon shutdown of the Python runtime.
+ //===================================================================
+
+ internal static void Finalize() {
+ Runtime.Decref(root.pyHandle);
+ Runtime.Decref(py_import);
+ }
+
+
+ //===================================================================
+ // The actual import hook that ties Python to the managed world.
+ //===================================================================
+
[CallConvCdecl()]
public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) {
@@ -114,7 +132,7 @@
// to make sure that each of the steps in the qualified name
// is recognized as a valid namespace. Otherwise the import
// process can encounter unknown namespaces before it gets to
- // load the assembly that would them valid.
+ // load the assembly that would make them valid.
if (mod_name.StartsWith("CLR.")) {
string real_name = mod_name.Substring(4);
=== PythonNet/src/runtime/PropertyObject.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/PropertyObject.cs:1.4 Wed Nov 5 22:35:10 2003
+++ PythonNet/src/runtime/PropertyObject.cs Thu Nov 6 23:05:05 2003
@@ -33,6 +33,7 @@
info = md;
}
+
//====================================================================
// Descriptor __get__ implementation. This method returns the
// value of the property on the given object. The returned value
@@ -98,6 +99,7 @@
return IntPtr.Zero;
}
}
+
//====================================================================
// Descriptor __set__ implementation. This method sets the value of
=== PythonNet/src/runtime/Python.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/Python.cs:1.4 Mon Oct 27 21:07:00 2003
+++ PythonNet/src/runtime/Python.cs Thu Nov 6 23:05:05 2003
@@ -70,7 +70,7 @@
public static void Finalize() {
if (initialized) {
- Runtime.Py_Finalize();
+ Runtime.Finalize();
initialized = false;
}
}
=== PythonNet/src/runtime/Runtime.cs 1.12 => 1.13 ===
--- PythonNet/src/runtime/Runtime.cs:1.12 Mon Oct 27 23:00:45 2003
+++ PythonNet/src/runtime/Runtime.cs Thu Nov 6 23:05:05 2003
@@ -98,6 +98,8 @@
Error = new IntPtr(-1);
+ AssemblyManager.Initialize();
+
PyCLRMetaType = MetaType.Initialize();
Exceptions.Initialize();
@@ -105,6 +107,13 @@
ImportHook.Initialize();
+ }
+
+ internal static void Finalize() {
+ AssemblyManager.Finalize();
+ Exceptions.Finalize();
+ ImportHook.Finalize();
+ Py_Finalize();
}
internal static IntPtr PyBaseObjectType;
More information about the Zope-CVS
mailing list