[glom/boostpythonretry: 6/6] More



commit 552952c01e09407c1b1b344acc2c418abd38c37b
Author: Murray Cumming <murrayc murrayc com>
Date:   Tue Feb 2 19:49:24 2010 +0100

    More

 glom/libglom/python_embed/py_glom_record.cc        |   10 ++-
 glom/libglom/python_embed/py_glom_record.h         |    3 -
 glom/libglom/python_embed/py_glom_relatedrecord.h  |    3 -
 .../libglom/python_embed/pygdavalue_conversions.cc |   85 ++++++++++++--------
 glom/libglom/python_embed/pygdavalue_conversions.h |    4 +-
 glom/python_embed/glom_python.cc                   |   29 +++++--
 glom/python_embed/python_module/py_glom_module.cc  |    2 +-
 glom/python_embed/python_module/py_glom_module.h   |    1 -
 tests/test_python_execute_func.cc                  |   23 +++++-
 9 files changed, 103 insertions(+), 57 deletions(-)
---
diff --git a/glom/libglom/python_embed/py_glom_record.cc b/glom/libglom/python_embed/py_glom_record.cc
index f329516..5d8b7e2 100644
--- a/glom/libglom/python_embed/py_glom_record.cc
+++ b/glom/libglom/python_embed/py_glom_record.cc
@@ -24,6 +24,9 @@
 #include <eval.h> /* for PyEval_EvalCode */
 #include <objimpl.h> /* for PyObject_New() */
 
+//#define NO_IMPORT_PYGOBJECT //To avoid a multiple definition in pygtk.
+//#include <pygobject.h> //For the PyGObject and PyGBoxed struct definitions.
+
 #include <libglom/python_embed/py_glom_record.h>
 #include <libglom/python_embed/py_glom_related.h>
 #include <libglom/python_embed/pygdavalue_conversions.h> //For pygda_value_as_pyobject().
@@ -44,13 +47,18 @@ PyGlomRecord::~PyGlomRecord()
 {
 }
 
+std::string PyGlomRecord::get_table_name() const
+{
+  return m_table_name;
+}
+
 boost::python::object PyGlomRecord::get_connection()
 {
   boost::python::object result;
   
   if(m_connection)
   {
-    PyObject* cobject = pygobject_new( G_OBJECT(m_connection->gobj()) ); //Creates a pygda Connection object.
+    PyObject* cobject = 0; //TODO: pygobject_new( G_OBJECT(m_connection->gobj()) ); //Creates a pygda Connection object.
     result = boost::python::object( boost::python::borrowed(cobject) );
   }
   
diff --git a/glom/libglom/python_embed/py_glom_record.h b/glom/libglom/python_embed/py_glom_record.h
index a82953b..f541768 100644
--- a/glom/libglom/python_embed/py_glom_record.h
+++ b/glom/libglom/python_embed/py_glom_record.h
@@ -21,9 +21,6 @@
 #ifndef GLOM_PYTHON_GLOM_RECORD_H
 #define GLOM_PYTHON_GLOM_RECORD_H
 
-#define NO_IMPORT_PYGOBJECT //To avoid a multiple definition in pygtk.
-#include <pygobject.h> //For the PyGObject and PyGBoxed struct definitions.
-
 #include <boost/python.hpp>
 
 #include <libglom/document/document.h>
diff --git a/glom/libglom/python_embed/py_glom_relatedrecord.h b/glom/libglom/python_embed/py_glom_relatedrecord.h
index 855aba1..caee847 100644
--- a/glom/libglom/python_embed/py_glom_relatedrecord.h
+++ b/glom/libglom/python_embed/py_glom_relatedrecord.h
@@ -21,9 +21,6 @@
 #ifndef GLOM_PYTHON_GLOM_RELATEDRECORD_H
 #define GLOM_PYTHON_GLOM_RELATEDRECORD_H
 
-#define NO_IMPORT_PYGOBJECT //To avoid a multiple definition in pygtk.
-#include <pygobject.h> //For the PyGObject and PyGBoxed struct definitions.
-
 #include <boost/python.hpp>
 
 #include <libglom/document/document.h>
diff --git a/glom/libglom/python_embed/pygdavalue_conversions.cc b/glom/libglom/python_embed/pygdavalue_conversions.cc
index 0428ade..50eaf4c 100644
--- a/glom/libglom/python_embed/pygdavalue_conversions.cc
+++ b/glom/libglom/python_embed/pygdavalue_conversions.cc
@@ -1,9 +1,6 @@
-#include <Python.h>
-#if PY_VERSION_HEX >= 0x02040000
-# include <datetime.h> /* From Python */
-#endif
-#include "pygdavalue_conversions.h"
+#include <boost/python.hpp>
 
+#include "pygdavalue_conversions.h"
 #include <iostream>
 
 
@@ -16,41 +13,63 @@
  * GValue. If the Python object can't be converted to the
  * type of the GValue, then an error is returned.
  *
- * Returns: 0 on success, -1 on error.
+ * Returns: true for success.
  */
-int
-glom_pygda_value_from_pyobject(GValue *boxed, PyObject *input)
+bool
+glom_pygda_value_from_pyobject(GValue *boxed, const boost::python::object& input)
 {
-    // We shouldn't need to call PyDateTime_IMPORT again, 
-    // after already doing it in libglom_init(),
-    // but PyDate_Check crashes (with valgrind warnings) if we don't.
-    //TODO: PyDateTime_IMPORT; //A macro, needed to use PyDate_Check(), PyDateTime_Check(), etc.
-    //g_assert(PyDateTimeAPI); //This should have been set by the PyDateTime_IMPORT macro.
-
     /* Use an appropriate gda_value_set_*() function.
        We can not know what GValue type is actually wanted, so
        we must still have the get_*() functions in the python API.
      */
 
-    if (G_IS_VALUE (boxed)) g_value_unset(boxed);
-    if (input == Py_None) {
-      /* Leave value uninitialized to represent NULL value */
-    } else if (PyString_Check (input)) {
-      const char* text = PyString_AsString (input);
-      g_value_init (boxed, G_TYPE_STRING);
-      g_value_set_string (boxed, text);
-    } else if (PyInt_Check (input)) {
+    if (G_IS_VALUE (boxed))
+      g_value_unset(boxed);
+    
+    boost::python::extract<std::string> extractor_string(input);
+    if(extractor_string.check())
+    {
+      const std::string str = extractor_string;
+      g_value_init(boxed, G_TYPE_STRING);
+      g_value_set_string(boxed, str.c_str());
+      return true;
+    }
+    
+    boost::python::extract<int> extractor_int(input);
+    if(extractor_int.check())
+    {
+      const int val = extractor_int;
       g_value_init (boxed, G_TYPE_INT);
-      g_value_set_int (boxed, PyInt_AsLong (input));
-    } else if (PyLong_Check (input)) {
+      g_value_set_int (boxed, val);
+      return true;
+    }
+    
+    boost::python::extract<long> extractor_long(input);
+    if(extractor_long.check())
+    {
+      const long val = extractor_long;
       g_value_init (boxed, G_TYPE_INT);
-      g_value_set_int (boxed, PyInt_AsLong (input));
-    } else if (PyFloat_Check (input)) {
+      g_value_set_int (boxed, val);
+      return true;
+    }
+    
+    boost::python::extract<double> extractor_double(input);
+    if(extractor_double.check())
+    {
+      const double val = extractor_double;
       g_value_init (boxed, G_TYPE_DOUBLE);
-      g_value_set_double (boxed, PyFloat_AsDouble (input));
-    } else if (PyBool_Check (input)) {
+      g_value_set_double (boxed, val);
+      return true;
+    }
+    
+    boost::python::extract<bool> extractor_bool(input);
+    if(extractor_bool.check())
+    {
+      const bool val = extractor_bool;
       g_value_init (boxed, G_TYPE_BOOLEAN);
-      g_value_set_boolean (boxed, (input == Py_True));
+      g_value_set_boolean (boxed, val);
+    }
+/*
 #if PY_VERSION_HEX >= 0x02040000
     } else if (PyDateTime_Check (input)) {
          GdaTimestamp gda;
@@ -78,12 +97,10 @@ glom_pygda_value_from_pyobject(GValue *boxed, PyObject *input)
          gda.timezone = 0;
          gda_value_set_time (boxed, &gda);
 #endif
-    } else {
-      g_warning("Unhandled python type.");
-      return -1; /* failed. */
-    }
+*/
 
-    return 0; /* success. */
+    g_warning("Unhandled python type.");
+    return false; /* failed. */
 }
 
 boost::python::object glom_pygda_value_as_boost_pyobject(const Glib::ValueBase& value)
diff --git a/glom/libglom/python_embed/pygdavalue_conversions.h b/glom/libglom/python_embed/pygdavalue_conversions.h
index b9af87f..e2e2780 100644
--- a/glom/libglom/python_embed/pygdavalue_conversions.h
+++ b/glom/libglom/python_embed/pygdavalue_conversions.h
@@ -8,8 +8,8 @@
 #include <libgda/libgda.h>
 #include <boost/python.hpp>
 
-int
-glom_pygda_value_from_pyobject(GValue *boxed, PyObject *input);
+bool
+glom_pygda_value_from_pyobject(GValue *boxed, const boost::python::object& input);
 
 //PyObject *
 //glom_pygda_value_as_pyobject(const GValue *value, gboolean copy_boxed);
diff --git a/glom/python_embed/glom_python.cc b/glom/python_embed/glom_python.cc
index 4568333..1492d65 100644
--- a/glom/python_embed/glom_python.cc
+++ b/glom/python_embed/glom_python.cc
@@ -25,8 +25,8 @@
 
 #include <boost/python.hpp>
 
-#define NO_IMPORT_PYGOBJECT //To avoid a multiple definition in pygtk.
-#include <pygobject.h> //For the PyGObject and PyGBoxed struct definitions.
+//#define NO_IMPORT_PYGOBJECT //To avoid a multiple definition in pygtk.
+//#include <pygobject.h> //For the PyGObject and PyGBoxed struct definitions.
 
 #include "glom_python.h"
 #include <libglom/data_structure/glomconversions.h>
@@ -213,14 +213,14 @@ Gnome::Gda::Value glom_evaluate_python_function_implementation(Field::glom_field
       {
         //TODO: Is there a boost::python equivalent for Py_CompileString()?
         PyObject* cObject = Py_CompileString(script.c_str(), name.c_str() /* "filename", for debugging info */,  Py_file_input /* "start token" for multiple lines of code. */); //Returns a reference.
-        boost::python::handle<> objectCompiled(cObject);
+        boost::python::handle<> objectCompiled(cObject); //Takes the reference.
 
         if(!objectCompiled)
           HandlePythonError();
           
       
         cObject = PyImport_ExecCodeModule(const_cast<char*>(name.c_str()), cObject); //Returns a reference. //This should make it importable.
-        boost::python::handle<> object(cObject);
+        boost::python::handle<> object(cObject); //Takes the reference.
 
         if(!object)
           HandlePythonError();
@@ -242,7 +242,7 @@ Gnome::Gda::Value glom_evaluate_python_function_implementation(Field::glom_field
   //PyObject* module_glom_dict = PyModule_GetDict(module_glom);
   
   //This seems to be different to PyGlomRecord_GetPyType() - we can PyObject_Call() this one to instantiate it.
-  PyObject* module_glom_dictC = boost::python::extract<PyObject*>(module_glom_dict);
+  PyObject* module_glom_dictC = boost::python::get_managed_object(module_glom_dict, boost::python::tag);
   PyObject* pyTypeGlomRecordC = PyDict_GetItemString(module_glom_dictC, (char*)"Record"); //TODO: Unref this?
   if(!pyTypeGlomRecordC || !PyType_Check(pyTypeGlomRecordC))
   {
@@ -250,7 +250,7 @@ Gnome::Gda::Value glom_evaluate_python_function_implementation(Field::glom_field
     return valueResult; // don't crash
   }
   
-  boost::python::handle<> ref(pyTypeGlomRecordC);
+  boost::python::handle<> ref(pyTypeGlomRecordC); //To unref it later.
   boost::python::object pyTypeGlomRecord(ref);
 
   boost::python::object module_gda = boost::python::import("gda");
@@ -262,7 +262,16 @@ Gnome::Gda::Value glom_evaluate_python_function_implementation(Field::glom_field
 
   //Create the function definition:
   //PyObject* pyValue = PyRun_String(func_def.c_str(), Py_file_input, pDict.ptr(), pDict.ptr());
-  boost::python::object pyValue = boost::python::eval(func_def.c_str(), pDict, pDict);
+  boost::python::object pyValue;
+  try
+  {
+    pyValue = boost::python::eval(func_def.c_str(), pDict, pDict); //TODO: This throws.
+  }
+  catch(const boost::python::error_already_set& ex)
+  {
+    ShowTrace();
+  }
+  
   if(!pyValue)
   {
     ShowTrace();
@@ -318,9 +327,11 @@ Gnome::Gda::Value glom_evaluate_python_function_implementation(Field::glom_field
         bool object_is_gda_value = false;
 
         GValue value = {0, {{0}}};
-        const int test = glom_pygda_value_from_pyobject(&value, pyResult);
+        boost::python::handle<> handle(boost::python::borrowed(pyResult));
+        boost::python::object pyResultCpp(handle);
+        const bool test = glom_pygda_value_from_pyobject(&value, pyResultCpp);
 
-        if(test == 0) //-1 means error.
+        if(test)
           object_is_gda_value = true;
 
         if(object_is_gda_value && G_IS_VALUE(&value))
diff --git a/glom/python_embed/python_module/py_glom_module.cc b/glom/python_embed/python_module/py_glom_module.cc
index 4ad0472..1dd7c02 100644
--- a/glom/python_embed/python_module/py_glom_module.cc
+++ b/glom/python_embed/python_module/py_glom_module.cc
@@ -31,7 +31,7 @@
 
 using namespace Glom;
 
-BOOST_PYTHON_MODULE(glom)
+BOOST_PYTHON_MODULE(glom_1_14)
 {
   boost::python::class_<PyGlomRecord>("Record")
     .add_property("table_name", &PyGlomRecord::get_table_name)
diff --git a/glom/python_embed/python_module/py_glom_module.h b/glom/python_embed/python_module/py_glom_module.h
index 1faa97e..aca23aa 100644
--- a/glom/python_embed/python_module/py_glom_module.h
+++ b/glom/python_embed/python_module/py_glom_module.h
@@ -37,7 +37,6 @@
  * - field values: for instance, name = record.related["contacts"]["name_first"];
  * - Summary functions: for instance, total = record.related["invoice_lines"].sum("price");
  */
-PyMODINIT_FUNC initglom_1_14(void);
 
 
 
diff --git a/tests/test_python_execute_func.cc b/tests/test_python_execute_func.cc
index 1cb8269..e4a4437 100644
--- a/tests/test_python_execute_func.cc
+++ b/tests/test_python_execute_func.cc
@@ -2,6 +2,8 @@
 #include <glom/python_embed/glom_python.h>
 #include <libglom/data_structure/glomconversions.h>
 
+#include <boost/python.hpp>
+
 int main()
 {
   Glom::libglom_init(); //Also initializes python.
@@ -11,9 +13,24 @@ int main()
   Glib::RefPtr<Gnome::Gda::Connection> connection;
 
   //Execute a python function:
-  const Gnome::Gda::Value value = Glom::glom_evaluate_python_function_implementation(
-    Glom::Field::TYPE_TEXT, calculation, field_values, 
-    0 /* document */, "" /* table name */, connection);
+  Gnome::Gda::Value value;
+  try
+  {
+    value = Glom::glom_evaluate_python_function_implementation(
+      Glom::Field::TYPE_TEXT, calculation, field_values, 
+      0 /* document */, "" /* table name */, connection);
+  }
+  catch(const std::exception& ex)
+  {
+    std::cerr << "Exception: " << ex.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+  catch(const boost::python::error_already_set& ex)
+  {
+    std::cerr << "Exception: boost::python::error_already_set" << std::endl;
+    return EXIT_FAILURE;
+  }
+
 
   //std::cout << "type=" << g_type_name(value.get_value_type()) << std::endl;
 



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