diff options
| author | Christian Tismer <tismer@stackless.com> | 2019-08-06 12:52:33 +0200 |
|---|---|---|
| committer | Christian Tismer <tismer@stackless.com> | 2019-08-06 18:53:13 +0200 |
| commit | 21d948aa47dfe62b58286a31c729e76c9e3c13db (patch) | |
| tree | 3edbc8b04de200ca2aea5656ff8d2f8d7212a601 | |
| parent | 5838387e31987286ae836135ecd06326f0c7e1ba (diff) | |
PySide: Create a framework for deprecated functions
During development of the patch
"Support Pointer Primitive Types by Arrays or Result Tuples"
some functions in QtGui turned out to be removal candidates.
The name "constData" should be deprecated in favor of the existing
"data" function. Other implementation also do not have this.
Instead of simply removing, we now create a surrogate function
with the name "constData" in fure Python that gives a warning
and calls the "data" function.
This is now extracted into its own commit since the deprecation
is a completely different and independent issue.
The implementation does not do any extra imports in advance.
and is easily extensible to more post-installation actions.
Task-number: PYSIDE-795
Change-Id: I410c69a87d9f0df78f736991b2ee0a2747678911
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
| -rw-r--r-- | sources/pyside2/PySide2/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | sources/pyside2/PySide2/support/__init__.py | 2 | ||||
| -rw-r--r-- | sources/pyside2/PySide2/support/deprecated.py | 80 | ||||
| -rw-r--r-- | sources/pyside2/tests/QtGui/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | sources/pyside2/tests/QtGui/timed_app_and_patching_test.py (renamed from sources/pyside2/tests/QtGui/timed_app_test.py) | 19 | ||||
| -rw-r--r-- | sources/shiboken2/libshiboken/signature.cpp | 19 | ||||
| -rw-r--r-- | sources/shiboken2/shibokenmodule/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py | 103 | ||||
| -rw-r--r-- | sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py | 12 |
9 files changed, 240 insertions, 3 deletions
diff --git a/sources/pyside2/PySide2/CMakeLists.txt b/sources/pyside2/PySide2/CMakeLists.txt index d666751ea..e39db75a1 100644 --- a/sources/pyside2/PySide2/CMakeLists.txt +++ b/sources/pyside2/PySide2/CMakeLists.txt @@ -37,6 +37,10 @@ endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/__init__.py" "${CMAKE_CURRENT_BINARY_DIR}/support/__init__.py" COPYONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/generate_pyi.py" + "${CMAKE_CURRENT_BINARY_DIR}/support/generate_pyi.py" COPYONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/deprecated.py" + "${CMAKE_CURRENT_BINARY_DIR}/support/deprecated.py" COPYONLY) # now compile all modules. file(READ "${CMAKE_CURRENT_BINARY_DIR}/pyside2_global.h" pyside2_global_contents) diff --git a/sources/pyside2/PySide2/support/__init__.py b/sources/pyside2/PySide2/support/__init__.py index dda01474d..8764fb5cb 100644 --- a/sources/pyside2/PySide2/support/__init__.py +++ b/sources/pyside2/PySide2/support/__init__.py @@ -38,3 +38,5 @@ ############################################################################# from shiboken2 import VoidPtr + +#eof diff --git a/sources/pyside2/PySide2/support/deprecated.py b/sources/pyside2/PySide2/support/deprecated.py new file mode 100644 index 000000000..8538826e4 --- /dev/null +++ b/sources/pyside2/PySide2/support/deprecated.py @@ -0,0 +1,80 @@ +# This Python file uses the following encoding: utf-8 +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of Qt for Python. +## +## $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$ +## +############################################################################# + +from __future__ import print_function, absolute_import + +""" +deprecated.py + +This module contains deprecated things that are removed from the interface. +They are implemented in Python again, together with a deprecation warning. + +Functions that are to be called for + PySide2.<module> must be named + fix_for_<module> . + +Note that this fixing code is run after all initializations, but before the +import is finished. But that is no problem since the module is passed in. +""" + +import warnings +from textwrap import dedent + + +class PySideDeprecationWarningRemovedInQt6(Warning): + pass + + +def constData(self): + cls = self.__class__ + name = cls.__name__ + warnings.warn(dedent(""" + {name}.constData is unpythonic and will be removed in Qt For Python 6.0 . + Please use {name}.data instead.""" + .format(**locals())), PySideDeprecationWarningRemovedInQt6, stacklevel=2) + return cls.data(self) + + +def fix_for_QtGui(QtGui): + for name, cls in QtGui.__dict__.items(): + if name.startswith("QMatrix") and "data" in cls.__dict__: + cls.constData = constData + +# eof diff --git a/sources/pyside2/tests/QtGui/CMakeLists.txt b/sources/pyside2/tests/QtGui/CMakeLists.txt index 927e72468..172703ab9 100644 --- a/sources/pyside2/tests/QtGui/CMakeLists.txt +++ b/sources/pyside2/tests/QtGui/CMakeLists.txt @@ -46,4 +46,4 @@ PYSIDE_TEST(qtextdocumentwriter_test.py) PYSIDE_TEST(qtextline_test.py) PYSIDE_TEST(qtransform_test.py) PYSIDE_TEST(repr_test.py) -PYSIDE_TEST(timed_app_test.py) +PYSIDE_TEST(timed_app_and_patching_test.py) diff --git a/sources/pyside2/tests/QtGui/timed_app_test.py b/sources/pyside2/tests/QtGui/timed_app_and_patching_test.py index dc0e7c4b0..014aeec1a 100644 --- a/sources/pyside2/tests/QtGui/timed_app_test.py +++ b/sources/pyside2/tests/QtGui/timed_app_and_patching_test.py @@ -29,6 +29,10 @@ import unittest from helper import TimedQApplication +from PySide2.support import deprecated +from PySide2.support.signature import importhandler +from PySide2 import QtGui + class TestTimedApp(TimedQApplication): '''Simple test case for TimedQApplication''' @@ -37,5 +41,20 @@ class TestTimedApp(TimedQApplication): #Simple test of TimedQApplication self.app.exec_() + +def fix_for_QtGui(QtGui): + QtGui.something = 42 + +class TestPatchingFramework(unittest.TestCase): + """Simple test that verifies that deprecated.py works""" + + deprecated.fix_for_QtGui = fix_for_QtGui + + def test_patch_works(self): + something = "something" + self.assertFalse(hasattr(QtGui, something)) + importhandler.finish_import(QtGui) + self.assertTrue(hasattr(QtGui, something)) + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index e62f861a2..7eaf35e1c 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -77,6 +77,7 @@ typedef struct safe_globals_struc { PyObject *create_signature_func; PyObject *seterror_argument_func; PyObject *make_helptext_func; + PyObject *finish_import_func; } safe_globals_struc, *safe_globals; static safe_globals pyside_globals = nullptr; @@ -543,6 +544,9 @@ init_phase_1(void) if (p->value_dict == nullptr) goto error; + // This function will be disabled until phase 2 is done. + p->finish_import_func = nullptr; + return p; } error: @@ -585,6 +589,10 @@ init_phase_2(safe_globals_struc *p, PyMethodDef *methods) p->make_helptext_func = PyObject_GetAttrString(loader, "make_helptext"); if (p->make_helptext_func == nullptr) goto error; + p->finish_import_func = PyObject_GetAttrString(loader, "finish_import"); + if (p->finish_import_func == nullptr) + goto error; + return 0; return 0; } error: @@ -1014,7 +1022,16 @@ PySide_FinishSignatures(PyObject *module, const char *signatures[]) return -1; if (_finish_nested_classes(obdict) < 0) return -1; - return 0; + // The finish_import function will not work the first time since phase 2 + // was not yet run. But that is ok, because the first import is always for + // the shiboken module (or a test module). + if (pyside_globals->finish_import_func == nullptr) { + assert(strncmp(name, "PySide2.", 8) != 0); + return 0; + } + Shiboken::AutoDecRef ret(PyObject_CallFunction( + pyside_globals->finish_import_func, const_cast<char *>("(O)"), module)); + return ret.isNull() ? -1 : 0; } static int diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index 057a995f8..5e5cf21d7 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -53,6 +53,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/ "${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" diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py new file mode 100644 index 000000000..0417f132a --- /dev/null +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py @@ -0,0 +1,103 @@ +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of Qt for Python. +## +## $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$ +## +############################################################################# + +from __future__ import print_function, absolute_import + +""" +importhandler.py + +This module handles special actions after the import of PySide modules. +The reason for this was the wish to replace some deprecated functions +by a Python implementation that gives a warning. + +It provides a framework to safely call functions outside of files.dir, +because the implementation of deprecated functions should be visible +to the users (in the hope they don't use it any longer <wink>). + +As a first approach, the function finish_import redirects to +PySide2/support/deprecated.py . There can come other extensions as well. +""" + +try: + from PySide2.support import deprecated + have_deprecated = True +except ImportError: + have_deprecated = False + + +# called by loader.py from signature.cpp +def finish_import(module): + if have_deprecated and module.__name__.startswith("PySide2."): + try: + name = "fix_for_" + module.__name__.split(".")[1] + func = getattr(deprecated, name, None) + if func: + func(module) + except Exception as e: + name = e.__class__.__name__ + print(72 * "*") + print("Error in deprecated.py, ignored:") + print(" {name}: {e}".format(**locals())) + +""" +A note for people who might think this could be written in pure Python: + +Sure, by an explicit import of the modules to patch, this is no problem. +But in the general case, a module should only be imported on user +request and not because we want to patch it. So I started over. + +I then tried to do it on demand by redirection of the __import__ function. +Things worked quite nicely as it seemed, but at second view this solution +was much less appealing. + +Reason: +If someone executes as the first PySide statement + + from PySide2 import QtGui + +then this import is already running. We can see the other imports like the +diverse initializations and QtCore, because it is triggered by import of +QtGui. But the QtGui import can not be seen at all! + +With a lot of effort, sys.setprofile() and stack inspection with the inspect +module, it is *perhaps* possible to solve that. I tried for a day and then +gave up, since the solution is anyway not too nice when __import__ must +be overridden. +""" +#eof diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py index 6c76483a0..3d25c5690 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py @@ -103,6 +103,10 @@ def _typevar__repr__(self): # break the Python license decorated files without an encoding line. # name used in signature.cpp +def pyside_type_init(type_key, sig_strings): + return parser.pyside_type_init(type_key, sig_strings) + +# name used in signature.cpp def create_signature(props, key): return layout.create_signature(props, key) @@ -114,6 +118,11 @@ def seterror_argument(args, func_name): def make_helptext(func): return errorhandler.make_helptext(func) +# name used in signature.cpp +def finish_import(module): + return importhandler.finish_import(module) + + import signature_bootstrap from shibokensupport import signature signature.get_signature = signature_bootstrap.get_signature @@ -194,6 +203,7 @@ def move_into_pyside_package(): put_into_package(PySide2.support.signature, layout) put_into_package(PySide2.support.signature, lib) put_into_package(PySide2.support.signature, parser) + put_into_package(PySide2.support.signature, importhandler) put_into_package(PySide2.support.signature.lib, enum_sig) put_into_package(PySide2.support.signature, typing) @@ -204,8 +214,8 @@ from shibokensupport.signature import errorhandler from shibokensupport.signature import layout from shibokensupport.signature import lib from shibokensupport.signature import parser +from shibokensupport.signature import importhandler from shibokensupport.signature.lib import enum_sig -from shibokensupport.signature.parser import pyside_type_init if "PySide2" in sys.modules: # We publish everything under "PySide2.support.signature", again. |
