Skip to content

Commit

Permalink
PyException cleanup (#2597)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepone authored Aug 2, 2024
1 parent 82e5cd9 commit c7a05c0
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 193 deletions.
2 changes: 1 addition & 1 deletion python/modules/IcePy/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ loggerNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/)
{
return nullptr;
}
self->logger = 0;
self->logger = nullptr;
return self;
}

Expand Down
4 changes: 2 additions & 2 deletions python/modules/IcePy/Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ Operation::marshalResult(Ice::OutputStream& os, PyObject* result)
{
try
{
PyException().raise();
throwPythonException();
}
catch (const Ice::UnknownException& ex)
{
Expand All @@ -879,7 +879,7 @@ Operation::marshalResult(Ice::OutputStream& os, PyObject* result)
{
try
{
PyException().raise();
throwPythonException();
}
catch (const Ice::UnknownException& ex)
{
Expand Down
265 changes: 84 additions & 181 deletions python/modules/IcePy/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,226 +269,132 @@ IcePy::PyObjectHandle::release()
return result;
}

IcePy::PyException::PyException()
{
ex = PyErr_GetRaisedException();
if (ex)
{
PyObject* type = reinterpret_cast<PyObject*>(Py_TYPE(ex.get()));
Py_INCREF(type);
_type = type;
_tb = PyException_GetTraceback(ex.get());
}
}
IcePy::PyException::PyException() { ex = PyErr_GetRaisedException(); }

IcePy::PyException::PyException(PyObject* raisedException)
{
Py_XINCREF(raisedException);
ex = raisedException;
PyObject* type = reinterpret_cast<PyObject*>(Py_TYPE(raisedException));
Py_INCREF(type);
_type = type;
_tb = PyException_GetTraceback(raisedException);
}

void
IcePy::PyException::raise()
namespace
{
assert(ex.get());

PyObject* userExceptionType = lookupType("Ice.UserException");
PyObject* localExceptionType = lookupType("Ice.LocalException");

// TODO: create better error messages.

if (PyObject_IsInstance(ex.get(), userExceptionType))
string getTypeName(PyObject* ex)
{
string tb = getTraceback();
if (!tb.empty())
{
throw Ice::UnknownUserException{__FILE__, __LINE__, tb};
}
else
{
PyObjectHandle name = PyObject_CallMethod(ex.get(), "ice_id", 0);
PyErr_Clear();
if (!name.get())
{
throw Ice::UnknownUserException{__FILE__, __LINE__, getTypeName()};
}
else
{
throw Ice::UnknownUserException{__FILE__, __LINE__, getString(name.get())};
}
}
PyObject* cls = reinterpret_cast<PyObject*>(ex->ob_type);
IcePy::PyObjectHandle name = IcePy::getAttr(cls, "__name__", false);
assert(name.get());
IcePy::PyObjectHandle mod = IcePy::getAttr(cls, "__module__", false);
assert(mod.get());
string result = IcePy::getString(mod.get());
result += ".";
result += IcePy::getString(name.get());
return result;
}
else if (PyObject_IsInstance(ex.get(), localExceptionType))
string createUnknownExceptionMessage(PyObject* ex)
{
raiseLocalException();
}
else
{
string tb = getTraceback();
if (!tb.empty())
{
throw Ice::UnknownException{__FILE__, __LINE__, tb};
}
else
ostringstream ostr;
ostr << getTypeName(ex);
IcePy::PyObjectHandle exStr = PyObject_Str(ex);
if (exStr.get() && IcePy::checkString(exStr.get()))
{
ostringstream ostr;

ostr << getTypeName();

IcePy::PyObjectHandle msg = PyObject_Str(ex.get());
if (msg.get())
string message = IcePy::getString(exStr.get());
if (!message.empty())
{
string s = getString(msg.get());
if (!s.empty())
{
ostr << ": " << s;
}
ostr << ": " << message;
}

throw Ice::UnknownException{__FILE__, __LINE__, ostr.str()};
}
return ostr.str();
}
}

void
IcePy::PyException::checkSystemExit()
IcePy::PyException::raise()
{
if (PyObject_IsInstance(ex.get(), PyExc_SystemExit))
assert(ex.get());
PyObject* localExceptionType = lookupType("Ice.LocalException");
if (PyObject_IsInstance(ex.get(), localExceptionType))
{
handleSystemExit(ex.get()); // Does not return.
}
}
string typeName = getTypeName(ex.get());

void
IcePy::PyException::raiseLocalException()
{
string typeName = getTypeName();
PyObject* requestFailedExceptionType = lookupType("Ice.RequestFailedException");

PyObject* requestFailedExceptionType = lookupType("Ice.RequestFailedException");
if (PyObject_IsInstance(ex.get(), requestFailedExceptionType))
{
PyObjectHandle idAttr = getAttr(ex.get(), "id", false);
Ice::Identity id;
if (idAttr.get())
{
IcePy::getIdentity(idAttr.get(), id);
}
PyObjectHandle facetAttr = getAttr(ex.get(), "facet", false);
string facet = getString(facetAttr.get());
PyObjectHandle operationAttr = getAttr(ex.get(), "operation", false);
string operation = getString(operationAttr.get());

if (PyObject_IsInstance(ex.get(), requestFailedExceptionType))
{
PyObjectHandle idAttr = getAttr(ex.get(), "id", false);
Ice::Identity id;
if (idAttr.get())
if (typeName == "Ice.ObjectNotExistException")
{
throw Ice::ObjectNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
}
else if (typeName == "Ice.OperationNotExistException")
{
throw Ice::OperationNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
}
else if (typeName == "Ice.FacetNotExistException")
{
throw Ice::FacetNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
}
}

IcePy::PyObjectHandle exStr = PyObject_Str(ex.get());
string message;
if (exStr.get() && checkString(exStr.get()))
{
IcePy::getIdentity(idAttr.get(), id);
message = getString(exStr.get());
}
PyObjectHandle facetAttr = getAttr(ex.get(), "facet", false);
string facet = getString(facetAttr.get());
PyObjectHandle operationAttr = getAttr(ex.get(), "operation", false);
string operation = getString(operationAttr.get());

if (typeName == "Ice.ObjectNotExistException")
if (typeName == "Ice.UnknownLocalException")
{
throw Ice::ObjectNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
throw Ice::UnknownLocalException{__FILE__, __LINE__, std::move(message)};
}
else if (typeName == "Ice.OperationNotExistException")
else if (typeName == "Ice.UnknownUserException")
{
throw Ice::OperationNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
throw Ice::UnknownUserException{__FILE__, __LINE__, std::move(message)};
}
else if (typeName == "Ice.FacetNotExistException")
else if (typeName == "Ice.UnknownException")
{
throw Ice::FacetNotExistException(
__FILE__,
__LINE__,
std::move(id),
std::move(facet),
std::move(operation));
throw Ice::UnknownException{__FILE__, __LINE__, std::move(message)};
}
}

IcePy::PyObjectHandle exStr = PyObject_Str(ex.get());
string message;
if (exStr.get() && checkString(exStr.get()))
{
message = getString(exStr.get());
}

if (typeName == "Ice.UnknownLocalException")
{
throw Ice::UnknownLocalException{__FILE__, __LINE__, std::move(message)};
}
else if (typeName == "Ice.UnknownUserException")
{
throw Ice::UnknownUserException{__FILE__, __LINE__, std::move(message)};
}
else if (typeName == "Ice.UnknownException")
{
throw Ice::UnknownException{__FILE__, __LINE__, std::move(message)};
}

string tb = getTraceback();
if (!tb.empty())
{
throw Ice::UnknownLocalException{__FILE__, __LINE__, tb};
throw Ice::UnknownLocalException{__FILE__, __LINE__, createUnknownExceptionMessage(ex.get())};
}
else
{
throw Ice::UnknownLocalException{__FILE__, __LINE__, typeName};
throw Ice::UnknownException{__FILE__, __LINE__, createUnknownExceptionMessage(ex.get())};
}
}

string
IcePy::PyException::getTraceback()
void
IcePy::PyException::checkSystemExit()
{
if (!_tb.get())
{
return string();
}

//
// We need the equivalent of the following Python code:
//
// import traceback
// list = traceback.format_exception(type, ex, tb)
//
PyObjectHandle str = createString("traceback");
PyObjectHandle mod = PyImport_Import(str.get());
assert(mod.get()); // Unable to import traceback module - Python installation error?
PyObject* func = PyDict_GetItemString(PyModule_GetDict(mod.get()), "format_exception");
assert(func); // traceback.format_exception must be present.
PyObjectHandle args = Py_BuildValue("(OOO)", _type.get(), ex.get(), _tb.get());
assert(args.get());
PyObjectHandle list = PyObject_CallObject(func, args.get());
assert(list.get());

string result;
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list.get()); ++i)
if (PyObject_IsInstance(ex.get(), PyExc_SystemExit))
{
string s = getString(PyList_GetItem(list.get(), i));
result += s;
handleSystemExit(ex.get()); // Does not return.
}

return result;
}

string
IcePy::PyException::getTypeName()
{
PyObject* cls = reinterpret_cast<PyObject*>(ex.get()->ob_type);
PyObjectHandle name = getAttr(cls, "__name__", false);
assert(name.get());
PyObjectHandle mod = getAttr(cls, "__module__", false);
assert(mod.get());
string result = getString(mod.get());
result += ".";
result += getString(name.get());
return result;
}

PyObject*
Expand Down Expand Up @@ -767,7 +673,6 @@ IcePy::convertException(std::exception_ptr exPtr)
IcePy::createString(ex.kindOfObject()),
IcePy::createString(ex.id()),
IcePy::createString(ex.what())};

return createPythonException(ex.ice_id(), std::move(args));
}
catch (const Ice::NotRegisteredException& ex)
Expand All @@ -776,7 +681,6 @@ IcePy::convertException(std::exception_ptr exPtr)
IcePy::createString(ex.kindOfObject()),
IcePy::createString(ex.id()),
IcePy::createString(ex.what())};

return createPythonException(ex.ice_id(), std::move(args));
}
catch (const Ice::ConnectionAbortedException& ex)
Expand All @@ -796,7 +700,6 @@ IcePy::convertException(std::exception_ptr exPtr)
IcePy::createString(ex.facet()),
IcePy::createString(ex.operation()),
IcePy::createString(ex.what())};

return createPythonException(ex.ice_id(), std::move(args));
}
// Then all other exceptions.
Expand Down
10 changes: 1 addition & 9 deletions python/modules/IcePy/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace IcePy
PyException(PyObject*);

//
// Convert the Python exception to its C++ equivalent.
// Converts the Python exception into one of the 6 special Ice local exceptions.
//
void raise();

Expand All @@ -97,14 +97,6 @@ namespace IcePy
void checkSystemExit();

PyObjectHandle ex;

private:
void raiseLocalException();
std::string getTraceback();
std::string getTypeName();

PyObjectHandle _type;
PyObjectHandle _tb;
};

//
Expand Down

0 comments on commit c7a05c0

Please sign in to comment.