From 10c6e8475588c68b3a613081aba39c5fee01ef18 Mon Sep 17 00:00:00 2001 From: Mariana Meireles Date: Fri, 29 Nov 2019 16:39:38 +0100 Subject: Remove QtScript from missing bindings script Change-Id: I456dbb729992146ca3d2320d0d2416d9d3b41339 Reviewed-by: Cristian Maureira-Fredes --- tools/missing_bindings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/missing_bindings.py b/tools/missing_bindings.py index 850716a2f..a4a418a6e 100644 --- a/tools/missing_bindings.py +++ b/tools/missing_bindings.py @@ -113,7 +113,6 @@ modules_to_test['QtDataVisualization'] = 'qtdatavisualization-module.html' modules_to_test['QtOpenGL'] = 'qtopengl-module.html' modules_to_test['QtPositioning'] = 'qtpositioning-module.html' modules_to_test['QtRemoteObjects'] = 'qtremoteobjects-module.html' -modules_to_test['QtScript'] = 'qtscript-module.html' modules_to_test['QtScriptTools'] = 'qtscripttools-module.html' modules_to_test['QtSensors'] = 'qtsensors-module.html' types_to_ignore = set() -- cgit v1.2.3 From 16daec09be3379f9e3768bddca23cf86f8a1a897 Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 5 Dec 2019 15:41:02 +0100 Subject: Doc: Fix warnings about link targets and indentation Also ensured that all the doc entities are in the toctree so that the navigation breadcrumb is generated. Change-Id: If993cca4c7e91723fa373d3453196bcfee9f3ffa Reviewed-by: Cristian Maureira-Fredes --- sources/pyside2/doc/api.rst | 1 + sources/pyside2/doc/contents.rst | 2 ++ sources/pyside2/doc/deployment-fbs.rst | 2 +- sources/pyside2/doc/extras/QtCore.ClassInfo.rst | 2 +- sources/pyside2/doc/extras/QtCore.Signal.rst | 2 +- sources/pyside2/doc/extras/QtCore.Slot.rst | 2 +- sources/pyside2/doc/gettingstarted-linux.rst | 20 +++++++++----- sources/pyside2/doc/gettingstarted-macOS.rst | 18 ++++++++----- sources/pyside2/doc/gettingstarted-windows.rst | 31 +++++++++++----------- sources/pyside2/doc/index.rst | 9 +++++++ .../pyside2/doc/tutorials/expenses/expenses.rst | 2 +- 11 files changed, 58 insertions(+), 33 deletions(-) diff --git a/sources/pyside2/doc/api.rst b/sources/pyside2/doc/api.rst index 34d065f49..2cc258c75 100644 --- a/sources/pyside2/doc/api.rst +++ b/sources/pyside2/doc/api.rst @@ -1,4 +1,5 @@ .. _pyside-api: + |project| Modules ================= diff --git a/sources/pyside2/doc/contents.rst b/sources/pyside2/doc/contents.rst index 2a6f08266..598a65c92 100644 --- a/sources/pyside2/doc/contents.rst +++ b/sources/pyside2/doc/contents.rst @@ -11,6 +11,8 @@ examples/index.rst videos.rst deployment.rst + licenses.rst + modules.rst considerations.rst shiboken2/index.rst diff --git a/sources/pyside2/doc/deployment-fbs.rst b/sources/pyside2/doc/deployment-fbs.rst index 311c78ac7..0a75f2c4d 100644 --- a/sources/pyside2/doc/deployment-fbs.rst +++ b/sources/pyside2/doc/deployment-fbs.rst @@ -1,7 +1,7 @@ |project| & fbs #################### -`fbs`_ provides a powerful environment for packaging, +``fbs`` provides a powerful environment for packaging, creating installers, and signing your application. It also lets you manage updates to your application. As it is based on PyInstaller, it supports Linux, macOS, and Windows. diff --git a/sources/pyside2/doc/extras/QtCore.ClassInfo.rst b/sources/pyside2/doc/extras/QtCore.ClassInfo.rst index d2267be9c..89ca926c7 100644 --- a/sources/pyside2/doc/extras/QtCore.ClassInfo.rst +++ b/sources/pyside2/doc/extras/QtCore.ClassInfo.rst @@ -1,4 +1,4 @@ -.. module:: PySide2.QtCore +.. currentmodule:: PySide2.QtCore .. _ClassInfo: ClassInfo diff --git a/sources/pyside2/doc/extras/QtCore.Signal.rst b/sources/pyside2/doc/extras/QtCore.Signal.rst index 16c640831..a0660f88f 100644 --- a/sources/pyside2/doc/extras/QtCore.Signal.rst +++ b/sources/pyside2/doc/extras/QtCore.Signal.rst @@ -1,4 +1,4 @@ -.. module:: PySide2.QtCore +.. currentmodule:: PySide2.QtCore .. _Signal: Signal diff --git a/sources/pyside2/doc/extras/QtCore.Slot.rst b/sources/pyside2/doc/extras/QtCore.Slot.rst index 3bc64c03a..5a59a2ae3 100644 --- a/sources/pyside2/doc/extras/QtCore.Slot.rst +++ b/sources/pyside2/doc/extras/QtCore.Slot.rst @@ -1,4 +1,4 @@ -.. module:: PySide2.QtCore +.. currentmodule:: PySide2.QtCore .. _Slot: Slot diff --git a/sources/pyside2/doc/gettingstarted-linux.rst b/sources/pyside2/doc/gettingstarted-linux.rst index fd5b83223..6192ab190 100644 --- a/sources/pyside2/doc/gettingstarted-linux.rst +++ b/sources/pyside2/doc/gettingstarted-linux.rst @@ -4,19 +4,25 @@ Getting Started on Linux Requirements ------------ - * Qt package from `here`_ or a custom build of Qt (preferably Qt 5.12 or greater) + * Qt package from `here`_ or a custom build of Qt (preferably + Qt 5.12 or greater) * A Python interpreter (version Python 3.5+ or Python 2.7). - - * You can use the one provided by your OS, or you can get python from the `official website`_. - * GCC, + You can either use the one provided by your OS, or get it + from the `official website`_. + * GCC * `CMake`_ version 3.1 or greater * Git version 2 or greater - * `libclang_` from your system or from the `precompiled Qt packages`_ is recommended. + * `libclang`_ from your system or the prebuilt version from the + ``Qt Downloads`` page is recommended. * ``virtualenv`` is strongly recommended, but optional. * ``sphinx`` package for the documentation (optional). - * Depending on your OS, other dependencies packages might be required: + * Depending on your linux distribution, the following dependencies might + also be required: - * ``libgl-dev, python-dev, python-distutils, and python-setuptools``. + * ``libgl-dev``, + * ``python-dev``, + * ``python-distutils``, + * and ``python-setuptools``. .. _here: https://qt.io/download .. _official website: https://www.python.org/downloads/ diff --git a/sources/pyside2/doc/gettingstarted-macOS.rst b/sources/pyside2/doc/gettingstarted-macOS.rst index 11305247f..fa6fc6037 100644 --- a/sources/pyside2/doc/gettingstarted-macOS.rst +++ b/sources/pyside2/doc/gettingstarted-macOS.rst @@ -4,19 +4,25 @@ Getting Started on macOS Requirements ------------ - * Qt package from `here`_ or a custom build of Qt (preferably Qt 5.12 or greater) + * Qt package from `here`_ or a custom build of Qt (preferably + Qt 5.12 or greater) * A Python interpreter (version Python 3.5+ or Python 2.7). - - * You can use the one provided by HomeBrew, or you can get python from the `official website`_. + You can use the one provided by HomeBrew, or you can get + python from the `official website`_. * `XCode`_ 8.2 (macOS 10.11), 8.3.3 (macOS 10.12), 9 (macOS 10.13), 10.1 (macOS 10.14) * `CMake`_ version 3.1 or greater * Git version 2 or greater - * `libclang_` from your system or from the `precompiled Qt packages`_ is recommended. + * `libclang`_ from your system or the prebuilt version from the + ``Qt Downloads`` page is recommended. * ``virtualenv`` is strongly recommended, but optional. * ``sphinx`` package for the documentation (optional). - * Depending on your OS, other dependencies packages might be required: + * Depending on your OS, the following dependencies might also + be required: - * ``libgl-dev, python-dev, python-distutils, and python-setuptools``. + * ``libgl-dev``, + * ``python-dev``, + * ``python-distutils``, + * and ``python-setuptools``. .. _XCode: https://developer.apple.com/xcode/ .. _here: https://qt.io/download diff --git a/sources/pyside2/doc/gettingstarted-windows.rst b/sources/pyside2/doc/gettingstarted-windows.rst index dea781545..8de20769e 100644 --- a/sources/pyside2/doc/gettingstarted-windows.rst +++ b/sources/pyside2/doc/gettingstarted-windows.rst @@ -7,27 +7,28 @@ selected when using the online installer. Requirements ------------ - * Qt package from `here`_ or a custom build of Qt (preferably Qt 5.12 or greater) - * A Python interpreter (version Python 3.5+). - - * Preferably get python from the `official website`_. - - .. note:: Python 2.7 interpreter is not supported. - The official Python 2.7 binary package which can be downloaded at - https://www.python.org/downloads/ is built using MSVC 2007, while - the Qt libraries are built using MSVC 2015/2017. - Note that if you build your own custom Python2.7 interpreter with - an MSVC version equivalent to the one that Qt was built with, - you can safely build and use Qt for Python against that interpreter. - + * Qt package from `here`_ or a custom build of Qt (preferably Qt 5.12 + or greater) + * A Python interpreter (version Python 3.5+). Preferably get it + from the `official website`_. * `MSVC2017`_ (or MSVC2019) for Python 3 on Windows, * `CMake`_ version 3.1 or greater * `Git`_ version 2 or greater - * `libclang_` from the `precompiled Qt packages`_ is recommended. - * `OpenSSL`_ (optional for SSL support, Qt must have been configured using the same SSL library) + * `libclang`_ prebuilt version from the + ``Qt Downloads`` page is recommended. + * `OpenSSL`_ (optional for SSL support, Qt must have been + configured using the same SSL library). * ``virtualenv`` is strongly recommended, but optional. * ``sphinx`` package for the documentation (optional). +.. note:: Python 2.7 interpreter is not supported. + The official Python 2.7 binary package offerred on the + `official website`_ is built using MSVC 2007, while + the Qt libraries are built using MSVC 2015/2017. + If you intend to use Python 2.7, build the interpreter yourself + with MSVC 2015 or later, and build Qt for Python with it. + + .. _here: https://qt.io/download .. _official website: https://www.python.org/downloads/ .. _MSVC2017: https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools diff --git a/sources/pyside2/doc/index.rst b/sources/pyside2/doc/index.rst index 5ffe405a5..93e3451c5 100644 --- a/sources/pyside2/doc/index.rst +++ b/sources/pyside2/doc/index.rst @@ -40,3 +40,12 @@ Documentation

Shiboken
Generate C++ to Python binding.

+ +.. toctree:: + :hidden: + :glob: + + contents.rst + gettingstarted* + pyside-examples/pyside2examples* + overviews/* diff --git a/sources/pyside2/doc/tutorials/expenses/expenses.rst b/sources/pyside2/doc/tutorials/expenses/expenses.rst index a19cec5c3..f643ec299 100644 --- a/sources/pyside2/doc/tutorials/expenses/expenses.rst +++ b/sources/pyside2/doc/tutorials/expenses/expenses.rst @@ -32,7 +32,7 @@ The base structure for a `QApplication` is located inside the `if __name__ == "_ code block. .. code-block:: python - :dedent: 4 + :linenos: if __name__ == "__main__": app = QApplication([]) -- cgit v1.2.3 From f9fc573a6ee7ccd9a436fbe55fdbf7d4e83a6248 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 18 Apr 2019 15:50:06 +0200 Subject: Add better error handling to debug windows python script Change-Id: Ibc5171cf94ef819cf7926b899b83cc9de3037d07 Reviewed-by: Christian Tismer Reviewed-by: Friedemann Kleint --- tools/debug_windows.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/debug_windows.py b/tools/debug_windows.py index ab1c03aba..02e00a504 100644 --- a/tools/debug_windows.py +++ b/tools/debug_windows.py @@ -154,17 +154,22 @@ def get_installed_windows_kits(): roots_key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots" log.info("Searching for Windows kits in registry path: " "{}".format(roots_key)) - roots = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, roots_key, 0, - winreg.KEY_READ) + kits = [] pattern = re.compile(r'KitsRoot(\d+)') - - for (name, value, value_type) in sub_values(roots): - if value_type == winreg.REG_SZ and name.startswith('KitsRoot'): - match = pattern.search(name) - if match: - version = match.group(1) - kits.append({'version': version, 'value': value}) + try: + roots = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, roots_key, 0, + winreg.KEY_READ) + + for (name, value, value_type) in sub_values(roots): + if value_type == winreg.REG_SZ and name.startswith('KitsRoot'): + match = pattern.search(name) + if match: + version = match.group(1) + kits.append({'version': version, 'value': value}) + + except WindowsError as e: + log.exception(e) if not kits: log.error(dedent(""" -- cgit v1.2.3 From 4b908a86dfae0a0be53e25d8a3357e2de7dd98e0 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 9 Dec 2019 15:19:39 +0100 Subject: Fix tools\debug_windows.py to properly display possible error snippets The check in find_error_like_snippets was incorrect, and thus never showed any snippets. Change-Id: Ie8d487b071e73c6f4a1352e9b10e616694b2e237 Reviewed-by: Friedemann Kleint --- tools/debug_windows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/debug_windows.py b/tools/debug_windows.py index 02e00a504..dbde5f534 100644 --- a/tools/debug_windows.py +++ b/tools/debug_windows.py @@ -268,7 +268,7 @@ def find_error_like_snippets(content): ('ERROR: Module load completed but symbols could ' 'not be loaded')} return (re.search('error', l, re.IGNORECASE) - and all(e not in errors for e in errors)) + and all(e not in l for e in errors)) for i in range(1, len(lines)): line = lines[i] -- cgit v1.2.3 From 8666fa17248fedee262c0d08d6edc12e8c537769 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Dec 2019 10:06:06 +0100 Subject: libshiboken/introduceWrapperType(): Emit warning on failures Emit a warning when PyModule_AddObject(), SbkSpecial_Type_Ready() fail, which can happen when passing the wrong parent. Task-number: PYSIDE-454 Change-Id: I0c2da7292dc0a354c58a21bf4a1df9d350d15ab6 Reviewed-by: Christian Tismer --- sources/shiboken2/libshiboken/basewrapper.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index dd5dc43e9..c4b640900 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -58,6 +58,8 @@ #include "qapp_macro.h" #include "voidptr.h" +#include + #if defined(__APPLE__) #include #endif @@ -917,8 +919,11 @@ introduceWrapperType(PyObject *enclosingObject, } } // PYSIDE-510: Here is the single change to support signatures. - if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast(type), signatureStrings) < 0) + if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast(type), signatureStrings) < 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to SbkSpecial_Type_Ready() failing\n"; return nullptr; + } initPrivateData(type); auto sotp = PepType_SOTP(type); @@ -934,7 +939,13 @@ introduceWrapperType(PyObject *enclosingObject, // PyModule_AddObject steals type's reference. Py_INCREF(ob_type); - return PyModule_AddObject(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; + if (PyModule_AddObject(enclosingObject, typeName, ob_type) != 0) { + std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " + << typeName << '/' << originalName << " due to PyModule_AddObject(enclosingObject=" + << enclosingObject << ",ob_type=" << ob_type << ") failing\n"; + return nullptr; + } + return type; } void setSubTypeInitHook(SbkObjectType *type, SubTypeInitHook func) -- cgit v1.2.3 From fd5768da8cc90faaa5a96c1c028db62915c18b0f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Dec 2019 12:58:23 +0100 Subject: shiboken: Refactor the generated getattro()-method Remove else after return and simplify accordingly. Replace the check for self by an assert. Change-Id: I219e4887f0a699c21f718563ac696baf4c7f9d73 Reviewed-by: Christian Tismer --- .../shiboken2/generator/shiboken2/cppgenerator.cpp | 132 +++++++++------------ 1 file changed, 57 insertions(+), 75 deletions(-) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 80c0f5a37..45ec619ef 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -5270,6 +5270,7 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, GeneratorContext &conte const AbstractMetaClass *metaClass = context.metaClass(); s << "static PyObject *" << cpythonGetattroFunctionName(metaClass) << "(PyObject *self, PyObject *name)\n{\n"; + s << INDENT << "assert(self);\n"; QString getattrFunc; if (usePySideExtensions() && metaClass->isQObject()) { @@ -5278,112 +5279,93 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, GeneratorContext &conte << cpythonWrapperCPtr(qobjectClass, QLatin1String("self")) << ", self, name)"; } else { - getattrFunc = QLatin1String("PyObject_GenericGetAttr(") + QLatin1String("self") - + QLatin1String(", name)"); + getattrFunc = QLatin1String("PyObject_GenericGetAttr(self, name)"); } if (classNeedsGetattroFunction(metaClass)) { - s << INDENT << "if (self) {\n"; + s << INDENT << "// Search the method in the instance dict\n"; + s << INDENT << "if (auto ob_dict = reinterpret_cast(self)->ob_dict) {\n"; { Indentation indent(INDENT); - s << INDENT << "// Search the method in the instance dict\n"; - s << INDENT << "if (reinterpret_cast(self)->ob_dict) {\n"; + s << INDENT << "if (auto meth = PyDict_GetItem(ob_dict, name)) {\n"; { Indentation indent(INDENT); - s << INDENT << "PyObject *meth = PyDict_GetItem(reinterpret_cast(self)->ob_dict, name);\n"; - s << INDENT << "if (meth) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "Py_INCREF(meth);\n"; - s << INDENT << "return meth;\n"; - } - s << INDENT << "}\n"; + s << INDENT << "Py_INCREF(meth);\n"; + s << INDENT << "return meth;\n"; } s << INDENT << "}\n"; - s << INDENT << "// Search the method in the type dict\n"; - s << INDENT << "if (Shiboken::Object::isUserType(self)) {\n"; + } + s << INDENT << "}\n"; + s << INDENT << "// Search the method in the type dict\n"; + s << INDENT << "if (Shiboken::Object::isUserType(self)) {\n"; + { + Indentation indent(INDENT); + // PYSIDE-772: Perform optimized name mangling. + s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));\n"; + s << INDENT << "if (auto meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp))\n"; { Indentation indent(INDENT); - // PYSIDE-772: Perform optimized name mangling. - s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));\n"; - s << INDENT << "PyObject *meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp);\n"; - s << INDENT << "if (meth)\n"; - { - Indentation indent(INDENT); - s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, self) : " << getattrFunc << ";\n"; - } + s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, self) : " << getattrFunc << ";\n"; } - s << INDENT << "}\n"; + } + s << INDENT << "}\n"; - const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass); - for (const AbstractMetaFunction *func : funcs) { - QString defName = cpythonMethodDefinitionName(func); - s << INDENT << "static PyMethodDef non_static_" << defName << " = {\n"; - { - Indentation indent(INDENT); - s << INDENT << defName << ".ml_name,\n"; - s << INDENT << defName << ".ml_meth,\n"; - s << INDENT << defName << ".ml_flags & (~METH_STATIC),\n"; - s << INDENT << defName << ".ml_doc,\n"; - } - s << INDENT << "};\n"; - s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)\n"; + const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass); + for (const AbstractMetaFunction *func : funcs) { + QString defName = cpythonMethodDefinitionName(func); + s << INDENT << "static PyMethodDef non_static_" << defName << " = {\n"; + { Indentation indent(INDENT); - s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);\n"; + s << INDENT << defName << ".ml_name,\n"; + s << INDENT << defName << ".ml_meth,\n"; + s << INDENT << defName << ".ml_flags & (~METH_STATIC),\n"; + s << INDENT << defName << ".ml_doc,\n"; } + s << INDENT << "};\n"; + s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)\n"; + Indentation indent(INDENT); + s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);\n"; } - s << INDENT << "}\n"; } if (context.forSmartPointer()) { s << INDENT << "PyObject *tmp = " << getattrFunc << ";\n"; - s << INDENT << "if (tmp) {\n"; + s << INDENT << "if (tmp)\n"; { Indentation indent(INDENT); s << INDENT << "return tmp;\n"; } - s << INDENT << "} else {\n"; + s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError))\n"; { Indentation indent(INDENT); - s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return nullptr;\n"; - s << INDENT << "PyErr_Clear();\n"; - - s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for " - "the corresponding C++ object held by the smart pointer.\n"; - s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, " - << writeSmartPointerGetterCast() << ", 0);\n"; - s << INDENT << "if (rawObj) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "PyObject *attribute = PyObject_GetAttr(rawObj, name);\n"; - s << INDENT << "if (attribute) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "tmp = attribute;\n"; - } - s << INDENT << "}\n"; - s << INDENT << "Py_DECREF(rawObj);\n"; - } - s << INDENT << "}\n"; - s << INDENT << "if (!tmp) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "PyTypeObject *tp = Py_TYPE(self);\n"; - s << INDENT << "PyErr_Format(PyExc_AttributeError,\n"; - s << INDENT << " \"'%.50s' object has no attribute '%.400s'\",\n"; - s << INDENT << " tp->tp_name, Shiboken::String::toCString(name));\n"; - s << INDENT << "return nullptr;\n"; - } - s << INDENT << "} else {\n"; + s << INDENT << "return nullptr;\n"; + } + s << INDENT << "PyErr_Clear();\n"; + + s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for " + "the corresponding C++ object held by the smart pointer.\n"; + s << INDENT << "if (auto rawObj = PyObject_CallMethod(self, " + << writeSmartPointerGetterCast() << ", 0)) {\n"; + { + Indentation indent(INDENT); + s << INDENT << "if (auto attribute = PyObject_GetAttr(rawObj, name))\n"; { Indentation indent(INDENT); - s << INDENT << "return tmp;\n"; + s << INDENT << "tmp = attribute;\n"; } - s << INDENT << "}\n"; - + s << INDENT << "Py_DECREF(rawObj);\n"; } s << INDENT << "}\n"; - + s << INDENT << "if (!tmp) {\n"; + { + Indentation indent(INDENT); + s << INDENT << "PyTypeObject *tp = Py_TYPE(self);\n"; + s << INDENT << "PyErr_Format(PyExc_AttributeError,\n"; + s << INDENT << " \"'%.50s' object has no attribute '%.400s'\",\n"; + s << INDENT << " tp->tp_name, Shiboken::String::toCString(name));\n"; + } + s << INDENT << "}\n"; + s << INDENT << "return tmp;\n"; } else { s << INDENT << "return " << getattrFunc << ";\n"; } -- cgit v1.2.3 From fbe8ed964094b36d807a70d26dd3906f16b65040 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Dec 2019 10:40:26 +0100 Subject: shiboken: Test setters/getters of classes held by smart pointers Add a setter/getter to the pointee. Task-number: PYSIDE-454 Change-Id: Ia6978300846ff82d8061df9f27c3fbd0c8e71b2f Reviewed-by: Christian Tismer --- sources/shiboken2/tests/libsmart/smart.cpp | 16 +++++++++++++--- sources/shiboken2/tests/libsmart/smart_integer.h | 8 ++++++-- sources/shiboken2/tests/libsmart/smart_obj.h | 2 +- .../shiboken2/tests/smartbinding/smart_pointer_test.py | 4 ++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp index 6a4deb50a..a426f0f41 100644 --- a/sources/shiboken2/tests/libsmart/smart.cpp +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -93,7 +93,7 @@ Obj::~Obj() void Obj::printObj() { if (shouldPrint()) { std::cout << "integer value: " << m_integer - << " internal integer value: " << m_internalInteger->m_int << '\n'; + << " internal integer value: " << m_internalInteger->value() << '\n'; } } @@ -134,7 +134,7 @@ int Obj::takeSharedPtrToObj(SharedPtr pObj) int Obj::takeSharedPtrToInteger(SharedPtr pInt) { pInt->printInteger(); - return pInt->m_int; + return pInt->value(); } Integer Obj::takeInteger(Integer val) @@ -173,7 +173,17 @@ Integer::~Integer() std::cout << "Integer destructor " << this << '\n'; } -void Integer::printInteger() +int Integer::value() const +{ + return m_int; +} + +void Integer::setValue(int v) +{ + m_int = v; +} + +void Integer::printInteger() const { if (shouldPrint()) std::cout << "Integer value for object " << this << " is " << m_int << '\n'; diff --git a/sources/shiboken2/tests/libsmart/smart_integer.h b/sources/shiboken2/tests/libsmart/smart_integer.h index 3756f68b0..126894120 100644 --- a/sources/shiboken2/tests/libsmart/smart_integer.h +++ b/sources/shiboken2/tests/libsmart/smart_integer.h @@ -37,8 +37,12 @@ public: Integer(const Integer &other); Integer &operator=(const Integer &other); ~Integer(); - void printInteger(); - int m_int; + void printInteger() const; + + int value() const; + void setValue(int v); + + int m_int; // public for testing member field access. }; namespace Smart { diff --git a/sources/shiboken2/tests/libsmart/smart_obj.h b/sources/shiboken2/tests/libsmart/smart_obj.h index 12425366e..18c085ae2 100644 --- a/sources/shiboken2/tests/libsmart/smart_obj.h +++ b/sources/shiboken2/tests/libsmart/smart_obj.h @@ -53,7 +53,7 @@ public: int takeSharedPtrToObj(SharedPtr pObj); int takeSharedPtrToInteger(SharedPtr pInt); - int m_integer; + int m_integer; // public for testing member field access. Integer *m_internalInteger; }; diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py index e1883c7cc..5f8840b23 100644 --- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py @@ -116,6 +116,10 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(integer.m_int, 50) # Set and get a member value via shared pointer (like operator->). + ptrToInteger.setValue(150) + self.assertEqual(ptrToInteger.value(), 150) + + # Set and get a member field via shared pointer (like operator->). ptrToInteger.m_int = 100 self.assertEqual(ptrToInteger.m_int, 100) -- cgit v1.2.3 From 642158e998b33cfc20ec93fd2b73234d7c79deb2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 11 Dec 2019 10:20:49 +0100 Subject: shiboken: Improve error message about not finding smart pointers List target lang name and C++ name. Task-number: PYSIDE-454 Change-Id: Ie3d17dd3cc2ed0334f032e9a918fb1930e8ae61f Reviewed-by: Christian Tismer --- sources/shiboken2/ApiExtractor/messages.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 546e9c4ed..d4cf53efe 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -334,8 +334,10 @@ QString msgCannotFindSmartPointer(const QString &instantiationType, QString result; QTextStream str(&result); str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; - for (auto t : pointers) - str << ' ' << t->fullName(); + for (auto t : pointers) { + auto typeEntry = t->typeEntry(); + str << ' ' << typeEntry->targetLangName() << '/' << typeEntry->qualifiedCppName(); + } str << ")."; return result; } -- cgit v1.2.3 From 518cb58a5417ff6e5f7690da02714036c127c56d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Dec 2019 09:17:58 +0100 Subject: shiboken: Do not generate smart pointer templates in namespaces std::shared_ptr would cause a wrapper to be generated within std. Task-number: PYSIDE-454 Change-Id: Id370d74fce6aaa0a3dddfa511b9373a95a39f373 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 45ec619ef..57b643f9a 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -343,7 +343,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); for (AbstractMetaClass *innerClass : innerClasses) { GeneratorContext innerClassContext(innerClass); - if (shouldGenerate(innerClass)) { + if (shouldGenerate(innerClass) && !innerClass->typeEntry()->isSmartPointer()) { QString headerfile = fileNameForContext(innerClassContext); headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); s << "#include \"" << headerfile << "\"\n"; -- cgit v1.2.3 From 0ffb486e27996bbd81cde5f3d73b2d8346386ffb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 11 Dec 2019 10:26:10 +0100 Subject: shiboken: Add explanatory comment to getattro function Make it clear how the dispatch works. Task-number: PYSIDE-454 Change-Id: Idd98eee5a7f7d45891c8a7dd0170f9188f136296 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 57b643f9a..eaa9fe8c4 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -5342,6 +5342,8 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, GeneratorContext &conte } s << INDENT << "PyErr_Clear();\n"; + // This generates the code which dispatches access to member functions + // and fields from the smart pointer to its pointee. s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for " "the corresponding C++ object held by the smart pointer.\n"; s << INDENT << "if (auto rawObj = PyObject_CallMethod(self, " -- cgit v1.2.3 From 2cfa859283355f7710b5fcd56b948a149d12032a Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 12 Dec 2019 09:20:27 +0100 Subject: Shiboken: QtDoc: Fix the fancy TOC in the module index page The TOC groups the classes alphabetically, ignoring the 'Q' prefix at the beginning. It did not consider classes without the 'Q' prefix, such as Signal and Slot in the QtCore module. The else block should handle that as well now. Change-Id: I0fc22ba86650299de924d22c970d6fe6e31567c3 Reviewed-by: Friedemann Kleint --- sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index ca9f9b3ae..9c9a2ff1e 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -2119,6 +2119,9 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 continue; if (item.startsWith(Q) && item.length() > 1) idx = item[1]; + else + idx = item[0]; // To group classes without the 'Q' prefix + item.chop(4); // Remove the .rst extension tocMap[idx] << item; } -- cgit v1.2.3 From df1e8c4670c04f1c9b83845e21edaab98d34c5e8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 11 Dec 2019 14:35:57 +0100 Subject: shiboken: Handle smart pointers with const pointees Treat them equally to smart pointers with non-const pointees by searching for the pointee type entry in the instantiation search and stripping the const there. Create an additional type index equal to the non-const pointee index for the const pointee instantiation. This has the slight drawback that it is possible to invoke non-const calls on the pointee in Python, but this is nearly unfixable since the dispatch happens in the getattro method, where the information about constness is lost. Task-number: PYSIDE-454 Change-Id: Ib514816e408d727656b1599060e105ccd021bb07 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/generator/generator.cpp | 47 ++++++++++++++++------ .../generator/shiboken2/headergenerator.cpp | 12 +++++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index b14edfc4c..585102b01 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -159,7 +159,6 @@ struct Generator::GeneratorPrivate QString licenseComment; QString moduleName; QStringList instantiatedContainersNames; - QStringList instantiatedSmartPointerNames; QVector instantiatedContainers; QVector instantiatedSmartPointers; @@ -211,6 +210,31 @@ QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType *type) return typeName; } +// Strip a "const QSharedPtr &" or similar to "QSharedPtr" (PYSIDE-1016/454) +const AbstractMetaType *canonicalSmartPtrInstantiation(const AbstractMetaType *type) +{ + AbstractMetaTypeList instantiations = type->instantiations(); + Q_ASSERT(instantiations.size() == 1); + const bool needsFix = type->isConstant() || type->referenceType() != NoReference; + const bool pointeeNeedsFix = instantiations.constFirst()->isConstant(); + if (!needsFix && !pointeeNeedsFix) + return type; + auto fixedType = type->copy(); + fixedType->setReferenceType(NoReference); + fixedType->setConstant(false); + if (pointeeNeedsFix) { + auto fixedPointeeType = instantiations.constFirst()->copy(); + fixedPointeeType->setConstant(false); + fixedType->setInstantiations(AbstractMetaTypeList(1, fixedPointeeType)); + } + return fixedType; +} + +static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType *smartPtrType) +{ + return smartPtrType->instantiations().constFirst()->typeEntry(); +} + void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, const QString &context) { @@ -244,18 +268,15 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType m_d->instantiatedContainers.append(type); } } else { - // Is smart pointer. - if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { - m_d->instantiatedSmartPointerNames.append(typeName); - if (type->isConstant() || type->referenceType() != NoReference) { - // Strip a "const QSharedPtr &" or similar to "QSharedPtr" (PYSIDE-1016) - auto fixedType = type->copy(); - fixedType->setReferenceType(NoReference); - fixedType->setConstant(false); - type = fixedType; - } - m_d->instantiatedSmartPointers.append(type); - } + // Is smart pointer. Check if the (const?) pointee is already known + auto pt = pointeeTypeEntry(type); + const bool present = + std::any_of(m_d->instantiatedSmartPointers.cbegin(), m_d->instantiatedSmartPointers.cend(), + [pt] (const AbstractMetaType *t) { + return pointeeTypeEntry(t) == pt; + }); + if (!present) + m_d->instantiatedSmartPointers.append(canonicalSmartPtrInstantiation(type)); } } diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index cf96c8d5c..a565659de 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -401,9 +401,17 @@ bool HeaderGenerator::finishGeneration() int smartPointerCount = 0; const QVector &instantiatedSmartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType), - smartPointerCountIndex); + QString indexName = getTypeIndexVariableName(metaType); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); macrosStream << ", // " << metaType->cppSignature() << Qt::endl; + // Add a the same value for const pointees (shared_ptr). + const auto ptrName = metaType->typeEntry()->entryName(); + int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive); + if (pos >= 0) { + indexName.insert(pos + ptrName.size() + 1, QLatin1String("CONST")); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // (const)\n"; + } ++smartPointerCountIndex; ++smartPointerCount; } -- cgit v1.2.3 From 0a078ecb1522b50dc7cc2f3512fcd7251edb4e00 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Dec 2019 15:15:11 +0100 Subject: Add a test for a Smartptr Task-number: PYSIDE-454 Change-Id: I8d362e50c742b79ae7239c3c3576310c96bf5554 Reviewed-by: Qt CI Bot Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/tests/libsmart/smart.cpp | 11 +++++++++++ sources/shiboken2/tests/libsmart/smart_obj.h | 2 ++ sources/shiboken2/tests/smartbinding/smart_pointer_test.py | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp index a426f0f41..81fa30c7e 100644 --- a/sources/shiboken2/tests/libsmart/smart.cpp +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -137,6 +137,17 @@ int Obj::takeSharedPtrToInteger(SharedPtr pInt) return pInt->value(); } +SharedPtr Obj::giveSharedPtrToConstInteger() +{ + SharedPtr co(new Integer); + return co; +} + +int Obj::takeSharedPtrToConstInteger(SharedPtr pInt) +{ + return pInt->m_int; +} + Integer Obj::takeInteger(Integer val) { return val; diff --git a/sources/shiboken2/tests/libsmart/smart_obj.h b/sources/shiboken2/tests/libsmart/smart_obj.h index 18c085ae2..e5709a071 100644 --- a/sources/shiboken2/tests/libsmart/smart_obj.h +++ b/sources/shiboken2/tests/libsmart/smart_obj.h @@ -49,6 +49,8 @@ public: SharedPtr giveSharedPtrToObj(); std::vector > giveSharedPtrToObjList(int size); SharedPtr giveSharedPtrToInteger(); + SharedPtr giveSharedPtrToConstInteger(); + int takeSharedPtrToConstInteger(SharedPtr pInt); SharedPtr giveSharedPtrToInteger2(); int takeSharedPtrToObj(SharedPtr pObj); int takeSharedPtrToInteger(SharedPtr pInt); diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py index 5f8840b23..6c4c2c8e9 100644 --- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py @@ -147,6 +147,18 @@ class SmartPointerTests(unittest.TestCase): self.assertEqual(objCount(), 0) self.assertEqual(integerCount(), 0) + def testConstIntegerSmartPointer(self): + # Uncomment to see more debug info about creation of objects and ref counts. + # Registry.getInstance().setShouldPrint(True) + + # Create Obj. + o = Obj() + ptrToConstInteger = o.giveSharedPtrToConstInteger() + self.assertEqual(ptrToConstInteger.m_int, 456) + result = o.takeSharedPtrToConstInteger(ptrToConstInteger) + self.assertEqual(result, 456) + self.assertEqual(ptrToConstInteger.value(), 456) + def testSmartPointersWithNamespace(self): # Create the main object o = Obj() -- cgit v1.2.3 From a0ed5a2a8cc92209440de755953ca1745aa1d6fa Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 11 Dec 2019 15:45:32 +0100 Subject: shiboken: Remove unused code Remove unused function _compareAbstractMetaFunctions() and type system types dating back to Java. Change-Id: Ica8ac020962edb82d4a7e030ff74795c8e599481 Reviewed-by: Christian Tismer --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 30 ---------------------- sources/shiboken2/ApiExtractor/typesystem.h | 30 ---------------------- 2 files changed, 60 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 312f72523..1adbb52d4 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -550,11 +550,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!entry->isPrimitive()) { if ((entry->isValue() || entry->isObject()) && !types->shouldDropTypeEntry(entry->qualifiedCppName()) - && !entry->isString() - && !entry->isChar() && !entry->isContainer() && !entry->isCustom() - && !entry->isVariant() && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken).noquote().nospace() @@ -1294,33 +1291,6 @@ static bool _compareAbstractMetaTypes(const AbstractMetaType *type, && (type == nullptr || type->compare(*other, flags)); } -static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, - const AbstractMetaFunction *other, - AbstractMetaType::ComparisonFlags argumentFlags = {}) -{ - if (!func && !other) - return true; - if (!func || !other) - return false; - if (func->name() != other->name()) - return false; - const int argumentsCount = func->arguments().count(); - if (argumentsCount != other->arguments().count() - || func->isConstant() != other->isConstant() - || func->isStatic() != other->isStatic() - || !_compareAbstractMetaTypes(func->type(), other->type())) { - return false; - } - for (int i = 0; i < argumentsCount; ++i) { - if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), - other->arguments().at(i)->type(), - argumentFlags)) { - return false; - } - } - return true; -} - AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass::Attributes *constructorAttributes, AbstractMetaClass *currentClass) diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 0cbcc9c25..8e155eb60 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -562,20 +562,14 @@ public: EnumValue, ConstantValueType, TemplateArgumentType, - ThreadType, BasicValueType, - StringType, ContainerType, InterfaceType, ObjectType, NamespaceType, - VariantType, - JObjectWrapperType, - CharType, ArrayType, TypeSystemType, CustomType, - TargetLangType, FunctionType, SmartPointerType, TypedefType @@ -629,14 +623,6 @@ public: { return m_type == ObjectType; } - bool isString() const - { - return m_type == StringType; - } - bool isChar() const - { - return m_type == CharType; - } bool isNamespace() const { return m_type == NamespaceType; @@ -649,14 +635,6 @@ public: { return m_type == SmartPointerType; } - bool isVariant() const - { - return m_type == VariantType; - } - bool isJObjectWrapper() const - { - return m_type == JObjectWrapperType; - } bool isArray() const { return m_type == ArrayType; @@ -673,18 +651,10 @@ public: { return m_type == VarargsType; } - bool isThread() const - { - return m_type == ThreadType; - } bool isCustom() const { return m_type == CustomType; } - bool isBasicValue() const - { - return m_type == BasicValueType; - } bool isTypeSystem() const { return m_type == TypeSystemType; -- cgit v1.2.3 From fb628016895e59cd5adf617281b2b75b26bf3378 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Thu, 12 Dec 2019 13:01:12 +0100 Subject: Finalize the Python 3.8 refcount fix This is a final optimization to the Py_TPFLAGS_METHOD_DESCRIPTOR fix. Instead of keeping the mro method alive, we are caching it's type only, because that is what we need to patch. Another effort to solve this problem completely has failed, again. This solution is good enough and has no time penalty. Task-number: PYSIDE-939 Change-Id: I98c165f9cd704b0f6ce55750189d6bda9a811f70 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/libshiboken/basewrapper.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index dd5dc43e9..3c861c761 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -505,12 +505,14 @@ PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *k // PYSIDE-939: This is a temporary patch that circumvents the problem // with Py_TPFLAGS_METHOD_DESCRIPTOR until this is finally solved. - PyObject *ob_PyType_Type = reinterpret_cast(&PyType_Type); - static PyObject *mro = PyObject_GetAttr(ob_PyType_Type, Shiboken::PyName::mro()); - auto hold = Py_TYPE(mro)->tp_flags; - Py_TYPE(mro)->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR; + // PyType_Ready uses mro(). We need to temporarily remove the flag from it's type. + // We cannot use PyMethodDescr_Type since it is not exported by Python 2.7 . + static PyTypeObject *PyMethodDescr_TypePtr = Py_TYPE( + PyObject_GetAttr(reinterpret_cast(&PyType_Type), Shiboken::PyName::mro())); + auto hold = PyMethodDescr_TypePtr->tp_flags; + PyMethodDescr_TypePtr->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR; auto *newType = reinterpret_cast(type_new(metatype, args, kwds)); - Py_TYPE(mro)->tp_flags = hold; + PyMethodDescr_TypePtr->tp_flags = hold; if (!newType) return nullptr; -- cgit v1.2.3 From 486af85cee90e81424f6e5293a399fc308eee7b3 Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 12 Dec 2019 09:41:38 +0100 Subject: Doc: Document the Property function in QtCore The content for this lived on the wiki till now. Change-Id: I3e6a2cb7f97ab7021621b7c687299a3199134bb5 Reviewed-by: Friedemann Kleint Reviewed-by: Cristian Maureira-Fredes --- sources/pyside2/doc/extras/QtCore.Property.rst | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 sources/pyside2/doc/extras/QtCore.Property.rst diff --git a/sources/pyside2/doc/extras/QtCore.Property.rst b/sources/pyside2/doc/extras/QtCore.Property.rst new file mode 100644 index 000000000..209704c46 --- /dev/null +++ b/sources/pyside2/doc/extras/QtCore.Property.rst @@ -0,0 +1,62 @@ +.. currentmodule:: PySide2.QtCore +.. _Property: +Property +******** + +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. + +Here is an example that illustrates how to use this +function: + +.. code-block:: + :linenos: + +from PySide2.QtCore import QObject, Property + +class MyObject(QObject): + def __init__(self,startval=42): + QObject.__init__(self) + self.ppval = startval + + def readPP(self): + return self.ppval + + def setPP(self,val): + self.ppval = val + + pp = Property(int, readPP, setPP) + +obj = MyObject() +obj.pp = 47 +print(obj.pp) + +Properties in QML expressions +----------------------------- + +If you are using properties of your objects in QML expressions, +QML requires that the property changes are notified. Here is an +example illustrating how to do this: + +.. code-block:: + :linenos: + +from PySide2.QtCore import QObject, Signal, Property + +class Person(QObject): + def __init__(self, name): + QObject.__init__(self) + self._person_name = name + + def _name(self): + return self._person_name + + @Signal + def name_changed(self): + pass + + name = Property(str, _name, notify=name_changed) -- cgit v1.2.3 From bbf9de174c92c1c7813d6e9f6320f40a21080df2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 12 Dec 2019 09:59:35 +0100 Subject: shiboken/TypeDatabase: Add a look up for names excluding inline namespaces Ensure for example the std::shared_ptr of AppleClang STL is found which is in an inline namespace std::__1. Add a shortName() to TypeEntry to represent the name and add lookups for it to the TypeDatabase once an inline namespace is traversed. Task-number: PYSIDE-454 Task-number: PYSIDE-990 Change-Id: I21d86ba3a77926d0910f11201cbd8978c13ca705 Reviewed-by: Cristian Maureira-Fredes --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 6 ++- sources/shiboken2/ApiExtractor/typedatabase.cpp | 43 ++++++++++++++++++++++ sources/shiboken2/ApiExtractor/typedatabase.h | 4 +- sources/shiboken2/ApiExtractor/typesystem.cpp | 9 +++++ sources/shiboken2/ApiExtractor/typesystem.h | 6 ++- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 1adbb52d4..f6c9e407c 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -755,7 +755,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName); return nullptr; } - type->setInlineNamespace(namespaceItem->type() == NamespaceType::Inline); + + if (namespaceItem->type() == NamespaceType::Inline) { + type->setInlineNamespace(true); + TypeDatabase::instance()->addInlineNamespaceLookups(type); + } // Continue populating namespace? AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 659a69922..c952f7b0e 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -149,6 +149,20 @@ void TypeDatabase::addSystemInclude(const QString &name) m_systemIncludes.append(name.toUtf8()); } +// Add a lookup for the short name excluding inline namespaces +// so that "std::shared_ptr" finds "std::__1::shared_ptr" as well. +// Note: This inserts duplicate TypeEntry * into m_entries. +void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n) +{ + QVector additionalEntries; // Store before modifying the hash + for (TypeEntry *entry : m_entries) { + if (entry->isChildOf(n)) + additionalEntries.append(entry); + } + for (const auto &ae : additionalEntries) + m_entries.insert(ae->shortName(), ae); +} + ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const { QString template_name = name; @@ -703,6 +717,35 @@ static void _computeTypeIndexes() computeTypeIndexes = false; } +// Build the C++ name excluding any inline namespaces +// ("std::__1::shared_ptr" -> "std::shared_ptr" +QString TypeEntry::shortName() const +{ + if (m_cachedShortName.isEmpty()) { + QVarLengthArray parents; + bool foundInlineNamespace = false; + for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { + if (p->type() == TypeEntry::NamespaceType + && static_cast(p)->isInlineNamespace()) { + foundInlineNamespace = true; + } else { + parents.append(p); + } + } + if (foundInlineNamespace) { + m_cachedShortName.reserve(m_name.size()); + for (int i = parents.size() - 1; i >= 0; --i) { + m_cachedShortName.append(parents.at(i)->entryName()); + m_cachedShortName.append(QLatin1String("::")); + } + m_cachedShortName.append(m_entryName); + } else { + m_cachedShortName = m_name; + } + } + return m_cachedShortName; +} + void TypeEntry::setRevision(int r) { if (m_revision != r) { diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index 6d800a3f0..f1bd0ac9f 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -87,6 +87,8 @@ public: const QByteArrayList &systemIncludes() const { return m_systemIncludes; } void addSystemInclude(const QString &name); + void addInlineNamespaceLookups(const NamespaceTypeEntry *n); + PrimitiveTypeEntry *findPrimitiveType(const QString &name) const; ComplexTypeEntry *findComplexType(const QString &name) const; ObjectTypeEntry *findObjectType(const QString &name) const; @@ -174,7 +176,7 @@ private: TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); bool m_suppressWarnings = true; - TypeEntryMultiMap m_entries; + TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). TypeEntryMap m_flagsEntries; TypedefEntryMap m_typedefEntries; TemplateEntryMap m_templates; diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 637dde363..f8199622a 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -684,6 +684,15 @@ TypeEntry::~TypeEntry() delete m_customConversion; } +bool TypeEntry::isChildOf(const TypeEntry *p) const +{ + for (auto e = m_parent; e; e = e->parent()) { + if (e == p) + return true; + } + return false; +} + const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const { for (auto e = this; e; e = e->parent()) { diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 8e155eb60..d0739c19b 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -599,6 +599,7 @@ public: const TypeEntry *parent() const { return m_parent; } void setParent(const TypeEntry *p) { m_parent = p; } + bool isChildOf(const TypeEntry *p) const; const TypeSystemTypeEntry *typeSystemTypeEntry() const; // cf AbstractMetaClass::targetLangEnclosingClass() const TypeEntry *targetLangEnclosingEntry() const; @@ -680,6 +681,8 @@ public: // The type's name in C++, fully qualified QString name() const { return m_name; } + // C++ excluding inline namespaces + QString shortName() const; // Name as specified in XML QString entryName() const { return m_entryName; } @@ -868,7 +871,8 @@ protected: private: const TypeEntry *m_parent; - QString m_name; // fully qualified + QString m_name; // C++ fully qualified + mutable QString m_cachedShortName; // C++ excluding inline namespaces QString m_entryName; QString m_targetLangPackage; mutable QString m_cachedTargetLangName; // "Foo.Bar" -- cgit v1.2.3