changeset 77:e7ff5efb100d

Custom exception "orthanc.OrthancException" is raised instead of "ValueError"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Aug 2021 18:16:42 +0200
parents 8da2a7bef495
children 2b9d82366e3a
files CodeAnalysis/FunctionBody.mustache NEWS Sources/Autogenerated/sdk_GlobalFunctions.impl.h Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h Sources/Plugin.cpp Sources/PythonLock.cpp
diffstat 8 files changed, 64 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/CodeAnalysis/FunctionBody.mustache	Mon Aug 09 17:00:53 2021 +0200
+++ b/CodeAnalysis/FunctionBody.mustache	Mon Aug 09 18:16:42 2021 +0200
@@ -90,7 +90,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 {{/return_bytes}}
--- a/NEWS	Mon Aug 09 17:00:53 2021 +0200
+++ b/NEWS	Mon Aug 09 18:16:42 2021 +0200
@@ -1,6 +1,8 @@
 Pending changes in the mainline
 ===============================
 
+* Custom exception "orthanc.OrthancException" is raised instead of "ValueError"
+
 
 Version 3.2 (2021-06-11)
 ========================
--- a/Sources/Autogenerated/sdk_GlobalFunctions.impl.h	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/Autogenerated/sdk_GlobalFunctions.impl.h	Mon Aug 09 18:16:42 2021 +0200
@@ -119,7 +119,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -144,7 +144,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -169,7 +169,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -195,7 +195,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -221,7 +221,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -299,7 +299,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -325,7 +325,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -705,7 +705,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -730,7 +730,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -839,7 +839,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -869,7 +869,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -896,7 +896,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -924,7 +924,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -952,7 +952,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -1508,7 +1508,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h	Mon Aug 09 18:16:42 2021 +0200
@@ -412,7 +412,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
@@ -473,7 +473,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
--- a/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h	Mon Aug 09 18:16:42 2021 +0200
@@ -154,7 +154,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h	Mon Aug 09 18:16:42 2021 +0200
@@ -124,7 +124,7 @@
   }
   else
   {
-    PythonLock::RaiseException(OrthancPluginErrorCode_InternalError);
+    PythonLock::RaiseException(code);
     return NULL;  
   }
 }
--- a/Sources/Plugin.cpp	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/Plugin.cpp	Mon Aug 09 18:16:42 2021 +0200
@@ -517,7 +517,7 @@
 #endif
 
         SetupGlobalFunctions();
-        PythonLock::GlobalInitialize("orthanc", "Exception",
+        PythonLock::GlobalInitialize("orthanc", "OrthancException",
                                      GetGlobalFunctions, InstallClasses,
                                      config.GetBooleanValue("PythonVerbose", false));
         PythonLock::AddSysPath(userScriptDirectory.string());
--- a/Sources/PythonLock.cpp	Mon Aug 09 17:00:53 2021 +0200
+++ b/Sources/PythonLock.cpp	Mon Aug 09 18:16:42 2021 +0200
@@ -40,7 +40,7 @@
 
 struct module_state 
 {
-  PyObject *exceptionClass_ = NULL;
+  PyObject *exceptionObject_ = NULL;
 };
 
 #if PY_MAJOR_VERSION >= 3
@@ -180,32 +180,27 @@
 
 
 static void RegisterException(PyObject* module,
-                              const std::string& name)
+                              const std::string& fqnName,
+                              const std::string& shortName)
 {
   struct module_state *state = GETSTATE(module);
 
-  state->exceptionClass_ = PyErr_NewException(const_cast<char*>(name.c_str()), NULL, NULL);
-  if (state->exceptionClass_ == NULL) 
+  state->exceptionObject_ = PyErr_NewException(const_cast<char*>(fqnName.c_str()), NULL, NULL);
+  if (state->exceptionObject_ == NULL) 
   {
     Py_DECREF(module);
     OrthancPlugins::LogError("Cannot create the Python exception class");
     ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
   }
 
-#if 1
-  Py_XINCREF(state->exceptionClass_);
-  if (PyModule_AddObject(module, "Exception", state->exceptionClass_) < 0)
+  Py_XINCREF(state->exceptionObject_);
+  if (PyModule_AddObject(module, shortName.c_str(), state->exceptionObject_) < 0)
   {
-    Py_XDECREF(state->exceptionClass_);
-    Py_CLEAR(state->exceptionClass_);
+    Py_XDECREF(state->exceptionObject_);
+    Py_CLEAR(state->exceptionObject_);
     OrthancPlugins::LogError("Cannot create the Python exception class");
     ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
   }
-#else
-  // Install the exception class
-  PyObject* dict = PyModule_GetDict(module);
-  PyDict_SetItemString(dict, "Exception", state->exceptionClass);
-#endif
 }
 
 
@@ -214,13 +209,13 @@
 
 static int sdk_traverse(PyObject *module, visitproc visit, void *arg) 
 {
-  Py_VISIT(GETSTATE(module)->exceptionClass_);
+  Py_VISIT(GETSTATE(module)->exceptionObject_);
   return 0;
 }
 
 static int sdk_clear(PyObject *module) 
 {
-  Py_CLEAR(GETSTATE(module)->exceptionClass_);
+  Py_CLEAR(GETSTATE(module)->exceptionObject_);
   return 0;
 }
 
@@ -258,7 +253,7 @@
     ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
   }
 
-  RegisterException(module, moduleName_ + "." + exceptionName_);
+  RegisterException(module, moduleName_ + "." + exceptionName_, exceptionName_);
   moduleClasses_(module);
 
   return module;
@@ -283,7 +278,7 @@
     ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
   }
 
-  RegisterException(module, moduleName_ + "." + exceptionName_);
+  RegisterException(module, moduleName_ + "." + exceptionName_, exceptionName_);
   moduleClasses_(module);
 }
 
@@ -476,21 +471,39 @@
 {
   if (code != OrthancPluginErrorCode_Success)
   {
-    PyErr_SetString(PyExc_ValueError, "Internal error");
-    
-#if 0
-    const char* message = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code);
-    
-    struct module_state *state = GETSTATE(module);
-    if (state->exceptionClass_ == NULL)
+    if (0)
     {
-      OrthancPlugins::LogError("No Python exception has been registered");
+      // This was the implementation in versions <= 3.2 of the Python plugin
+      PyErr_SetString(PyExc_ValueError, "Internal error");
     }
     else
     {
-      PyErr_SetString(state->exceptionClass_, message);
+      // "Python custom exceptions in C(++) extensions"
+      // https://www.pierov.org/2020/03/01/python-custom-exceptions-c-extensions/
+      
+      const char* message = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code);
+      
+      PythonLock lock;
+      
+#if PY_MAJOR_VERSION >= 3
+      PythonModule module(lock, moduleName_);
+#endif
+      
+      struct module_state *state = GETSTATE(module.GetPyObject());
+      if (state->exceptionObject_ == NULL)
+      {
+        OrthancPlugins::LogError("No Python exception has been registered");
+      }
+      else
+      {
+        PythonString str(lock, message);
+        
+        PyObject *exception = PyTuple_New(2);
+        PyTuple_SetItem(exception, 0, PyLong_FromLong(code));
+        PyTuple_SetItem(exception, 1, str.Release());
+        PyErr_SetObject(state->exceptionObject_, exception);
+      }
     }
-#endif
   }
 }