aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2021-10-26 17:38:46 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-10-28 16:15:28 +0000
commitec3a7035e8415e8b9067519069c6f5b1cfde15df (patch)
tree85cded3b932239cda746c5aa8fdb5ecdb721632f /sources
parent6c98706c5148f0b60aa92d9e63571309967fc2b4 (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.rst30
-rw-r--r--sources/pyside6/libpyside/feature_select.cpp32
-rw-r--r--sources/pyside6/libpyside/pysidestaticstrings.cpp1
-rw-r--r--sources/pyside6/libpyside/pysidestaticstrings.h1
-rw-r--r--sources/shiboken6/libshiboken/signature/signature_p.h2
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);