[glom/glom-1-18] Do not crash if PyDateTime_IMPORT fails.



commit 4b837426c3a3ead83a8611dfe86a2255e249f97a
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                                |   14 ++++-
 .../libglom/python_embed/pygdavalue_conversions.cc |   64 ++++++++++----------
 4 files changed, 83 insertions(+), 43 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index aef2345..882a97b 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>
+
 	Require the latest libgdamm, because we use its latest API.
 
 	* configure.ac: Require libgdamm 4.1.2.
diff --git a/glom/libglom/init.cc b/glom/libglom/init.cc
index f345601..639b967 100644
--- a/glom/libglom/init.cc
+++ b/glom/libglom/init.cc
@@ -38,26 +38,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 0c59f62..ea8f2b7 100644
--- a/glom/libglom/init.h
+++ b/glom/libglom/init.h
@@ -59,12 +59,12 @@
  *
  * If your source file is @c program.cc, you can compile it with:
  * @code
- * g++ program.cc -o program  `pkg-config --cflags --libs glom-1.16`
+ * g++ program.cc -o program  `pkg-config --cflags --libs glom-1.18`
  * @endcode
  *
  * Alternatively, if using autoconf, use the following in @c configure.ac:
  * @code
- * PKG_CHECK_MODULES([DEPS], [glom-1.16])
+ * PKG_CHECK_MODULES([DEPS], [glom-1.18])
  * @endcode
  * Then use the generated @c DEPS_CFLAGS and @c DEPS_LIBS variables in the
  * project @c Makefile.am files. For example:
@@ -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 4368ea9..ed7a46a 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]