From: <bc...@wo...> - 2001-12-22 20:11:31
|
[Phil Surette] >I submitted a patch to support this to jython-dev a while back. I'm sorry that I didn't reply to you back then. >After poking through the jython code, I found that this patch to >org/jython/core/imp.java in jython-2.1a3 does the trick: >imp.java >498a499,502 >> //if it's not a builtin or in the python path, try the classpath >> ret = loadFromClassLoader(name, imp.class.getClassLoader()); >> if (ret != null) return ret; It isn't general enough and it doesn't work. It can only import top-level modules. Modules in packages can't be imported. That can be fixed by enabling the snippet in PyModule that is commented out. Other issues with the patch are: - Only support for .py files. That is too slow for a general solution. - Setting __path__ to None to signal classloader is probably OK for a specialized solution, but we have to come up with something more general. - The classloader is hardcoded. Eventually a user want to put the python modules into a .jar loaded by another classloader. All in all, more though have to go into this. We also want to restructure the "imp" code a bit. At the moment a lot of logic is duplicated in loadFromZipFile and loadFromPath. The loadFromClassLoader method will eventually contain the same logic one more time. I understand the desire for this feature, I just don't think we are able to add it the Right Way in version 2.1. Instead we could maybe make the loadFromClassLoader() method public and suggest that embedding user temporarily use the hack below to load python modules from their classloader. The hack must be explicit enabled with a call like this: org.python.util.ClassLoaderImport.install() Comments? regards, finn package org.python.util; import org.python.core.*; public class ClassLoaderImport extends PyObject { PyObject importer; ClassLoaderImport(PyObject importer) { this.importer = importer; } public PyObject __call__(PyObject args[], String keywords[]) { if (!(args.length < 1 || args[0] instanceof PyString)) throw Py.TypeError("first argument must be a string"); if (keywords.length > 0) throw Py.TypeError("__import__() takes no keyword "+ "arguments"); int argc = args.length; String module = args[0].__str__().toString(); PyObject globals = (argc > 1 && args[1] != null) ? args[1] : null; PyObject fromlist = (argc > 3 && args[3] != null) ? args[3] : Py.EmptyTuple; System.out.println("module:" + module); PyObject ret = imp.loadFromClassLoader(module, imp.class.getClassLoader()); if (ret != null) return ret; return importer.__call__(args, keywords); } public static void install() { PyObject builtin = Py.getSystemState().modules. __finditem__("__builtin__"); PyObject importer = builtin.__getattr__("__import__"); builtin.__setattr__("__import__", new ClassLoaderImport(importer)); } } |