Permalink
Browse files

Merge branch 'develop'

  • Loading branch information...
2 parents 87bf00e + 53d5085 commit d3d3e48e61e66f01867a212ad32c0c86e3e28976 Mike Johnson committed Jun 6, 2012
Showing with 178 additions and 102 deletions.
  1. +2 −0 .gitignore
  2. +7 −10 ChangeLog
  3. +21 −37 README.rst
  4. +1 −1 commands/test.py
  5. +36 −8 jep/hook.py
  6. +1 −1 jep/version.py
  7. +14 −13 src/jep/pyembed.c
  8. +20 −25 src/jep/pyjarray.c
  9. +9 −6 src/jep/util.c
  10. +2 −1 tests/__init__.py
  11. BIN tests/lib/sqlitejdbc-v056.jar
  12. +13 −0 tests/test_import.py
  13. +52 −0 tests/test_jdbc.py
View
@@ -23,3 +23,5 @@ build
dist
*.pyc
MANIFEST
+.DS_Store
+.idea
View
@@ -1,14 +1,11 @@
-2012-04-09 Mike Johnson <mike@mrj0.com>
- * setup.py: distutils build, pypi integration
- * tests: unittesting implemented in python
- * jep: added `jep` command line script for launching console.py
- * exception mapping (dynamic creation of python exceptions) no longer supported
- * pyjobject.c: implement richcompare using Java .equals
- * pyjobject.c: missing attribute raises AttributeError
- * pyjobject.c: don't change optimization flag by default
- * pyjarray.c: fix for iterator, so list() works on jarrays
+2012-05-05 3.1.0 - Mike Johnson <mike@mrj0.com>
+ * lazy load classes imported via import hook
-2007-03-19 Mike Johnson <mike@mrj0.com>
+2012-03-06 3.0.0 - Mike Johnson <mike@mrj0.com>
+ * project uses distutils now, is pip installable
+ * added a proper import hook
+
+2007-03-19 Mike Johnson <mrjohnson0@users.sourceforge.net>
* pyembed.c: patch from Jon Wright to convert packed strings to float array in java.
* pyembed.c: return jarray object in invoke and getValue
* pyembed.c: throw exception if invocation object not found
View
@@ -27,16 +27,16 @@ response.
Jep is licensed zlib/libpng license to avoid linking issues.
-Dependencies
-------------
-* Python version >= 2.6
-* JNI >= 1.4
-
Installation
------------
Simply run ``pip install jep``.
+Dependencies
+------------
+* Python version >= 2.6
+* JNI >= 1.4
+
*Building on Mac OS X*
OS X requires the `Java Developer Package and Xcode
@@ -53,33 +53,30 @@ on Windows has not worked in recent years because the compilers are
not widely available. If an OpenJDK build used MinGW, that'd be
much more likely to work.
+Running scripts
+---------------
+
+The ``setup.py`` script will provide a ``jep`` shortcut to make launching Java and Python easier.
+
+::
+
+ $ jep
+ >>> from java.lang import System
+ >>> System.out.println('hello, world')
+ hello, world
+ >>>
+
Running on \*nix
-----------------
Due to some (common) difficulties with Java and C projects
that dlopen libraries, you may need to set LD_PRELOAD environment
variable. That's in addition to setting LD_LIBRARY_PATH if you've
installed libjep into a directory not cached by ld.so.
-For example, my Tomcat startup.sh script starts with this:
-
-::
-
- #!/bin/sh
- # force system to load python
- export LD_PRELOAD=/usr/lib/libpython2.7.so
-
- # this is where my libjep.so is.
- export LD_LIBRARY_PATH=/usr/local/lib
-
-The libpython used here is whatever you've compiled jep against. If
-you don't know, try this command:
+See the contents of the installed ``jep`` script for an example how to do this.
+The script should have the correct values for your interpreter and virtualenv
+(if present).
-::
-
- $ ldd /usr/local/lib/libjep.so | grep python
- /usr/lib/libpython2.7.so (0x00007f74adfbd000)
-
-That's the libpython you want to set in LD_PRELOAD.
Running the tests
-----------------
@@ -90,19 +87,6 @@ The tests are run from setup.py:
$ python setup.py test
-Running scripts
----------------
-
-There is a ``jep`` shell script to make launching Java and Python a little easier.
-
-::
-
- $ jep
- >>> from java.lang import System
- >>> System.out.println('hello, world')
- hello, world
- >>>
-
Support
-------
View
@@ -18,4 +18,4 @@ def finalize_options(self):
pass
def run(self):
- spawn(['java', '-cp', 'build/java/', 'jep.Test'])
+ spawn(['java', '-cp', 'build/java/:tests/lib/sqlitejdbc-v056.jar', 'jep.Test'])
View
@@ -1,6 +1,31 @@
-from _jep import *
+from _jep import findClass
import sys
-import imp
+from types import ModuleType
+
+
+class module(ModuleType):
+ """Lazy load classes not found at runtime.
+
+ Introspecting Java packages is difficult, there is not a good
+ way to get a list of all classes for a package. By providing
+ a __getattr__ implementation for modules, this class can
+ try to find classes manually.
+
+ Due to this Java limitation, some classes will not appear in dir()
+ but will import correctly.
+ """
+
+ def __getattr__(self, name):
+ try:
+ return super(module, self).__getattribute__(name)
+ except AttributeError as ae:
+ try:
+ clazz = findClass('{0}.{1}'.format(self.__name__, name))
+ setattr(self, name, clazz)
+ return clazz
+ except Exception:
+ # should raise AttributeError, not JepException
+ raise ae
class JepImporter(object):
@@ -14,19 +39,22 @@ def find_module(self, fullname, path=None):
def load_module(self, fullname):
if fullname in sys.modules:
- return fullname
-
- mod = imp.new_module(fullname)
- mod.__loader__ = self
+ return sys.modules[fullname]
+
+ mod = module(fullname)
+ mod.__dict__.update({
+ '__loader__': self,
+ '__path__': [],
+ '__file__': '<java>',
+ })
sys.modules[fullname] = mod
- mod.__path__ = []
- mod.__file__ = '<java>'
# list of classes in package
for name in self.classlist.get(fullname):
setattr(mod, name.split('.')[-1], findClass(name))
return mod
+
sys.meta_path = [importer for importer in sys.meta_path if isinstance(importer, JepImporter)]
sys.meta_path.append(JepImporter())
View
@@ -1,2 +1,2 @@
-__VERSION__ = '3.0.0'
+__VERSION__ = '3.0.1'
VERSION = __VERSION__
View
@@ -222,7 +222,7 @@ void pyembed_shutdown(void) {
intptr_t pyembed_thread_init(JNIEnv *env, jobject cl, jobject caller) {
JepThread *jepThread;
- PyObject *tdict, *main_module, *globals;
+ PyObject *tdict, *mod_main, *globals;
if(cl == NULL) {
THROW_JEP(env, "Invalid Classloader.");
@@ -247,14 +247,14 @@ intptr_t pyembed_thread_init(JNIEnv *env, jobject cl, jobject caller) {
if(!cache_primitive_classes(env))
printf("WARNING: failed to get primitive class types.\n");
- main_module = PyImport_AddModule("__main__"); /* borrowed */
- if(main_module == NULL) {
+ mod_main = PyImport_AddModule("__main__"); /* borrowed */
+ if(mod_main == NULL) {
THROW_JEP(env, "Couldn't add module __main__.");
PyEval_ReleaseLock();
return 0;
}
- globals = PyModule_GetDict(main_module);
+ globals = PyModule_GetDict(mod_main);
Py_INCREF(globals);
// init static module
@@ -394,7 +394,7 @@ static PyObject* pyembed_jproxy(PyObject *self, PyObject *args) {
jclass clazz;
jobject cl;
jobject classes;
- int inum, i;
+ Py_ssize_t inum, i;
jobject proxy;
if(!PyArg_ParseTuple(args, "OO!:jproxy",
@@ -437,7 +437,7 @@ static PyObject* pyembed_jproxy(PyObject *self, PyObject *args) {
// now convert string list to java array
- classes = (*env)->NewObjectArray(env, inum, JSTRING_TYPE, NULL);
+ classes = (*env)->NewObjectArray(env, (jsize) inum, JSTRING_TYPE, NULL);
if(process_java_exception(env) || !classes)
return NULL;
@@ -448,12 +448,12 @@ static PyObject* pyembed_jproxy(PyObject *self, PyObject *args) {
item = PyList_GET_ITEM(interfaces, i);
if(!PyString_Check(item))
- return PyErr_Format(PyExc_ValueError, "Item %i not a string.", i);
+ return PyErr_Format(PyExc_ValueError, "Item %zd not a string.", i);
str = PyString_AsString(item);
jstr = (*env)->NewStringUTF(env, (const char *) str);
- (*env)->SetObjectArrayElement(env, classes, i, jstr);
+ (*env)->SetObjectArrayElement(env, classes, (jsize) i, jstr);
(*env)->DeleteLocalRef(env, jstr);
}
@@ -507,7 +507,7 @@ static PyObject* pyembed_jimport(PyObject *self, PyObject *args) {
jclass clazz;
jobject cl;
JepThread *jepThread;
- int len, i;
+ Py_ssize_t len, i;
jobjectArray jar;
char *name;
@@ -623,7 +623,7 @@ static PyObject* pyembed_jimport(PyObject *self, PyObject *args) {
PyObject *pclass = NULL;
PyObject *memberList = NULL;
- member = (*env)->GetObjectArrayElement(env, jar, i);
+ member = (*env)->GetObjectArrayElement(env, jar, (jsize) i);
if(process_import_exception(env) || !member) {
(*env)->DeleteLocalRef(env, member);
continue;
@@ -653,7 +653,8 @@ static PyObject* pyembed_jimport(PyObject *self, PyObject *args) {
PyString_AsString(PyTuple_GET_ITEM(fromlist, 0))[0] != '*') {
PyObject *pymember;
- int found, i, len;
+ int found;
+ Py_ssize_t i, len;
pymember = PyList_GET_ITEM(
memberList,
@@ -1177,7 +1178,7 @@ jobject pyembed_box_py(JNIEnv *env, PyObject *result) {
if(PyInt_Check(result)) {
jclass clazz;
- jlong i = PyInt_AS_LONG(result);
+ jint i = (jint) PyInt_AS_LONG(result);
clazz = (*env)->FindClass(env, "java/lang/Integer");
@@ -1547,7 +1548,7 @@ static int maybe_pyc_file(FILE *fp,
/* Read only two bytes of the magic. If the file was opened in
text mode, the bytes 3 and 4 of the magic (\r\n) might not
be read as they are on disk. */
- long halfmagic = PyImport_GetMagicNumber() & 0xFFFF;
+ unsigned int halfmagic = (unsigned int) PyImport_GetMagicNumber() & 0xFFFF;
unsigned char buf[2];
/* Mess: In case of -x, the stream is NOT at its start now,
and ungetc() was used to push back the first newline,
Oops, something went wrong.

0 comments on commit d3d3e48

Please sign in to comment.