From cdbd7d921607e4dd138fe5dfbc3773ef3181978e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 4 Mar 2021 11:44:27 +0100 Subject: Add a license changer tool Run the qtsdk change tool on selected directories. Task-number: QTQAINFRA-4142 Change-Id: I93aa2c46e08b704b9f7f26b0d175b6a8d6e70bea Reviewed-by: Cristian Maureira-Fredes --- tools/license_changer.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tools/license_changer.py diff --git a/tools/license_changer.py b/tools/license_changer.py new file mode 100644 index 000000000..0c3443b83 --- /dev/null +++ b/tools/license_changer.py @@ -0,0 +1,85 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt for Python project. +## +## $QT_BEGIN_LICENSE:COMM$ +## +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## $QT_END_LICENSE$ +## +############################################################################# + +from argparse import ArgumentParser, RawTextHelpFormatter +import os +from pathlib import Path +import subprocess +import sys + + +DESC = """ +Tool to adapt licenses to a commercial LTS branch +Requires the qtsdk/tqtc-qtsdk and qtqa repos to be checked out as siblings. +""" + + +REPO_DIR = Path(__file__).resolve().parents[1] + + +EXCLUSIONS = ['/build_scripts/', '/coin/', '/doc/', '/examples/', + '/testing/', '/tests/', + '/coin_build_instructions.py', '/coin_test_instructions.py', + '/ez_setup.py', '/setup.py', '/testrunner.py'] + + +if __name__ == '__main__': + argument_parser = ArgumentParser(description=DESC, + formatter_class=RawTextHelpFormatter) + argument_parser.add_argument('--dry-run', '-d', action='store_true', + help='Dry run, print commands') + options = argument_parser.parse_args() + dry_run = options.dry_run + + license_changer = (REPO_DIR.parent / 'tqtc-qtsdk' / 'packaging-tools' + / 'release_tools' / 'license_changer.pl') + print('Checking ', license_changer) + if not license_changer.is_file: + print('Not found, please clone the qtsdk/tqtc-qtsdk repo') + sys.exit(1) + template = (REPO_DIR.parent / 'qtqa' / 'tests' / 'prebuild' + / 'license' / 'templates' / 'header.COMM') + print('Checking ', template) + if not template.is_file(): + print('Not found, please clone the qtqa repo') + sys.exit(1) + + os.chdir(REPO_DIR) + fixed_cmd = [str(license_changer), '--path', str(REPO_DIR), + '--headerfile', str(template)] + for e in EXCLUSIONS: + fixed_cmd.append('--exclude') + fixed_cmd.append(e) + + for license in ['GPL-EXCEPT', 'GPL', 'LGPL']: + log = f'license_{license.lower()}_log.txt' + cmd = fixed_cmd + cmd.extend(['--replacehdr', license, '--errorlog', log]) + cmds = ' '.join(cmd) + print('Running: ', cmds) + if not dry_run: + ex = subprocess.call(cmd) + if ex != 0: + print('FAIL! ', cmds) + sys.exit(1) + + if not dry_run: + subprocess.call(['git', 'diff']) -- cgit v1.2.3 From 92f5479681e63b54aaf26c0b7b6972b0cf3cbf87 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Mar 2021 17:19:05 +0100 Subject: Fix broken return type conversions of QOpenGLExtraFunctions::glGetStringi() The function returns const unsigned char*, which was converted using the wrong snippet (QString conversion of parameter 1). Add a new snippet using the char *conversion of the return value at the end. Fixes warning: PySide6/QtGui/PySide6/QtGui/qopenglextrafunctions_wrapper.cpp:4630:35: warning: unused variable cppResunused-variable] const unsigned char * cppResult = cppSelf->glGetStringi(cppArg0, cppArg1); Change-Id: Iae3f0abd4a34fb3b6a41534508fb5d64a3eae224 Reviewed-by: Cristian Maureira-Fredes --- sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml | 3 ++- sources/pyside2/PySide2/glue/qtgui.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index aa8391f8f..2a5a905ba 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -2835,7 +2835,8 @@ - + diff --git a/sources/pyside2/PySide2/glue/qtgui.cpp b/sources/pyside2/PySide2/glue/qtgui.cpp index a2bdafa37..43185ba9b 100644 --- a/sources/pyside2/PySide2/glue/qtgui.cpp +++ b/sources/pyside2/PySide2/glue/qtgui.cpp @@ -45,6 +45,10 @@ const char *sources[] = {buffer.constData()}; %CPPSELF->%FUNCTION_NAME(%1, 1, sources, nullptr); // @snippet glshadersource +// @snippet glgetstring-return +%PYARG_0 = %CONVERTTOPYTHON[const char *](%0); +// @snippet glgetstring-return + // @snippet qtransform-quadtoquad QTransform _result; if (QTransform::quadToQuad(%1, %2, _result)) { -- cgit v1.2.3 From 5c6505c134a2c7fa6a9a8933bab8b2c1d5ca0e27 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Mar 2021 13:25:56 +0100 Subject: shiboken6: Brush up the code injection documentation Link from the code injection page to the type system variables. Link from conversion rule to templates. Modernize the code a bit. Pick-to: 6.0 Change-Id: Ibc8e56a2e3313a0be50dc8bbc92f49a7afc775a2 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 4972d8cf6ea55884e501c452f32f558ad24240ae) --- sources/shiboken2/doc/typesystem_codeinjection.rst | 20 ++++++++++++-------- sources/shiboken2/doc/typesystem_conversionrule.rst | 3 +++ sources/shiboken2/doc/typesystem_variables.rst | 12 +++++++----- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/sources/shiboken2/doc/typesystem_codeinjection.rst b/sources/shiboken2/doc/typesystem_codeinjection.rst index b0d5f3851..836609508 100644 --- a/sources/shiboken2/doc/typesystem_codeinjection.rst +++ b/sources/shiboken2/doc/typesystem_codeinjection.rst @@ -112,7 +112,8 @@ Below is the example C++ class for whom wrapper code will be generated. .. code-block:: c++ - class InjectCode { + class InjectCode + { public: InjectCode(); double overloadedMethod(int arg); @@ -124,6 +125,10 @@ From the C++ class, |project| will generate a ``injectcode_wrapper.cpp`` file with the binding code. The next section will use a simplified version of the generated wrapper code with the injection spots marked with comments. +There are a number of placeholders indicated by a percent sign ``%``, which +will be expanded when inserting the code. For a list, see +:ref:`typesystemvariables`. + Noteworthy Cases ---------------- @@ -196,7 +201,7 @@ class is polymorphic. int InjectCodeWrapper::virtualMethod(int arg) { - PyObject* method = BindingManager::instance().getOverride(this, "virtualMethod"); + PyObject *method = BindingManager::instance().getOverride(this, "virtualMethod"); if (!py_override) return this->InjectCode::virtualMethod(arg); @@ -228,10 +233,9 @@ own ``beginning`` and ``end`` code injections. .. code-block:: c++ - static PyObject* - PyInjectCode_overloadedMethod(PyObject* self, PyObject* arg) + static PyObject *PyInjectCode_overloadedMethod(PyObject *self, PyObject *arg) { - PyObject* py_result = 0; + PyObject* py_result{}; if (PyFloat_Check(arg)) { double cpp_arg0 = Shiboken::Converter::toCpp(arg); @@ -250,13 +254,13 @@ own ``beginning`` and ``end`` code injections. } else goto PyInjectCode_overloadedMethod_TypeError; if (PyErr_Occurred() || !py_result) - return 0; + return {}; return py_result; PyInjectCode_overloadedMethod_TypeError: PyErr_SetString(PyExc_TypeError, "'overloadedMethod()' called with wrong parameters."); - return 0; + return {}; } @@ -371,7 +375,7 @@ to prevent bad custom code to pass unnoticed. // INJECT-CODE: // Uses: do something before the module is created. - PyObject* module = Py_InitModule("MODULENAME", MODULENAME_methods); + PyObject *module = Py_InitModule("MODULENAME", MODULENAME_methods); (... initialization of wrapped classes, namespaces, functions and enums ...) diff --git a/sources/shiboken2/doc/typesystem_conversionrule.rst b/sources/shiboken2/doc/typesystem_conversionrule.rst index 27e7a72de..430c4e4b3 100644 --- a/sources/shiboken2/doc/typesystem_conversionrule.rst +++ b/sources/shiboken2/doc/typesystem_conversionrule.rst @@ -32,6 +32,9 @@ conversion-rule + The code can be inserted directly or via ``insert-template`` (see + :ref:`using-code-templates`). + The example above show the structure of a complete conversion rule. Each of the child tags comprising the conversion rule are described in their own sections below. diff --git a/sources/shiboken2/doc/typesystem_variables.rst b/sources/shiboken2/doc/typesystem_variables.rst index 73d4dd12c..3d4638253 100644 --- a/sources/shiboken2/doc/typesystem_variables.rst +++ b/sources/shiboken2/doc/typesystem_variables.rst @@ -1,3 +1,5 @@ +.. _typesystemvariables: + ********************* Type System Variables ********************* @@ -24,9 +26,9 @@ Variables .. _arg_number: -**%#** +**%** - Replaced by the name of a C++ argument in the position indicated by ``#``. + Replaced by the name of a C++ argument in the position indicated by ````. The argument counting starts with ``%1``, since ``%0`` represents the return variable name. If the number indicates a variable that was removed in the type system description, but there is a default value for it, this value will @@ -214,13 +216,13 @@ Variables .. _pyarg: -**%PYARG_#** +**%PYARG_** - Similar to ``%#``, but is replaced by the Python arguments (PyObjects) + Similar to ``%``, but is replaced by the Python arguments (PyObjects) received by the Python wrapper method. If used in the context of a native code injection, i.e. in a virtual method - override, ``%PYARG_#`` will be translated to one item of the Python tuple + override, ``%PYARG_`` will be translated to one item of the Python tuple holding the arguments that should be passed to the Python override for this virtual method. -- cgit v1.2.3 From 29040a39c8dbfbfa6810907527b58e1fde1f1fe9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 10 Mar 2021 11:31:54 +0100 Subject: shiboken6: Mention add-conversion for conversion rules Amends 4972d8cf6ea55884e501c452f32f558ad24240ae. Pick-to: 6.0 Change-Id: I09a98e37646bb207239fc249e0a45812d3968dab Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 2701e617906bc2c00d03cb48bbb8ba319d5e389d) --- sources/shiboken2/doc/typesystem_conversionrule.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sources/shiboken2/doc/typesystem_conversionrule.rst b/sources/shiboken2/doc/typesystem_conversionrule.rst index 430c4e4b3..fc87a85c9 100644 --- a/sources/shiboken2/doc/typesystem_conversionrule.rst +++ b/sources/shiboken2/doc/typesystem_conversionrule.rst @@ -32,8 +32,9 @@ conversion-rule - The code can be inserted directly or via ``insert-template`` (see - :ref:`using-code-templates`). + The code can be inserted directly, via ``add-conversion`` (providing snippet + functionality) or via ``insert-template`` (XML template, + see :ref:`using-code-templates`). The example above show the structure of a complete conversion rule. Each of the child tags comprising the conversion rule are described in their own sections -- cgit v1.2.3 From ecd78360d6c29b46a61ca11e441dd77fa76385e1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 11 Mar 2021 09:31:12 +0100 Subject: libshiboken: Silence unimplemented array type warning It is more of an annoyance than helpful since it is triggered by the implicit conversion checks already. Task-number: PYSIDE-354 Fixes: PYSIDE-979 Pick-to: 6.0 5.15 Change-Id: I213ad607c61e0279c8cada4efa0a2cfd3cad8892 Reviewed-by: Christian Tismer (cherry picked from commit 7d602dc46163be603e87b1ef4f8db7b1ab87c1f6) --- sources/shiboken2/libshiboken/sbkarrayconverter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp index 57638eeb3..5b45d4b89 100644 --- a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp +++ b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp @@ -72,7 +72,6 @@ SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFu static PythonToCppFunc unimplementedArrayCheck(PyObject *, int, int) { - warning(PyExc_RuntimeWarning, 0, "SbkConverter: Unimplemented C++ array type."); return nullptr; } -- cgit v1.2.3 From 0f272cb12e1448b5e48604150640180e07cfbc9d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Mar 2021 09:09:24 +0100 Subject: Add a tool to run a license check Change-Id: Ib81950a4fa9a8fcbc708c70d478782c567af379f Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit e947ada707a7a4e70e334c39478126932264a1bf) Reviewed-by: Qt Cherry-pick Bot --- tools/license_check.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tools/license_check.py diff --git a/tools/license_check.py b/tools/license_check.py new file mode 100644 index 000000000..052c41ca5 --- /dev/null +++ b/tools/license_check.py @@ -0,0 +1,70 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt for Python project. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import os +from pathlib import Path +import subprocess +import sys + + +"""Tool to run a license check + +Requires the qtqa repo to be checked out as sibling. +""" + + +REPO_DIR = Path(__file__).resolve().parents[1] + + +if __name__ == '__main__': + license_check = (REPO_DIR.parent / 'qtqa' / 'tests' / 'prebuild' + / 'license' / 'tst_licenses.pl') + print('Checking ', license_check) + if not license_check.is_file(): + print('Not found, please clone the qtqa repo') + sys.exit(1) + + os.environ['QT_MODULE_TO_TEST'] = str(REPO_DIR) + cmd = [str(license_check), '-m', 'pyside-setup'] + cmds = ' '.join(cmd) + print('Running: ', cmds) + ex = subprocess.call(cmd) + if ex != 0: + print('FAIL! ', cmds) + sys.exit(1) -- cgit v1.2.3 From 8160ac2e10f99066ee801637ad1f0fd0cc7c585c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 16 Mar 2021 10:49:36 +0100 Subject: shiboken6: Fix AbstractMetaClass::fullName() for nested classes Use the fully qualified name. Task-number: PYSIDE-1520 Change-Id: I58bf8f2d3e1b95947769b725746f560947d25f06 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 3521dfcee8a800927aaf024ab2b64b1402e8256b) --- sources/shiboken2/ApiExtractor/abstractmetalang.cpp | 6 +++++- sources/shiboken2/ApiExtractor/abstractmetalang.h | 5 +---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index bac700912..97bfd8f1b 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -2164,6 +2164,11 @@ void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(Abstrac } } +QString AbstractMetaClass::fullName() const +{ + return package() + QLatin1Char('.') + m_typeEntry->targetLangName(); +} + static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) { if (!type) @@ -2735,4 +2740,3 @@ QString AbstractMetaEnum::package() const { return m_typeEntry->targetLangPackage(); } - diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index ea6e268b0..52adebf94 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1435,10 +1435,7 @@ public: void getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionList *funcList) const; - QString fullName() const - { - return package() + QLatin1Char('.') + name(); - } + QString fullName() const; /** * Retrieves the class name without any namespace/scope information. -- cgit v1.2.3 From 4001a6b3ffd264bf54d99ffed88d91280676a44f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 12 Mar 2021 09:23:16 +0100 Subject: Add QOpenGLVersionFunctionsFactory from Qt 6 To make it possible to obtain versioned OpenGL functions, add the Qt 6 class to QtOpenGLFunctions, which provides a factory function. Task-number: PYSIDE-955 Change-Id: I043a6132a2a1e669bbb071693a8269dde72a59b4 Reviewed-by: Cristian Maureira-Fredes --- .../PySide2/QtOpenGLFunctions/CMakeLists.txt | 6 +- .../QtOpenGLFunctions_global.post.h.in | 2 + .../typesystem_openglfunctions.xml | 9 +++ sources/pyside2/PySide2/glue/qtopenglfunctions.cpp | 76 ++++++++++++++++++++++ .../PySide2/qopenglversionfunctionsfactory.h | 45 +++++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 sources/pyside2/PySide2/glue/qtopenglfunctions.cpp create mode 100644 sources/pyside2/PySide2/qopenglversionfunctionsfactory.h diff --git a/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt b/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt index 383afb68f..62ed669cc 100644 --- a/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt +++ b/sources/pyside2/PySide2/QtOpenGLFunctions/CMakeLists.txt @@ -42,7 +42,8 @@ else() ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_4_compatibility_wrapper.cpp ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_4_core_wrapper.cpp ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_5_compatibility_wrapper.cpp - ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_5_core_wrapper.cpp) + ${QtOpenGLFunctions_GEN_DIR}/qopenglfunctions_4_5_core_wrapper.cpp + ${QtOpenGLFunctions_GEN_DIR}/qopenglversionfunctionsfactory_wrapper.cpp) message(STATUS "Qt${QT_MAJOR_VERSION}OpenGLFunctions: Adding Desktop OpenGL classes") endif() @@ -71,3 +72,6 @@ create_pyside_module(NAME QtOpenGLFunctions SOURCES QtOpenGLFunctions_SRC TYPESYSTEM_NAME ${QtOpenGLFunctions_BINARY_DIR}/typesystem_openglfunctions.xml DROPPED_ENTRIES QtOpenGLFunctions_DROPPED_ENTRIES) + +install(FILES ${pyside2_SOURCE_DIR}/qopenglversionfunctionsfactory.h + DESTINATION include/PySide2/QtOpenGLFunctions) diff --git a/sources/pyside2/PySide2/QtOpenGLFunctions/QtOpenGLFunctions_global.post.h.in b/sources/pyside2/PySide2/QtOpenGLFunctions/QtOpenGLFunctions_global.post.h.in index b633d582a..e92d1dd83 100644 --- a/sources/pyside2/PySide2/QtOpenGLFunctions/QtOpenGLFunctions_global.post.h.in +++ b/sources/pyside2/PySide2/QtOpenGLFunctions/QtOpenGLFunctions_global.post.h.in @@ -52,3 +52,5 @@ #if QT_CONFIG(opengles2) # include #endif + +#include "qopenglversionfunctionsfactory.h" // PySide class diff --git a/sources/pyside2/PySide2/QtOpenGLFunctions/typesystem_openglfunctions.xml b/sources/pyside2/PySide2/QtOpenGLFunctions/typesystem_openglfunctions.xml index 1d5b08edb..edb271362 100644 --- a/sources/pyside2/PySide2/QtOpenGLFunctions/typesystem_openglfunctions.xml +++ b/sources/pyside2/PySide2/QtOpenGLFunctions/typesystem_openglfunctions.xml @@ -404,6 +404,15 @@ &openglfunctions_modifications1_0; &openglfunctions_modifications1_1; + + + + + + + diff --git a/sources/pyside2/PySide2/glue/qtopenglfunctions.cpp b/sources/pyside2/PySide2/glue/qtopenglfunctions.cpp new file mode 100644 index 000000000..c839ae44b --- /dev/null +++ b/sources/pyside2/PySide2/glue/qtopenglfunctions.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// @snippet qopenglversionfunctionsfactory-get +QAbstractOpenGLFunctions *af = %CPPSELF.%FUNCTION_NAME(%1, %2); +if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_5_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_5_Compatibility *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_4_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_4_Compatibility *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_3_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_2_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_1_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_0_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_4_0_Compatibility *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_3_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_3_Compatibility *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_2_Core *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_2_Compatibility *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_1 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_3_0 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_2_1 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_2_0 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_5 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_4 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_3 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_2 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_1 *](f); +} else if (auto *f = dynamic_cast(af)) { + %PYARG_0 = %CONVERTTOPYTHON[QOpenGLFunctions_1_0 *](f); +} else { + QString message; + QDebug(&message) << "No OpenGL functions could be obtained for" << %1; + PyErr_SetString(PyExc_RuntimeError, message.toUtf8().constData()); + %PYARG_0 = Py_None; +} +// @snippet qopenglversionfunctionsfactory-get diff --git a/sources/pyside2/PySide2/qopenglversionfunctionsfactory.h b/sources/pyside2/PySide2/qopenglversionfunctionsfactory.h new file mode 100644 index 000000000..27b8373fa --- /dev/null +++ b/sources/pyside2/PySide2/qopenglversionfunctionsfactory.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt for Python. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOPENGLVERSIONFUNCTIONSFACTORY_H +#define QOPENGLVERSIONFUNCTIONSFACTORY_H + +#include + +QT_BEGIN_NAMESPACE + +class QOpenGLVersionProfile; + +class QOpenGLVersionFunctionsFactory +{ +public: + static QAbstractOpenGLFunctions *get(const QOpenGLVersionProfile &versionProfile, + QOpenGLContext *context) + { + return context + ? context->versionFunctions(versionProfile) + : nullptr; + } +}; + +QT_END_NAMESPACE + +#endif // QOPENGLVERSIONFUNCTIONSFACTORY_H -- cgit v1.2.3 From 4621b1afab446e5171af0f10ab6ae987dc4c6ff7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Sat, 13 Mar 2021 21:45:24 +0100 Subject: PySide2: Implement QOpenGLContext.versionFunctions() Forward the call to QOpenGLVersionFunctionsFactory.get(). Fixes: PYSIDE-955 Change-Id: I17df7784acdf1311c4c22c54537620bcc9d2a3b2 Reviewed-by: Cristian Maureira-Fredes --- .../pyside2/PySide2/QtGui/typesystem_gui_common.xml | 4 ++++ sources/pyside2/PySide2/glue/qtgui.cpp | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index 2a5a905ba..e55d40eb9 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -2601,6 +2601,10 @@ + + + diff --git a/sources/pyside2/PySide2/glue/qtgui.cpp b/sources/pyside2/PySide2/glue/qtgui.cpp index 43185ba9b..d96e9f78f 100644 --- a/sources/pyside2/PySide2/glue/qtgui.cpp +++ b/sources/pyside2/PySide2/glue/qtgui.cpp @@ -23,6 +23,27 @@ * INJECT CODE ********************************************************************/ +// @snippet qopenglcontext-versionfunctions + +// %CPPSELF.%FUNCTION_NAME(%1, %2); Pretend to shiboken we call the function + +// Import QtOpenGLFunctions and call the factory function +// QOpenGLVersionFunctionsFactory.get() +PyObject *module = PyImport_ImportModule("PySide2.QtOpenGLFunctions"); +if (module == nullptr) + return nullptr; +PyObject *loc = PyModule_GetDict(module); +static PyObject *const factoryName = + Shiboken::String::createStaticString("QOpenGLVersionFunctionsFactory"); +auto factory = PyDict_GetItem(loc, factoryName); +if (factory == nullptr) + return nullptr; + +static PyObject *const getMethod = Shiboken::String::createStaticString("get"); +%PYARG_0 = PyObject_CallMethodObjArgs(factory, getMethod, pyArgs[0], %PYSELF, + nullptr); +// @snippet qopenglcontext-versionfunctions + // @snippet glgetshadersource GLsizei bufSize = 4096; GLsizei length = bufSize - 1; -- cgit v1.2.3 From 3e1976ce059e0da40ba55acf9b60bd89da851d73 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 3 Mar 2021 09:56:40 +0100 Subject: Qt Datavisualization: Fix crashes in QBar/SurfaceDataProxy add/set/insertRow() These function take an allocated array. Replace them by functions that take the list by const-ref and pass the allocated copy. Fixes: PYSIDE-1438 Change-Id: Id58cdbc4b939713b71724f5d4a67f0448c74f33f Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 3a18da91353a71e801658329c55b170c18bcd824) Reviewed-by: Christian Tismer --- .../typesystem_datavisualization.xml | 123 ++++++++++----------- .../pyside2/PySide2/glue/qtdatavisualization.cpp | 32 ++++++ .../QtDataVisualization/datavisualization_test.py | 13 +++ 3 files changed, 103 insertions(+), 65 deletions(-) diff --git a/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml b/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml index f10aeea3e..bffb95416 100644 --- a/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml +++ b/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml @@ -119,56 +119,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -251,21 +238,27 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/sources/pyside2/PySide2/glue/qtdatavisualization.cpp b/sources/pyside2/PySide2/glue/qtdatavisualization.cpp index 9cd5ecc62..542c46054 100644 --- a/sources/pyside2/PySide2/glue/qtdatavisualization.cpp +++ b/sources/pyside2/PySide2/glue/qtdatavisualization.cpp @@ -22,3 +22,35 @@ // @snippet releaseownership Shiboken::Object::releaseOwnership(%PYARG_1); // @snippet releaseownership + +// @snippet dataproxy-addrow +using VectorType = decltype(%1); +%RETURN_TYPE %0 = %CPPSELF.addRow(new VectorType(%1)); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); +// @snippet dataproxy-addrow + +// @snippet dataproxy-addrow-string +using VectorType = decltype(%1); +%RETURN_TYPE %0 = %CPPSELF.addRow(new VectorType(%1), %2); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); +// @snippet dataproxy-addrow-string + +// @snippet dataproxy-insertrow +using VectorType = decltype(%2); +%CPPSELF.insertRow(%1, new VectorType(%2)); +// @snippet dataproxy-insertrow + +// @snippet dataproxy-insertrow-string +using VectorType = decltype(%2); +%CPPSELF.insertRow(%1, new VectorType(%2), %3); +// @snippet dataproxy-insertrow-string + +// @snippet dataproxy-setrow +using VectorType = decltype(%2); +%CPPSELF.setRow(%1, new VectorType(%2)); +// @snippet dataproxy-setrow + +// @snippet dataproxy-setrow-string +using VectorType = decltype(%2); +%CPPSELF.setRow(%1, new VectorType(%2), %3); +// @snippet dataproxy-setrow-string diff --git a/sources/pyside2/tests/QtDataVisualization/datavisualization_test.py b/sources/pyside2/tests/QtDataVisualization/datavisualization_test.py index af6e5f5d5..32fd432e8 100644 --- a/sources/pyside2/tests/QtDataVisualization/datavisualization_test.py +++ b/sources/pyside2/tests/QtDataVisualization/datavisualization_test.py @@ -88,5 +88,18 @@ class QtDataVisualizationTestCase(UsesQGuiApplication): QTimer.singleShot(500, self.app.quit) self.app.exec_() + def testBarDataProxy(self): + '''PSYSIDE-1438, crashes in QBarDataProxy.addRow()''' + items = [QtDataVisualization.QBarDataItem(v) for v in [1.0, 2.0]] + data_proxy = QtDataVisualization.QBarDataProxy() + data_proxy.addRow(items) + data_proxy.addRow(items, 'bla') + data_proxy.insertRow(0, items) + data_proxy.insertRow(0, items, 'bla') + data_proxy.setRow(0, items) + data_proxy.setRow(0, items, 'bla') + self.assertTrue(data_proxy.rowCount(), 4) + + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 2a0ba00b6582b0264d731f7d7de1f82a69952361 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Mar 2021 09:28:28 +0100 Subject: shiboken6: Fix crash when using enumeration types from other classes qtbase/969337bcfd6af6d91b988e4b412703274a0b5877 changed QHostAddress to use enum values from QAbstractSocket which appear as fields. This caused a crash in the module initialization since QAbstractSocket was not initialized when creating the field entries. Consider this in the dependency calculation. Change-Id: Ie07dd39a373695cd604d0ebcf233be34a004c8bc Reviewed-by: Maximilian Goldstein Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 2ac1870053370e017567ae53e62cd1155a01c88f) --- sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index a3b62a613..b664c508d 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -3081,8 +3081,11 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const // Member fields need to be initialized const AbstractMetaFieldList &fields = clazz->fields(); for (AbstractMetaField *field : fields) { - addClassDependency(field->type()->typeEntry(), clazz, classIndex, - map, &graph); + auto typeEntry = field->type()->typeEntry(); + if (typeEntry->isEnum()) // Enum defined in class? + typeEntry = typeEntry->parent(); + if (typeEntry != nullptr) + addClassDependency(typeEntry, clazz, classIndex, map, &graph); } } -- cgit v1.2.3 From 434b2f2219e6b299c7852ad0a2ee72dc4bc7b64d Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sun, 21 Mar 2021 13:08:07 +0100 Subject: PySide import: Make imports more safe against installation errors This patch originally was "__feature__: Make imports more safe against installation errors" After applying the patch to 5.15 with errors, it became clear that not __feature__ was a problem, but the "import PySideX.support" did not work in the embedding case. This observation made the error message concerning PyInstaller pointless. Instead, the pseudo-import of PySideX.support was fixed to work correctly in all cases. Tested on 5.15 with PyInstaller, this is now going back into dev. Manually cherry-picked to 6.0 Task-number: PYSIDE-1502 Change-Id: I2fd680a6a28de00f5392147b0d050deb7663dc22 Reviewed-by: Friedemann Kleint (cherry picked from commit becf20de7cda9a98801e109f542aab4ac9fa96ad) Reviewed-by: Qt CI Bot --- sources/shiboken2/shibokenmodule/CMakeLists.txt | 4 +- .../files.dir/shibokensupport/__feature__.py | 171 --------------------- .../files.dir/shibokensupport/feature.py | 171 +++++++++++++++++++++ .../files.dir/shibokensupport/signature/loader.py | 27 ++-- 4 files changed, 188 insertions(+), 185 deletions(-) delete mode 100644 sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py create mode 100644 sources/shiboken2/shibokenmodule/files.dir/shibokensupport/feature.py diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index b14de5c9e..faf579c57 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -42,8 +42,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_config.py" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in" "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/__feature__.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/__feature__.py" COPYONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/feature.py" + "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/feature.py" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/__init__.py" "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/__init__.py" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/__init__.py" diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py deleted file mode 100644 index fe3491f9e..000000000 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py +++ /dev/null @@ -1,171 +0,0 @@ -############################################################################# -## -## Copyright (C) 2021 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:COMM$ -## -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## $QT_END_LICENSE$ -## -############################################################################# - -from __future__ import print_function, absolute_import - -""" -__feature__.py - -This is the feature file for the Qt for Python project. There is some -similarity to Python's `__future__` file, but also some distinction. - -The normal usage is like - - from __feature__ import [, ...] - ... - -Alternatively, there is the `set_selection` function which uses select_id's -and takes an optional `mod_name` parameter. - -The select id `-1` has the spectial meaning "ignore this module". -""" - -import sys - -all_feature_names = [ - "snake_case", - "true_property", - "_feature_04", - "_feature_08", - "_feature_10", - "_feature_20", - "_feature_40", - "_feature_80", -] - -__all__ = ["all_feature_names", "set_selection", "info"] + all_feature_names - -snake_case = 0x01 -true_property = 0x02 -_feature_04 = 0x04 -_feature_08 = 0x08 -_feature_10 = 0x10 -_feature_20 = 0x20 -_feature_40 = 0x40 -_feature_80 = 0x80 - -# let's remove the dummies for the normal user -_really_all_feature_names = all_feature_names[:] -all_feature_names = list(_ for _ in all_feature_names if not _.startswith("_")) - -# Install an import hook that controls the `__feature__` import. -""" -Note: This are two imports. ->>> import dis ->>> def test(): -... from __feature__ import snake_case -... ->>> dis.dis(test) - 2 0 LOAD_CONST 1 (0) - 2 LOAD_CONST 2 (('snake_case',)) - 4 IMPORT_NAME 0 (__feature__) - 6 IMPORT_FROM 1 (snake_case) - 8 STORE_FAST 0 (snake_case) - 10 POP_TOP - 12 LOAD_CONST 0 (None) - 14 RETURN_VALUE -""" -# XXX build an improved C version? I guess not. -def _import(name, *args, **kwargs): - # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules. - # PYSIDE-1398: sys._getframe(1) may not exist when embedding. - calling_frame = _cf = sys._getframe().f_back - importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__" - existing = pyside_feature_dict.get(importing_module, 0) - - if name == "__feature__" and args[2]: - __init__() - - # This is an `import from` statement that corresponds to `IMPORT_NAME`. - # The following `IMPORT_FROM` will handle errors. (Confusing, ofc.) - flag = 0 - for feature in args[2]: - if feature in _really_all_feature_names: - flag |= globals()[feature] - else: - raise SyntaxError("PySide feature {} is not defined".format(feature)) - - flag |= existing & 255 if isinstance(existing, int) and existing >= 0 else 0 - pyside_feature_dict[importing_module] = flag - - if importing_module == "__main__": - # We need to add all modules here which should see __feature__. - pyside_feature_dict["rlcompleter"] = flag - - # Initialize feature (multiple times allowed) and clear cache. - sys.modules["PySide2.QtCore"].__init_feature__() - return sys.modules["__feature__"] - - if name.split(".")[0] == "PySide2": - # This is a module that imports PySide2. - flag = existing if isinstance(existing, int) else 0 - else: - # This is some other module. Ignore it in switching. - flag = -1 - pyside_feature_dict[importing_module] = flag - return original_import(name, *args, **kwargs) - -_is_initialized = False - -def __init__(): - global _is_initialized - if not _is_initialized: - # use _one_ recursive import... - import PySide2.QtCore - # Initialize all prior imported modules - for name in sys.modules: - pyside_feature_dict.setdefault(name, -1) - - -def set_selection(select_id, mod_name=None): - """ - Internal use: Set the feature directly by Id. - Id == -1: ignore this module in switching. - """ - mod_name = mod_name or sys._getframe(1).f_globals['__name__'] - __init__() - # Reset the features to the given id - flag = 0 - if isinstance(select_id, int): - flag = select_id & 255 - pyside_feature_dict[mod_name] = flag - sys.modules["PySide2.QtCore"].__init_feature__() - return _current_selection(flag) - - -def info(mod_name=None): - """ - Internal use: Return the current selection - """ - mod_name = mod_name or sys._getframe(1).f_globals['__name__'] - flag = pyside_feature_dict.get(mod_name, 0) - return _current_selection(flag) - - -def _current_selection(flag): - names = [] - if flag >= 0: - for idx, name in enumerate(_really_all_feature_names): - if (1 << idx) & flag: - names.append(name) - return names - -#eof diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/feature.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/feature.py new file mode 100644 index 000000000..fe3491f9e --- /dev/null +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/feature.py @@ -0,0 +1,171 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of Qt for Python. +## +## $QT_BEGIN_LICENSE:COMM$ +## +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## $QT_END_LICENSE$ +## +############################################################################# + +from __future__ import print_function, absolute_import + +""" +__feature__.py + +This is the feature file for the Qt for Python project. There is some +similarity to Python's `__future__` file, but also some distinction. + +The normal usage is like + + from __feature__ import [, ...] + ... + +Alternatively, there is the `set_selection` function which uses select_id's +and takes an optional `mod_name` parameter. + +The select id `-1` has the spectial meaning "ignore this module". +""" + +import sys + +all_feature_names = [ + "snake_case", + "true_property", + "_feature_04", + "_feature_08", + "_feature_10", + "_feature_20", + "_feature_40", + "_feature_80", +] + +__all__ = ["all_feature_names", "set_selection", "info"] + all_feature_names + +snake_case = 0x01 +true_property = 0x02 +_feature_04 = 0x04 +_feature_08 = 0x08 +_feature_10 = 0x10 +_feature_20 = 0x20 +_feature_40 = 0x40 +_feature_80 = 0x80 + +# let's remove the dummies for the normal user +_really_all_feature_names = all_feature_names[:] +all_feature_names = list(_ for _ in all_feature_names if not _.startswith("_")) + +# Install an import hook that controls the `__feature__` import. +""" +Note: This are two imports. +>>> import dis +>>> def test(): +... from __feature__ import snake_case +... +>>> dis.dis(test) + 2 0 LOAD_CONST 1 (0) + 2 LOAD_CONST 2 (('snake_case',)) + 4 IMPORT_NAME 0 (__feature__) + 6 IMPORT_FROM 1 (snake_case) + 8 STORE_FAST 0 (snake_case) + 10 POP_TOP + 12 LOAD_CONST 0 (None) + 14 RETURN_VALUE +""" +# XXX build an improved C version? I guess not. +def _import(name, *args, **kwargs): + # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules. + # PYSIDE-1398: sys._getframe(1) may not exist when embedding. + calling_frame = _cf = sys._getframe().f_back + importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__" + existing = pyside_feature_dict.get(importing_module, 0) + + if name == "__feature__" and args[2]: + __init__() + + # This is an `import from` statement that corresponds to `IMPORT_NAME`. + # The following `IMPORT_FROM` will handle errors. (Confusing, ofc.) + flag = 0 + for feature in args[2]: + if feature in _really_all_feature_names: + flag |= globals()[feature] + else: + raise SyntaxError("PySide feature {} is not defined".format(feature)) + + flag |= existing & 255 if isinstance(existing, int) and existing >= 0 else 0 + pyside_feature_dict[importing_module] = flag + + if importing_module == "__main__": + # We need to add all modules here which should see __feature__. + pyside_feature_dict["rlcompleter"] = flag + + # Initialize feature (multiple times allowed) and clear cache. + sys.modules["PySide2.QtCore"].__init_feature__() + return sys.modules["__feature__"] + + if name.split(".")[0] == "PySide2": + # This is a module that imports PySide2. + flag = existing if isinstance(existing, int) else 0 + else: + # This is some other module. Ignore it in switching. + flag = -1 + pyside_feature_dict[importing_module] = flag + return original_import(name, *args, **kwargs) + +_is_initialized = False + +def __init__(): + global _is_initialized + if not _is_initialized: + # use _one_ recursive import... + import PySide2.QtCore + # Initialize all prior imported modules + for name in sys.modules: + pyside_feature_dict.setdefault(name, -1) + + +def set_selection(select_id, mod_name=None): + """ + Internal use: Set the feature directly by Id. + Id == -1: ignore this module in switching. + """ + mod_name = mod_name or sys._getframe(1).f_globals['__name__'] + __init__() + # Reset the features to the given id + flag = 0 + if isinstance(select_id, int): + flag = select_id & 255 + pyside_feature_dict[mod_name] = flag + sys.modules["PySide2.QtCore"].__init_feature__() + return _current_selection(flag) + + +def info(mod_name=None): + """ + Internal use: Return the current selection + """ + mod_name = mod_name or sys._getframe(1).f_globals['__name__'] + flag = pyside_feature_dict.get(mod_name, 0) + return _current_selection(flag) + + +def _current_selection(flag): + names = [] + if flag >= 0: + for idx, name in enumerate(_really_all_feature_names): + if (1 << idx) & flag: + names.append(name) + return names + +#eof diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py index fa0d762bc..6582c1373 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py @@ -96,7 +96,7 @@ def finish_import(module): import signature_bootstrap -from shibokensupport import signature, __feature__ +from shibokensupport import signature, feature as __feature__ signature.get_signature = signature_bootstrap.get_signature # PYSIDE-1019: Publish the __feature__ dictionary. __feature__.pyside_feature_dict = signature_bootstrap.pyside_feature_dict @@ -177,8 +177,9 @@ def move_into_pyside_package(): try: import PySide2.support except ModuleNotFoundError: - PySide2.support = types.ModuleType("PySide2.support") - put_into_package(PySide2.support, __feature__) + # This can happen in the embedding case. + put_into_package(PySide2, shibokensupport, "support") + put_into_package(PySide2.support, __feature__, "__feature__") put_into_package(PySide2.support, signature) put_into_package(PySide2.support.signature, mapping) put_into_package(PySide2.support.signature, errorhandler) @@ -202,16 +203,18 @@ from shibokensupport.signature.lib import enum_sig if "PySide2" in sys.modules: # We publish everything under "PySide2.support.signature", again. move_into_pyside_package() + # PYSIDE-1502: Make sure that support can be imported. + try: + import PySide2.support + except ModuleNotFoundError as e: + print("PySide2.support could not be imported. " + "This is a serious configuration error.", file=sys.stderr) + raise # PYSIDE-1019: Modify `__import__` to be `__feature__` aware. # __feature__ is already in sys.modules, so this is actually no import - try: - import PySide2.support.__feature__ - sys.modules["__feature__"] = PySide2.support.__feature__ - PySide2.support.__feature__.original_import = __builtins__["__import__"] - __builtins__["__import__"] = PySide2.support.__feature__._import - # Maybe we should optimize that and change `__import__` from C, instead? - except ModuleNotFoundError: - print("__feature__ could not be imported. " - "This is an unsolved PyInstaller problem.", file=sys.stderr) + import PySide2.support.__feature__ + sys.modules["__feature__"] = PySide2.support.__feature__ + PySide2.support.__feature__.original_import = __builtins__["__import__"] + __builtins__["__import__"] = PySide2.support.__feature__._import # end of file -- cgit v1.2.3 From ce32d7226499115463c4a057b2b0e272490f5f6e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 25 Mar 2021 13:22:25 +0100 Subject: Doc: remove note about 5.14 versions as it is no longer needed Change-Id: Ifb1f03eb8bbbf5e0261ad4e9df76e90817531d92 Reviewed-by: Cristian Maureira-Fredes --- sources/pyside2/doc/quickstart.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sources/pyside2/doc/quickstart.rst b/sources/pyside2/doc/quickstart.rst index 87471a8a8..db2e93280 100644 --- a/sources/pyside2/doc/quickstart.rst +++ b/sources/pyside2/doc/quickstart.rst @@ -52,12 +52,6 @@ constructs to print version information:: # Prints the Qt version used to compile PySide2 print(PySide2.QtCore.__version__) -.. note:: - - As it happened in 5.14.2, PySide had a couple of new releases to fix - issues in 5.14.2, adding yet another version level. In that case, you - will have different versions being shown for Qt and PySide. - Create a Simple Application --------------------------- -- cgit v1.2.3 From 6d342a1857af6ae3a48c1b18e4d3d2730488c942 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Thu, 18 Mar 2021 16:05:22 +0100 Subject: enum: implement enums on module level This was actually already implemented in a different way. Removing the message which was a wrong left-over solved it. Change-Id: I5618a700aa63c4031a7f5d490013d77cf4002684 Fixes: PYSIDE-1519 Reviewed-by: Friedemann Kleint (cherry picked from commit 6629810389d0d546a9306d7a65b4c2c20bd5b9a6) Reviewed-by: Cristian Maureira-Fredes --- .../shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py index 2aad8a65c..5b2368a3c 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py @@ -85,8 +85,6 @@ class ExactEnumerator(object): self.fmt.class_name = None for class_name, klass in members: ret.update(self.klass(class_name, klass)) - if isinstance(klass, EnumMeta): - raise SystemError("implement enum instances at module level") for func_name, func in functions: ret.update(self.function(func_name, func)) return ret -- cgit v1.2.3 From de4a7ac254b316096c866e735ef4dd71d2746369 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 8 Apr 2021 13:43:58 +0200 Subject: Disable shiboken2 documentation build for macOS It produces an encoding error on macOS: Running Sphinx v3.5.3 Encoding error: 'ascii' codec can't decode byte 0xc2 in position 69: ordinal not in range(128) Change-Id: I522fbdb8a765a7e17821ef7ff306aaae5744a42c Reviewed-by: Qt CI Bot Reviewed-by: Christian Tismer --- build_scripts/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_scripts/main.py b/build_scripts/main.py index 796ea2040..25f8ed2e6 100644 --- a/build_scripts/main.py +++ b/build_scripts/main.py @@ -930,7 +930,8 @@ class PysideBuild(_build, DistUtilsCommandMixin): if run_process(cmd_make) != 0: raise DistutilsSetupError("Error compiling {}".format(extension)) - if not OPTION["SKIP_DOCS"]: + # macOS Python3 shows an encoding problem with sphinx + if not OPTION["SKIP_DOCS"] and sys.platform != 'darwin': if extension.lower() == "shiboken2": try: # Check if sphinx is installed to proceed. -- cgit v1.2.3 From 33d6f1b4928d605b9e6f6b8348576506810f3bd2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 6 Apr 2021 10:09:41 +0200 Subject: Prospective fix for QPixmap/QDataStream serialization test The pixmaps are converted to QImage for conversion which seems to result in odd image formats in some cases. Use a transparent color to force alpha. Fixes: PYSIDE-1533 Change-Id: I1499e18fa9d2176182c890171888b76153aef06f Reviewed-by: Christian Tismer (cherry picked from commit be356545daca6add940256d7fb2022bb2a0866aa) --- sources/pyside2/tests/QtGui/qdatastream_gui_operators_test.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sources/pyside2/tests/QtGui/qdatastream_gui_operators_test.py b/sources/pyside2/tests/QtGui/qdatastream_gui_operators_test.py index c9b5c16a5..4db0a0a6e 100644 --- a/sources/pyside2/tests/QtGui/qdatastream_gui_operators_test.py +++ b/sources/pyside2/tests/QtGui/qdatastream_gui_operators_test.py @@ -47,7 +47,9 @@ class QPixmapQDatastream(UsesQApplication): def setUp(self): super(QPixmapQDatastream, self).setUp() self.source_pixmap = QPixmap(100, 100) - self.source_pixmap.fill(Qt.red) + # PYSIDE-1533: Use Qt.transparent to force Format_ARGB32_Premultiplied + # when converting to QImage in any case. + self.source_pixmap.fill(Qt.transparent) self.output_pixmap = QPixmap() self.buffer = QByteArray() self.read_stream = QDataStream(self.buffer, QIODevice.ReadOnly) @@ -60,8 +62,8 @@ class QPixmapQDatastream(UsesQApplication): image = self.output_pixmap.toImage() pixel = image.pixel(10,10) - self.assertEqual(pixel, QColor(Qt.red).rgba()) - self.assertEqual(self.source_pixmap.toImage(), self.output_pixmap.toImage()) + self.assertEqual(pixel, QColor(Qt.transparent).rgba()) + self.assertEqual(self.source_pixmap.toImage(), image) if __name__ == '__main__': -- cgit v1.2.3 From f9025b3f1999c1191a094c1dfdd3e0d215d47610 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Thu, 18 Mar 2021 16:05:22 +0100 Subject: signature: protect an unrecognized item from raising exceptions A special case "std::optional" caused an exception at an unforeseen place, because "std" was not recognized in an eval. Turn this into another runtime warning. Also, the "std::optional" case was added as "typing.Optional" after applying und testing the above fix. Change-Id: I722ae463d133125e96ab09aeb38f21cdc2453d5b Fixes: PYSIDE-1538 Reviewed-by: Renato Araujo Oliveira Filho Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Friedemann Kleint (cherry picked from commit 0a47111b454b8e1582d8595cadc348b61989ff29) --- .../files.dir/shibokensupport/signature/mapping.py | 4 ++++ .../files.dir/shibokensupport/signature/parser.py | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index 18fe1d8e2..43f571c08 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -333,6 +333,10 @@ type_map.update({ "self" : "self", }) +# PYSIDE-1538: We need to treat "std::optional" accordingly. +type_map.update({ + "std.optional": typing.Optional, + }) # The Shiboken Part def init_Shiboken(): diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py index f63f5bfd4..689861d35 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -178,7 +178,7 @@ def _resolve_value(thing, valtype, line): if res is not None: type_map[thing] = res return res - warnings.warn("""pyside_type_init: + warnings.warn("""pyside_type_init:_resolve_value UNRECOGNIZED: {!r} OFFENDING LINE: {!r} @@ -259,7 +259,15 @@ def _resolve_type(thing, line, level, var_handler): pieces.append(to_string(part)) thing = ", ".join(pieces) result = "{contr}[{thing}]".format(**locals()) - return eval(result, namespace) + # PYSIDE-1538: Make sure that the eval does not crash. + try: + return eval(result, namespace) + except Exception as e: + warnings.warn("""pyside_type_init:_resolve_type + + UNRECOGNIZED: {!r} + OFFENDING LINE: {!r} + """.format(result, line), RuntimeWarning) return _resolve_value(thing, None, line) -- cgit v1.2.3 From f8d109aef3d54c9522c185b1dc427be45196d1fb Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sat, 10 Apr 2021 16:00:10 +0200 Subject: Enable shiboken documentation build for macOS again Python v3.6 and docutils v0.17 have an encoding problem, because the default encoding is ASCII. That produces an encoding error on macOS in Sphinx: Running Sphinx v3.5.3 Encoding error: 'ascii' codec can't decode byte 0xc2 in position 69: ordinal not in range(128) The problem happens on macOS because CI uses that old version. It can be avoided by setting UTF-8 encoding. Change-Id: I88ee27cfb529dfec291dc079bcc2d52f656f180f Reviewed-by: Friedemann Kleint (cherry picked from commit 2f88c10f824fb9aa6cb1dbfd18b2d071a48745f1) Reviewed-by: Qt CI Bot --- build_scripts/main.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build_scripts/main.py b/build_scripts/main.py index 25f8ed2e6..86b9cbbbc 100644 --- a/build_scripts/main.py +++ b/build_scripts/main.py @@ -930,8 +930,14 @@ class PysideBuild(_build, DistUtilsCommandMixin): if run_process(cmd_make) != 0: raise DistutilsSetupError("Error compiling {}".format(extension)) - # macOS Python3 shows an encoding problem with sphinx - if not OPTION["SKIP_DOCS"] and sys.platform != 'darwin': + if sys.version_info == (3, 6) and sys.platform == "darwin": + # Python 3.6 has a Sphinx problem because of docutils 0.17 . + # Instead of pinning v0.16, setting the default encoding fixes that. + # Since other platforms are not affected, we restrict this to macOS. + if "UTF-8" not in os.environ.get("LC_ALL", ""): + os.environ["LC_ALL"] = "en_US.UTF-8" + + if not OPTION["SKIP_DOCS"]: if extension.lower() == "shiboken2": try: # Check if sphinx is installed to proceed. -- cgit v1.2.3 From 7e1f66cd048722f2118a9e8ddbe6f481c68840ca Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 6 Apr 2021 14:53:15 +0200 Subject: TestQSettings: Do not clutter the current directory Put the settings file into a temporary directory, which ensures it is cleaned up. Pick-to: 6.0 5.15 Change-Id: Iacab066e1b1da20a8771a844e20751d1e5fb90d2 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 5109bcc49ee907d15c7e9735f8642f15bef90eb9) Reviewed-by: Qt CI Bot --- sources/pyside2/tests/QtCore/qsettings_test.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sources/pyside2/tests/QtCore/qsettings_test.py b/sources/pyside2/tests/QtCore/qsettings_test.py index 639f6d276..a9f42a5d5 100644 --- a/sources/pyside2/tests/QtCore/qsettings_test.py +++ b/sources/pyside2/tests/QtCore/qsettings_test.py @@ -38,7 +38,7 @@ init_test_paths(False) from helper.helper import adjust_filename import py3kcompat as py3k -from PySide2.QtCore import QSettings +from PySide2.QtCore import QDir, QSettings, QTemporaryDir class TestQSettings(unittest.TestCase): def testConversions(self): @@ -59,7 +59,11 @@ class TestQSettings(unittest.TestCase): def testDefaultValueConversion(self): - settings = QSettings('foo.ini', QSettings.IniFormat) + temp_dir = QDir.tempPath() + dir = QTemporaryDir('{}/qsettings_XXXXXX'.format(temp_dir)) + self.assertTrue(dir.isValid()) + file_name = dir.filePath('foo.ini') + settings = QSettings(file_name, QSettings.IniFormat) settings.setValue('zero_value', 0) settings.setValue('empty_list', []) settings.setValue('bool1', False) @@ -67,7 +71,7 @@ class TestQSettings(unittest.TestCase): del settings # Loading values already set - settings = QSettings('foo.ini', QSettings.IniFormat) + settings = QSettings(file_name, QSettings.IniFormat) # Getting value that doesn't exist r = settings.value("variable") -- cgit v1.2.3 From d47736aef4794c4eb81199d71f82ec1ebaced6cf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Apr 2021 15:21:19 +0200 Subject: PySide6: Fix performance of QPainter::drawPoints(QPolygon) Reorder the overloads so that the QPolygon overload is checked first before the costly sequence type check of the QPoint list. Speeds up the example from 1800ms to 80ms. Fixes: PYSIDE-1540 Change-Id: I108b0e98c82540703ee80345026ecdc3b55dfd4e Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit ef707d2077862933b767bccf17ca0c54f9475de0) --- sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index e55d40eb9..b0c61fe64 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -1871,18 +1871,23 @@ + - + - + + + + -- cgit v1.2.3 From 49c115b88d9175c7c160e81d11450c6d42029b5f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 9 Apr 2021 14:41:40 +0200 Subject: shiboken6: Prevent crashes when registering static fields Registering static fields invokes converters, which can cause crashes for uninitialized types (see also 2ac1870053370e017567ae53e62cd1155a01c88f). To solve this problem, move the static field initialization to the end of the module initialization function to ensure all converters are available. Fixes: PYSIDE-1529 Change-Id: If40c6faf049077db8afcdee2069f4441c21beaa4 Reviewed-by: Renato Araujo Oliveira Filho Reviewed-by: Christian Tismer (cherry picked from commit af1bdd8447771728321984f87447187f0284db6b) Reviewed-by: Qt CI Bot --- .../shiboken2/ApiExtractor/abstractmetalang.cpp | 6 +++ sources/shiboken2/ApiExtractor/abstractmetalang.h | 2 + .../shiboken2/generator/shiboken2/cppgenerator.cpp | 59 +++++++++++++++++----- .../shiboken2/generator/shiboken2/cppgenerator.h | 3 ++ 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 97bfd8f1b..06d5af14c 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -2116,6 +2116,12 @@ AbstractMetaField *AbstractMetaClass::findField(const QString &name) const return AbstractMetaField::find(m_fields, name); } +bool AbstractMetaClass::hasStaticFields() const +{ + return std::any_of(m_fields.cbegin(), m_fields.cend(), + [](const AbstractMetaField *f) { return f->isStatic(); }); +} + AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) { if (AbstractMetaEnum *e = findByName(m_enums, enumName)) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 52adebf94..9d0facd7d 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1417,6 +1417,8 @@ public: AbstractMetaField *findField(const QString &name) const; + bool hasStaticFields() const; + const AbstractMetaEnumList &enums() const { return m_enums; } void setEnums(const AbstractMetaEnumList &enums) { diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 4f3bd2d0a..f299ba428 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -755,6 +755,9 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo writeConverterFunctions(s, metaClass, classContext); writeClassRegister(s, metaClass, classContext, signatureStream); + if (metaClass->hasStaticFields()) + writeStaticFieldInitialization(s, metaClass); + // class inject-code native/end if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), @@ -5274,6 +5277,12 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me return initFunctionName; } +QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const +{ + return QLatin1String("init_") + getSimpleClassInitFunctionName(metaClass) + + QLatin1String("StaticFields"); +} + QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const { return !context.forSmartPointer() @@ -5476,18 +5485,6 @@ void CppGenerator::writeClassRegister(QTextStream &s, if (metaClass->hasSignals()) writeSignalInitialization(s, metaClass); - // Write static fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField *field : fields) { - if (!field->isStatic()) - continue; - s << INDENT << QLatin1String("PyDict_SetItemString(reinterpret_cast(") + cpythonTypeName(metaClass) + QLatin1String(")->tp_dict, \""); - s << field->name() << "\", "; - writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name()); - s << ");\n"; - } - s << Qt::endl; - // class inject-code target/end if (!classTypeEntry->codeSnips().isEmpty()) { s << Qt::endl; @@ -5517,6 +5514,29 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << "}\n"; } +void CppGenerator::writeStaticFieldInitialization(QTextStream &s, + const AbstractMetaClass *metaClass) +{ + s << "\nvoid " << getSimpleClassStaticFieldsInitFunctionName(metaClass) + << "()\n{\n" << INDENT << "auto dict = reinterpret_cast(" + << cpythonTypeName(metaClass) << ")->tp_dict;\n"; + const auto &fields = metaClass->fields(); + for (const AbstractMetaField *field : fields) { + if (field->isStatic()) { + QString cppName = field->originalName(); + if (cppName.isEmpty()) + cppName = field->name(); + const QString name = field->enclosingClass()->qualifiedCppName() + + QLatin1String("::") + cppName; + s << INDENT << "PyDict_SetItemString(dict, \"" << field->name() + << "\",\n" << INDENT << " "; + writeToPythonConversion(s, field->type(), metaClass, name); + s << ");\n"; + } + } + s << "\n}\n"; +} + void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); @@ -5927,11 +5947,18 @@ bool CppGenerator::finishGeneration() } const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); + QVector classesWithStaticFields; + for (const AbstractMetaClass *cls : lst){ if (shouldGenerate(cls)) { writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT, getSimpleClassInitFunctionName(cls), cls->typeEntry()->targetLangEnclosingEntry()); + if (cls->hasStaticFields()) { + s_classInitDecl << "void " + << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + classesWithStaticFields.append(cls); + } } } @@ -6233,6 +6260,14 @@ bool CppGenerator::finishGeneration() s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n"; s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n"; + // Static fields are registered last since they may use converter functions + // of the previously registered types (PYSIDE-1529). + if (!classesWithStaticFields.isEmpty()) { + s << "\n// Static field initialization\n"; + for (auto cls : qAsConst(classesWithStaticFields)) + s << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + } + s << '\n' << INDENT << "if (PyErr_Occurred()) {\n" << indent(INDENT) << INDENT << "PyErr_Print();\n" << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n" diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index 79b8774a9..cc03c86e0 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -250,6 +250,7 @@ private: QString getInitFunctionName(const GeneratorContext &context) const; QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const; + QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const; void writeSignatureStrings(QTextStream &s, QTextStream &signatureStream, const QString &arrayName, @@ -258,6 +259,8 @@ private: const AbstractMetaClass *metaClass, const GeneratorContext &classContext, QTextStream &signatureStream); + void writeStaticFieldInitialization(QTextStream &s, + const AbstractMetaClass *metaClass); void writeClassDefinition(QTextStream &s, const AbstractMetaClass *metaClass, const GeneratorContext &classContext); -- cgit v1.2.3 From 871e9e6827d4e987546631befb62b833dd46af23 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Apr 2021 13:31:58 +0200 Subject: shiboken6: Refactor handling of the brief class documentation Move the extraction of the brief text from the QtDocGenerator to the QtDocParser and store the brief text in class Documentation, allowing for later extraction. The handling for qdoc and doxygen should then be consistent. Change-Id: I86b37ae1c4a92f96508a03f5dbcfb6dc56014382 Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Christian Tismer (cherry picked from commit 1c4b7ddb0f879909f5d2f9f6207c06dfd2493340) --- sources/shiboken2/ApiExtractor/abstractmetalang.h | 1 + sources/shiboken2/ApiExtractor/qtdocparser.cpp | 36 ++++++++++++++++++++-- .../ApiExtractor/tests/testmodifydocumentation.cpp | 7 +++-- .../shiboken2/generator/qtdoc/qtdocgenerator.cpp | 31 ++----------------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 9d0facd7d..92c9189b8 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -77,6 +77,7 @@ public: Format fmt = Documentation::Native); bool isEmpty() const; + bool hasBrief() const { return m_data.contains(Brief); } QString value(Type t = Documentation::Detailed) const; void setValue(const QString& value, Type t = Documentation::Detailed, diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp index 0550e13d3..4c119cb06 100644 --- a/sources/shiboken2/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp @@ -34,6 +34,9 @@ #include #include +static inline QString briefStartElement() { return QStringLiteral(""); } +static inline QString briefEndElement() { return QStringLiteral(""); } + Documentation QtDocParser::retrieveModuleDocumentation() { return retrieveModuleDocumentation(packageName()); @@ -199,6 +202,25 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName, return result; } +// Extract the section from a WebXML (class) documentation and remove it +// from the source. +static QString extractBrief(QString *value) +{ + const auto briefStart = value->indexOf(briefStartElement()); + if (briefStart < 0) + return {}; + const auto briefEnd = value->indexOf(briefEndElement(), + briefStart + briefStartElement().size()); + if (briefEnd < briefStart) + return {}; + const auto briefLength = briefEnd + briefEndElement().size() - briefStart; + QString briefValue = value->mid(briefStart, briefLength); + briefValue.insert(briefValue.size() - briefEndElement().size(), + QLatin1String(" More_...")); + value->remove(briefStart, briefLength); + return briefValue; +} + void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) { if (!metaClass) @@ -250,9 +272,17 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) signedModifs.append(docModif); } - Documentation doc(getDocumentation(xquery, query, classModifs)); - if (doc.isEmpty()) - qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); + QString docString = getDocumentation(xquery, query, classModifs); + if (docString.isEmpty()) { + qCWarning(lcShibokenDoc, "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); + } + const QString brief = extractBrief(&docString); + + Documentation doc; + if (!brief.isEmpty()) + doc.setValue(brief, Documentation::Brief); + doc.setValue(docString); metaClass->setDocumentation(doc); //Functions Documentation diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp index 6acac41d5..cf3982a18 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp @@ -72,13 +72,14 @@ R"( docParser.setDocumentationDataDirectory(tempDir.path()); docParser.fillDocumentation(classA); - const QString actualDocSimplified = classA->documentation().value().simplified(); + const Documentation &doc = classA->documentation(); + const QString actualDocSimplified = doc.value(Documentation::Detailed).simplified(); + const QString actualBriefSimplified = doc.value(Documentation::Brief).simplified(); QVERIFY(!actualDocSimplified.isEmpty()); const char expectedDoc[] = R"( oi -Modified Brief Paragraph number 1 Paragraph number 2 Some changed contents here @@ -86,7 +87,7 @@ R"( )"; const QString expectedDocSimplified = QString::fromLatin1(expectedDoc).simplified(); // Check whether the first modification worked. - QVERIFY(actualDocSimplified.contains(QLatin1String("Modified Brief"))); + QVERIFY(actualBriefSimplified.contains(QLatin1String("Modified Brief"))); #ifndef HAVE_LIBXSLT // QtXmlPatterns is unable to handle para[3] in style sheets, diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 40af0958d..784cdfbf2 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -1581,30 +1581,6 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl s << classes.join(QLatin1String(", ")) << Qt::endl << Qt::endl; } -// Extract the section from a WebXML (class) documentation and remove it -// from the source. -static bool extractBrief(Documentation *sourceDoc, Documentation *brief) -{ - if (sourceDoc->format() != Documentation::Native) - return false; - QString value = sourceDoc->value(); - const int briefStart = value.indexOf(briefStartElement()); - if (briefStart < 0) - return false; - const int briefEnd = value.indexOf(briefEndElement(), briefStart + briefStartElement().size()); - if (briefEnd < briefStart) - return false; - const int briefLength = briefEnd + briefEndElement().size() - briefStart; - brief->setFormat(Documentation::Native); - QString briefValue = value.mid(briefStart, briefLength); - briefValue.insert(briefValue.size() - briefEndElement().size(), - QLatin1String(" More_...")); - brief->setValue(briefValue); - value.remove(briefStart, briefLength); - sourceDoc->setValue(value); - return true; -} - void QtDocGenerator::generateClass(QTextStream &s, const GeneratorContext &classContext) { const AbstractMetaClass *metaClass = classContext.metaClass(); @@ -1623,9 +1599,8 @@ void QtDocGenerator::generateClass(QTextStream &s, const GeneratorContext &class s << Pad('*', className.count()) << Qt::endl << Qt::endl; auto documentation = metaClass->documentation(); - Documentation brief; - if (extractBrief(&documentation, &brief)) - writeFormattedText(s, brief.value(), metaClass); + if (documentation.hasBrief()) + writeFormattedText(s, documentation.value(Documentation::Brief), metaClass); s << ".. inheritance-diagram:: " << metaClass->fullName() << Qt::endl << " :parts: 2" << Qt::endl << Qt::endl; @@ -1652,7 +1627,7 @@ void QtDocGenerator::generateClass(QTextStream &s, const GeneratorContext &class writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, nullptr); if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, nullptr)) - writeFormattedText(s, documentation.value(), metaClass); + writeFormattedText(s, documentation.value(Documentation::Detailed), metaClass); if (!metaClass->isNamespace()) writeConstructors(s, metaClass); -- cgit v1.2.3 From b833d09c0a83d54899bbdf36367c15fb820d63c6 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Tue, 20 Apr 2021 17:46:31 +0200 Subject: signature: Refine the decision heuristics of result tuples Result tuples do not (yet) get information from XML. Instead, they fetch their info solely from the embedded signature strings and information encoded in mapping.py . When a variable is determined as a result variable, it is removed from the arg list and normally appended to the return tuple. It turned out that a special rule is needed: A variable that comes first in the variable list should also be first in the result tuple. This heuristics should be replaced by more introspection. Right now, this suffices as a working fix. Fixes: PYSIDE-1409 Change-Id: Ib65682439e2f678380e0f58a42a36506d0766ddf Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 3506158551488788450498f9b4ffe86375172fea) Reviewed-by: Christian Tismer --- .../shibokenmodule/files.dir/shibokensupport/signature/parser.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py index 689861d35..ec77208c8 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -370,7 +370,9 @@ def fix_variables(props, line): if not isinstance(ann, ResultVariable): continue # We move the variable to the end and remove it. - retvars.append(ann.type) + # PYSIDE-1409: If the variable was the first arg, we move it to the front. + # XXX This algorithm should probably be replaced by more introspection. + retvars.insert(0 if idx == 0 else len(retvars), ann.type) deletions.append(idx) del annos[name] for idx in reversed(deletions): -- cgit v1.2.3 From 6cc3c07431ede5cb2487b09d4725b54f014a64d2 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Fri, 2 Apr 2021 15:49:58 +0200 Subject: cmake: add dependencies to rebuild libshiboken embedded files It was often a pain to handle embedded files correctly. Often, when embedding was used, one could not see any effect after re-compiling when --reuse-build was specified. This rendered the --reuse-build option often quite useless. The new approach adds dependencies for all involved Python files, and at the same time reduces them to a single list. Fixes: PYSIDE-1536 Change-Id: I6ef36c9ffccd2cd1ac290bb8e879b050f633eaf4 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit e641c225d2954cfc5c85e00eda83f5319c84b3c8) Reviewed-by: Friedemann Kleint --- sources/shiboken2/CMakeLists.txt | 29 +++++++++++++++++ sources/shiboken2/libshiboken/CMakeLists.txt | 24 +++++++++++++- .../libshiboken/embed/embedding_generator.py | 22 +++++++++++-- sources/shiboken2/shibokenmodule/CMakeLists.txt | 37 ++++------------------ 4 files changed, 78 insertions(+), 34 deletions(-) diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt index 3de5d3223..8b626af09 100644 --- a/sources/shiboken2/CMakeLists.txt +++ b/sources/shiboken2/CMakeLists.txt @@ -196,6 +196,35 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_debug_build() endif() +###################################################################### +## Define the Python files involved in the build process. +## +## They are installed into the file system (see shibokenmodule) +## and embedded into the libshiboken binary through a .zip file. +###################################################################### + +set(shiboken_python_files + "signature/lib/__init__.py" + "signature/lib/enum_sig.py" + "signature/lib/tool.py" + "signature/__init__.py" + "signature/errorhandler.py" + "signature/importhandler.py" + "signature/layout.py" + "signature/loader.py" + "signature/mapping.py" + "signature/parser.py" + "__init__.py" + "feature.py" + ) + +if (PYTHON_VERSION_MAJOR LESS 3) + list(APPEND shiboken_python_files + "backport_inspect.py" + "typing27.py" + ) +endif() + ###################################################################### # Adding sub directories to build ###################################################################### diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index 45b41fd13..96effd280 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -29,13 +29,35 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/embed/signature_bootstrap.py" "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap.py" @ONLY) +# Variable from enclosing scope. +# list(TRANSFORM shiboken_python_files +# PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/../shibokenmodule/files.dir/shibokensupport/" +# OUTPUT_VARIABLE embedded_shiboken_files) +# Replacement for CMake version < 3.12: +set(embedded_shiboken_files "") +foreach(item IN LISTS shiboken_python_files) + list(APPEND embedded_shiboken_files + "${CMAKE_CURRENT_SOURCE_DIR}/../shibokenmodule/files.dir/shibokensupport/${item}") +endforeach() + +if (QUIET_BUILD) + set(embedding_option "--quiet") +else() + set(embedding_option "") +endif() + add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap_inc.h" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_inc.h" COMMAND ${PYTHON_EXECUTABLE} -E "${CMAKE_CURRENT_SOURCE_DIR}/embed/embedding_generator.py" --cmake-dir "${CMAKE_CURRENT_BINARY_DIR}/embed" - --limited-api ${PYTHON_LIMITED_API}) + --limited-api ${PYTHON_LIMITED_API} + ${embedding_option} + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/embed/embedding_generator.py" + "${CMAKE_CURRENT_SOURCE_DIR}/embed/signature_bootstrap.py" + ${embedded_shiboken_files} + ) set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) diff --git a/sources/shiboken2/libshiboken/embed/embedding_generator.py b/sources/shiboken2/libshiboken/embed/embedding_generator.py index 61eca27f5..e6256a369 100644 --- a/sources/shiboken2/libshiboken/embed/embedding_generator.py +++ b/sources/shiboken2/libshiboken/embed/embedding_generator.py @@ -64,7 +64,7 @@ def runpy(cmd, **kw): subprocess.call([sys.executable, '-E'] + cmd.split(), **kw) -def create_zipfile(limited_api): +def create_zipfile(limited_api, quiet): """ Collect all Python files, compile them, create a zip file and make a chunked base64 encoded file from it. @@ -111,11 +111,28 @@ def create_zipfile(limited_api): with open(inc_name, "w") as inc: _embed_file(tmp, inc) tmp.close() + # also generate a simple embeddable .pyc file for signature_bootstrap.pyc boot_name = "signature_bootstrap.py" if limited_api else "signature_bootstrap.pyc" with open(boot_name, "rb") as ldr, open("signature_bootstrap_inc.h", "w") as inc: _embed_bytefile(ldr, inc, limited_api) os.chdir(cur_dir) + if quiet: + return + + # have a look at our populated folder unless quiet option + def list_files(startpath): + for root, dirs, files in os.walk(startpath): + level = root.replace(startpath, '').count(os.sep) + indent = ' ' * 4 * (level) + print('+ {}{}/'.format(indent, os.path.basename(root))) + subindent = ' ' * 4 * (level + 1) + for f in files: + print('+ {}{}'.format(subindent, f)) + + print("++++ Current contents of") + list_files(work_dir) + print("++++") def _embed_file(fin, fout): @@ -218,7 +235,8 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('--cmake-dir', nargs="?") parser.add_argument('--limited-api', type=str2bool) + parser.add_argument('--quiet', action='store_true') args = parser.parse_args() if args.cmake_dir: work_dir = os.path.abspath(args.cmake_dir) - create_zipfile(args.limited_api) + create_zipfile(args.limited_api, args.quiet) diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index faf579c57..9b2b58528 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -42,37 +42,12 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_config.py" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in" "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/feature.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/feature.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/__init__.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/__init__.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/__init__.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/__init__.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/errorhandler.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/errorhandler.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/layout.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/layout.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/loader.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/loader.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/importhandler.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/importhandler.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/mapping.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/mapping.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/parser.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/parser.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/lib/__init__.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/__init__.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/lib/enum_sig.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/enum_sig.py" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/lib/tool.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/tool.py" COPYONLY) -if (PYTHON_VERSION_MAJOR EQUAL 3) -else() - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/backport_inspect.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/backport_inspect.py" COPYONLY) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/typing27.py" - "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/typing27.py" COPYONLY) -endif() +# Variable from enclosing scope. +foreach(item IN LISTS shiboken_python_files) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/${item}" + "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/${item}" COPYONLY) +endforeach() + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/files.dir" DESTINATION "${PYTHON_SITE_PACKAGES}/shiboken2") -- cgit v1.2.3 From c4067b118b2fdf701ce89603ed4fa0c3bc459364 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Wed, 24 Mar 2021 13:01:48 +0100 Subject: signature: silence a compiler warning Change-Id: I648dfaa0049e7ca9bba0b90f6e06ea6e0bda1bd3 Fixes: PYSIDE-1524 Reviewed-by: Friedemann Kleint (cherry picked from commit 2f18ab9c93d4fae8d8d7e4d84bd9cd2e7fd22c3d) --- sources/shiboken2/libshiboken/signature/signature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/shiboken2/libshiboken/signature/signature.cpp b/sources/shiboken2/libshiboken/signature/signature.cpp index e4e8135c5..8cda6f810 100644 --- a/sources/shiboken2/libshiboken/signature/signature.cpp +++ b/sources/shiboken2/libshiboken/signature/signature.cpp @@ -481,7 +481,7 @@ static PyObject *adjustFuncName(const char *func_name) } // Finally, generate the correct path expression. - char _buf[200 + 1] = {}; + char _buf[250 + 1] = {}; if (is_prop) { auto _prop_name = String::toCString(prop_name); if (is_class_prop) -- cgit v1.2.3 From 792ab2f160ea64ba25300dbe766c7eb6956bc50d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 22 Apr 2021 16:14:21 +0200 Subject: shiboken6: Fix XML errors when injecting target format (RST) documentation In writeInjectDocumentation(), pass class Documentation (including format) instead of just the string to writeFormattedText() to prevent it from running through XMLToSphinx. Change-Id: I6116552fc3ea8f7ddc1cc07d51370f868de97bb3 Reviewed-by: Christian Tismer (cherry picked from commit d9b11bb733e3a3e2546634f6792691aaa473be65) --- sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 784cdfbf2..8622c6c5b 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -1940,7 +1940,7 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, continue; doc.setValue(mod.code(), Documentation::Detailed, fmt); - writeFormattedText(s, doc.value(), cppClass); + writeFormattedText(s, doc, cppClass); didSomething = true; } } -- cgit v1.2.3 From 7cd2c319fdc334bc442ed882446a08c7c92f7635 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 23 Apr 2021 13:24:57 +0200 Subject: Fix the text object example The example apparently has never worked. Fix it by using QPyTextObject as a base class and using a different character (as done in qabstracttextdocumentlayout_test.py). Ported from 1dec709b4da110b4f42a248b5af44c94b964d7e0. Task-number: PYSIDE-1112 Change-Id: I67fa6b6906bec33ae7a3b98fceb94ec6d95b5afd Reviewed-by: Christian Tismer --- examples/widgets/richtext/textobject/textobject.py | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/widgets/richtext/textobject/textobject.py b/examples/widgets/richtext/textobject/textobject.py index b828ea3d0..e82ea95dc 100644 --- a/examples/widgets/richtext/textobject/textobject.py +++ b/examples/widgets/richtext/textobject/textobject.py @@ -42,13 +42,17 @@ """PySide2 port of the widgets/richtext/textobject example from Qt v5.x""" +import os + from PySide2 import QtCore, QtGui, QtWidgets, QtSvg -class SvgTextObject(QtCore.QObject, QtGui.QTextObjectInterface): +class SvgTextObject(QtGui.QPyTextObject): + def __init__(self, parent=None): + super(SvgTextObject, self).__init__(parent) def intrinsicSize(self, doc, posInDocument, format): - renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData).toByteArray()) + renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData)) size = renderer.defaultSize() if size.height() > 25: @@ -57,7 +61,7 @@ class SvgTextObject(QtCore.QObject, QtGui.QTextObjectInterface): return QtCore.QSizeF(size) def drawObject(self, painter, rect, doc, posInDocument, format): - renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData).toByteArray()) + renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData)) renderer.render(painter, rect) @@ -80,8 +84,10 @@ class Window(QtWidgets.QWidget): file = QtCore.QFile(fileName) if not file.open(QtCore.QIODevice.ReadOnly): - QtWidgets.QMessageBox.warning(self, self.tr("Error Opening File"), - self.tr("Could not open '%1'").arg(fileName)) + reason = file.errorString() + message = "Could not open '{}': {}".format(fileName, reason) + QtWidgets.QMessageBox.warning(self, "Error Opening File", + message.arg(fileName)) svgData = file.readAll() @@ -90,7 +96,7 @@ class Window(QtWidgets.QWidget): svgCharFormat.setProperty(Window.SvgData, svgData) cursor = self.textEdit.textCursor() - cursor.insertText(u"\uFFFD", svgCharFormat) + cursor.insertText(chr(0xfffc), svgCharFormat) self.textEdit.setTextCursor(cursor) def setupTextObject(self): @@ -102,8 +108,9 @@ class Window(QtWidgets.QWidget): self.fileNameLineEdit = QtWidgets.QLineEdit() insertTextObjectButton = QtWidgets.QPushButton(self.tr("Insert Image")) - self.fileNameLineEdit.setText('./files/heart.svg') - QtCore.QObject.connect(insertTextObjectButton, QtCore.SIGNAL('clicked()'), self.insertTextObject) + file = os.path.join(os.path.dirname(__file__), 'files', 'heart.svg') + self.fileNameLineEdit.setText(file) + insertTextObjectButton.clicked.connect(self.insertTextObject) bottomLayout = QtWidgets.QHBoxLayout() bottomLayout.addWidget(fileNameLabel) -- cgit v1.2.3 From 2298749493084eba1c66546fe3219eab3b1ea1c2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 27 Apr 2021 13:17:37 +0200 Subject: Test bug_686.py: Fix warning about destroying a locked QReadWriteLock Unlock in the threads, fixing warnings: QReadWriteLock: destroying locked QReadWriteLock QReadWriteLock: destroying locked QReadWriteLock Change-Id: I484b7947fdcf241fca069c02ecd9e0ff7c20c151 Reviewed-by: Christian Tismer (cherry picked from commit 8245dd6356dbb0124a7477b16f19e5f031074f85) --- sources/pyside2/tests/QtCore/bug_686.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/pyside2/tests/QtCore/bug_686.py b/sources/pyside2/tests/QtCore/bug_686.py index 6e4f8994a..d944cafe8 100644 --- a/sources/pyside2/tests/QtCore/bug_686.py +++ b/sources/pyside2/tests/QtCore/bug_686.py @@ -49,6 +49,7 @@ class MyWriteThread(QThread): self.started = True while not self.lock.tryLockForWrite(): pass + self.lock.unlock() self.canQuit = True class MyReadThread(QThread): @@ -62,6 +63,7 @@ class MyReadThread(QThread): self.started = True while not self.lock.tryLockForRead(): pass + self.lock.unlock() self.canQuit = True class MyMutexedThread(QThread): -- cgit v1.2.3 From 97852daa226b1f2a432e4a289b37d5eb5a91df44 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 30 Apr 2021 13:31:37 +0200 Subject: Add a testing tool for uic Task-number: PYSIDE-1404 Change-Id: Ie7722933b48228bd5a32c16a0c22f76f6dd37c6c Reviewed-by: Christian Tismer (cherry picked from commit 9dc33d2aa2809efe5548896568907eada85eb3c5) Reviewed-by: Qt Cherry-pick Bot --- tools/uic_test.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tools/uic_test.py diff --git a/tools/uic_test.py b/tools/uic_test.py new file mode 100644 index 000000000..1d1a4c580 --- /dev/null +++ b/tools/uic_test.py @@ -0,0 +1,123 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt for Python project. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import os +import re +import subprocess +import sys +import tempfile +from argparse import ArgumentParser, RawTextHelpFormatter +from pathlib import Path +from textwrap import dedent +from typing import Optional, Tuple + + +VERSION = 6 + + +DESC = """Runs uic on a set of UI files and displays the resulting widgets.""" + + +TEMP_DIR = Path(tempfile.gettempdir()) + + +def get_class_name(file: Path) -> Tuple[Optional[str], Optional[str]]: + """Return class name and widget name of UI file.""" + pattern = re.compile('^\s*.*$') + for l in Path(file).read_text().splitlines(): + match = pattern.match(l) + if match: + return (match.group(1), match.group(2)) + return (None, None) + + +def test_file(file: str, uic: bool=False) -> bool: + """Run uic on a UI file and show the resulting UI.""" + path = Path(file) + (klass, name) = get_class_name(path) + if not klass: + print(f'{file} does not appear to be a UI file', file=sys.stderr) + return False + py_klass = f'Ui_{name}' + py_file_basename = py_klass.lower() + py_file = TEMP_DIR / (py_file_basename + '.py') + py_main = TEMP_DIR / 'main.py' + cmd = ['uic', '-g', 'python'] if uic else [f'pyside{VERSION}-uic'] + cmd.extend(['-o', os.fspath(py_file), file]) + try: + subprocess.call(cmd) + except FileNotFoundError as e: + print(str(e) + " (try -u for uic)", file=sys.stderr) + return False + main_source = dedent(f'''\ + import sys + from PySide{VERSION}.QtWidgets import QApplication, {klass} + from {py_file_basename} import {py_klass} + + if __name__ == "__main__": + app = QApplication(sys.argv) + ui = {py_klass}() + widget = {klass}() + ui.setupUi(widget) + widget.show() + sys.exit(app.exec_())''') + py_main.write_text(main_source) + exit_code = subprocess.call([sys.executable, os.fspath(py_main)]) + py_main.unlink() + py_file.unlink() + return exit_code == 0 + + +if __name__ == '__main__': + argument_parser = ArgumentParser(description=DESC, + formatter_class=RawTextHelpFormatter) + argument_parser.add_argument('--uic', '-u', action='store_true', + help='Use uic instead of pyside-uic') + argument_parser.add_argument("files", help="UI Files", + nargs='+', type=str) + options = argument_parser.parse_args() + failed = 0 + count = len(options.files) + for i, file in enumerate(options.files): + print(f'{i+1}/{count} {file}') + if not test_file(file, options.uic): + failed += 1 + if failed != 0: + print(f'{failed}/{count} failed.') + sys.exit(failed) -- cgit v1.2.3 From 3c977e3fce0ed4920bbc3acba7dfdff647ea4366 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Sun, 2 May 2021 12:27:59 +0200 Subject: Adapt version of the uic testing tool Task-number: PYSIDE-1404 Change-Id: I751af0dbbbfa51bef5231405df03d84e58485e6e Reviewed-by: Christian Tismer --- tools/uic_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/uic_test.py b/tools/uic_test.py index 1d1a4c580..6c1f2b888 100644 --- a/tools/uic_test.py +++ b/tools/uic_test.py @@ -48,7 +48,7 @@ from textwrap import dedent from typing import Optional, Tuple -VERSION = 6 +VERSION = 2 DESC = """Runs uic on a set of UI files and displays the resulting widgets.""" -- cgit v1.2.3 From 8b9cfcb2da0b3a561777de5edf1522865decf48d Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Fri, 30 Apr 2021 15:20:32 +0200 Subject: Property: provide some hopefully exact documentation Task-number: PYSIDE-1513 Change-Id: I5817869aaf495f4005c4fda92d15fceafb15600a Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 6a06abd970bc55ae3439897a7399c3acbfd5d0a7) Reviewed-by: Friedemann Kleint --- sources/pyside2/doc/extras/QtCore.Property.rst | 73 ++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/sources/pyside2/doc/extras/QtCore.Property.rst b/sources/pyside2/doc/extras/QtCore.Property.rst index 8aa629f6b..6bcfc2655 100644 --- a/sources/pyside2/doc/extras/QtCore.Property.rst +++ b/sources/pyside2/doc/extras/QtCore.Property.rst @@ -9,7 +9,9 @@ Detailed Description The Property function lets you declare properties that behave both as Qt and Python properties, and have their -setters and getters defined as Python functions. +getters and setters defined as Python functions. + +They are equivalent to the ``Q_PROPERTY`` macro in the `Qt Docs`_. Here is an example that illustrates how to use this function: @@ -20,14 +22,14 @@ function: from PySide2.QtCore import QObject, Property class MyObject(QObject): - def __init__(self,startval=42): + def __init__(self, startval=42): QObject.__init__(self) self.ppval = startval def readPP(self): return self.ppval - def setPP(self,val): + def setPP(self, val): self.ppval = val pp = Property(int, readPP, setPP) @@ -36,6 +38,68 @@ function: obj.pp = 47 print(obj.pp) +The full options for ``QtCore.Property`` can be found with ``QtCore.Property.__doc__``: + +.. code-block:: + + Property(self, type: type, + fget: Optional[Callable] = None, + fset: Optional[Callable] = None, + freset: Optional[Callable] = None, + fdel: Optional[Callable] = None, + doc: str = '', notify: Optional[Callable] = None, + designable: bool = True, scriptable: bool = True, + stored: bool = True, user: bool = False, + constant: bool = False, final: bool = False) -> PySide2.QtCore.Property + +Normally, only ``type``, ``fget``and ``fset`` are used. + + +Properties compared with Python properties +------------------------------------------ + +``Python`` has property objects very similar to ``QtCore.Property``. +Despite the fact that the latter has an extra ``freset`` function, the usage +of properties is almost the same. The main difference is that ``QtCore.Property`` +requires a ``type`` parameter. + +In the above example, the following lines would be equivalent properties: + +.. code-block:: + + pp = QtCore.Property(int, readPP, setPP) # PySide version + pp = property(readPP, setPP) # Python version + +As you know from the `Python Docs`_, ``Python`` allows to break the property +creation into multiple steps, using the decorator syntax. We can do this in +``PySide`` as well: + +.. code-block:: + :linenos: + + from PySide2.QtCore import QObject, Property + + class MyObject(QObject): + def __init__(self, startval=42): + QObject.__init__(self) + self.ppval = startval + + @Property(int) + def pp(self): + return self.ppval + + @pp.setter + def pp(self, val): + self.ppval = val + + obj = MyObject() + obj.pp = 47 + print(obj.pp) + +Please be careful here: The two ``Python`` functions have the same name, intentionally. +This is needed to let ``Python`` know that these functions belong to the same property. + + Properties in QML expressions ----------------------------- @@ -61,3 +125,6 @@ example illustrating how to do this: pass name = Property(str, _name, notify=name_changed) + +.. _`Python Docs`: https://docs.python.org/3/library/functions.html?highlight=property#property +.. _`Qt Docs`: https://doc.qt.io/qt-5/properties.html -- cgit v1.2.3 From 60681bbda7df61cb42f1411aaeb07a0b5b055fea Mon Sep 17 00:00:00 2001 From: Cristian Maureira-Fredes Date: Tue, 6 Apr 2021 20:29:21 +0200 Subject: doc: make sure '--skip-docs' skip the docs Even when using the code, some portions of the cmake file in sources/pyside6/doc/ was still being executed. This makes sure everything is skipped if we use the '--skip-docs' option when building. Change-Id: If78b19b9650b61b642e447b8c96b814e82994d7c Reviewed-by: Friedemann Kleint (cherry picked from commit fbbae556c9bf060be366fd578986cae85ff8caec) Reviewed-by: Cristian Maureira-Fredes --- build_scripts/main.py | 22 ++++++++++++++-------- sources/pyside2/CMakeLists.txt | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/build_scripts/main.py b/build_scripts/main.py index 86b9cbbbc..461e5a712 100644 --- a/build_scripts/main.py +++ b/build_scripts/main.py @@ -805,6 +805,8 @@ class PysideBuild(_build, DistUtilsCommandMixin): # Add source location for generating documentation cmake_src_dir = OPTION["QT_SRC"] if OPTION["QT_SRC"] else qt_src_dir cmake_cmd.append("-DQT_SRC_DIR={}".format(cmake_src_dir)) + if OPTION['SKIP_DOCS']: + cmake_cmd.append("-DSKIP_DOCS=yes") log.info("Qt Source dir: {}".format(cmake_src_dir)) if self.build_type.lower() == 'debug': @@ -905,15 +907,18 @@ class PysideBuild(_build, DistUtilsCommandMixin): cmake_cmd.append("-DCMAKE_C_COMPILER=cl.exe") cmake_cmd.append("-DCMAKE_CXX_COMPILER=cl.exe") - if OPTION["DOC_BUILD_ONLINE"]: - log.info("Output format will be HTML") - cmake_cmd.append("-DDOC_OUTPUT_FORMAT=html") - else: - log.info("Output format will be qthelp") - cmake_cmd.append("-DDOC_OUTPUT_FORMAT=qthelp") + if not OPTION["SKIP_DOCS"]: + # Build the whole documentation (rst + API) by default + cmake_cmd.append("-DFULLDOCSBUILD=1") - # Build the whole documentation (rst + API) by default - cmake_cmd.append("-DFULLDOCSBUILD=1") + if OPTION["DOC_BUILD_ONLINE"]: + log.info("Output format will be HTML") + cmake_cmd.append("-DDOC_OUTPUT_FORMAT=html") + else: + log.info("Output format will be qthelp") + cmake_cmd.append("-DDOC_OUTPUT_FORMAT=qthelp") + else: + cmake_cmd.append("-DSKIP_DOCS=1") if not OPTION["SKIP_CMAKE"]: log.info("Configuring module {} ({})...".format(extension, module_src_dir)) @@ -951,6 +956,7 @@ class PysideBuild(_build, DistUtilsCommandMixin): log.info("Sphinx not found, skipping documentation build") else: log.info("Skipped documentation generation") + cmake_cmd.append("-DSKIP_DOCS=1") if not OPTION["SKIP_MAKE_INSTALL"]: log.info("Installing module {}...".format(extension)) diff --git a/sources/pyside2/CMakeLists.txt b/sources/pyside2/CMakeLists.txt index dc2beded0..4336d6cc4 100644 --- a/sources/pyside2/CMakeLists.txt +++ b/sources/pyside2/CMakeLists.txt @@ -268,7 +268,7 @@ endif () find_program(SPHINX_BUILD sphinx-build) find_program(DOT_EXEC dot) -if (QT_SRC_DIR AND SPHINX_BUILD AND DOT_EXEC) +if (QT_SRC_DIR AND SPHINX_BUILD AND DOT_EXEC AND NOT SKIP_DOCS) add_subdirectory(doc) else () set(DOCS_TARGET_DISABLED_MESSAGE "apidoc generation targets disabled.") -- cgit v1.2.3 From 967be4ead8781da67b71b177d124764de5fd0aa3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 12 May 2021 16:38:20 +0200 Subject: Fix crash in QCustom3DVolume::setTextureData() Similar to 3a18da91353a71e801658329c55b170c18bcd824, pass an allocated list to the function. [ChangeLog][PySide2] A crash in QCustom3DVolume::setTextureData() has been fixed. Fixes: PYSIDE-1362 Change-Id: I7dddaf7be33b84b89d66378ec61f6a065f6d71be Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit a6dfbb2a72235ecabc7b1d61c085a7d7de3df8d0) --- .../PySide2/QtDataVisualization/typesystem_datavisualization.xml | 8 +++++++- sources/pyside2/PySide2/glue/qtdatavisualization.cpp | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml b/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml index bffb95416..5dc87a013 100644 --- a/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml +++ b/sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml @@ -169,7 +169,13 @@ - + + + + + + diff --git a/sources/pyside2/PySide2/glue/qtdatavisualization.cpp b/sources/pyside2/PySide2/glue/qtdatavisualization.cpp index 542c46054..438829102 100644 --- a/sources/pyside2/PySide2/glue/qtdatavisualization.cpp +++ b/sources/pyside2/PySide2/glue/qtdatavisualization.cpp @@ -23,6 +23,11 @@ Shiboken::Object::releaseOwnership(%PYARG_1); // @snippet releaseownership +// @snippet qcustom3dvolume-settexturedata +using VectorType = decltype(%1); +%CPPSELF.setTextureData(new VectorType(%1)); +// @snippet qcustom3dvolume-settexturedata + // @snippet dataproxy-addrow using VectorType = decltype(%1); %RETURN_TYPE %0 = %CPPSELF.addRow(new VectorType(%1)); -- cgit v1.2.3 From 2641a665fbcf1d0326bde6e4f610e775881f8430 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 May 2021 15:48:11 +0200 Subject: Fix crashes when using the QImage(uchar *) data constructors The constructors expect a range of memory that remains valid through the lifetime of the image and may also modify it. Crashes occurred since apparently the Py_Buffer was released before it. To fix this, add a new buffer helper, copyData() that makes a copy of the data and pass that along with std::free() as cleanup function. Fixes: PYSIDE-1563 Change-Id: Idb09eadea658f02968f75c6bdfc6cc3f467111d5 Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Qt CI Bot (cherry picked from commit cc011c8980cc4ce02e3d9cceb74ee028c204214e) Reviewed-by: Christian Tismer --- sources/pyside2/PySide2/templates/gui_common.xml | 4 ++-- sources/shiboken2/libshiboken/shibokenbuffer.cpp | 23 +++++++++++++++++++++++ sources/shiboken2/libshiboken/shibokenbuffer.h | 8 ++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/sources/pyside2/PySide2/templates/gui_common.xml b/sources/pyside2/PySide2/templates/gui_common.xml index a139a5fe9..16116877f 100644 --- a/sources/pyside2/PySide2/templates/gui_common.xml +++ b/sources/pyside2/PySide2/templates/gui_common.xml @@ -80,8 +80,8 @@