aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/pyside6/doc/extras/QtCore.ClassInfo.rst17
-rw-r--r--sources/pyside6/libpyside/pysideclassinfo.cpp22
-rw-r--r--sources/pyside6/tests/QtCore/classinfo_test.py29
3 files changed, 56 insertions, 12 deletions
diff --git a/sources/pyside6/doc/extras/QtCore.ClassInfo.rst b/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
index b767ae153..0cb6d32ed 100644
--- a/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
+++ b/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
@@ -4,20 +4,33 @@
ClassInfo
*********
-This class is used to associates extra information to the class, which is available
+This class is used to associate extra information to the class, which is available
using QObject.metaObject(). Qt and PySide doesn't use this information.
The extra information takes the form of a dictionary with key and value in a literal string.
+The recommended usage is to provide the key/value using python keyword syntax, where the
+keyword becomes the key, and the provided string becomes the value.
+
+If the key needs to contain special characters (spaces, commas, '::', start with a number, etc),
+it is also possible to pass a python dictionary with arbitrary strings for both the key and
+value and enabling special characters in the key.
+
.. note:: This Class is a implementation of Q_CLASSINFO macro.
-
+
Example
-------
::
+ # Recommended syntax
@ClassInfo(Author='PySide Team', URL='http://www.pyside.org')
class MyObject(QObject):
...
+
+ # Provided to support keys not supported by Python's keyword syntax
+ @ClassInfo({'Some key text $': 'This syntax supports special characters in keys'})
+ class MyObject(QObject):
+ ...
diff --git a/sources/pyside6/libpyside/pysideclassinfo.cpp b/sources/pyside6/libpyside/pysideclassinfo.cpp
index 6bd5a7650..01f72968d 100644
--- a/sources/pyside6/libpyside/pysideclassinfo.cpp
+++ b/sources/pyside6/libpyside/pysideclassinfo.cpp
@@ -136,8 +136,19 @@ static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject * /* args */, Py
int classInfoTpInit(PyObject *self, PyObject *args, PyObject *kwds)
{
- if (PyTuple_Check(args) && PyTuple_Size(args) > 0) {
- PyErr_Format(PyExc_TypeError, "ClassInfo() takes exactly 0 positional arguments (%zd given)", PyTuple_Size(args));
+ PyObject *infoDict = nullptr;
+ auto size = PyTuple_Size(args);
+ if (size == 1 && !kwds) {
+ PyObject *tmp = PyTuple_GET_ITEM(args, 0);
+ if (PyDict_Check(tmp))
+ infoDict = tmp;
+ } else if (size == 0 && kwds && PyDict_Check(kwds)) {
+ infoDict = kwds;
+ }
+
+ if (!infoDict) {
+ PyErr_Format(PyExc_TypeError, "ClassInfo() takes either keyword argument(s) or "
+ "a single dictionary argument");
return -1;
}
@@ -149,12 +160,13 @@ int classInfoTpInit(PyObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t pos = 0;
// PyDict_Next causes a segfault if kwds is empty
- if (kwds && PyDict_Check(kwds) && PyDict_Size(kwds) > 0) {
- while (PyDict_Next(kwds, &pos, &key, &value)) {
+ if (PyDict_Size(infoDict) > 0) {
+ while (PyDict_Next(infoDict, &pos, &key, &value)) {
if (Shiboken::String::check(key) && Shiboken::String::check(value)) {
pData->m_data[Shiboken::String::toCString(key)] = Shiboken::String::toCString(value);
} else {
- PyErr_SetString(PyExc_TypeError, "All keys and values provided to ClassInfo() must be strings");
+ PyErr_SetString(PyExc_TypeError, "All keys and values provided to ClassInfo() "
+ "must be strings");
return -1;
}
}
diff --git a/sources/pyside6/tests/QtCore/classinfo_test.py b/sources/pyside6/tests/QtCore/classinfo_test.py
index 7fed56bf7..697f9c8d8 100644
--- a/sources/pyside6/tests/QtCore/classinfo_test.py
+++ b/sources/pyside6/tests/QtCore/classinfo_test.py
@@ -57,6 +57,23 @@ class TestClassInfo(unittest.TestCase):
self.assertEqual(ci.name(), 'url')
self.assertEqual(ci.value(), 'http://www.pyside.org')
+ def test_dictionary(self):
+ @ClassInfo({'author':'pyside', 'author company':'The Qt Company'})
+ class MyObject(QObject):
+ pass
+
+ o = MyObject()
+ mo = o.metaObject()
+ self.assertEqual(mo.classInfoCount(), 2)
+
+ ci = mo.classInfo(0) # author
+ self.assertEqual(ci.name(), 'author')
+ self.assertEqual(ci.value(), 'pyside')
+
+ ci = mo.classInfo(1) # url
+ self.assertEqual(ci.name(), 'author company')
+ self.assertEqual(ci.value(), 'The Qt Company')
+
def test_verify_metadata_types(self):
valid_dict = { '123': '456' }
@@ -94,25 +111,27 @@ class TestClassInfo(unittest.TestCase):
self.assertRaises(TypeError, decorator, MyObject2)
def test_can_only_be_used_on_qobjects(self):
+ def make_info():
+ return ClassInfo(author='pyside')
def test_function():
pass
- self.assertRaises(TypeError, ClassInfo(), test_function)
+ self.assertRaises(TypeError, make_info(), test_function)
class NotAQObject(object):
pass
- self.assertRaises(TypeError, ClassInfo(), NotAQObject)
+ self.assertRaises(TypeError, make_info(), NotAQObject)
class QObjectSubclass(QObject):
pass
- ClassInfo()(QObjectSubclass)
+ make_info()(QObjectSubclass)
class SubclassOfNativeQObjectSubclass(QCoreApplication):
pass
- ClassInfo()(SubclassOfNativeQObjectSubclass)
+ make_info()(SubclassOfNativeQObjectSubclass)
class SubclassOfPythonQObjectSubclass(QObjectSubclass):
pass
- ClassInfo()(SubclassOfPythonQObjectSubclass)
+ make_info()(SubclassOfPythonQObjectSubclass)
if __name__ == '__main__':