Hello,
On Tuesday 04 February 2014 15:28:09 you wrote:
> I'm curious, does PySide's test suite work under Nuitka?
Running the tests using my previous patches resulted in lots of failed tests,
so I've been rewritting my patches in order to fix these. You'll find attached
patches replacing the precedent ones, that solve some troubles under nuitka
(not all of them though), but do not affect the normal path too much (there are
one shiboken and one pyside tests that no longer pass). I intend to to
investigate these non-passing tests, but this makes this set of patches more
reliable than the previous one.
These patches also include the possibility to run PySide's tests under nuitka,
so anyone willing to test is welcome.
The current status is that 50% of pyside tests pass when run under nuitka.
Even though this looks like a bad score, it enabled me to run a moderately
complicated GUI app under nuitka.
Best,
Vincent
>From 0c3f539af09b7648fd6553b0c2e1ebb06859ac46 Mon Sep 17 00:00:00 2001
From: Vincent Barrielle <[email protected]>
Date: Thu, 6 Feb 2014 18:28:33 +0100
Subject: [PATCH] Make use of the shiboken's method checking code
Running under nuitka requires replacing code that makes use of functions
like PyMethod_Check(). This patch removes some of them. CMake switches
enabling running the tests using nuitka-run are also added.
---
CMakeLists.txt | 10 ++++++++++
PySide/QtCore/glue/qobject_connect.cpp | 9 +++++++--
libpyside/dynamicqmetaobject.cpp | 2 +-
libpyside/globalreceiverv2.cpp | 19 ++++++++++++-------
libpyside/pysideslot.cpp | 4 ++--
tests/CMakeLists.txt | 4 ++++
6 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 26aac24..a349716 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,9 @@ if(USE_XVFB)
endif()
option(BUILD_TESTS "Build tests." TRUE)
+option(TEST_USING_NUITKA "Run tests using the nuitka python compiler" FALSE)
option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE)
+set(NUITKA-RUN_PATH "" CACHE FILEPATH "Path to the nuitka-run executable")
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
if(CMAKE_HOST_APPLE)
@@ -151,6 +153,8 @@ if (NOT SITE_PACKAGE)
endif()
endif()
+#message("shiboken python interp: ${SHIBOKEN_PYTHON_INTERPRETER}")
+#set(SHIBOKEN_PYTHON_INTERPRETER /home/vincent/devel/Nuitka/bin/nuitka-run)
set(GENERATOR_EXTRA_FLAGS --generator-set=shiboken --enable-parent-ctor-heuristic --enable-pyside-extensions --enable-return-value-heuristic --use-isnull-as-nb_nonzero)
if(WIN32 OR DEFINED AVOID_PROTECTED_HACK)
message(STATUS "PySide will be generated avoiding the protected hack!")
@@ -167,6 +171,12 @@ endif()
# project directories
add_subdirectory(PySide)
if (BUILD_TESTS)
+ if( TEST_USING_NUITKA AND NOT EXISTS ${NUITKA-RUN_PATH})
+ message(
+ FATAL_ERROR
+ "Told to run tests under nuitka but nuitka-run path is not correct"
+ )
+ endif()
enable_testing()
add_subdirectory(tests)
endif ()
diff --git a/PySide/QtCore/glue/qobject_connect.cpp b/PySide/QtCore/glue/qobject_connect.cpp
index 96bcfb2..c0b78ab 100644
--- a/PySide/QtCore/glue/qobject_connect.cpp
+++ b/PySide/QtCore/glue/qobject_connect.cpp
@@ -10,9 +10,10 @@ static bool isDecorator(PyObject* method, PyObject* self)
static bool getReceiver(QObject *source, const char* signal, PyObject* callback, QObject** receiver, PyObject** self, QByteArray* callbackSig)
{
+ static PyObject* pySelfAttrName = NULL;
bool forceGlobalReceiver = false;
- if (PyMethod_Check(callback)) {
- *self = PyMethod_GET_SELF(callback);
+ if (Shiboken::PyMethodCheck(callback)) {
+ *self = Shiboken::PyMethodGetSelf(callback);
if (%CHECKTYPE[QObject*](*self))
*receiver = %CONVERTTOCPP[QObject*](*self);
forceGlobalReceiver = isDecorator(callback, *self);
@@ -24,6 +25,10 @@ static bool getReceiver(QObject *source, const char* signal, PyObject* callback,
// Ok, just a callable object
*receiver = 0;
*self = 0;
+ } else if ( Py_TYPE(callback)->tp_call ) {
+ // callable compiled object
+ *receiver = 0;
+ *self = 0;
}
bool usingGlobalReceiver = !*receiver || forceGlobalReceiver;
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
index 4f9af32..aa90ef1 100644
--- a/libpyside/dynamicqmetaobject.cpp
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -500,7 +500,7 @@ void DynamicQMetaObject::parsePythonType(PyTypeObject* type)
if (d.superdata->indexOfSignal(sig) == -1)
addSignal(sig);
}
- } else if (PyFunction_Check(value)) { // Register slots
+ } else if (Shiboken::PyFunctionCheck(value)) { // Register slots
if (PyObject_HasAttr(value, slotAttrName)) {
PyObject* signatureList = PyObject_GetAttr(value, slotAttrName);
for(Py_ssize_t i = 0, i_max = PyList_Size(signatureList); i < i_max; ++i) {
diff --git a/libpyside/globalreceiverv2.cpp b/libpyside/globalreceiverv2.cpp
index a0fd9ac..d3b8ac0 100644
--- a/libpyside/globalreceiverv2.cpp
+++ b/libpyside/globalreceiverv2.cpp
@@ -80,15 +80,15 @@ DynamicSlotDataV2::DynamicSlotDataV2(PyObject* callback, GlobalReceiverV2* paren
{
Shiboken::GilState gil;
- m_isMethod = PyMethod_Check(callback);
+ m_isMethod = Shiboken::PyMethodCheck(callback);
if (m_isMethod) {
//Can not store calback pointe because this will be destroyed at the end of the scope
//To avoid increment intance reference keep the callback information
- m_callback = PyMethod_GET_FUNCTION(callback);
+ m_callback = Shiboken::PyMethodGetFunction(callback);
#ifndef IS_PY3K
- m_pyClass = PyMethod_GET_CLASS(callback);
+ m_pyClass = Shiboken::PyMethodGetClass(callback);
#endif
- m_pythonSelf = PyMethod_GET_SELF(callback);
+ m_pythonSelf = Shiboken::PyMethodGetSelf(callback);
//monitor class from method lifetime
m_weakRef = WeakRef::create(m_pythonSelf, DynamicSlotDataV2::onCallbackDestroyed, this);
@@ -112,9 +112,14 @@ QByteArray DynamicSlotDataV2::hash() const
QByteArray DynamicSlotDataV2::hash(PyObject* callback)
{
Shiboken::GilState gil;
- if (PyMethod_Check(callback))
- return QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_FUNCTION(callback)))
- + QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_SELF(callback)));
+
+ bool isMethod = Shiboken::PyMethodCheck(callback);
+ if (isMethod) {
+ PyObject * self = Shiboken::PyMethodGetSelf(callback);
+ PyObject * func = Shiboken::PyMethodGetFunction(callback);
+ return QByteArray::number((qlonglong) PyObject_Hash(func))
+ + QByteArray::number((qlonglong)PyObject_Hash(self));
+ }
else
return QByteArray::number((qlonglong)PyObject_Hash(callback));
}
diff --git a/libpyside/pysideslot.cpp b/libpyside/pysideslot.cpp
index 97aa60d..637cf80 100644
--- a/libpyside/pysideslot.cpp
+++ b/libpyside/pysideslot.cpp
@@ -144,11 +144,11 @@ PyObject* slotCall(PyObject* self, PyObject* args, PyObject* kw)
callback = PyTuple_GetItem(args, 0);
Py_INCREF(callback);
- if (PyFunction_Check(callback)) {
+ if (Shiboken::PyFunctionCheck(callback)) {
PySideSlot *data = reinterpret_cast<PySideSlot*>(self);
if (!data->slotName) {
- PyObject *funcName = reinterpret_cast<PyFunctionObject*>(callback)->func_name;
+ PyObject * funcName = Shiboken::PyFunctionGetName(callback);
data->slotName = strdup(Shiboken::String::toCString(funcName));
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 282e4b7..531edc7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,6 +5,10 @@ else()
set(CTEST_TESTING_TIMEOUT 60)
endif()
+ if(TEST_USING_NUITKA)
+ set(SHIBOKEN_PYTHON_INTERPRETER ${NUITKA-RUN_PATH})
+ endif()
+
if(WIN32)
set(TEST_PYTHONPATH "${CMAKE_BINARY_DIR};${CMAKE_SOURCE_DIR}/tests/util;${pysidetest_BINARY_DIR};$ENV{PYTHONPATH}")
set(TEST_LIBRARY_PATH "${libpyside_BINARY_DIR};${pysidetest_BINARY_DIR};${SHIBOKEN_INCLUDE_DIR}/../../bin;$ENV{PATH}")
--
1.7.10.4
>From 05d33583c57bc05a6d515635c0fc7b0ea0fa177e Mon Sep 17 00:00:00 2001
From: Vincent Barrielle <[email protected]>
Date: Fri, 7 Feb 2014 15:37:02 +0100
Subject: [PATCH] Added method/function checking methods compatible with
nuitka
Using functions such as PyMethod_Check/PyFunction_Check makes the
inherent assumption that the code is run under CPython, however,
CPython-compatible implementations such as the Nuitka python compiler
exist, and these functions won't work as intended. This patch hence
makes the necessary changes so that shiboken can check wether a
specific object is a method/function while being agnostic to whether
it's interacting with CPython or Nuitka.
---
libshiboken/CMakeLists.txt | 1 +
libshiboken/bindingmanager.cpp | 7 +++-
libshiboken/sbkpython.cpp | 89 ++++++++++++++++++++++++++++++++++++++++
libshiboken/sbkpython.h | 19 +++++++++
4 files changed, 114 insertions(+), 2 deletions(-)
create mode 100644 libshiboken/sbkpython.cpp
diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt
index c8575e7..0d2bffe 100644
--- a/libshiboken/CMakeLists.txt
+++ b/libshiboken/CMakeLists.txt
@@ -37,6 +37,7 @@ bindingmanager.cpp
threadstatesaver.cpp
typeresolver.cpp
shibokenbuffer.cpp
+sbkpython.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp
index cb61000..8811b70 100644
--- a/libshiboken/bindingmanager.cpp
+++ b/libshiboken/bindingmanager.cpp
@@ -256,8 +256,11 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName)
PyObject* pyMethodName = Shiboken::String::fromCString(methodName);
PyObject* method = PyObject_GetAttr((PyObject*)wrapper, pyMethodName);
- if (method && PyMethod_Check(method)
- && reinterpret_cast<PyMethodObject*>(method)->im_self == reinterpret_cast<PyObject*>(wrapper)) {
+ bool isMethod = method && Shiboken::PyMethodCheck(method);
+ bool wrapsParent = false;
+ if (isMethod)
+ wrapsParent = Shiboken::PyMethodGetSelf(method) == reinterpret_cast<PyObject*>(wrapper);
+ if (isMethod && wrapsParent) {
PyObject* defaultMethod;
PyObject* mro = Py_TYPE(wrapper)->tp_mro;
diff --git a/libshiboken/sbkpython.cpp b/libshiboken/sbkpython.cpp
new file mode 100644
index 0000000..4a35743
--- /dev/null
+++ b/libshiboken/sbkpython.cpp
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the Shiboken Python Bindings Generator project.
+ *
+ * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sbkpython.h>
+#include <sbkstring.h>
+
+namespace Shiboken
+{
+
+static PyObject* pySelfAttrName;
+static PyObject* pyFuncAttrName;
+static PyObject* pyClassAttrName;
+static PyObject* pyClosureAttrName;
+static PyObject* pyNameAttrName;
+
+bool PyMethodCheck(PyObject * object)
+{
+ if (!pySelfAttrName)
+ pySelfAttrName = Shiboken::String::fromCString("__self__");
+ if (!pyFuncAttrName)
+ pyFuncAttrName = Shiboken::String::fromCString("__func__");
+
+ bool hasSelf = PyObject_HasAttr(object, pySelfAttrName);
+ bool hasFunc = PyObject_HasAttr(object, pyFuncAttrName);
+ bool isMethod = object && Py_TYPE(object)->tp_call != NULL
+ && hasSelf && hasFunc;
+
+ return isMethod;
+}
+
+bool PyFunctionCheck(PyObject * object)
+{
+ if (!pyClosureAttrName)
+ pyClosureAttrName = Shiboken::String::fromCString("__closure__");
+
+ bool hasClosure = PyObject_HasAttr(object, pyClosureAttrName);
+ bool isFunc = object && Py_TYPE(object)->tp_call != NULL && hasClosure;
+
+ return isFunc;
+}
+
+PyObject * PyMethodGetFunction(PyObject * object)
+{
+ if (!pyFuncAttrName)
+ pyFuncAttrName = Shiboken::String::fromCString("__func__");
+ return PyObject_GetAttr(object, pyFuncAttrName);
+}
+
+PyObject * PyMethodGetClass(PyObject * object)
+{
+ if (!pyClassAttrName)
+ pyClassAttrName = Shiboken::String::fromCString("__class__");
+ return PyObject_GetAttr(object, pyClassAttrName);
+}
+
+PyObject * PyMethodGetSelf(PyObject * object)
+{
+ if (!pySelfAttrName)
+ pySelfAttrName = Shiboken::String::fromCString("__self__");
+ return PyObject_GetAttr(object, pySelfAttrName);
+}
+
+PyObject * PyFunctionGetName(PyObject * object)
+{
+ if (!pyNameAttrName)
+ pyNameAttrName = Shiboken::String::fromCString("__name__");
+ return PyObject_GetAttr(object, pyNameAttrName);
+}
+
+}
diff --git a/libshiboken/sbkpython.h b/libshiboken/sbkpython.h
index ccacb91..6de316d 100644
--- a/libshiboken/sbkpython.h
+++ b/libshiboken/sbkpython.h
@@ -26,6 +26,8 @@
#include "Python.h"
#include "python25compat.h"
+#include "shibokenmacros.h"
+
#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
@@ -54,4 +56,21 @@
#define Py_hash_t long
#endif
+namespace Shiboken
+{
+
+LIBSHIBOKEN_API bool PyMethodCheck(PyObject * object);
+
+LIBSHIBOKEN_API bool PyFunctionCheck(PyObject * object);
+
+LIBSHIBOKEN_API PyObject * PyMethodGetFunction(PyObject * object);
+
+LIBSHIBOKEN_API PyObject * PyMethodGetClass(PyObject * object);
+
+LIBSHIBOKEN_API PyObject * PyMethodGetSelf(PyObject * object);
+
+LIBSHIBOKEN_API PyObject * PyFunctionGetName(PyObject * object);
+
+}
+
#endif
--
1.7.10.4
_______________________________________________
PySide mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/pyside