aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp7
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp10
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h8
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp31
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp47
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h2
-rw-r--r--sources/shiboken2/tests/libsample/modifications.cpp19
-rw-r--r--sources/shiboken2/tests/libsample/modifications.h8
-rw-r--r--sources/shiboken2/tests/samplebinding/modifications_test.py8
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml10
10 files changed, 141 insertions, 9 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index f16a142b3..6b230f1f4 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -1613,7 +1613,12 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction);
}
} else {
- metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction);
+ auto type = AbstractMetaFunction::NormalFunction;
+ if (metaFunction->name() == QLatin1String("__getattro__"))
+ type = AbstractMetaFunction::GetAttroFunction;
+ else if (metaFunction->name() == QLatin1String("__setattro__"))
+ type = AbstractMetaFunction::SetAttroFunction;
+ metaFunction->setFunctionType(type);
}
metaFunction->setDeclaringClass(metaClass);
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 1b2ee5568..390143cda 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -2065,6 +2065,16 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue
if ((query & GenerateExceptionHandling) && !f->generateExceptionHandling())
return false;
+ if (query.testFlag(GetAttroFunction)
+ && f->functionType() != AbstractMetaFunction::GetAttroFunction) {
+ return false;
+ }
+
+ if (query.testFlag(SetAttroFunction)
+ && f->functionType() != AbstractMetaFunction::SetAttroFunction) {
+ return false;
+ }
+
return true;
}
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index 7db5ec1bd..00f137100 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -763,7 +763,9 @@ public:
SignalFunction,
EmptyFunction,
SlotFunction,
- GlobalScopeFunction
+ GlobalScopeFunction,
+ GetAttroFunction,
+ SetAttroFunction
};
Q_ENUM(FunctionType)
@@ -1271,7 +1273,9 @@ public:
VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang
NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang
OperatorOverloads = 0x2000000, // Only functions that are operator overloads
- GenerateExceptionHandling = 0x4000000
+ GenerateExceptionHandling = 0x4000000,
+ GetAttroFunction = 0x8000000,
+ SetAttroFunction = 0x10000000
};
Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption)
Q_FLAG(FunctionQueryOption)
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 724b390e0..166a31dfd 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -5308,6 +5308,22 @@ void CppGenerator::writeSetattroFunction(QTextStream &s, AttroCheck attroCheck,
Indentation indent(INDENT);
s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);\n";
}
+
+ if (attroCheck.testFlag(AttroCheckFlag::SetattroUser)) {
+ auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::SetAttroFunction);
+ Q_ASSERT(func);
+ s << INDENT << "{\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n";
+ writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, metaClass);
+ }
+ s << INDENT << "}\n";
+ }
+
writeSetattroDefaultReturn(s);
}
@@ -5412,6 +5428,21 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, AttroCheck attroCheck,
}
}
+ if (attroCheck.testFlag(AttroCheckFlag::GetattroUser)) {
+ auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::GetAttroFunction);
+ Q_ASSERT(func);
+ s << INDENT << "{\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n";
+ writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, metaClass);
+ }
+ s << INDENT << "}\n";
+ }
+
s << INDENT << "return " << getattrFunc << ";\n}\n\n";
}
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 90ae4299d..47cca8173 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -1555,16 +1555,34 @@ void ShibokenGenerator::writeUnusedVariableCast(QTextStream &s, const QString &v
s << INDENT << "SBK_UNUSED(" << variableName<< ")\n";
}
+static bool filterFunction(const AbstractMetaFunction *func, bool avoidProtectedHack)
+{
+ switch (func->functionType()) {
+ case AbstractMetaFunction::DestructorFunction:
+ case AbstractMetaFunction::SignalFunction:
+ case AbstractMetaFunction::GetAttroFunction:
+ case AbstractMetaFunction::SetAttroFunction:
+ return false;
+ default:
+ break;
+ }
+ if (func->usesRValueReferences())
+ return false;
+ if (func->isModifiedRemoved() && !func->isAbstract()
+ && (!avoidProtectedHack || !func->isProtected())) {
+ return false;
+ }
+ return true;
+}
+
AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass *metaClass)
{
AbstractMetaFunctionList result;
const AbstractMetaFunctionList &funcs = metaClass->functions();
+ result.reserve(funcs.size());
for (AbstractMetaFunction *func : funcs) {
- if (func->isSignal() || func->isDestructor() || func->usesRValueReferences()
- || (func->isModifiedRemoved() && !func->isAbstract()
- && (!avoidProtectedHack() || !func->isProtected())))
- continue;
- result << func;
+ if (filterFunction(func, avoidProtectedHack()))
+ result.append(func);
}
return result;
}
@@ -2199,10 +2217,18 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A
} else {
if (getGeneratorClassInfo(metaClass).needsGetattroFunction)
result |= AttroCheckFlag::GetattroOverloads;
+ if (metaClass->queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::GetAttroFunction)) {
+ result |= AttroCheckFlag::GetattroUser;
+ }
if (usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))
result |= AttroCheckFlag::SetattroQObject;
if (useOverrideCaching(metaClass))
result |= AttroCheckFlag::SetattroMethodOverride;
+ if (metaClass->queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::SetAttroFunction)) {
+ result |= AttroCheckFlag::SetattroUser;
+ }
// PYSIDE-1255: If setattro is generated for a class inheriting
// QObject, the property code needs to be generated, too.
if ((result & AttroCheckFlag::SetattroMask) != 0
@@ -2380,7 +2406,16 @@ static void dumpFunction(AbstractMetaFunctionList lst)
static bool isGroupable(const AbstractMetaFunction *func)
{
- if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract()))
+ switch (func->functionType()) {
+ case AbstractMetaFunction::DestructorFunction:
+ case AbstractMetaFunction::SignalFunction:
+ case AbstractMetaFunction::GetAttroFunction:
+ case AbstractMetaFunction::SetAttroFunction:
+ return false;
+ default:
+ break;
+ }
+ if (func->isModifiedRemoved() && !func->isAbstract())
return false;
// weird operator overloads
if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators?
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
index 2ad5ffbdf..0d4b1344a 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -69,10 +69,12 @@ public:
None = 0x0,
GetattroOverloads = 0x01,
GetattroSmartPointer = 0x02,
+ GetattroUser = 0x04, // Injected code
GetattroMask = 0x0F,
SetattroQObject = 0x10,
SetattroSmartPointer = 0x20,
SetattroMethodOverride = 0x40,
+ SetattroUser = 0x80, // Injected code
SetattroMask = 0xF0,
};
Q_DECLARE_FLAGS(AttroCheck, AttroCheckFlag);
diff --git a/sources/shiboken2/tests/libsample/modifications.cpp b/sources/shiboken2/tests/libsample/modifications.cpp
index 56ba81875..627d17b45 100644
--- a/sources/shiboken2/tests/libsample/modifications.cpp
+++ b/sources/shiboken2/tests/libsample/modifications.cpp
@@ -165,3 +165,22 @@ Modifications::TestEnum Modifications::defaultEnumValue() const
return TestEnumValue2;
}
+bool Modifications::wasGetAttroCalled() const
+{
+ return m_getAttroCalled;
+}
+
+void Modifications::notifyGetAttroCalled()
+{
+ m_getAttroCalled = true;
+}
+
+bool Modifications::wasSetAttroCalled() const
+{
+ return m_setAttroCalled;
+}
+
+void Modifications::notifySetAttroCalled()
+{
+ m_setAttroCalled = true;
+}
diff --git a/sources/shiboken2/tests/libsample/modifications.h b/sources/shiboken2/tests/libsample/modifications.h
index 674a05f27..888c66d18 100644
--- a/sources/shiboken2/tests/libsample/modifications.h
+++ b/sources/shiboken2/tests/libsample/modifications.h
@@ -132,9 +132,17 @@ public:
TestEnum enumValue() const;
TestEnum defaultEnumValue() const;
+ bool wasGetAttroCalled() const;
+ void notifyGetAttroCalled();
+
+ bool wasSetAttroCalled() const;
+ void notifySetAttroCalled();
+
private:
ObjectType* m_object;
TestEnum m_enumValue = TestEnumValue1;
+ bool m_getAttroCalled = false;
+ bool m_setAttroCalled = false;
};
class LIBSAMPLE_API AbstractModifications : public Modifications
diff --git a/sources/shiboken2/tests/samplebinding/modifications_test.py b/sources/shiboken2/tests/samplebinding/modifications_test.py
index e6e9c5626..763ba04e5 100644
--- a/sources/shiboken2/tests/samplebinding/modifications_test.py
+++ b/sources/shiboken2/tests/samplebinding/modifications_test.py
@@ -235,6 +235,14 @@ class ModificationsTest(unittest.TestCase):
modifications.setEnumValue()
self.assertEqual(modifications.enumValue(), Modifications.TestEnumValue2)
+ def testSetGetAttro(self):
+ modifications = Modifications()
+ self.assertFalse(modifications.wasSetAttroCalled())
+ setattr(modifications, 'Foo', 'Bar')
+ self.assertTrue(modifications.wasSetAttroCalled())
+ self.assertEqual(getattr(modifications, 'Foo'), 'Bar')
+ self.assertTrue(modifications.wasGetAttroCalled())
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
index c3db91324..32df8fd7b 100644
--- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
@@ -1293,6 +1293,16 @@
<replace-default-expression with="cppSelf->defaultEnumValue()"/>
</modify-argument>
</modify-function>
+ <add-function signature="__getattro__" return-type="PyObject *">
+ <inject-code class="target" position="beginning">
+ cppSelf->notifyGetAttroCalled();
+ </inject-code>
+ </add-function>
+ <add-function signature="__setattro__" return-type="int">
+ <inject-code class="target" position="beginning">
+ cppSelf->notifySetAttroCalled();
+ </inject-code>
+ </add-function>
</object-type>
<object-type name="AbstractModifications">