Explorar o código

HPCC-12912 - Some examples in regression suite fail on python 2.6

Need a dummy frame to be able to execute some functions.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman %!s(int64=10) %!d(string=hai) anos
pai
achega
0069208958
Modificáronse 1 ficheiros con 51 adicións e 0 borrados
  1. 51 0
      plugins/pyembed/pyembed.cpp

+ 51 - 0
plugins/pyembed/pyembed.cpp

@@ -17,6 +17,7 @@
 
 #include "platform.h"
 #include "Python.h"
+#include "frameobject.h"
 #include "jexcept.hpp"
 #include "jthread.hpp"
 #include "hqlplugins.hpp"
@@ -84,6 +85,25 @@ public:
     inline PyObject **ref()                 { return &ptr; }
 };
 
+template <class X>
+class OwnedPyX
+{
+    X *ptr;
+public:
+    inline OwnedPyX<X>() : ptr(NULL) {}
+    inline OwnedPyX<X>(X *_ptr) : ptr(_ptr) {}
+    inline ~OwnedPyX<X>()            { if (ptr) Py_DECREF(ptr); }
+    inline X * get() const           { return ptr; }
+    inline X * getClear()            { PyObject *ret = ptr; ptr = NULL; return ret; }
+    inline X * operator -> () const  { return ptr; }
+    inline operator X *() const      { return ptr; }
+    inline void clear()              { if (ptr) Py_DECREF(ptr); ptr = NULL; }
+    inline void setown(X *_ptr)      { clear(); ptr = _ptr; }
+    inline void set(X *_ptr)         { clear(); ptr = _ptr; if (ptr) Py_INCREF(ptr);}
+    inline X *getLink()              { if (ptr) Py_INCREF(ptr); return ptr;}
+    inline X **ref()                 { return &ptr; }
+};
+
 // call checkPythonError to throw an exception if Python error state is set
 
 static void checkPythonError()
@@ -277,6 +297,34 @@ public:
     {
         return initialized;
     }
+    PyFrameObject *pushDummyFrame()
+    {
+        PyThreadState* threadstate = PyThreadState_GET();
+        if (!threadstate->frame)
+        {
+            OwnedPyObject globals = PyDict_New();
+            OwnedPyObject locals = PyDict_New();
+            OwnedPyObject dummyString = PyString_FromString("Dummy");
+            OwnedPyObject dummyTuple = PyTuple_New(0);
+            OwnedPyObject empty = PyString_FromString("");
+            OwnedPyX<PyCodeObject> code = PyCode_New(0,0,0,0,empty,dummyTuple,dummyTuple,dummyTuple,dummyTuple,dummyTuple,dummyString,dummyString,0,empty);
+//            OwnedPyX<PyCodeObject> code = PyCode_NewEmpty("<dummy>","<dummy>", 0); // (this would be easier but won't compile in Python 2.6)
+            checkPythonError();
+            PyFrameObject *frame = PyFrame_New(threadstate, code, globals, locals);
+            checkPythonError();
+            threadstate->frame = frame;
+            return frame;
+        }
+        return NULL;
+    }
+
+    void popDummyFrame(PyFrameObject *frame)
+    {
+        PyThreadState* threadstate = PyThreadState_GET();
+        if (threadstate->frame == frame)
+            threadstate->frame = NULL;
+    }
+
     PyObject *getNamedTupleType(const RtlTypeInfo *type)
     {
         // It seems the customized namedtuple types leak, and they are slow to create, so take care to reuse
@@ -309,7 +357,10 @@ public:
         {
             OwnedPyObject recname = PyString_FromString("namerec");     // MORE - do we care what the name is?
             OwnedPyObject ntargs = PyTuple_Pack(2, recname.get(), pnames.get());
+            OwnedPyX<PyFrameObject> frame = pushDummyFrame();
             mynamedtupletype.setown(PyObject_CallObject(namedtuple, ntargs));
+            popDummyFrame(frame);
+            checkPythonError();
             PyDict_SetItem(namedtupleTypes, pnames, mynamedtupletype);
         }
         checkPythonError();