From 3eed19c59a08d7cf9f75925e743980bde6c2ebe6 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Tue, 23 Apr 2019 16:13:06 -0400 Subject: [PATCH 1/3] Fix setRedirectStdInCallbackEnabled This changes the conditions in setRedirectStdInCallbackEnabled to correctly check for the presence of 'pythonqt_stdin' and 'pythonqt_original_stdin' attributes. This ensures proper redirection of stdin. (cherry picked from commit commontk/PythonQt@ddecb44c8a81b75d397e4efca3df6147f1a088ab) --- src/PythonQt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 4d01a15bb..9f6a88a68 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -502,11 +502,11 @@ void PythonQt::setRedirectStdInCallbackEnabled(bool enabled) sys.setNewRef(PyImport_ImportModule("sys")); if (enabled) { - if( !PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) { + if( PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) { PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_stdin")); } } else { - if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) { + if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) { PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin")); } } From f630bc9ec2d92cbdd4e8eb7a77626e2f83da066b Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Tue, 23 Apr 2019 16:13:33 -0400 Subject: [PATCH 2/3] Add support for enabling stdout/stderr redirection This improves the PythonQt module by adding functionality to redirect stdout and stderr to custom callbacks. It includes methods to enable or disable redirection and to check if redirection is currently enabled. (cherry picked from commit commontk/PythonQt@3d3943fdd24f2bcfb8c90314f64b4d33bd7feff0) --- src/PythonQt.cpp | 64 +++++++++++++++++++++++++++++++++++++++--------- src/PythonQt.h | 12 +++++++++ 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 9f6a88a68..535402664 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -1864,18 +1864,22 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ PythonQtObjectPtr sys; sys.setNewRef(PyImport_ImportModule("sys")); - if (redirectStdOut) { - PythonQtObjectPtr out; - PythonQtObjectPtr err; - // create a redirection object for stdout and stderr - out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,nullptr, nullptr); - ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB; - err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,nullptr, nullptr); - ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB; - // replace the built in file objects with our own objects - PyModule_AddObject(sys, "stdout", out); - PyModule_AddObject(sys, "stderr", err); - } + // Backup original 'sys.stdout' and 'sys.stderr' + PyModule_AddObject(sys, "pythonqt_original_stdout", PyObject_GetAttrString(sys, "stdout")); + PyModule_AddObject(sys, "pythonqt_original_stderr", PyObject_GetAttrString(sys, "stderr")); + + // Create a redirection object for stdout and stderr + PythonQtObjectPtr out; + PythonQtObjectPtr err; + out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL); + ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB; + err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL); + ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB; + // replace the built in file objects with our own objects + PyModule_AddObject(sys, "pythonqt_stdout", out); + PyModule_AddObject(sys, "pythonqt_stderr", err); + + setRedirectStdOutCallbackEnabled(redirectStdOut); // add PythonQt to the list of builtin module names PyObject *old_module_names = PyObject_GetAttrString(sys.object(),"builtin_module_names"); @@ -1901,6 +1905,42 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ #endif } +bool PythonQt::redirectStdOutCallbackEnabled() const +{ + PythonQtObjectPtr sys; + sys.setNewRef(PyImport_ImportModule("sys")); + + PythonQtObjectPtr pythonqt_stdout; + pythonqt_stdout.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdout")); + + PythonQtObjectPtr stdout; + stdout.setNewRef(PyObject_GetAttrString(sys.object(), "stdout")); + + return PyObject_RichCompareBool(pythonqt_stdout.object(), stdout.object(), Py_EQ); +} + +void PythonQt::setRedirectStdOutCallbackEnabled(bool enabled) +{ + PythonQtObjectPtr sys; + sys.setNewRef(PyImport_ImportModule("sys")); + + if (enabled) { + if( PyObject_HasAttrString(sys.object(), "pythonqt_stdout") ) { + PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_stdout")); + } + if( PyObject_HasAttrString(sys.object(), "pythonqt_stderr") ) { + PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_stderr")); + } + } else { + if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdout") ) { + PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdout")); + } + if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stderr") ) { + PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_original_stderr")); + } + } +} + QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name) { QStringList tmp = name.split("."); diff --git a/src/PythonQt.h b/src/PythonQt.h index 761d2446b..59b17557a 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -268,6 +268,18 @@ class PYTHONQT_EXPORT PythonQt : public QObject { //@} + //--------------------------------------------------------------------------- + //! \name Standard output handling + //@{ + + //! return \a true if std out/err redirection is enabled. + bool redirectStdOutCallbackEnabled() const; + + //! enable or disable std out/err redirection to pythonStdOut() and pythonStdErr() signals. + void setRedirectStdOutCallbackEnabled(bool enabled); + + //@} + //--------------------------------------------------------------------------- //! \name Modules //@{ From 46a00b8199ee2b7cc41692b182bfd600fd2fc335 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Wed, 24 Apr 2019 02:00:04 -0400 Subject: [PATCH 3/3] Fix windows build error renaming stdout ivar This fixes a build error on Windows by renaming the 'stdout' variable to `sys_stdout' to avoid conflicts with system headers. (cherry picked from commit commontk/PythonQt@5487c61d381840e727fd730f388bf6764b4da8b1) --- src/PythonQt.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 535402664..a8c102cba 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -1913,10 +1913,10 @@ bool PythonQt::redirectStdOutCallbackEnabled() const PythonQtObjectPtr pythonqt_stdout; pythonqt_stdout.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdout")); - PythonQtObjectPtr stdout; - stdout.setNewRef(PyObject_GetAttrString(sys.object(), "stdout")); + PythonQtObjectPtr sys_stdout; + sys_stdout.setNewRef(PyObject_GetAttrString(sys.object(), "stdout")); - return PyObject_RichCompareBool(pythonqt_stdout.object(), stdout.object(), Py_EQ); + return PyObject_RichCompareBool(pythonqt_stdout.object(), sys_stdout.object(), Py_EQ); } void PythonQt::setRedirectStdOutCallbackEnabled(bool enabled)