diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2025-11-03 09:53:13 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2025-11-03 14:10:00 +0100 |
| commit | 2aff6a35a9aa2f233c9801456daa6986437d2647 (patch) | |
| tree | a677819e66ba4fd6cf59f408eb8f313bb2659c1a /sources/pyside6/tests/pysidetest/properties_test.py | |
| parent | c1fbb035daf8940fd134bb9065da1154af225bd0 (diff) | |
PySide6/Property: Fix read-only properties when using the decorator syntax
The @setter decorator causes the property to be recreated with Py_None
set for the non-existent members, apparently due to a long-closed Python
bug (see_property_copy()). As a band-aid fix, check for Py_None.
Fixes: PYSIDE-3227
Pick-to: 6.10
Change-Id: Ib818e9930bd598306270377e26e625bfa9692a92
Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/pyside6/tests/pysidetest/properties_test.py')
| -rw-r--r-- | sources/pyside6/tests/pysidetest/properties_test.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/sources/pyside6/tests/pysidetest/properties_test.py b/sources/pyside6/tests/pysidetest/properties_test.py index 00d7aad1b..4452afe72 100644 --- a/sources/pyside6/tests/pysidetest/properties_test.py +++ b/sources/pyside6/tests/pysidetest/properties_test.py @@ -76,6 +76,40 @@ class TestDerivedObject(QStringListModel): notify=valueChanged) +class SpecialProperties(QObject): + _value = 1 + + def __init__(self): + super().__init__() + self._readWriteInt = 2 + self._readWriteDecoratedInt = 3 + + def readOnlyInt(self): # Class variable properties + return 4 + + def readWriteInt(self): + return self._readWriteInt + + def setReadWriteInt(self, v): + self._readWriteInt = v + + @Property(int) # Property decorators + def readOnlyDecoratedInt(self): + return 5 + + @Property(int) + def readWriteDecoratedInt(self): + return self._readWriteDecoratedInt + + @readWriteDecoratedInt.setter + def readWriteDecoratedInt(self, v): + self._readWriteDecoratedInt = v + + constantValue = Property(int, lambda self: self._value, constant=True) + readOnlyInt = Property(int, readOnlyInt) + readWriteInt = Property(int, readWriteInt, fset=setReadWriteInt) + + class PropertyTest(unittest.TestCase): def test1Object(self): @@ -104,6 +138,49 @@ class PropertyTest(unittest.TestCase): self.assertEqual(testObject.setter_called, 1) self.assertEqual(testObject.getter_called, 2) + def testSpecialProperties(self): + """PYSIDE-924, PYSIDE-3227, constant, read-only.""" + testObject = SpecialProperties() + mo = testObject.metaObject() + + i = mo.indexOfProperty("constantValue") + self.assertTrue(i != -1) + metaProperty = mo.property(i) + self.assertTrue(metaProperty.isConstant()) + self.assertEqual(testObject.constantValue, 1) + + i = mo.indexOfProperty("readWriteInt") + self.assertTrue(i != -1) + metaProperty = mo.property(i) + self.assertTrue(metaProperty.isWritable()) + self.assertEqual(testObject.readWriteInt, 2) + testObject.readWriteInt = 42 + self.assertEqual(testObject.readWriteInt, 42) + + i = mo.indexOfProperty("readWriteDecoratedInt") + self.assertTrue(i != -1) + metaProperty = mo.property(i) + self.assertTrue(metaProperty.isWritable()) + self.assertEqual(testObject.readWriteDecoratedInt, 3) + testObject.readWriteDecoratedInt = 42 + self.assertEqual(testObject.readWriteDecoratedInt, 42) + + i = mo.indexOfProperty("readOnlyInt") + self.assertTrue(i != -1) + metaProperty = mo.property(i) + self.assertFalse(metaProperty.isWritable()) + self.assertEqual(testObject.readOnlyInt, 4) + with self.assertRaises(AttributeError): + testObject.readOnlyInt = 42 + + i = mo.indexOfProperty("readOnlyDecoratedInt") + self.assertTrue(i != -1) + metaProperty = mo.property(i) + self.assertFalse(metaProperty.isWritable()) + self.assertEqual(testObject.readOnlyDecoratedInt, 5) + with self.assertRaises(AttributeError): + testObject.readOnlyDecoratedInt = 42 + if __name__ == '__main__': unittest.main() |
