Skip to content

Commit

Permalink
Add __repr__ support for pyjobject. If method defined on java class, …
Browse files Browse the repository at this point in the history
…it will be picked up for tp_repr of the python wrapper
  • Loading branch information
jsnps authored and bsteffensmeier committed Sep 3, 2021
1 parent 32a11b7 commit 6589210
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
41 changes: 40 additions & 1 deletion src/main/c/Objects/pyjobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,45 @@ static PyObject* pyjobject_str(PyJObject *self)
return pyres;
}

// call __repr__() on jobject. returns null on error.
// expected to return new reference.
static PyObject* pyjobject_repr(PyJObject *self)
{
PyObject *pyres = NULL;
JNIEnv *env;
jmethodID __repr__ = 0;
jstring jrepr = NULL;

//check if __repr__ method exists on java object
if (self->object && self->clazz) {
env = pyembed_get_env();

Py_BEGIN_ALLOW_THREADS
if (JNI_METHOD(__repr__, env, self->clazz, "__repr__", "()Ljava/lang/String;")) {
jrepr = (jstring) (*env)->CallObjectMethod(env, self->object, __repr__);
} else {
//method does not exist, clear exception
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionClear(env);
}
}
Py_END_ALLOW_THREADS
if (process_java_exception(env)) {
return NULL;
}
if (jrepr != NULL) {
pyres = jstring_As_PyString(env, jrepr);
}
(*env)->DeleteLocalRef(env, jrepr);
}

if (pyres == NULL) {
//default (see: PyObject_Repr)
pyres = PyUnicode_FromFormat("<%s object at %p>", Py_TYPE(self)->tp_name, self);
}
return pyres;
}


static PyObject* pyjobject_richcompare(PyJObject *self,
PyObject *_other,
Expand Down Expand Up @@ -531,7 +570,7 @@ PyTypeObject PyJObject_Type = {
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
(reprfunc) pyjobject_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/jep/test/TestPyJObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package jep.test;

/**
* Supporting test_object.py
*/
public class TestPyJObject {

public static class ReprClass {
public String __repr__() {
return getClass().getSimpleName();
}
}

public static class ReprSubClass extends ReprClass {
}

}
7 changes: 7 additions & 0 deletions src/test/python/test_object.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import unittest
from java.lang import Object
import jep

TestPyJObject = jep.findClass('jep.test.TestPyJObject')

class TestObject(unittest.TestCase):

Expand All @@ -12,6 +14,11 @@ def test_str(self):
o = Object()
self.assertIn('java.lang.Object@', str(o))

def test_repr(self):
self.assertEquals(repr(TestPyJObject.ReprClass()), "ReprClass")
self.assertEquals(repr(TestPyJObject.ReprSubClass()), "ReprSubClass")
self.assertIn("<jep.PyJObject object at", repr(Object()))

def test_del_throws_exception(self):
o = Object()
with self.assertRaises(TypeError):
Expand Down

0 comments on commit 6589210

Please sign in to comment.