Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to add cause info #1057

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions jpype/_jexception.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ class JException(_jpype._JException, internal=True):
``java.lang.Throwable``.

"""
def __new__(cls, *args):
self = _jpype._JException.__new__(cls, *args)
# Exceptions generated from Java require a different path.
if len(args) == 2 and type(args[1]) == tuple:
return self
# Connect the Java cause to the __cause__ field.
self.__cause__ = _jpype._java_lang_Throwable.getCause(self)
return self

# Included for compatibility with JPype 0.6.3
def message(self):
Expand Down
9 changes: 6 additions & 3 deletions native/common/jp_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,10 @@ JPPyObject JPClass::convertToPythonObject(JPJavaFrame& frame, jvalue value, bool
JPPyString::fromStringUTF8(frame.toString(value.l)).get()));
}
}
JPValue jv(cls, value);
JPPyObject cap = JPPyObject::claim(PyCapsule_New(&jv, JValueKey, NULL));
JPPyObject tuple1 = JPPyObject::call(PyTuple_Pack(2,
_JObjectKey, tuple0.get()));
cap.get(), tuple0.get()));
// Exceptions need new and init
obj = JPPyObject::call(PyObject_Call(wrapper.get(), tuple1.get(), NULL));
} else
Expand All @@ -393,10 +395,11 @@ JPPyObject JPClass::convertToPythonObject(JPJavaFrame& frame, jvalue value, bool
PyObject *obj2 = type->tp_alloc(type, 0);
JP_PY_CHECK();
obj = JPPyObject::claim(obj2);

// Fill in the Java slot
PyJPValue_assignJavaSlot(frame, obj.get(), JPValue(cls, value));
}

// Fill in the Java slot
PyJPValue_assignJavaSlot(frame, obj.get(), JPValue(cls, value));
return obj;
JP_TRACE_OUT;
}
Expand Down
2 changes: 1 addition & 1 deletion native/python/include/pyjp.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ extern PyObject *_JClassDoc;
extern PyObject *_JMethodDoc;
extern PyObject *_JMethodAnnotations;
extern PyObject *_JMethodCode;
extern PyObject *_JObjectKey;
extern PyObject *_JVMNotRunning;
extern PyObject* PyJPClassMagic;
extern char* JValueKey;

extern JPContext* JPContext_global;

Expand Down
3 changes: 1 addition & 2 deletions native/python/pyjp_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ PyObject* _JMethodAnnotations = NULL;
PyObject* _JMethodCode = NULL;
PyObject* _JObjectKey = NULL;
PyObject* _JVMNotRunning = NULL;
char* JValueKey = "jvalue";

void PyJPModule_loadResources(PyObject* module)
{
Expand Down Expand Up @@ -121,8 +122,6 @@ void PyJPModule_loadResources(PyObject* module)
JP_PY_CHECK();
Py_INCREF(_JMethodCode);

_JObjectKey = PyCapsule_New(module, "constructor key", NULL);

} catch (JPypeException&) // GCOVR_EXCL_LINE
{
// GCOVR_EXCL_START
Expand Down
27 changes: 21 additions & 6 deletions native/python/pyjp_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ extern "C"
{
#endif

/** Construct a new PyJPObject.
*
* This method is only called when Python is requesting a new object be constructed.
* If the object already exists, then the JPClass::convertToPythonObject
* skips the new and init method and directly populates the fields.
*
* The only exception is Throwables which must be allocated using the
* standard Python new/init paths.
*/
static PyObject *PyJPObject_new(PyTypeObject *type, PyObject *pyargs, PyObject *kwargs)
{
JP_PY_TRY("PyJPObject_new");
Expand Down Expand Up @@ -247,14 +256,20 @@ static PyObject *PyJPException_new(PyTypeObject *type, PyObject *pyargs, PyObjec
return NULL;
} // GCOVR_EXCL_STOP

// Special constructor path for Exceptions
JPPyObjectVector args(pyargs);
if (args.size() == 2 && args[0] == _JObjectKey)
return ((PyTypeObject*) PyExc_BaseException)->tp_new(type, args[1], kwargs);

// Create an instance (this may fail)
JPContext *context = PyJPModule_getContext();
JPJavaFrame frame = JPJavaFrame::outer(context);

// Special constructor path for Exceptions
JPPyObjectVector args(pyargs);
if (args.size() == 2 && PyCapsule_CheckExact(args[0]))
{
PyObject* self = ((PyTypeObject*) PyExc_BaseException)->tp_new(type, args[1], kwargs);
JPValue* jv = (JPValue*) PyCapsule_GetPointer(args[0], JValueKey);
PyJPValue_assignJavaSlot(frame, self, *jv);
return self;
}

JPValue jv = cls->newInstance(frame, args);

// Exception must be constructed with the BaseException_new
Expand All @@ -271,7 +286,7 @@ static int PyJPException_init(PyObject *self, PyObject *pyargs, PyObject *kwargs
{
JP_PY_TRY("PyJPException_init");
JPPyObjectVector args(pyargs);
if (args.size() == 2 && args[0] == _JObjectKey)
if (args.size() == 2 && PyCapsule_CheckExact(args[0]))
return ((PyTypeObject*) PyExc_BaseException)->tp_init(self, args[1], kwargs);

// Exception must be constructed with the BaseException_new
Expand Down