diff options
author | Christian Tismer <tismer@stackless.com> | 2021-10-26 17:38:46 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-10-28 16:15:28 +0000 |
commit | ec3a7035e8415e8b9067519069c6f5b1cfde15df (patch) | |
tree | 85cded3b932239cda746c5aa8fdb5ecdb721632f /sources | |
parent | 6c98706c5148f0b60aa92d9e63571309967fc2b4 (diff) |
__feature__: handle properties with function overloads
This is the implementation, see the conclusion of the issue.
[ChangeLog][PySide6] When a property would override an
existing function with multiple arity or parameters,
append an underscore to the property name.
REMARK: The current implementation is very correct. It uses
introspection via the signature module.
But that adds a constant overhead to the true_property
feature. Actually, there are only 2 known cases where this
overlap happens. It might be considered to simplify things
by checking the string names of these two functions?
Fixes: PYSIDE-1670
Change-Id: I14927995698726957ba8c515dddf5e37c21910ce
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit bee4cd31d60f3b35a37a2eb98fdfc60ba76cfe1c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside6/doc/feature-why.rst | 30 | ||||
-rw-r--r-- | sources/pyside6/libpyside/feature_select.cpp | 32 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysidestaticstrings.cpp | 1 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysidestaticstrings.h | 1 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/signature/signature_p.h | 2 |
5 files changed, 65 insertions, 1 deletions
diff --git a/sources/pyside6/doc/feature-why.rst b/sources/pyside6/doc/feature-why.rst index a2f3e146b..a795e640c 100644 --- a/sources/pyside6/doc/feature-why.rst +++ b/sources/pyside6/doc/feature-why.rst @@ -220,6 +220,36 @@ the Qt documentation, it would be easier to add all properties that should be properties and are obviously missing. +Name Clashes and Solution +------------------------- + +There are some rare cases where a property already exists as a function, +either with multiple signatures or having parameters. +This is not very nice in C++ as well, but for Python this is forbidden. +Example: + +.. code-block:: python + + >>> from PySide6 import * + >>> import pprint + >>> pprint.pprint(QtCore.QTimer.singleShot.__signature__) + [<Signature (arg__1: int, arg__2: Callable) -> None>, + <Signature (msec: int, receiver: PySide6.QtCore.QObject, member: bytes) -> None>, + <Signature (msec: int, timerType: PySide6.QtCore.Qt.TimerType, + receiver: PySide6.QtCore.QObject, member: bytes) -> None>] + +When creating this property, we respect the existing function and use a slightly +different name for the property by appending an underscore. + +.. code-block:: python + + >>> from __feature__ import true_property + >>> QtCore.QTimer.singleShot_ + <property object at 0x118e5f8b0> + +We hope that these clashes can be removed in future Qt versions. + + The __feature__ import ====================== diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp index 8b9834620..c82cccce1 100644 --- a/sources/pyside6/libpyside/feature_select.cpp +++ b/sources/pyside6/libpyside/feature_select.cpp @@ -44,6 +44,7 @@ #include <shiboken.h> #include <sbkfeature_base.h> +#include <signature_p.h> ////////////////////////////////////////////////////////////////////////////// // @@ -613,6 +614,34 @@ static PyObject *make_snake_case(QString s, bool lower) return String::getSnakeCaseName(s.toLatin1().data(), lower); } +PyObject *adjustPropertyName(PyObject *dict, PyObject *name) +{ + // PYSIDE-1670: If this is a function with multiple arity or with + // parameters, we use a mangled name for the property. + PyObject *existing = PyDict_GetItem(dict, name); // borrowed + if (existing) { + Shiboken::AutoDecRef sig(get_signature_intern(existing, nullptr)); + if (sig.object()) { + bool name_clash = false; + if (PyList_CheckExact(sig)) { + name_clash = true; + } else { + Shiboken::AutoDecRef params(PyObject_GetAttr(sig, PyName::parameters())); + // Are there parameters except self or cls? + if (PyObject_Size(params.object()) > 1) + name_clash = true; + } + if (name_clash) { + // PyPy has no PyUnicode_AppendAndDel function, yet + Shiboken::AutoDecRef hold(name); + Shiboken::AutoDecRef under(Py_BuildValue("s", "_")); + name = PyUnicode_Concat(hold, under); + } + } + } + return name; +} + static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, int id) { /* @@ -652,6 +681,9 @@ static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, in continue; PyObject *setter = haveWrite ? PyDict_GetItem(prev_dict, write) : nullptr; + // PYSIDE-1670: If multiple arities exist as a property name, rename it. + name = adjustPropertyName(prop_dict, name); + AutoDecRef PyProperty(createProperty(type, getter, setter)); if (PyProperty.isNull()) return false; diff --git a/sources/pyside6/libpyside/pysidestaticstrings.cpp b/sources/pyside6/libpyside/pysidestaticstrings.cpp index 8f74cd19f..ddaf07a79 100644 --- a/sources/pyside6/libpyside/pysidestaticstrings.cpp +++ b/sources/pyside6/libpyside/pysidestaticstrings.cpp @@ -59,6 +59,7 @@ STATIC_STRING_IMPL(dict_ring, "dict_ring") STATIC_STRING_IMPL(im_func, "im_func") STATIC_STRING_IMPL(im_self, "im_self") STATIC_STRING_IMPL(name, "name") +STATIC_STRING_IMPL(parameters, "parameters") STATIC_STRING_IMPL(property, "property") STATIC_STRING_IMPL(select_id, "select_id") } // namespace PyName diff --git a/sources/pyside6/libpyside/pysidestaticstrings.h b/sources/pyside6/libpyside/pysidestaticstrings.h index 86e2515dc..43544f489 100644 --- a/sources/pyside6/libpyside/pysidestaticstrings.h +++ b/sources/pyside6/libpyside/pysidestaticstrings.h @@ -54,6 +54,7 @@ PyObject *dict_ring(); PyObject *im_func(); PyObject *im_self(); PyObject *name(); +PyObject *parameters(); PyObject *property(); PyObject *select_id(); } // namespace PyName diff --git a/sources/shiboken6/libshiboken/signature/signature_p.h b/sources/shiboken6/libshiboken/signature/signature_p.h index 7e622f3f1..029cd7cca 100644 --- a/sources/shiboken6/libshiboken/signature/signature_p.h +++ b/sources/shiboken6/libshiboken/signature/signature_p.h @@ -76,7 +76,7 @@ PyObject *GetSignature_Function(PyObject *, PyObject *); PyObject *GetSignature_TypeMod(PyObject *, PyObject *); PyObject *GetSignature_Wrapper(PyObject *, PyObject *); -PyObject *get_signature_intern(PyObject *ob, PyObject *modifier); +LIBSHIBOKEN_API PyObject *get_signature_intern(PyObject *ob, PyObject *modifier); PyObject *PySide_BuildSignatureProps(PyObject *class_mod); PyObject *GetClassOrModOf(PyObject *ob); |