aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/libpyside
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2020-10-07 19:25:47 +0200
committerChristian Tismer <tismer@stackless.com>2020-10-09 22:51:46 +0200
commit8847a47aad95d7f85d5e184071bf95c44826c4c7 (patch)
treefa68d8a0f6d481b73d305cbb63ca70d289c4be14 /sources/pyside2/libpyside
parent9d8a918d35c8de3400a5e0471e37981a2514c96f (diff)
feature_select: finish properties and postpone static properties
Static properties are not easy to support. They need an extra property subtype and support in the meta-class. A problem is that the implementation needs to go deeply into the innards of things and need to use `_PyType_Lookup`. That is hard to circumvent when the limited API is used. Therefore, the current implementation will be it for 5.15 . At most we might add a few missing properties through XML. Task-number: PYSIDE-1019 Change-Id: I56a9eabe5f774c1ff04c149227e06318c8bf4f29 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside2/libpyside')
-rw-r--r--sources/pyside2/libpyside/feature_select.cpp79
1 files changed, 76 insertions, 3 deletions
diff --git a/sources/pyside2/libpyside/feature_select.cpp b/sources/pyside2/libpyside/feature_select.cpp
index b26810add..6a21d168d 100644
--- a/sources/pyside2/libpyside/feature_select.cpp
+++ b/sources/pyside2/libpyside/feature_select.cpp
@@ -445,6 +445,8 @@ void finalize()
Py_DECREF(fast_id_array[idx]);
}
+static bool patch_property_impl();
+
void init()
{
// This function can be called multiple times.
@@ -457,6 +459,7 @@ void init()
featurePointer = featureProcArray;
initSelectableFeature(SelectFeatureSet);
registerCleanupFunction(finalize);
+ patch_property_impl();
is_initialized = true;
}
// Reset the cache. This is called at any "from __feature__ import".
@@ -551,9 +554,8 @@ static PyObject *createProperty(PyObject *getter, PyObject *setter)
assert(getter != nullptr);
if (setter == nullptr)
setter = Py_None;
- PyObject *prop = PyObject_CallObject(reinterpret_cast<PyObject *>(&PyProperty_Type), nullptr);
- AutoDecRef args(Py_BuildValue("OO", getter, setter));
- PyProperty_Type.tp_init(prop, args, nullptr);
+ auto obtype = reinterpret_cast<PyObject *>(&PyProperty_Type);
+ PyObject *prop = PyObject_CallFunctionObjArgs(obtype, getter, setter, nullptr);
return prop;
}
@@ -635,6 +637,77 @@ static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, in
//////////////////////////////////////////////////////////////////////////////
//
+// These are a number of patches to make Python's property object better
+// suitable for us.
+// We turn `__doc__` into a lazy attribute saving signature initialization.
+//
+// Currently, there is no static extension planned, because _PyType_Lookup
+// and Limited_API are hard to use at the same time.
+//
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *prop_get;
+ PyObject *prop_set;
+ PyObject *prop_del;
+ PyObject *prop_doc;
+ int getter_doc;
+} propertyobject;
+
+static PyObject *property_doc_get(PyObject *self, void *)
+{
+ auto po = reinterpret_cast<propertyobject *>(self);
+
+ if (po->prop_doc != nullptr && po->prop_doc != Py_None) {
+ Py_INCREF(po->prop_doc);
+ return po->prop_doc;
+ }
+ if (po->prop_get) {
+ // PYSIDE-1019: Fetch the default `__doc__` from fget. We do it late.
+ auto txt = PyObject_GetAttr(po->prop_get, PyMagicName::doc());
+ if (txt != nullptr) {
+ Py_INCREF(txt);
+ po->prop_doc = txt;
+ Py_INCREF(txt);
+ return txt;
+ }
+ PyErr_Clear();
+ }
+ Py_RETURN_NONE;
+}
+
+static int property_doc_set(PyObject *self, PyObject *value, void *)
+{
+ auto po = reinterpret_cast<propertyobject *>(self);
+
+ Py_INCREF(value);
+ po->prop_doc = value;
+ return 0;
+}
+
+static PyGetSetDef property_getset[] = {
+ // This gets added to the existing getsets
+ {const_cast<char *>("__doc__"), property_doc_get, property_doc_set, nullptr, nullptr},
+ {nullptr, nullptr, nullptr, nullptr, nullptr}
+};
+
+static bool patch_property_impl()
+{
+ // Turn `__doc__` into a computed attribute without changing writability.
+ auto gsp = property_getset;
+ auto type = &PyProperty_Type;
+ auto dict = type->tp_dict;
+ AutoDecRef descr(PyDescr_NewGetSet(type, gsp));
+ if (descr.isNull())
+ return false;
+ if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
+ return false;
+ // Replace property_descr_get/set by slightly changed versions
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
// PYSIDE-1019: Support switchable extensions
//
// Feature 0x04..0x40: A fake switchable option for testing