[glom] Do not crash if PyDateTime_IMPORT fails.



commit 9718918d098a2a2a83c669ae45fb99d08e9b693c
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Mar 14 22:46:57 2011 +0100

    Do not crash if PyDateTime_IMPORT fails.
    
    * glom/libglom/init.[h|cc]: Added libglom_pydatetime_import() and
    libglom_pydatetime_imported(). Remove the g_assert() when it fails.
    * glom/libglom/python_embed/pygdavalue_conversions.cc: Use the new
    utility function instead of repeating our reimplementation here.
    
    There will now just be an error message on stderr. We must fix this properly
    but in the meantime it is better than requiring the use of a separate glom
    branch just for OnlineGlom.
    See https://bugzilla.gnome.org/show_bug.cgi?id=644702

 ChangeLog                                          |   14 ++++
 glom/libglom/init.cc                               |   34 +++++++---
 glom/libglom/init.h                                |   10 +++
 .../libglom/python_embed/pygdavalue_conversions.cc |   64 ++++++++++----------
 4 files changed, 81 insertions(+), 41 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index cdc3ffc..afee355 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2011-03-14  Murray Cumming  <murrayc murrayc com>
 
+	Do not crash if PyDateTime_IMPORT fails.
+
+	* glom/libglom/init.[h|cc]: Added libglom_pydatetime_import() and 
+	libglom_pydatetime_imported(). Remove the g_assert() when it fails.
+	* glom/libglom/python_embed/pygdavalue_conversions.cc: Use the new 
+	utility function instead of repeating our reimplementation here.
+	
+	There will now just be an error message on stderr. We must fix this properly
+	but in the meantime it is better than requiring the use of a separate glom 
+	branch just for OnlineGlom.
+	See https://bugzilla.gnome.org/show_bug.cgi?id=644702
+	
+2011-03-14  Murray Cumming  <murrayc murrayc com>
+
 	Project Manager example: Resave.
 
 	* examples/example_project_manager.glom: Edit the Teams list layout, so
diff --git a/glom/libglom/init.cc b/glom/libglom/init.cc
index 4e2d45a..8dba623 100644
--- a/glom/libglom/init.cc
+++ b/glom/libglom/init.cc
@@ -39,26 +39,40 @@
 namespace Glom
 {
 
-void libglom_init()
-{
-  if (!Glib::thread_supported())
-    Glib::thread_init(0); //So we can use GMutex.
+static bool pydatetime_imported = false;
 
-  Gnome::Gda::init();
-  Gio::init();
+bool libglom_pydatetime_imported()
+{
+  return pydatetime_imported;
+}
 
-  Py_Initialize();
+void libglom_pydatetime_import()
+{
   PyDateTime_IMPORT; //A macro, needed to use PyDate_Check(), PyDateTime_Check(), etc.
-  if(!PyDateTimeAPI)
+  if(!PyDateTimeAPI) //This should have been set by the PyDateTime_IMPORT macro.
   {
     //Give people a clue on stdout:
     std::cerr << G_STRFUNC << ": PyDateTime_IMPORT (a python module import) failed." << std::endl;
 
     //This gives more information. When this happens it is generally a linker
-    //failure while importing a python module:
+    //failure while importing a python module.
+    //See https://bugzilla.gnome.org/show_bug.cgi?id=644702
     PyErr_Print();
   }
-  g_assert(PyDateTimeAPI); //This should have been set by the PyDateTime_IMPORT macro.
+  else
+    pydatetime_imported = true;
+}
+
+void libglom_init()
+{
+  if (!Glib::thread_supported())
+    Glib::thread_init(0); //So we can use GMutex.
+
+  Gnome::Gda::init();
+  Gio::init();
+
+  Py_Initialize();
+  libglom_pydatetime_import();
 }
 
 void libglom_deinit()
diff --git a/glom/libglom/init.h b/glom/libglom/init.h
index 2353995..062e025 100644
--- a/glom/libglom/init.h
+++ b/glom/libglom/init.h
@@ -85,6 +85,16 @@ void libglom_init();
 
 void libglom_deinit();
 
+/** For some reason, we must call this repeatedly.
+ * Maybe it is happening in different processes somehow.
+ */
+void libglom_pydatetime_import();
+
+/** Whether libglom_init() successfully imported the python DateTime API.
+ * This lets other code work around it when it is broken.
+ */
+bool libglom_pydatetime_imported();
+
 } //namespace Glom
 
 #endif //GLOM_LIBGLOM_INIT_H
diff --git a/glom/libglom/python_embed/pygdavalue_conversions.cc b/glom/libglom/python_embed/pygdavalue_conversions.cc
index 11724e3..41636bd 100644
--- a/glom/libglom/python_embed/pygdavalue_conversions.cc
+++ b/glom/libglom/python_embed/pygdavalue_conversions.cc
@@ -3,6 +3,7 @@
 # include <datetime.h> /* From Python */
 #endif
 #include "pygdavalue_conversions.h"
+#include <libglom/init.h>
 
 #include <boost/python.hpp>
 
@@ -85,40 +86,41 @@ glom_pygda_value_from_pyobject(GValue* boxed, const boost::python::object& input
     // Causes a C++ compiler warning, so we use its definition directly.
     // See http://bugs.python.org/issue7463.
     // PyDateTime_IMPORT; //A macro, needed to use PyDate_Check(), PyDateTime_Check(), etc.
-    PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_Import((char*)"datetime", (char*)"datetime_CAPI");
-    g_assert(PyDateTimeAPI); //This should have been set by the PyDateTime_IMPORT macro
-    
-    //TODO: Find some way to do this with boost::python
-    PyObject* input_c = input.ptr();
-    if (PyDateTime_Check (input_c)) {
-         GdaTimestamp gda;
-         gda.year = PyDateTime_GET_YEAR(input_c);
-         gda.month = PyDateTime_GET_MONTH(input_c);
-         gda.day = PyDateTime_GET_DAY(input_c);
-         gda.hour = PyDateTime_DATE_GET_HOUR(input_c);
-         gda.minute = PyDateTime_DATE_GET_MINUTE(input_c);
-         gda.second = PyDateTime_DATE_GET_SECOND(input_c);
-         gda.timezone = 0;
-         gda_value_set_timestamp (boxed, &gda);
-         return true;
+    Glom::libglom_pydatetime_import();
+    if(Glom::libglom_pydatetime_imported())
+    {
+      //TODO: Find some way to do this with boost::python
+      PyObject* input_c = input.ptr();
+      if(PyDateTime_Check (input_c)) {
+        GdaTimestamp gda;
+        gda.year = PyDateTime_GET_YEAR(input_c);
+        gda.month = PyDateTime_GET_MONTH(input_c);
+        gda.day = PyDateTime_GET_DAY(input_c);
+        gda.hour = PyDateTime_DATE_GET_HOUR(input_c);
+        gda.minute = PyDateTime_DATE_GET_MINUTE(input_c);
+        gda.second = PyDateTime_DATE_GET_SECOND(input_c);
+        gda.timezone = 0;
+        gda_value_set_timestamp (boxed, &gda);
+        return true;
      } else if (PyDate_Check (input_c)) {
-         GDate *gda = g_date_new_dmy(
-           PyDateTime_GET_DAY(input_c),
-           (GDateMonth)PyDateTime_GET_MONTH(input_c),
-           PyDateTime_GET_YEAR(input_c) );
-         g_value_init (boxed, G_TYPE_DATE);
-         g_value_set_boxed(boxed, gda);
-         g_date_free(gda);
-         return true;
+       GDate *gda = g_date_new_dmy(
+         PyDateTime_GET_DAY(input_c),
+         (GDateMonth)PyDateTime_GET_MONTH(input_c),
+         PyDateTime_GET_YEAR(input_c) );
+       g_value_init (boxed, G_TYPE_DATE);
+       g_value_set_boxed(boxed, gda);
+       g_date_free(gda);
+       return true;
      } else if (PyTime_Check (input_c)) {
-         GdaTime gda;
-         gda.hour = PyDateTime_TIME_GET_HOUR(input_c);
-         gda.minute = PyDateTime_TIME_GET_MINUTE(input_c);
-         gda.second = PyDateTime_TIME_GET_SECOND(input_c);
-         gda.timezone = 0;
-         gda_value_set_time (boxed, &gda);
-         return true;
+       GdaTime gda;
+       gda.hour = PyDateTime_TIME_GET_HOUR(input_c);
+       gda.minute = PyDateTime_TIME_GET_MINUTE(input_c);
+       gda.second = PyDateTime_TIME_GET_SECOND(input_c);
+       gda.timezone = 0;
+       gda_value_set_time (boxed, &gda);
+       return true;
      }
+   }
 #else
   //std::cout << "DEBUG Dates not supported." << std::endl;
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]