diff --git a/jnius/signatures.py b/jnius/signatures.py new file mode 100644 index 0000000..4b69387 --- /dev/null +++ b/jnius/signatures.py @@ -0,0 +1,72 @@ +''' +signatures.py +============= + +A handy API for writing JNI signatures easily + +Author: chrisjrn + +''' + +__version__ = '0.0.1' + +from . import JavaClass +from . import java_method + + +''' Type specifiers for primitives ''' + +class _SignaturePrimitive(object): + _spec = "" + +def _MakeSignaturePrimitive(name, spec): + class __Primitive(_SignaturePrimitive): + ''' PyJnius signature for Java %s type ''' % name + _name = name + _spec = spec + __name__ = "j" + name + return __Primitive + +jboolean = _MakeSignaturePrimitive("boolean", "Z") +jbyte = _MakeSignaturePrimitive("byte", "B") +jchar = _MakeSignaturePrimitive("char", "C") +jdouble = _MakeSignaturePrimitive("double", "D") +jfloat = _MakeSignaturePrimitive("float", "F") +jint = _MakeSignaturePrimitive("int", "I") +jlong = _MakeSignaturePrimitive("long", "J") +jshort = _MakeSignaturePrimitive("short", "S") +jvoid = _MakeSignaturePrimitive("void", "V") + +def JArray(of_type): + ''' Marks that this is an array of the given Primitive of JavaClass + type specified. ''' + + spec = "[" + _jni_type_spec(of_type) + return _MakeSignaturePrimitive("array", spec) + +def java_signature(returns, takes): + ''' Alternative version of @java_method that takes JavaClass + objects to produce the method signature. ''' + + sig = _produce_sig(returns, takes) + return java_method(sig) + +def _produce_sig(returns, takes): + ''' Produces a JNI method signature. ''' + out_takes = [] + for arg in takes: + out_takes.append(_jni_type_spec(arg)) + + return "(" + "".join(out_takes) + ")" + _jni_type_spec(returns) + +def _jni_type_spec(jclass): + ''' Produces a JNI type specification string for the given argument. + If the argument is a jnius.JavaClass, it produces the JNI type spec + for the class. Signature primitives return their stored type spec. + ''' + + if issubclass(jclass, JavaClass): + return "L" + jclass.__javaclass__ + ";" + elif issubclass(jclass, _SignaturePrimitive): + return jclass._spec + \ No newline at end of file diff --git a/tests/test_signature.py b/tests/test_signature.py new file mode 100644 index 0000000..a0166e0 --- /dev/null +++ b/tests/test_signature.py @@ -0,0 +1,117 @@ +import unittest + +from jnius import autoclass, java_method, PythonJavaClass, cast + +from jnius.signatures import * + +JObject = autoclass('java/lang/Object') +JString = autoclass('java/lang/String') + +class TestImplemIterator(PythonJavaClass): + __javainterfaces__ = [ + 'java/util/ListIterator', ] + + def __init__(self, collection, index=0): + super(TestImplemIterator, self).__init__() + self.collection = collection + self.index = index + + @java_signature(jboolean, ()) + def hasNext(self): + return self.index < len(self.collection.data) - 1 + + @java_signature(JObject, ()) + def next(self): + obj = self.collection.data[self.index] + self.index += 1 + return obj + + @java_signature(jboolean, ()) + def hasPrevious(self): + return self.index >= 0 + + @java_signature(JObject, ()) + def previous(self): + self.index -= 1 + obj = self.collection.data[self.index] + return obj + + @java_signature(jint, ()) + def previousIndex(self): + return self.index - 1 + + @java_signature(JString, ()) + def toString(self): + return repr(self) + + @java_signature(JObject, (jint, )) + def get(self, index): + return self.collection.data[index - 1] + + @java_signature(jvoid, (JObject, )) + def set(self, obj): + self.collection.data[self.index - 1] = obj + + +class TestImplem(PythonJavaClass): + __javainterfaces__ = ['java/util/List'] + + def __init__(self, *args): + super(TestImplem, self).__init__(*args) + self.data = list(args) + + @java_signature(autoclass("java.util.Iterator"), ()) + def iterator(self): + it = TestImplemIterator(self) + return it + + @java_signature(JString, ()) + def toString(self): + return repr(self) + + @java_signature(jint, ()) + def size(self): + return len(self.data) + + @java_signature(JObject, (jint,)) + def get(self, index): + return self.data[index] + + @java_signature(JObject, (jint, JObject)) + def set(self, index, obj): + old_object = self.data[index] + self.data[index] = obj + return old_object + + @java_signature(JArray(JObject), ()) + def toArray(self): + return self.data + + @java_signature(autoclass("java.util.ListIterator"), ()) + def listIterator(self): + it = TestImplemIterator(self) + return it + + # TODO cover this case of listIterator. + @java_method('(I)Ljava/util/ListIterator;', + name='ListIterator') + def listIteratorI(self, index): + it = TestImplemIterator(self, index) + return it + + +from jnius.reflect import autoclass + +class SignaturesTest(unittest.TestCase): + + def test_construct_stack_from_testimplem(self): + Stack = autoclass("java.util.Stack") + pyjlist = TestImplem(1, 2, 3, 4, 5, 6, 7) + stack = Stack() + stack.addAll(pyjlist) + self.assertEquals(7, pyjlist.size()) + self.assertEquals(stack.size(), pyjlist.size()) + array = pyjlist.toArray + + +