diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-05-21 15:20:10 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-05-21 15:20:10 +0200 |
commit | 11214e92a465d07e58116584849f168e1a6de884 (patch) | |
tree | 5f0e28ec5f930250d8d0d70ab48f8c9e75381d41 /sources | |
parent | 9ce268b576b00538aac3fa4b3a78a222f0f10380 (diff) | |
parent | c134129bd55ebf91d3a74c720b8bd659f13bd93d (diff) |
Merge remote-tracking branch 'origin/5.13' into dev
Change-Id: I47bd00e96eebbefcf8304b7094bf00ff7e762cec
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside2/cmake/Macros/PySideModules.cmake | 13 | ||||
-rw-r--r-- | sources/pyside2/doc/deployment-fbs.rst | 20 | ||||
-rw-r--r-- | sources/pyside2/doc/deployment-pyinstaller.rst | 49 | ||||
-rw-r--r-- | sources/pyside2/doc/deployment.rst | 10 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 99 |
5 files changed, 163 insertions, 28 deletions
diff --git a/sources/pyside2/cmake/Macros/PySideModules.cmake b/sources/pyside2/cmake/Macros/PySideModules.cmake index cbf401102..77dc8c8ac 100644 --- a/sources/pyside2/cmake/Macros/PySideModules.cmake +++ b/sources/pyside2/cmake/Macros/PySideModules.cmake @@ -169,6 +169,19 @@ macro(create_pyside_module) set(ld_prefix "LD_LIBRARY_PATH=") endif() set(ld_prefix "${ld_prefix}${pysidebindings_BINARY_DIR}/libpyside${PATH_SEP}${SHIBOKEN_SHARED_LIBRARY_DIR}") + + # On Windows we also need to propagate the whole environment PATH value, because pyside modules + # import Qt, and the Qt modules are found from PATH. + if(WIN32) + # Get the value of PATH with CMake separators. + file(TO_CMAKE_PATH "$ENV{PATH}" path_value) + + # Replace the CMake list separators with "\;"s, to avoid the PATH values being + # interpreted as CMake list elements, we actually want to pass the whole string separated + # by ";" to the command line. + make_path(path_value "${path_value}") + string(APPEND ld_prefix "${PATH_SEP}${path_value}") + endif() set(generate_pyi_options run --skip --sys-path "${pysidebindings_BINARY_DIR}" "${SHIBOKEN_PYTHON_MODULE_DIR}") diff --git a/sources/pyside2/doc/deployment-fbs.rst b/sources/pyside2/doc/deployment-fbs.rst index 94c52a08b..ff489f745 100644 --- a/sources/pyside2/doc/deployment-fbs.rst +++ b/sources/pyside2/doc/deployment-fbs.rst @@ -14,9 +14,9 @@ options. Preparation =========== -Installing `fbs` can be done via **pip**:: +Installing `fbs` (>= 0.7.6) can be done via **pip**:: - pip install fbs pyinstaller==3.4 + pip install fbs If you are using a virtual environment, remember to activate it before installing it. @@ -62,18 +62,12 @@ The main file will be under the `python` directory, and its content by default i import sys - class AppContext(ApplicationContext): # 1. Subclass ApplicationContext - def run(self): # 2. Implement run() - window = QMainWindow() - version = self.build_settings['version'] - window.setWindowTitle("MyApp v" + version) - window.resize(250, 150) - window.show() - return self.app.exec_() # 3. End run() with this line - if __name__ == '__main__': - appctxt = AppContext() # 4. Instantiate the subclass - exit_code = appctxt.run() # 5. Invoke run() + appctxt = ApplicationContext() # 1. Instantiate ApplicationContext + window = QMainWindow() + window.resize(250, 150) + window.show() + exit_code = appctxt.app.exec_() # 2. Invoke appctxt.app.exec_() sys.exit(exit_code) The example will show an empty `QMainWindow`, and you can execute it by running:: diff --git a/sources/pyside2/doc/deployment-pyinstaller.rst b/sources/pyside2/doc/deployment-pyinstaller.rst index 8e6a76052..f361daf4a 100644 --- a/sources/pyside2/doc/deployment-pyinstaller.rst +++ b/sources/pyside2/doc/deployment-pyinstaller.rst @@ -122,3 +122,52 @@ an executable inside the `dist/` directory that you can execute:: cd dist/ ./MyApplication + + +Current Caveats To Be Aware Of +============================== + + +PyInstaller Problem +------------------- + +As already mentioned, `PyInstaller` will pick a system installation of PySide2 or +Shiboken2 instead of your virtualenv version without notice, if it exists. +This may be no problem if those PySide2 or shiboken2 versions are the same. + +If you are working with different versions, this can result in frustrating sessions, +when you think you are testing a new version, but `PyInstaller` +is silently working with a different, older version. + + +Problem with numpy in Python 2.7.16 +----------------------------------- + +A recent problem of PyInstaller is the appearance of Python 2.7.16 . +This Python version creates a problem that is known from Python 3 as a `Tcl/Tk` problem. +This does rarely show up in Python 3 because `Tcl/Tk` is seldom used with `PyInstaller. + +On Python 2.7.16, this problem is very much visible, since many people are using numpy. +For some reason, installing `numpy` creates a dependency of `Tcl/Tk`, which can +be circumvented only by explicitly excluding `Tcl/Tk` related things by adding +this line to the analysis section of the spec-file:: + + excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'], + + +Safety Instructions +------------------- + +o When using `PyInstaller` with `virtualenv`, make sure that there is no system + installation of PySide2 or shiboken2. + +o Before compiling, use `pip -uninstall pyside2 shiboken2 -y` multiple times, until + none of the programs is found anymore. + +o Pip is usually a good tool. But to be 100 % sure, you should directly remove + the PySide2 and shiboken2 folders from site-packages. + +o Be sure to use the right version of pip. The safest way to really run the right + pip, use the Python that you mean: Instead of the pip command, better use:: + + <path/to/your/>python -m pip diff --git a/sources/pyside2/doc/deployment.rst b/sources/pyside2/doc/deployment.rst index 582e38992..a125dc4d7 100644 --- a/sources/pyside2/doc/deployment.rst +++ b/sources/pyside2/doc/deployment.rst @@ -12,6 +12,7 @@ The options for a project are: 3. Freezing the application in a single binary file, or into a directory. For the **third** option, there are many available tools: + * `fbs <https://build-system.fman.io/>`_, * `PyInstaller <https://www.pyinstaller.org/>`_, * `cx_Freeze <https://anthony-tuininga.github.io/cx_Freeze/>`_, * `py2exe <http://www.py2exe.org/>`_, @@ -26,13 +27,14 @@ The following table summarizes the above mentioned tools support: =========== ======= ===== ===== ======= Name License Linux macOS Windows =========== ======= ===== ===== ======= +fbs GPL yes yes yes +PyInstaller GPL yes yes yes +cx_Freeze MIT yes yes yes py2exe MIT no no yes py2app MIT no yes no -cx_Freeze MIT yes yes yes -PyInstaller GPL yes yes yes =========== ======= ===== ===== ======= -From the table we can see that only *cx_Freeze* and *PyInstaller* +From the table we can see that only *fbs*, *cx_Freeze* and *PyInstaller* meet our requirements. All tools are command-line based, and it could become @@ -65,6 +67,6 @@ described tools. :name: mastertoc :maxdepth: 2 + deployment-fbs.rst deployment-pyinstaller.rst deployment-cxfreeze.rst - deployment-fbs.rst diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 6ea793a79..faaca5e4b 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -94,6 +94,92 @@ static PyType_Spec SbkObjectType_Type_spec = { }; +#if PY_VERSION_HEX < 0x03000000 +/***************************************************************************** + * + * PYSIDE-816: Workaround for Python 2.7 + * + * This is an add-on for function typeobject.c:tp_new_wrapper from Python 2.7 . + * Problem: + * In Python 3.X, tp_new_wrapper uses this check: + + while (staticbase && (staticbase->tp_new == slot_tp_new)) + + * In Python 2.7, it uses this, instead: + + while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE)) + + * The problem is that heap types have this unwanted dependency. + * But we cannot get at static slot_tp_new, and so we have to use + * the original function and patch Py_TPFLAGS_HEAPTYPE away during the call. + */ + +static PyCFunction old_tp_new_wrapper = nullptr; + +static PyObject * +tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyTypeObject *type = reinterpret_cast<PyTypeObject *>(self); + Py_ssize_t orig_flags = type->tp_flags; + type->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; + PyObject *ret = reinterpret_cast<ternaryfunc>(old_tp_new_wrapper)(self, args, kwds); + type->tp_flags = orig_flags; + return ret; +} + +// This is intentionally the new docstring of Python 3.7 . +static struct PyMethodDef tp_new_methoddef[] = { + {"__new__", (PyCFunction)tp_new_wrapper, METH_VARARGS|METH_KEYWORDS, + PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n" + "Create and return a new object. " + "See help(type) for accurate signature.")}, + {0} +}; + +static int +get_old_tp_new_wrapper(void) +{ + // We get the old tp_new_wrapper from any initialized type. + PyTypeObject *type = &PyType_Type; + PyObject *dict = type->tp_dict; + PyObject *key, *func = nullptr; + Py_ssize_t pos = 0; + while (PyDict_Next(dict, &pos, &key, &func)) { + char *name = PyString_AsString(key); + if (strcmp(name, "__new__") == 0) { + break; + } + } + if (func == nullptr) + return -1; + PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func); + old_tp_new_wrapper = pycf_ob->m_ml->ml_meth; + return 0; +} + +static int +add_tp_new_wrapper(PyTypeObject *type) +{ + // get the original tp_new_wrapper + if (old_tp_new_wrapper == nullptr && get_old_tp_new_wrapper() < 0) + return -1; + // initialize tp_dict + if (type->tp_dict == nullptr) + type->tp_dict = PyDict_New(); + if (type->tp_dict == nullptr) + return -1; + PyObject *ob_type = reinterpret_cast<PyObject *>(type); + Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type)); + if (func.isNull()) + return -1; + if (PyDict_SetItemString(type->tp_dict, "__new__", func)) + return -1; + return 0; +} +/*****************************************************************************/ +#endif // PY_VERSION_HEX < 0x03000000 + + PyTypeObject *SbkObjectType_TypeF(void) { static PyTypeObject *type = nullptr; @@ -102,13 +188,8 @@ PyTypeObject *SbkObjectType_TypeF(void) PepHeapType_SIZE + sizeof(SbkObjectTypePrivate); type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObjectType_Type_spec)); #if PY_VERSION_HEX < 0x03000000 - // PYSIDE-816: Python 2.7 has a bad check for Py_TPFLAGS_HEAPTYPE in - // typeobject.c func tp_new_wrapper. In Python 3 it was updated after - // the transition to the new type API, but not in 2.7 . Fortunately, - // the types did not change much when transitioning to heaptypes. We - // pretend that this type is a normal type in 2.7 and hope that this - // has no bad effect. - type->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; + if (add_tp_new_wrapper(type) < 0) + return nullptr; #endif } return type; @@ -299,10 +380,6 @@ void SbkObjectTypeDealloc(PyObject* pyObj) SbkObjectTypePrivate *sotp = PepType_SOTP(pyObj); PyTypeObject *type = reinterpret_cast<PyTypeObject*>(pyObj); -#if PY_VERSION_HEX < 0x03000000 - // PYSIDE-816: Restore the heap type flag. Better safe than sorry. - type->tp_flags |= Py_TPFLAGS_HEAPTYPE; -#endif PyObject_GC_UnTrack(pyObj); #ifndef Py_LIMITED_API Py_TRASHCAN_SAFE_BEGIN(pyObj); |