aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-07-01 16:06:29 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-07-02 16:51:12 +0200
commit9f0eb243cd264ae4f174ba38a1c958f42d338c80 (patch)
tree7955ddd930356f1c221a01a1b7a1d59f6a3120e4 /sources
parente2a3fa037b8133d857b34ddcecf1afe156095a4f (diff)
shiboken6: Add support for operator bool
[ChangeLog][shiboken6] operator bool can now be used for bool conversions (nb_bool) besides Qt-style isNull() methods. Add a command line option --use-operator-bool-as-nb_nonzero similar to use-isnull-as-nb_nonzero, enabling the use of operator bool for bool conversions. Make it possible to override both settings in typesystem XML. Task-number: PYSIDE-1334 Change-Id: I9c567e1b2cb97b22b41b3d9918046d793632160e Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.cpp29
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.h5
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp22
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h3
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp26
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.h7
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem_enums.h6
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp31
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp51
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp11
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h3
-rw-r--r--sources/shiboken6/tests/libsample/pen.cpp29
-rw-r--r--sources/shiboken6/tests/libsample/pen.h20
-rw-r--r--sources/shiboken6/tests/samplebinding/CMakeLists.txt1
-rw-r--r--sources/shiboken6/tests/samplebinding/nonzero_test.py13
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml3
16 files changed, 237 insertions, 23 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
index 5b344f6e1..334288ebf 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
@@ -223,6 +223,23 @@ void AbstractMetaFunction::setExplicit(bool isExplicit)
d->m_explicit = isExplicit;
}
+bool AbstractMetaFunction::returnsBool() const
+{
+ if (d->m_type.typeUsagePattern() != AbstractMetaType::PrimitivePattern)
+ return false;
+ auto *pte = static_cast<const PrimitiveTypeEntry *>(d->m_type.typeEntry());
+ // Walk along typedefs
+ while (auto *referencedPte = pte->referencedTypeEntry())
+ pte =referencedPte;
+ return pte->name() == u"bool";
+}
+
+bool AbstractMetaFunction::isOperatorBool() const
+{
+ return d->m_functionType == AbstractMetaFunction::ConversionOperator
+ && d->m_constant && returnsBool();
+}
+
AbstractMetaFunction::AbstractMetaFunction() : d(new AbstractMetaFunctionPrivate)
{
}
@@ -1100,6 +1117,18 @@ bool AbstractMetaFunction::isAssignmentOperator() const
|| d->m_functionType == MoveAssignmentOperatorFunction;
}
+bool AbstractMetaFunction::isGetter() const
+{
+ return d->m_functionType == NormalFunction && !isVoid()
+ && d->m_constant && d->m_access == Access::Public
+ && d->m_arguments.isEmpty();
+}
+
+bool AbstractMetaFunction::isQtIsNullMethod() const
+{
+ return isGetter() && d->m_name == u"isNull" && returnsBool();
+}
+
int AbstractMetaFunction::arityOfOperator() const
{
if (!isOperatorOverload() || isCallOperator())
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
index 177eb5ea2..9bdbafb3d 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
@@ -191,6 +191,8 @@ public:
bool isExplicit() const;
void setExplicit(bool isExplicit);
+ bool returnsBool() const;
+ bool isOperatorBool() const;
static bool isConversionOperator(const QString& funcName);
ExceptionSpecification exceptionSpecification() const;
@@ -210,6 +212,9 @@ public:
bool isLogicalOperator() const;
bool isSubscriptOperator() const;
bool isAssignmentOperator() const; // Assignment or move assignment
+ bool isGetter() const;
+ /// Returns whether it is a Qt-style isNull() method suitable for nb_bool
+ bool isQtIsNullMethod() const;
/**
* Informs the arity of the operator or -1 if the function is not
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
index 3c33f52bc..0caf4812e 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
@@ -607,6 +607,28 @@ AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(const QString &function
return AbstractMetaFunction::find(d->m_functions, functionName);
}
+AbstractMetaFunctionCPtr AbstractMetaClass::findOperatorBool() const
+{
+ auto it = std::find_if(d->m_functions.cbegin(), d->m_functions.cend(),
+ [](const AbstractMetaFunctionCPtr &f) {
+ return f->isOperatorBool();
+ });
+ if (it == d->m_functions.cend())
+ return {};
+ return *it;
+}
+
+AbstractMetaFunctionCPtr AbstractMetaClass::findQtIsNullMethod() const
+{
+ auto it = std::find_if(d->m_functions.cbegin(), d->m_functions.cend(),
+ [](const AbstractMetaFunctionCPtr &f) {
+ return f->isQtIsNullMethod();
+ });
+ if (it == d->m_functions.cend())
+ return {};
+ return *it;
+}
+
bool AbstractMetaClass::hasProtectedFunctions() const
{
for (const auto &func : d->m_functions) {
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h
index daa9eba1e..7b5ef4cc2 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h
@@ -95,6 +95,9 @@ public:
void addFunction(const AbstractMetaFunctionCPtr &function);
bool hasFunction(const QString &str) const;
AbstractMetaFunctionCPtr findFunction(const QString& functionName) const;
+ AbstractMetaFunctionCPtr findOperatorBool() const;
+ // Find a Qt-style isNull() method suitable for nb_bool
+ AbstractMetaFunctionCPtr findQtIsNullMethod() const;
bool hasSignal(const AbstractMetaFunction *f) const;
bool hasConstructors() const;
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index acc4f7009..c15abf69a 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -1179,6 +1179,8 @@ public:
TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified;
TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified;
TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Unspecified;
+ TypeSystem::BoolCast m_operatorBoolMode = TypeSystem::BoolCast::Unspecified;
+ TypeSystem::BoolCast m_isNullMode = TypeSystem::BoolCast::Unspecified;
};
ComplexTypeEntry::ComplexTypeEntry(const QString &entryName, TypeEntry::Type t,
@@ -1199,6 +1201,30 @@ void ComplexTypeEntry::setTypeFlags(TypeFlags flags)
d->m_typeFlags = flags;
}
+TypeSystem::BoolCast ComplexTypeEntry::operatorBoolMode() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_operatorBoolMode;
+}
+
+void ComplexTypeEntry::setOperatorBoolMode(TypeSystem::BoolCast b)
+{
+ S_D(ComplexTypeEntry);
+ d->m_operatorBoolMode = b;
+}
+
+TypeSystem::BoolCast ComplexTypeEntry::isNullMode() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_isNullMode;
+}
+
+void ComplexTypeEntry::setIsNullMode(TypeSystem::BoolCast b)
+{
+ S_D(ComplexTypeEntry);
+ d->m_isNullMode = b;
+}
+
ComplexTypeEntry::TypeFlags ComplexTypeEntry::typeFlags() const
{
S_D(const ComplexTypeEntry);
diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h
index 8d2169731..bd3d2c189 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.h
+++ b/sources/shiboken6/ApiExtractor/typesystem.h
@@ -513,6 +513,13 @@ public:
TypeFlags typeFlags() const;
void setTypeFlags(TypeFlags flags);
+ // Override command line options to generate nb_bool from
+ // operator bool or method isNull().
+ TypeSystem::BoolCast operatorBoolMode() const;
+ void setOperatorBoolMode(TypeSystem::BoolCast b);
+ TypeSystem::BoolCast isNullMode() const;
+ void setIsNullMode(TypeSystem::BoolCast b);
+
FunctionModificationList functionModifications() const;
void setFunctionModifications(const FunctionModificationList &functionModifications);
void addFunctionModification(const FunctionModification &functionModification);
diff --git a/sources/shiboken6/ApiExtractor/typesystem_enums.h b/sources/shiboken6/ApiExtractor/typesystem_enums.h
index 1953fef6a..1a972ec1f 100644
--- a/sources/shiboken6/ApiExtractor/typesystem_enums.h
+++ b/sources/shiboken6/ApiExtractor/typesystem_enums.h
@@ -92,6 +92,12 @@ enum Visibility { // For namespaces
Auto
};
+enum class BoolCast { // Generate nb_bool (overriding command line)
+ Unspecified,
+ Disabled,
+ Enabled
+};
+
enum : int { OverloadNumberUnset = -1, OverloadNumberDefault = 99999 };
} // namespace TypeSystem
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index bdab34126..c821a15e7 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -79,8 +79,10 @@ static inline QString generateGetSetDefAttribute() { return QStringLiteral("gene
static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); }
static inline QString indexAttribute() { return QStringLiteral("index"); }
static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); }
+static inline QString isNullAttribute() { return QStringLiteral("isNull"); }
static inline QString locationAttribute() { return QStringLiteral("location"); }
static inline QString modifiedTypeAttribute() { return QStringLiteral("modified-type"); }
+static inline QString operatorBoolAttribute() { return QStringLiteral("operator-bool"); }
static inline QString pyiTypeAttribute() { return QStringLiteral("pyi-type"); }
static inline QString overloadNumberAttribute() { return QStringLiteral("overload-number"); }
static inline QString ownershipAttribute() { return QStringLiteral("owner"); }
@@ -222,6 +224,17 @@ ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive,
};
ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive,
+ boolCastFromAttribute)
+ {
+ {u"yes", TypeSystem::BoolCast::Enabled},
+ {u"true", TypeSystem::BoolCast::Enabled},
+ {u"no", TypeSystem::BoolCast::Disabled},
+ {u"false", TypeSystem::BoolCast::Disabled},
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive,
languageFromAttribute)
{
@@ -1639,6 +1652,24 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
+ } else if (name == isNullAttribute()) {
+ const auto attribute = attributes->takeAt(i);
+ const auto boolCastOpt = boolCastFromAttribute(attribute.value());
+ if (boolCastOpt.has_value()) {
+ ctype->setIsNullMode(boolCastOpt.value());
+ } else {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgInvalidAttributeValue(attribute)));
+ }
+ } else if (name == operatorBoolAttribute()) {
+ const auto attribute = attributes->takeAt(i);
+ const auto boolCastOpt = boolCastFromAttribute(attribute.value());
+ if (boolCastOpt.has_value()) {
+ ctype->setOperatorBoolMode(boolCastOpt.value());
+ } else {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgInvalidAttributeValue(attribute)));
+ }
}
}
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 182e3a112..25f34bd40 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -279,19 +279,23 @@ QList<AbstractMetaFunctionCList>
AbstractMetaFunctionCPtr CppGenerator::boolCast(const AbstractMetaClass *metaClass) const
{
- if (!useIsNullAsNbNonZero())
- return {};
- // TODO: This could be configurable someday
- const auto func = metaClass->findFunction(QLatin1String("isNull"));
- if (func.isNull() || func->isVoid() || !func->type().typeEntry()->isPrimitive()
- || !func->isPublic()) {
- return {};
+ const auto *te = metaClass->typeEntry();
+ auto mode = te->operatorBoolMode();
+ if (useOperatorBoolAsNbNonZero()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findOperatorBool();
+ if (!func.isNull())
+ return func;
+ }
+
+ mode = te->isNullMode();
+ if (useIsNullAsNbNonZero()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findQtIsNullMethod();
+ if (!func.isNull())
+ return func;
}
- auto pte = static_cast<const PrimitiveTypeEntry *>(func->type().typeEntry());
- while (pte->referencedTypeEntry())
- pte = pte->referencedTypeEntry();
- return func->isConstant() && pte->name() == QLatin1String("bool")
- && func->arguments().isEmpty() ? func : AbstractMetaFunctionCPtr{};
+ return {};
}
std::optional<AbstractMetaType>
@@ -686,15 +690,20 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject *self)\n"
<< "{\n" << indent;
writeCppSelfDefinition(s, classContext);
- if (f->allowThread()) {
- s << "int result;\n"
- << BEGIN_ALLOW_THREADS << '\n'
- << "result = !" << CPP_SELF_VAR << "->isNull();\n"
- << END_ALLOW_THREADS << '\n'
- << "return result;\n";
- } else {
- s << "return !" << CPP_SELF_VAR << "->isNull();\n";
- }
+
+ const bool allowThread = f->allowThread();
+ if (allowThread)
+ s << "int result;\n" << BEGIN_ALLOW_THREADS << "\nresult = ";
+ else
+ s << "return ";
+
+ if (f->isOperatorBool())
+ s << '*' << CPP_SELF_VAR << " ? 1 : 0;\n";
+ else
+ s << CPP_SELF_VAR << "->isNull() ? 0 : 1;\n";
+
+ if (allowThread)
+ s << END_ALLOW_THREADS << "\nreturn result;\n";
s << outdent << "}\n\n";
}
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index 233b95776..ae187e536 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -57,6 +57,7 @@ static const char RETURN_VALUE_HEURISTIC[] = "enable-return-value-heuristic";
static const char ENABLE_PYSIDE_EXTENSIONS[] = "enable-pyside-extensions";
static const char DISABLE_VERBOSE_ERROR_MESSAGES[] = "disable-verbose-error-messages";
static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero";
+static const char USE_OPERATOR_BOOL_AS_NB_NONZERO[] = "use-operator-bool-as-nb_nonzero";
static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics";
const char *CPP_ARG = "cppArg";
@@ -2367,6 +2368,9 @@ Generator::OptionDescriptions ShibokenGenerator::options() const
{QLatin1String(USE_ISNULL_AS_NB_NONZERO),
QLatin1String("If a class have an isNull() const method, it will be used to compute\n"
"the value of boolean casts")},
+ {QLatin1String(USE_OPERATOR_BOOL_AS_NB_NONZERO),
+ QLatin1String("If a class has an operator bool, it will be used to compute\n"
+ "the value of boolean casts")},
{QLatin1String(WRAPPER_DIAGNOSTICS),
QLatin1String("Generate diagnostic code around wrappers")}
};
@@ -2384,6 +2388,8 @@ bool ShibokenGenerator::handleOption(const QString &key, const QString & /* valu
return (m_verboseErrorMessagesDisabled = true);
if (key == QLatin1String(USE_ISNULL_AS_NB_NONZERO))
return (m_useIsNullAsNbNonZero = true);
+ if (key == QLatin1String(USE_OPERATOR_BOOL_AS_NB_NONZERO))
+ return (m_useOperatorBoolAsNbNonZero = true);
if (key == QLatin1String(AVOID_PROTECTED_HACK))
return (m_avoidProtectedHack = true);
if (key == QLatin1String(WRAPPER_DIAGNOSTICS))
@@ -2491,6 +2497,11 @@ bool ShibokenGenerator::useIsNullAsNbNonZero() const
return m_useIsNullAsNbNonZero;
}
+bool ShibokenGenerator::useOperatorBoolAsNbNonZero() const
+{
+ return m_useOperatorBoolAsNbNonZero;
+}
+
bool ShibokenGenerator::avoidProtectedHack() const
{
return m_avoidProtectedHack;
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index ba904ea49..c4c93a600 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -325,6 +325,8 @@ protected:
bool useReturnValueHeuristic() const;
/// Returns true if the generator should use the result of isNull()const to compute boolean casts.
bool useIsNullAsNbNonZero() const;
+ /// Returns true if the generator should use operator bool to compute boolean casts.
+ bool useOperatorBoolAsNbNonZero() const;
/// Returns true if the generated code should use the "#define protected public" hack.
bool avoidProtectedHack() const;
static QString cppApiVariableName(const QString &moduleName = QString());
@@ -518,6 +520,7 @@ private:
bool m_usePySideExtensions = false;
bool m_verboseErrorMessagesDisabled = false;
bool m_useIsNullAsNbNonZero = false;
+ bool m_useOperatorBoolAsNbNonZero = false;
bool m_avoidProtectedHack = false;
bool m_wrapperDiagnostics = false;
diff --git a/sources/shiboken6/tests/libsample/pen.cpp b/sources/shiboken6/tests/libsample/pen.cpp
index 1f39e7cbb..e538a6a49 100644
--- a/sources/shiboken6/tests/libsample/pen.cpp
+++ b/sources/shiboken6/tests/libsample/pen.cpp
@@ -45,6 +45,35 @@ bool Color::isNull() const
return m_null;
}
+Brush::Brush(const Color &c) : m_color(c)
+{
+}
+
+Brush::operator bool() const
+{
+ return !m_color.isNull();
+}
+
+Brush::Style Brush::style() const
+{
+ return m_style;
+}
+
+void Brush::setStyle(Style newStyle)
+{
+ m_style = newStyle;
+}
+
+const Color &Brush::color() const
+{
+ return m_color;
+}
+
+void Brush::setColor(const Color &newColor)
+{
+ m_color = newColor;
+}
+
Pen::Pen() : m_ctor(EmptyCtor)
{
}
diff --git a/sources/shiboken6/tests/libsample/pen.h b/sources/shiboken6/tests/libsample/pen.h
index 20977fdeb..4feb9f540 100644
--- a/sources/shiboken6/tests/libsample/pen.h
+++ b/sources/shiboken6/tests/libsample/pen.h
@@ -44,6 +44,26 @@ private:
bool m_null;
};
+class LIBSAMPLE_API Brush
+{
+public:
+ enum Style { Solid, Cross };
+
+ explicit Brush(const Color &c = {});
+
+ operator bool() const;
+
+ Style style() const;
+ void setStyle(Style newStyle);
+
+ const Color &color() const;
+ void setColor(const Color &newColor);
+
+private:
+ Style m_style = Solid;
+ Color m_color;
+};
+
class LIBSAMPLE_API Pen
{
public:
diff --git a/sources/shiboken6/tests/samplebinding/CMakeLists.txt b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
index cfdc21041..558140279 100644
--- a/sources/shiboken6/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
@@ -15,6 +15,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/base4_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/base5_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/brush_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/bytearray_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/classwithfunctionpointer_wrapper.cpp
diff --git a/sources/shiboken6/tests/samplebinding/nonzero_test.py b/sources/shiboken6/tests/samplebinding/nonzero_test.py
index 0e14b674b..16f675547 100644
--- a/sources/shiboken6/tests/samplebinding/nonzero_test.py
+++ b/sources/shiboken6/tests/samplebinding/nonzero_test.py
@@ -38,14 +38,23 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Color, Brush
class TestNonZeroOperator(unittest.TestCase):
- def testIt(self):
+ def testColor(self):
+ """Color has a Qt-style isNull()"""
c = Color()
self.assertFalse(c)
c = Color(2)
self.assertTrue(c)
+ def testBrush(self):
+ """Brush enables its operator bool in the typesystem XML"""
+ b = Brush()
+ self.assertFalse(b)
+ b = Brush(Color(2))
+ self.assertTrue(b)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index d86a637ff..e479256b7 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -2324,6 +2324,9 @@
</value-type>
<value-type name="Color" />
+ <value-type name="Brush" operator-bool="true">
+ <enum-type name="Style"/>
+ </value-type>
<value-type name="Pen">
<enum-type identified-by-value="EnumCtor"/>
<enum-type name="RenderHints"/>