aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2020-06-13 00:41:37 +0200
committerChristian Tismer <tismer@stackless.com>2020-07-10 11:06:45 +0200
commit9a8beeeccf8c097cc4e6a216813353e67ac95ecc (patch)
treefe29c7748dc7abb0c18bbefaee5b639b0d9dad25 /sources/shiboken2/libshiboken
parent3d4d91334dc608a41963d9acb5080139202f33c5 (diff)
feature-select: Implement a selectable feature framework
This is the framework for selectable features. There are no real features implemented. Planned is a maximum of 8 features. They are all implemented as a dummy for now. The decision depends of the following setting at the beginning of a module after PySide2 import: from __feature__ import <feature name> For more info, see the Jira issue, section The Principle Of Selectable Features In PySide Task-number: PYSIDE-1019 Change-Id: If355e9294b5c16090b39d30422a90ea9c8523390 Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp39
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h3
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp53
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h7
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.cpp3
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.h3
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h1
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp59
-rw-r--r--sources/shiboken2/libshiboken/signature.h1
9 files changed, 110 insertions, 59 deletions
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 4c15582e9..5c2dc7807 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -95,12 +95,31 @@ void Sbk_object_dealloc(PyObject *self)
static void SbkObjectTypeDealloc(PyObject *pyObj);
static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
+static SelectableFeatureHook SelectFeatureSet = nullptr;
+
+void initSelectableFeature(SelectableFeatureHook func)
+{
+ SelectFeatureSet = func;
+}
+
+// PYSIDE-1019: Switch type's tp_dict to the currently active namespace.
+static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context)
+{
+ auto dict = type->tp_dict;
+ if (dict == NULL)
+ Py_RETURN_NONE;
+ if (SelectFeatureSet != nullptr)
+ dict = SelectFeatureSet(type);
+ return PyDictProxy_New(dict);
+}
+
// PYSIDE-908: The function PyType_Modified does not work in PySide, so we need to
// explicitly pass __doc__. For __signature__ it _did_ actually work, because
// it was not existing before. We add them both for clarity.
static PyGetSetDef SbkObjectType_Type_getsetlist[] = {
{const_cast<char *>("__signature__"), (getter)Sbk_TypeGet___signature__},
{const_cast<char *>("__doc__"), (getter)Sbk_TypeGet___doc__},
+ {const_cast<char *>("__dict__"), (getter)Sbk_TypeGet___dict__},
{nullptr} // Sentinel
};
@@ -121,8 +140,25 @@ static PyObject *SbkObjectType_repr(PyObject *type)
#endif // PY_VERSION_HEX < 0x03000000
+// PYSIDE-1019: Switch type's tp_dict to the currently active namespace.
+static PyObject *(*type_getattro)(PyObject *type, PyObject *name);
+
+static PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
+{
+ /*
+ * Note: This `type_getattro` version is only the default that comes
+ * from `PyType_Type.tp_getattro`. This does *not* interfere in any way
+ * with the complex `tp_getattro` of `QObject` and other instances.
+ * What we change here is the meta class of `QObject`.
+ */
+ if (SelectFeatureSet != nullptr)
+ type->tp_dict = SelectFeatureSet(type);
+ return type_getattro(reinterpret_cast<PyObject *>(type), name);
+}
+
static PyType_Slot SbkObjectType_Type_slots[] = {
{Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectTypeDealloc)},
+ {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)},
{Py_tp_setattro, reinterpret_cast<void *>(PyObject_GenericSetAttr)},
{Py_tp_base, static_cast<void *>(&PyType_Type)},
{Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
@@ -235,6 +271,9 @@ PyTypeObject *SbkObjectType_TypeF(void)
{
static PyTypeObject *type = nullptr;
if (!type) {
+ // PYSIDE-1019: Insert the default tp_getattro explicitly here
+ // so we can overwrite it a bit.
+ type_getattro = PyType_Type.tp_getattro;
SbkObjectType_Type_spec.basicsize =
PepHeapType_SIZE + sizeof(SbkObjectTypePrivate);
type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObjectType_Type_spec));
diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h
index 7248103cc..a4a8629fb 100644
--- a/sources/shiboken2/libshiboken/basewrapper.h
+++ b/sources/shiboken2/libshiboken/basewrapper.h
@@ -93,6 +93,9 @@ typedef void (*ObjectDestructor)(void *);
typedef void (*SubTypeInitHook)(SbkObjectType *, PyObject *, PyObject *);
+typedef PyObject *(*SelectableFeatureHook)(PyTypeObject *);
+LIBSHIBOKEN_API void initSelectableFeature(SelectableFeatureHook func);
+
extern LIBSHIBOKEN_API PyTypeObject *SbkObjectType_TypeF(void);
extern LIBSHIBOKEN_API SbkObjectType *SbkObject_TypeF(void);
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
index 5e0053e2e..4149bbcbf 100644
--- a/sources/shiboken2/libshiboken/pep384impl.cpp
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -78,14 +78,20 @@ static PyGetSetDef probe_getseters[] = {
{nullptr} /* Sentinel */
};
+static PyMemberDef probe_members[] = {
+ {nullptr} /* Sentinel */
+};
+
#define probe_tp_dealloc make_dummy(1)
#define probe_tp_repr make_dummy(2)
#define probe_tp_call make_dummy(3)
+#define probe_tp_getattro make_dummy(16)
#define probe_tp_str make_dummy(4)
#define probe_tp_traverse make_dummy(5)
#define probe_tp_clear make_dummy(6)
#define probe_tp_iternext make_dummy(7)
#define probe_tp_methods probe_methoddef
+#define probe_tp_members probe_members
#define probe_tp_getset probe_getseters
#define probe_tp_descr_get make_dummy(10)
#define probe_tp_init make_dummy(11)
@@ -101,11 +107,13 @@ static PyType_Slot typeprobe_slots[] = {
{Py_tp_dealloc, probe_tp_dealloc},
{Py_tp_repr, probe_tp_repr},
{Py_tp_call, probe_tp_call},
+ {Py_tp_getattro, probe_tp_getattro},
{Py_tp_str, probe_tp_str},
{Py_tp_traverse, probe_tp_traverse},
{Py_tp_clear, probe_tp_clear},
{Py_tp_iternext, probe_tp_iternext},
{Py_tp_methods, probe_tp_methods},
+ {Py_tp_members, probe_tp_members},
{Py_tp_getset, probe_tp_getset},
{Py_tp_descr_get, probe_tp_descr_get},
{Py_tp_init, probe_tp_init},
@@ -144,6 +152,7 @@ check_PyTypeObject_valid()
|| probe_tp_dealloc != check->tp_dealloc
|| probe_tp_repr != check->tp_repr
|| probe_tp_call != check->tp_call
+ || probe_tp_getattro != check->tp_getattro
|| probe_tp_str != check->tp_str
|| probe_tp_traverse != check->tp_traverse
|| probe_tp_clear != check->tp_clear
@@ -427,27 +436,6 @@ PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
#endif // Py_LIMITED_API
-// This is only a simple local helper that returns a computed variable.
-// Used also in Python 2.
-#if defined(Py_LIMITED_API) || defined(IS_PY2)
-static PyObject *
-PepRun_GetResult(const char *command)
-{
- PyObject *d, *v, *res;
-
- d = PyDict_New();
- 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_GetItem(d, Shiboken::PyName::result()) : nullptr;
- Py_XDECREF(v);
- Py_DECREF(d);
- return res;
-}
-#endif // defined(Py_LIMITED_API) || defined(IS_PY2)
-
/*****************************************************************************
*
* Support for classobject.h
@@ -669,6 +657,29 @@ PyImport_GetModule(PyObject *name)
#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+// 2020-06-16: For simplicity of creating arbitrary things, this function
+// is now made public.
+
+PyObject *
+PepRun_GetResult(const char *command)
+{
+ /*
+ * Evaluate a string and return the variable `result`
+ */
+ PyObject *d, *v, *res;
+
+ d = PyDict_New();
+ 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_GetItem(d, Shiboken::PyName::result()) : nullptr;
+ Py_XDECREF(v);
+ Py_DECREF(d);
+ return res;
+}
+
/*****************************************************************************
*
* Python 2 incompatibilities
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
index 2bfe52254..2a14d6543 100644
--- a/sources/shiboken2/libshiboken/pep384impl.h
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -98,7 +98,7 @@ typedef struct _typeobject {
void *X13; // hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
- void *X16; // getattrofunc tp_getattro;
+ getattrofunc tp_getattro;
void *X17; // setattrofunc tp_setattro;
void *X18; // PyBufferProcs *tp_as_buffer;
unsigned long tp_flags;
@@ -110,7 +110,7 @@ typedef struct _typeobject {
void *X25; // getiterfunc tp_iter;
iternextfunc tp_iternext;
struct PyMethodDef *tp_methods;
- void *X28; // struct PyMemberDef *tp_members;
+ struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
@@ -531,6 +531,9 @@ extern LIBSHIBOKEN_API PyTypeObject *PepMethodDescr_TypePtr;
LIBSHIBOKEN_API PyObject *PyImport_GetModule(PyObject *name);
#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+// Evaluate a script and return the variable `result`
+LIBSHIBOKEN_API PyObject *PepRun_GetResult(const char *command);
+
/*****************************************************************************
*
* Python 2 incompatibilities
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
index 541d74918..9dd98eef3 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
@@ -52,9 +52,11 @@ namespace Shiboken
{
namespace PyName {
// exported:
+STATIC_STRING_IMPL(dict_ring, "dict_ring")
STATIC_STRING_IMPL(dumps, "dumps")
STATIC_STRING_IMPL(loads, "loads")
STATIC_STRING_IMPL(result, "result")
+STATIC_STRING_IMPL(select_id, "select_id")
STATIC_STRING_IMPL(value, "value")
STATIC_STRING_IMPL(values, "values")
@@ -75,6 +77,7 @@ STATIC_STRING_IMPL(staticmethod, "staticmethod")
namespace PyMagicName {
// exported:
STATIC_STRING_IMPL(class_, "__class__")
+STATIC_STRING_IMPL(dict, "__dict__")
STATIC_STRING_IMPL(ecf, "__ecf__")
STATIC_STRING_IMPL(file, "__file__")
STATIC_STRING_IMPL(members, "__members__")
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h
index 4078d163c..ebb64579c 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.h
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h
@@ -49,11 +49,13 @@ namespace Shiboken
namespace PyName
{
LIBSHIBOKEN_API PyObject *co_name();
+LIBSHIBOKEN_API PyObject *dict_ring();
LIBSHIBOKEN_API PyObject *dumps();
LIBSHIBOKEN_API PyObject *f_code();
LIBSHIBOKEN_API PyObject *f_lineno();
LIBSHIBOKEN_API PyObject *loads();
LIBSHIBOKEN_API PyObject *result();
+LIBSHIBOKEN_API PyObject *select_id();
LIBSHIBOKEN_API PyObject *value();
LIBSHIBOKEN_API PyObject *values();
} // namespace PyName
@@ -61,6 +63,7 @@ LIBSHIBOKEN_API PyObject *values();
namespace PyMagicName
{
LIBSHIBOKEN_API PyObject *class_();
+LIBSHIBOKEN_API PyObject *dict();
LIBSHIBOKEN_API PyObject *ecf();
LIBSHIBOKEN_API PyObject *file();
LIBSHIBOKEN_API PyObject *members();
diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h
index 0d2d6b0a6..3e1df5235 100644
--- a/sources/shiboken2/libshiboken/shiboken.h
+++ b/sources/shiboken2/libshiboken/shiboken.h
@@ -55,6 +55,7 @@
#include "sbkstaticstrings.h"
#include "shibokenmacros.h"
#include "shibokenbuffer.h"
+#include "signature.h"
#endif // SHIBOKEN_H
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index b09b68d47..4614a131e 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -74,8 +74,8 @@ typedef struct safe_globals_struc {
PyObject *helper_module;
PyObject *arg_dict;
PyObject *map_dict;
- PyObject *value_dict; // for writing signatures
- PyObject *feature_dict; // registry for PySide.__feature__
+ PyObject *value_dict; // for writing signatures
+ PyObject *feature_dict; // registry for PySide.support.__feature__
// init part 2: run module
PyObject *pyside_type_init_func;
PyObject *create_signature_func;
@@ -653,22 +653,17 @@ _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp)
}
}
}
- PyMemberDef *md = type->tp_members;
- if (md != nullptr)
- for (; md->name != nullptr; md++)
- if (strcmp(md->name, name) == 0)
- return 1;
- // staticmethod has just a `__doc__` in the class
- assert(strcmp(type->tp_name, "staticmethod") == 0 && strcmp(name, "__doc__") == 0);
+ // staticmethod has just a __doc__ in the class
+ assert(strcmp(type->tp_name, "staticmethod") == 0);
return 0;
}
static int
-add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr)
+add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr)
{
/*
- * This function is used to assign a new `__signature__` attribute,
- * and also to override a `__doc__` or `__name__` attribute.
+ * This function is used to assign a new __signature__ attribute,
+ * and also to override a __doc__ attribute.
*/
assert(PyType_Check(type));
PyType_Ready(type);
@@ -676,11 +671,9 @@ add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr)
for (; gsp->name != nullptr; gsp++) {
PyObject *have_descr = PyDict_GetItemString(dict, gsp->name);
if (have_descr != nullptr) {
+ assert(strcmp(gsp->name, "__doc__") == 0);
Py_INCREF(have_descr);
- if (strcmp(gsp->name, "__doc__") == 0)
- *doc_descr = have_descr;
- else
- assert(false);
+ *old_descr = have_descr;
if (!_fixup_getset(type, gsp->name, gsp))
continue;
}
@@ -831,7 +824,7 @@ static PyGetSetDef new_PyWrapperDescr_getsets[] = {
//
// Additionally to the interface via __signature__, we also provide
// a general function, which allows for different signature layouts.
-// The "modifier" argument is a string that is passed in from 'loader.py'.
+// The "modifier" argument is a string that is passed in from loader.py .
// Configuration what the modifiers mean is completely in Python.
//
@@ -916,25 +909,13 @@ PySide_PatchTypes(void)
reinterpret_cast<PyObject *>(&PyString_Type), "split"));
Shiboken::AutoDecRef wrap_descr(PyObject_GetAttrString(
reinterpret_cast<PyObject *>(Py_TYPE(Py_True)), "__add__"));
- // abbreviations for readability
- auto md_gs = new_PyMethodDescr_getsets;
- auto md_doc = &old_md_doc_descr;
- auto cf_gs = new_PyCFunction_getsets;
- auto cf_doc = &old_cf_doc_descr;
- auto sm_gs = new_PyStaticMethod_getsets;
- auto sm_doc = &old_sm_doc_descr;
- auto tp_gs = new_PyType_getsets;
- auto tp_doc = &old_tp_doc_descr;
- auto wd_gs = new_PyWrapperDescr_getsets;
- auto wd_doc = &old_wd_doc_descr;
-
if (meth_descr.isNull() || wrap_descr.isNull()
|| PyType_Ready(Py_TYPE(meth_descr)) < 0
- || add_more_getsets(PepMethodDescr_TypePtr, md_gs, md_doc) < 0
- || add_more_getsets(&PyCFunction_Type, cf_gs, cf_doc) < 0
- || add_more_getsets(PepStaticMethod_TypePtr, sm_gs, sm_doc) < 0
- || add_more_getsets(&PyType_Type, tp_gs, tp_doc) < 0
- || add_more_getsets(Py_TYPE(wrap_descr), wd_gs, wd_doc) < 0
+ || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets, &old_md_doc_descr) < 0
+ || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets, &old_cf_doc_descr) < 0
+ || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets, &old_sm_doc_descr) < 0
+ || add_more_getsets(&PyType_Type, new_PyType_getsets, &old_tp_doc_descr) < 0
+ || add_more_getsets(Py_TYPE(wrap_descr), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0
)
return -1;
#ifndef _WIN32
@@ -1233,8 +1214,8 @@ FinishSignatureInitialization(PyObject *module, const char *signatures[])
* Still, it is not possible to call init phase 2 from here,
* because the import is still running. Do it from Python!
*/
- if ( PySide_PatchTypes() < 0
- || PySide_FinishSignatures(module, signatures) < 0) {
+ PySide_PatchTypes();
+ if (PySide_FinishSignatures(module, signatures) < 0) {
PyErr_Print();
PyErr_SetNone(PyExc_ImportError);
}
@@ -1285,4 +1266,10 @@ PyObject *Sbk_TypeGet___doc__(PyObject *ob)
return pyside_tp_get___doc__(ob);
}
+PyObject *GetFeatureDict()
+{
+ init_module_1();
+ return pyside_globals->feature_dict;
+}
+
} //extern "C"
diff --git a/sources/shiboken2/libshiboken/signature.h b/sources/shiboken2/libshiboken/signature.h
index b22a78497..2a69df9cf 100644
--- a/sources/shiboken2/libshiboken/signature.h
+++ b/sources/shiboken2/libshiboken/signature.h
@@ -50,6 +50,7 @@ LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *[]);
LIBSHIBOKEN_API void SetError_Argument(PyObject *, const char *);
LIBSHIBOKEN_API PyObject *Sbk_TypeGet___signature__(PyObject *, PyObject *);
LIBSHIBOKEN_API PyObject *Sbk_TypeGet___doc__(PyObject *);
+LIBSHIBOKEN_API PyObject *GetFeatureDict();
} // extern "C"