diff options
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r-- | sources/shiboken2/libshiboken/CMakeLists.txt | 10 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 12 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/embed/embedding_generator.py | 4 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/helper.cpp | 3 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/pep384impl.cpp | 27 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkenum.cpp | 7 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkstaticstrings.cpp | 91 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkstaticstrings.h | 65 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkstaticstrings_p.h | 72 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkstring.cpp | 64 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/sbkstring.h | 9 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/shiboken.h | 1 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/signature.cpp | 145 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/signature.h | 2 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/signature_doc.rst | 10 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/typespec.cpp | 3 |
16 files changed, 415 insertions, 110 deletions
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index 7cbb22978..a38da8d89 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -30,8 +30,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/embed/signature_bootstrap.py" "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap.py" @ONLY) add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap.inc" - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature.inc" + 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" @@ -53,6 +53,7 @@ sbkconverter.cpp sbkenum.cpp sbkmodule.cpp sbkstring.cpp +sbkstaticstrings.cpp bindingmanager.cpp threadstatesaver.cpp shibokenbuffer.cpp @@ -62,8 +63,8 @@ pep384impl.cpp voidptr.cpp typespec.cpp bufferprocs_py37.cpp -embed/signature_bootstrap.inc -embed/signature.inc +embed/signature_bootstrap_inc.h +embed/signature_inc.h ) get_numpy_location() @@ -129,6 +130,7 @@ install(FILES python25compat.h sbkdbg.h sbkstring.h + sbkstaticstrings.h shiboken.h shibokenmacros.h threadstatesaver.h diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 9d233b847..000035627 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -44,6 +44,7 @@ #include "sbkconverter.h" #include "sbkenum.h" #include "sbkstring.h" +#include "sbkstaticstrings_p.h" #include "autodecref.h" #include "gilstate.h" #include <string> @@ -160,11 +161,10 @@ patch_tp_new_wrapper(PyTypeObject *type) * The old tp_new_wrapper is added to all types that have tp_new. * We patch that with a version that ignores the heaptype flag. */ - static PyObject *__new__ = nullptr; + auto newMethod = Shiboken::PyMagicName::new_(); if (old_tp_new_wrapper == nullptr) { - if ((__new__ = Py_BuildValue("s", "__new__")) == nullptr) - return -1; - PyObject *func = PyDict_GetItem(PyType_Type.tp_dict, __new__); + PyObject *func = PyDict_GetItem(PyType_Type.tp_dict, newMethod); + assert(func); PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func); old_tp_new_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth); } @@ -172,7 +172,7 @@ patch_tp_new_wrapper(PyTypeObject *type) Py_ssize_t i, n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i)); - PyObject *existing = PyDict_GetItem(type->tp_dict, __new__); + PyObject *existing = PyDict_GetItem(type->tp_dict, newMethod); if (existing && PyCFunction_Check(existing) && type->tp_flags & Py_TPFLAGS_HEAPTYPE) { auto *pycf_ob = reinterpret_cast<PyCFunctionObject *>(existing); @@ -182,7 +182,7 @@ patch_tp_new_wrapper(PyTypeObject *type) if (existing_wrapper == old_tp_new_wrapper) { PyObject *ob_type = reinterpret_cast<PyObject *>(type); Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type)); - if (func.isNull() || PyDict_SetItem(type->tp_dict, __new__, func)) + if (func.isNull() || PyDict_SetItem(type->tp_dict, newMethod, func)) return -1; } } diff --git a/sources/shiboken2/libshiboken/embed/embedding_generator.py b/sources/shiboken2/libshiboken/embed/embedding_generator.py index 77aa5c329..15f63649b 100644 --- a/sources/shiboken2/libshiboken/embed/embedding_generator.py +++ b/sources/shiboken2/libshiboken/embed/embedding_generator.py @@ -88,7 +88,7 @@ def create_zipfile(limited_api): and make a chunked base64 encoded file from it. """ zip_name = "signature.zip" - inc_name = "signature.inc" + inc_name = "signature_inc.h" flag = '-b' if sys.version_info >= (3,) else '' os.chdir(work_dir) @@ -131,7 +131,7 @@ def create_zipfile(limited_api): 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", "w") as inc: + 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) diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp index fac72d56f..013080b6e 100644 --- a/sources/shiboken2/libshiboken/helper.cpp +++ b/sources/shiboken2/libshiboken/helper.cpp @@ -39,6 +39,7 @@ #include "helper.h" #include "sbkstring.h" +#include "sbkstaticstrings.h" #include <stdarg.h> #ifdef _WIN32 @@ -78,7 +79,7 @@ bool listToArgcArgv(PyObject *argList, int *argc, char ***argv, const char *defa if (hasEmptyArgList) { // Try to get the script name PyObject *globals = PyEval_GetGlobals(); - PyObject *appName = PyDict_GetItemString(globals, "__file__"); + PyObject *appName = PyDict_GetItem(globals, Shiboken::PyMagicName::file()); (*argv)[0] = strdup(appName ? Shiboken::String::toCString(appName) : defaultAppName); } else { for (int i = 0; i < numArgs; ++i) { diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp index fe7157d24..f4e404bed 100644 --- a/sources/shiboken2/libshiboken/pep384impl.cpp +++ b/sources/shiboken2/libshiboken/pep384impl.cpp @@ -39,6 +39,8 @@ #include "pep384impl.h" #include "autodecref.h" +#include "sbkstaticstrings.h" +#include "sbkstaticstrings_p.h" extern "C" { @@ -125,16 +127,16 @@ check_PyTypeObject_valid() { auto *obtype = reinterpret_cast<PyObject *>(&PyType_Type); auto *probe_tp_base = reinterpret_cast<PyTypeObject *>( - PyObject_GetAttrString(obtype, "__base__")); - PyObject *probe_tp_bases = PyObject_GetAttrString(obtype, "__bases__"); + PyObject_GetAttr(obtype, Shiboken::PyMagicName::base())); + auto *probe_tp_bases = PyObject_GetAttr(obtype, Shiboken::PyMagicName::bases()); auto *check = reinterpret_cast<PyTypeObject *>( PyType_FromSpecWithBases(&typeprobe_spec, probe_tp_bases)); auto *typetype = reinterpret_cast<PyTypeObject *>(obtype); - PyObject *w = PyObject_GetAttrString(obtype, "__weakrefoffset__"); + PyObject *w = PyObject_GetAttr(obtype, Shiboken::PyMagicName::weakrefoffset()); long probe_tp_weakrefoffset = PyLong_AsLong(w); - PyObject *d = PyObject_GetAttrString(obtype, "__dictoffset__"); + PyObject *d = PyObject_GetAttr(obtype, Shiboken::PyMagicName::dictoffset()); long probe_tp_dictoffset = PyLong_AsLong(d); - PyObject *probe_tp_mro = PyObject_GetAttrString(obtype, "__mro__"); + PyObject *probe_tp_mro = PyObject_GetAttr(obtype, Shiboken::PyMagicName::mro()); if (false || strcmp(probe_tp_name, check->tp_name) != 0 || probe_tp_basicsize != check->tp_basicsize @@ -416,9 +418,10 @@ PepRun_GetResult(const char *command, const char *resvar) PyObject *d, *v, *res; d = PyDict_New(); - if (d == NULL || PyDict_SetItemString(d, "__builtins__", - PyEval_GetBuiltins()) < 0) - return NULL; + if (d == nullptr + || PyDict_SetItem(d, Shiboken::PyMagicName::builtins(), PyEval_GetBuiltins()) < 0) { + return nullptr; + } v = PyRun_String(command, Py_file_input, d, d); res = v ? PyDict_GetItemString(d, resvar) : NULL; Py_XDECREF(v); @@ -457,7 +460,7 @@ PyMethod_New(PyObject *func, PyObject *self) PyObject * PyMethod_Function(PyObject *im) { - PyObject *ret = PyObject_GetAttrString(im, "__func__"); + PyObject *ret = PyObject_GetAttr(im, Shiboken::PyMagicName::func()); // We have to return a borrowed reference. Py_DECREF(ret); @@ -467,7 +470,7 @@ PyMethod_Function(PyObject *im) PyObject * PyMethod_Self(PyObject *im) { - PyObject *ret = PyObject_GetAttrString(im, "__self__"); + PyObject *ret = PyObject_GetAttr(im, Shiboken::PyMagicName::self()); // We have to return a borrowed reference. // If we don't obey that here, then we get a test error! @@ -620,8 +623,8 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name) return name; } #endif - Shiboken::AutoDecRef privateobj(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(Py_TYPE(self)), "__name__")); + Shiboken::AutoDecRef privateobj(PyObject_GetAttr( + reinterpret_cast<PyObject *>(Py_TYPE(self)), Shiboken::PyMagicName::name())); #ifndef Py_LIMITED_API return _Py_Mangle(privateobj, name); #else diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp index 2dc785884..71fcf5f64 100644 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ b/sources/shiboken2/libshiboken/sbkenum.cpp @@ -412,13 +412,6 @@ PyTypeObject *createScopedEnum(SbkObjectType *scope, const char *name, const cha static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue) { - char mangled[20]; - if (strcmp(itemName, "None") == 0 - || strcmp(itemName, "False") == 0 || strcmp(itemName, "True") == 0) { - strcpy(mangled, itemName); - strcat(mangled, "_"); - itemName = mangled; - } PyObject *enumItem = newItem(enumType, itemValue, itemName); if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) return nullptr; diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp new file mode 100644 index 000000000..dcd25da16 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "sbkstaticstrings.h" +#include "sbkstaticstrings_p.h" +#include "sbkstring.h" + +#define STATIC_STRING_IMPL(funcName, value) \ +PyObject *funcName() \ +{ \ + static PyObject *const s = Shiboken::String::createStaticString(value); \ + return s; \ +} + +namespace Shiboken +{ +namespace PyName { +// exported: +STATIC_STRING_IMPL(dumps, "dumps") +STATIC_STRING_IMPL(loads, "loads") + +// Internal: +STATIC_STRING_IMPL(classmethod, "classmethod") +STATIC_STRING_IMPL(compile, "compile"); +STATIC_STRING_IMPL(function, "function") +STATIC_STRING_IMPL(marshal, "marshal") +STATIC_STRING_IMPL(method, "method") +STATIC_STRING_IMPL(overload, "overload") +STATIC_STRING_IMPL(staticmethod, "staticmethod") +} // namespace PyName + +namespace PyMagicName { +// exported: +STATIC_STRING_IMPL(class_, "__class__") +STATIC_STRING_IMPL(ecf, "__ecf__") +STATIC_STRING_IMPL(file, "__file__") +STATIC_STRING_IMPL(module, "__module__") +STATIC_STRING_IMPL(name, "__name__") + +// Internal: +STATIC_STRING_IMPL(base, "__base__") +STATIC_STRING_IMPL(bases, "__bases__") +STATIC_STRING_IMPL(builtins, "__builtins__") +STATIC_STRING_IMPL(code, "__code__") +STATIC_STRING_IMPL(dictoffset, "__dictoffset__") +STATIC_STRING_IMPL(func, "__func__") +STATIC_STRING_IMPL(func_kind, "__func_kind__") +STATIC_STRING_IMPL(mro, "__mro__") +STATIC_STRING_IMPL(new_, "__new__") +STATIC_STRING_IMPL(objclass, "__objclass__") +STATIC_STRING_IMPL(self, "__self__") +STATIC_STRING_IMPL(signature, "__signature__") +STATIC_STRING_IMPL(weakrefoffset, "__weakrefoffset__") +} // namespace PyMagicName +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h new file mode 100644 index 000000000..fa21a8e2c --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef SBKSTATICSTRINGS_H +#define SBKSTATICSTRINGS_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +namespace Shiboken +{ +// Some often-used strings +namespace PyName +{ +LIBSHIBOKEN_API PyObject *dumps(); +LIBSHIBOKEN_API PyObject *loads(); +} // namespace PyName + +namespace PyMagicName +{ +LIBSHIBOKEN_API PyObject *class_(); +LIBSHIBOKEN_API PyObject *ecf(); +LIBSHIBOKEN_API PyObject *file(); +LIBSHIBOKEN_API PyObject *module(); +LIBSHIBOKEN_API PyObject *name(); +} // namespace PyMagicName +} // namespace Shiboken + +#endif // SBKSTATICSTRINGS_H diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings_p.h b/sources/shiboken2/libshiboken/sbkstaticstrings_p.h new file mode 100644 index 000000000..bb4cb13c3 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkstaticstrings_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "sbkpython.h" +#include "shibokenmacros.h" + +namespace Shiboken +{ +namespace PyName +{ +PyObject *classmethod(); +PyObject *compile(); +PyObject *function(); +PyObject *marshal(); +PyObject *method(); +PyObject *overload(); +PyObject *staticmethod(); +} // namespace PyName +namespace PyMagicName +{ +PyObject *base(); +PyObject *bases(); +PyObject *builtins(); +PyObject *code(); +PyObject *dictoffset(); +PyObject *func(); +PyObject *func_kind(); +PyObject *module(); +PyObject *mro(); +PyObject *new_(); +PyObject *objclass(); +PyObject *self(); +PyObject *signature(); +PyObject *weakrefoffset(); +} // namespace PyMagicName +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp index 9ba5be281..2e638a413 100644 --- a/sources/shiboken2/libshiboken/sbkstring.cpp +++ b/sources/shiboken2/libshiboken/sbkstring.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -40,6 +40,8 @@ #include "sbkstring.h" #include "autodecref.h" +#include <vector> + namespace Shiboken { @@ -200,6 +202,64 @@ Py_ssize_t len(PyObject *str) return 0; } -} // namespace String +/////////////////////////////////////////////////////////////////////// +// +// Implementation of efficient Python strings +// ------------------------------------------ +// +// Instead of repetitively executing +// +// PyObject *attr = PyObject_GetAttrString(obj, "__name__"); +// +// a helper of the form +// +// PyObject *name() +// { +// static PyObject *const s = Shiboken::String::createStaticString("__name__"); +// return result; +// } +// +// can now be implemented, which registers the string into a static set avoiding +// repetitive string creation. The resulting code looks like: +// +// PyObject *attr = PyObject_GetAttr(obj, name()); +// +// Missing: +// There is no finalization for the string structures, yet. +// But this is a global fault in shiboken. We are missing a true +// finalization like in all other modules. + +using StaticStrings = std::vector<PyObject *>; + +static StaticStrings &staticStrings() +{ + static StaticStrings result; + return result; +} + +PyObject *createStaticString(const char *str) +{ +#if PY_VERSION_HEX >= 0x03000000 + PyObject *result = PyUnicode_InternFromString(str); +#else + PyObject *result = PyString_InternFromString(str); +#endif + if (result == nullptr) { + // This error is never checked, but also very unlikely. Report and exit. + PyErr_Print(); + Py_FatalError("unexpected error in createStaticString()"); + } + staticStrings().push_back(result); + return result; +} +void finalizeStaticStrings() // Currently unused +{ + auto &list = staticStrings(); + for (auto s : list) + Py_DECREF(s); + list.clear(); +} + +} // namespace String } // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.h b/sources/shiboken2/libshiboken/sbkstring.h index 7f434e1b9..c82ed5a22 100644 --- a/sources/shiboken2/libshiboken/sbkstring.h +++ b/sources/shiboken2/libshiboken/sbkstring.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. @@ -43,12 +43,6 @@ #include "sbkpython.h" #include "shibokenmacros.h" -#if PY_MAJOR_VERSION >= 3 - #define SBK_BYTES_NAME "bytes" -#else - #define SBK_BYTES_NAME "str" -#endif - namespace Shiboken { namespace String @@ -65,6 +59,7 @@ namespace String LIBSHIBOKEN_API PyObject *fromStringAndSize(const char *str, Py_ssize_t size); LIBSHIBOKEN_API int compare(PyObject *val1, const char *val2); LIBSHIBOKEN_API Py_ssize_t len(PyObject *str); + LIBSHIBOKEN_API PyObject *createStaticString(const char *str); } // namespace String } // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h index 1356670aa..0d2d6b0a6 100644 --- a/sources/shiboken2/libshiboken/shiboken.h +++ b/sources/shiboken2/libshiboken/shiboken.h @@ -52,6 +52,7 @@ #include "sbkenum.h" #include "sbkmodule.h" #include "sbkstring.h" +#include "sbkstaticstrings.h" #include "shibokenmacros.h" #include "shibokenbuffer.h" diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index 0afdbcdc9..5430ab064 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -39,6 +39,8 @@ #include "basewrapper.h" #include "autodecref.h" +#include "sbkstaticstrings.h" +#include "sbkstaticstrings_p.h" extern "C" { @@ -51,11 +53,11 @@ extern "C" // These constants were needed in former versions of the module: #define PYTHON_HAS_QUALNAME (PY_VERSION_HEX >= 0x03030000) -#define PYTHON_HAS_UNICODE (PY_VERSION_HEX >= 0x03000000) #define PYTHON_HAS_WEAKREF_PYCFUNCTION (PY_VERSION_HEX >= 0x030500A0) #define PYTHON_IS_PYTHON3 (PY_VERSION_HEX >= 0x03000000) #define PYTHON_HAS_KEYWORDONLY (PYTHON_IS_PYTHON3) #define PYTHON_USES_PERCENT_V_FORMAT (PYTHON_IS_PYTHON3) +#define PYTHON_USES_D_COMMON (PY_VERSION_HEX >= 0x03020000) #define PYTHON_HAS_DESCR_REDUCE (PY_VERSION_HEX >= 0x03040000) #define PYTHON_HAS_METH_REDUCE (PYTHON_HAS_DESCR_REDUCE) #define PYTHON_NEEDS_ITERATOR_FLAG (!PYTHON_IS_PYTHON3) @@ -64,7 +66,7 @@ extern "C" #define PYTHON_HAS_INT_AND_LONG (!PYTHON_IS_PYTHON3) // These constants are still in use: -#define PYTHON_USES_D_COMMON (PY_VERSION_HEX >= 0x03020000) +#define PYTHON_USES_UNICODE (PY_VERSION_HEX >= 0x03000000) typedef struct safe_globals_struc { // init part 1: get arg_dict @@ -77,17 +79,18 @@ 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; static PyObject *GetTypeKey(PyObject *ob); -static PyObject *GetSignature_Function(PyObject *, const char *); -static PyObject *GetSignature_TypeMod(PyObject *, const char *); -static PyObject *GetSignature_Wrapper(PyObject *, const char *); +static PyObject *GetSignature_Function(PyObject *, PyObject *); +static PyObject *GetSignature_TypeMod(PyObject *, PyObject *); +static PyObject *GetSignature_Wrapper(PyObject *, PyObject *); static PyObject *get_signature(PyObject *self, PyObject *args); -static PyObject *get_signature_intern(PyObject *ob, const char *modifier); +static PyObject *get_signature_intern(PyObject *ob, PyObject *modifier); static PyObject *PySide_BuildSignatureProps(PyObject *class_mod); @@ -107,10 +110,10 @@ CreateSignature(PyObject *props, PyObject *key) const_cast<char *>("(OO)"), props, key); } -typedef PyObject *(*signaturefunc)(PyObject *, const char *); +typedef PyObject *(*signaturefunc)(PyObject *, PyObject *); static PyObject * -_get_written_signature(signaturefunc sf, PyObject *ob, const char *modifier) +_get_written_signature(signaturefunc sf, PyObject *ob, PyObject *modifier) { /* * Be a writable Attribute, but have a computed value. @@ -133,19 +136,19 @@ _get_written_signature(signaturefunc sf, PyObject *ob, const char *modifier) } static PyObject * -pyside_cf_get___signature__(PyObject *func, const char *modifier) +pyside_cf_get___signature__(PyObject *func, PyObject *modifier) { init_module_2(); return _get_written_signature(GetSignature_Function, func, modifier); } static PyObject * -pyside_sm_get___signature__(PyObject *sm, const char *modifier) +pyside_sm_get___signature__(PyObject *sm, PyObject *modifier) { init_module_2(); - Shiboken::AutoDecRef func(PyObject_GetAttrString(sm, "__func__")); + Shiboken::AutoDecRef func(PyObject_GetAttr(sm, Shiboken::PyMagicName::func())); if (Py_TYPE(func) == PepFunction_TypePtr) - return PyObject_GetAttrString(func, "__signature__"); + return PyObject_GetAttr(func, Shiboken::PyMagicName::signature()); return _get_written_signature(GetSignature_Function, func, modifier); } @@ -157,7 +160,7 @@ _get_class_of_cf(PyObject *ob_cf) selftype = PyDict_GetItem(pyside_globals->map_dict, ob_cf); if (selftype == nullptr) { // This must be an overloaded function that we handled special. - Shiboken::AutoDecRef special(Py_BuildValue("(Os)", ob_cf, "overload")); + Shiboken::AutoDecRef special(Py_BuildValue("(OO)", ob_cf, Shiboken::PyName::overload())); selftype = PyDict_GetItem(pyside_globals->map_dict, special); if (selftype == nullptr) { // This is probably a module function. We will return type(None). @@ -175,15 +178,15 @@ _get_class_of_cf(PyObject *ob_cf) static PyObject * _get_class_of_sm(PyObject *ob_sm) { - Shiboken::AutoDecRef func(PyObject_GetAttrString(ob_sm, "__func__")); + Shiboken::AutoDecRef func(PyObject_GetAttr(ob_sm, Shiboken::PyMagicName::func())); return _get_class_of_cf(func); } static PyObject * _get_class_of_descr(PyObject *ob) { - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob, "__name__")); - return PyObject_GetAttrString(ob, "__objclass__"); + Shiboken::AutoDecRef func_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name())); + return PyObject_GetAttr(ob, Shiboken::PyMagicName::objclass()); } static PyObject * @@ -215,10 +218,10 @@ get_funcname(PyObject *ob) { PyObject *func = ob; if (Py_TYPE(ob) == PepStaticMethod_TypePtr) - func = PyObject_GetAttrString(ob, "__func__"); + func = PyObject_GetAttr(ob, Shiboken::PyMagicName::func()); else Py_INCREF(func); - PyObject *func_name = PyObject_GetAttrString(func, "__name__"); + PyObject *func_name = PyObject_GetAttr(func, Shiboken::PyMagicName::name()); Py_DECREF(func); if (func_name == nullptr) Py_FatalError("unexpected name problem in compute_name_key"); @@ -286,7 +289,7 @@ name_key_to_func(PyObject *ob) } static PyObject * -pyside_md_get___signature__(PyObject *ob_md, const char *modifier) +pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier) { init_module_2(); Shiboken::AutoDecRef func(name_key_to_func(ob_md)); @@ -298,14 +301,14 @@ pyside_md_get___signature__(PyObject *ob_md, const char *modifier) } static PyObject * -pyside_wd_get___signature__(PyObject *ob, const char *modifier) +pyside_wd_get___signature__(PyObject *ob, PyObject *modifier) { init_module_2(); return _get_written_signature(GetSignature_Wrapper, ob, modifier); } static PyObject * -pyside_tp_get___signature__(PyObject *obtype_mod, const char *modifier) +pyside_tp_get___signature__(PyObject *obtype_mod, PyObject *modifier) { init_module_2(); return _get_written_signature(GetSignature_TypeMod, obtype_mod, modifier); @@ -313,7 +316,7 @@ pyside_tp_get___signature__(PyObject *obtype_mod, const char *modifier) // forward static PyObject * -GetSignature_Cached(PyObject *props, const char *func_kind, const char *modifier); +GetSignature_Cached(PyObject *props, PyObject *func_kind, PyObject *modifier); static PyObject * GetTypeKey(PyObject *ob) @@ -331,8 +334,8 @@ GetTypeKey(PyObject *ob) * * This is the PyCFunction behavior, as opposed to Python functions. */ - Shiboken::AutoDecRef class_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::AutoDecRef module_name(PyObject_GetAttrString(ob, "__module__")); + Shiboken::AutoDecRef class_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name())); + Shiboken::AutoDecRef module_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::module())); if (module_name.isNull()) PyErr_Clear(); @@ -363,7 +366,7 @@ TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype) } static PyObject * -GetSignature_Function(PyObject *obfunc, const char *modifier) +GetSignature_Function(PyObject *obfunc, PyObject *modifier) { // make sure that we look into PyCFunction, only... if (Py_TYPE(obfunc) == PepFunction_TypePtr) @@ -375,29 +378,29 @@ GetSignature_Function(PyObject *obfunc, const char *modifier) PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod); if (dict == nullptr) return nullptr; - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(obfunc, "__name__")); + Shiboken::AutoDecRef func_name(PyObject_GetAttr(obfunc, Shiboken::PyMagicName::name())); PyObject *props = !func_name.isNull() ? PyDict_GetItem(dict, func_name) : nullptr; if (props == nullptr) Py_RETURN_NONE; int flags = PyCFunction_GET_FLAGS(obfunc); - const char *func_kind; + PyObject *func_kind; if (PyModule_Check(obtype_mod)) - func_kind = "function"; + func_kind = Shiboken::PyName::function(); else if (flags & METH_CLASS) - func_kind = "classmethod"; + func_kind = Shiboken::PyName::classmethod(); else if (flags & METH_STATIC) - func_kind = "staticmethod"; + func_kind = Shiboken::PyName::staticmethod(); else - func_kind = "method"; + func_kind = Shiboken::PyName::method(); return GetSignature_Cached(props, func_kind, modifier); } static PyObject * -GetSignature_Wrapper(PyObject *ob, const char *modifier) +GetSignature_Wrapper(PyObject *ob, PyObject *modifier) { - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::AutoDecRef objclass(PyObject_GetAttrString(ob, "__objclass__")); + Shiboken::AutoDecRef func_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name())); + Shiboken::AutoDecRef objclass(PyObject_GetAttr(ob, Shiboken::PyMagicName::objclass())); Shiboken::AutoDecRef class_key(GetTypeKey(objclass)); if (func_name.isNull() || objclass.isNull() || class_key.isNull()) @@ -408,13 +411,13 @@ GetSignature_Wrapper(PyObject *ob, const char *modifier) PyObject *props = PyDict_GetItem(dict, func_name); if (props == nullptr) Py_RETURN_NONE; - return GetSignature_Cached(props, "method", modifier); + return GetSignature_Cached(props, Shiboken::PyName::method(), modifier); } static PyObject * -GetSignature_TypeMod(PyObject *ob, const char *modifier) +GetSignature_TypeMod(PyObject *ob, PyObject *modifier) { - Shiboken::AutoDecRef ob_name(PyObject_GetAttrString(ob, "__name__")); + Shiboken::AutoDecRef ob_name(PyObject_GetAttr(ob, Shiboken::PyMagicName::name())); Shiboken::AutoDecRef ob_key(GetTypeKey(ob)); PyObject *dict = TypeKey_to_PropsDict(ob_key, ob); @@ -423,19 +426,26 @@ GetSignature_TypeMod(PyObject *ob, const char *modifier) PyObject *props = PyDict_GetItem(dict, ob_name); if (props == nullptr) Py_RETURN_NONE; - return GetSignature_Cached(props, "method", modifier); + return GetSignature_Cached(props, Shiboken::PyName::method(), modifier); } static PyObject * -GetSignature_Cached(PyObject *props, const char *func_kind, const char *modifier) +GetSignature_Cached(PyObject *props, PyObject *func_kind, PyObject *modifier) { // Special case: We want to know the func_kind. - if (modifier && strcmp(modifier, "__func_kind__") == 0) - return Py_BuildValue("s", func_kind); + if (modifier) { +#if PYTHON_USES_UNICODE + PyUnicode_InternInPlace(&modifier); +#else + PyString_InternInPlace(&modifier); +#endif + if (modifier == Shiboken::PyMagicName::func_kind()) + return Py_BuildValue("O", func_kind); + } Shiboken::AutoDecRef key(modifier == nullptr - ? Py_BuildValue("s", func_kind) - : Py_BuildValue("(ss)", func_kind, modifier)); + ? Py_BuildValue("O", func_kind) + : Py_BuildValue("(OO)", func_kind, modifier)); PyObject *value = PyDict_GetItem(props, key); if (value == nullptr) { // we need to compute a signature object @@ -454,11 +464,11 @@ GetSignature_Cached(PyObject *props, const char *func_kind, const char *modifier } static const char *PySide_CompressedSignaturePackage[] = { -#include "embed/signature.inc" +#include "embed/signature_inc.h" }; static const unsigned char PySide_SignatureLoader[] = { -#include "embed/signature_bootstrap.inc" +#include "embed/signature_bootstrap_inc.h" }; static safe_globals_struc * @@ -477,13 +487,10 @@ init_phase_1(void) #ifdef Py_LIMITED_API // We must work for multiple versions, so use source code. #else - Shiboken::AutoDecRef marshal_str(Py_BuildValue("s", "marshal")); - if (marshal_str.isNull()) - goto error; - Shiboken::AutoDecRef marshal_module(PyImport_Import(marshal_str)); + Shiboken::AutoDecRef marshal_module(PyImport_Import(Shiboken::PyName::marshal())); if (marshal_module.isNull()) goto error; - Shiboken::AutoDecRef loads(PyObject_GetAttrString(marshal_module, "loads")); + Shiboken::AutoDecRef loads(PyObject_GetAttr(marshal_module, Shiboken::PyName::loads())); if (loads.isNull()) goto error; #endif @@ -495,7 +502,7 @@ init_phase_1(void) goto error; #ifdef Py_LIMITED_API PyObject *builtins = PyEval_GetBuiltins(); - PyObject *compile = PyDict_GetItemString(builtins, "compile"); + PyObject *compile = PyDict_GetItem(builtins, Shiboken::PyName::compile()); if (compile == nullptr) goto error; Shiboken::AutoDecRef code_obj(PyObject_CallFunction(compile, "Oss", @@ -512,7 +519,7 @@ init_phase_1(void) goto error; // Initialize the module PyObject *mdict = PyModule_GetDict(p->helper_module); - if (PyDict_SetItemString(mdict, "__builtins__", PyEval_GetBuiltins()) < 0) + if (PyDict_SetItem(mdict, Shiboken::PyMagicName::builtins(), PyEval_GetBuiltins()) < 0) goto error; /* * Unpack an embedded ZIP file with more signature modules. @@ -551,11 +558,14 @@ 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: PyErr_Print(); - PyErr_SetString(PyExc_SystemError, "could not initialize part 1"); + Py_FatalError("could not initialize part 1"); return nullptr; } @@ -593,11 +603,14 @@ 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; } error: PyErr_Print(); - PyErr_SetString(PyExc_SystemError, "could not initialize part 2"); + Py_FatalError("could not initialize part 2"); return -1; } @@ -795,7 +808,7 @@ static PyGetSetDef new_PyWrapperDescr_getsets[] = { // static PyObject * -get_signature_intern(PyObject *ob, const char *modifier) +get_signature_intern(PyObject *ob, PyObject *modifier) { if (PyType_IsSubtype(Py_TYPE(ob), &PyCFunction_Type)) return pyside_cf_get___signature__(ob, modifier); @@ -814,11 +827,11 @@ static PyObject * get_signature(PyObject * /* self */, PyObject *args) { PyObject *ob; - const char *modifier = nullptr; + PyObject *modifier = nullptr; init_module_1(); - if (!PyArg_ParseTuple(args, "O|s", &ob, &modifier)) + if (!PyArg_ParseTuple(args, "O|O", &ob, &modifier)) return nullptr; if (Py_TYPE(ob) == PepFunction_TypePtr) Py_RETURN_NONE; @@ -1030,7 +1043,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 @@ -1093,13 +1115,14 @@ _build_func_to_type(PyObject *obtype) * "{name}.overload". */ PyObject *descr = PyDict_GetItemString(dict, meth->ml_name); - const char *look_attr = meth->ml_flags & METH_STATIC ? "__func__" : "__name__"; + PyObject *look_attr = meth->ml_flags & METH_STATIC + ? Shiboken::PyMagicName::func() : Shiboken::PyMagicName::name(); int check_name = meth->ml_flags & METH_STATIC ? 0 : 1; if (descr == nullptr) return -1; // We first check all methods if one is hidden by something else. - Shiboken::AutoDecRef look(PyObject_GetAttrString(descr, look_attr)); + Shiboken::AutoDecRef look(PyObject_GetAttr(descr, look_attr)); Shiboken::AutoDecRef given(Py_BuildValue("s", meth->ml_name)); if (look.isNull() || (check_name && PyObject_RichCompareBool(look, given, Py_EQ) != 1)) { @@ -1206,7 +1229,7 @@ SetError_Argument(PyObject *args, const char *func_name) */ PyObject * -Sbk_TypeGet___signature__(PyObject *ob, const char *modifier) +Sbk_TypeGet___signature__(PyObject *ob, PyObject *modifier) { return pyside_tp_get___signature__(ob, modifier); } diff --git a/sources/shiboken2/libshiboken/signature.h b/sources/shiboken2/libshiboken/signature.h index 57fd4047a..b22a78497 100644 --- a/sources/shiboken2/libshiboken/signature.h +++ b/sources/shiboken2/libshiboken/signature.h @@ -48,7 +48,7 @@ extern "C" LIBSHIBOKEN_API int SbkSpecial_Type_Ready(PyObject *, PyTypeObject *, const char *[]); LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *[]); LIBSHIBOKEN_API void SetError_Argument(PyObject *, const char *); -LIBSHIBOKEN_API PyObject *Sbk_TypeGet___signature__(PyObject *, const char *); +LIBSHIBOKEN_API PyObject *Sbk_TypeGet___signature__(PyObject *, PyObject *); LIBSHIBOKEN_API PyObject *Sbk_TypeGet___doc__(PyObject *); } // extern "C" diff --git a/sources/shiboken2/libshiboken/signature_doc.rst b/sources/shiboken2/libshiboken/signature_doc.rst index 9c42c5976..a984de4ce 100644 --- a/sources/shiboken2/libshiboken/signature_doc.rst +++ b/sources/shiboken2/libshiboken/signature_doc.rst @@ -73,8 +73,8 @@ It calls ``GetSignature_Function`` which returns the signature if it is found. Why this Code is Fast --------------------- -It costs a little time (maybe 4 seconds) to run througs every single signature -object, since these are more than 15000 Python objects. But all the signature +It costs a little time (maybe 6 seconds) to run througs every single signature +object, since these are more than 25000 Python objects. But all the signature objects will be rarely accessed but in special applications. The normal case are only a few accesses, and these are working pretty fast. @@ -111,10 +111,6 @@ the ``signature`` Python package. It has the following structure:: shiboken2/files.dir/shibokensupport/ backport_inspect.py - python_minilib_2_7.py - python_minilib_3_5.py - python_minilib_3_6.py - python_minilib_3_7.py signature/ loader.py @@ -125,6 +121,8 @@ the ``signature`` Python package. It has the following structure:: lib/ enum_sig.py + tool.py + Really important are the **parser**, **mapping**, **errorhandler**, **enum_sig**, diff --git a/sources/shiboken2/libshiboken/typespec.cpp b/sources/shiboken2/libshiboken/typespec.cpp index 6dc5b00bc..510ed51e6 100644 --- a/sources/shiboken2/libshiboken/typespec.cpp +++ b/sources/shiboken2/libshiboken/typespec.cpp @@ -39,6 +39,7 @@ #include "sbkpython.h" #include "typespec.h" +#include "sbkstaticstrings.h" #include <structmember.h> #if PY_MAJOR_VERSION < 3 @@ -730,7 +731,7 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) } // no PyId_ things in Python 2 // err = _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname); - err = PyDict_SetItemString(type->tp_dict, "__module__", modname); + err = PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::module(), modname); Py_DECREF(modname); if (err != 0) goto fail; |