From 159c5f0f017c91f932a2061dbf6bdb4f71c247d4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 5 Apr 2022 18:20:35 +0200 Subject: shiboken6: Add a function to check argument counts This reduces the generated code. Task-number: PYSIDE-661 Change-Id: I4d06fd9223a8e87fbe3a7e2d8c6a482e56a10cf5 Reviewed-by: Qt CI Bot Reviewed-by: Cristian Maureira-Fredes --- .../shiboken6/generator/shiboken/cppgenerator.cpp | 59 ++++++++-------------- sources/shiboken6/libshiboken/basewrapper.cpp | 16 ++++++ sources/shiboken6/libshiboken/basewrapper.h | 5 ++ 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index eeefae010..61f1679ed 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -2329,47 +2329,32 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData & bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); s << "// invalid argument lengths\n"; - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (usesNamedArguments) { - if (!ownerClassIsQObject) { - s << "if (numArgs > " << maxArgs << ") {\n"; - { - Indentation indent(s); - s << "static PyObject *const too_many = " - "Shiboken::String::createStaticString(\">\");\n" - << "errInfo.reset(too_many);\n" - << "Py_INCREF(errInfo.object());\n" - << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n"; - } - s << '}'; - } - if (minArgs > 0) { - if (!ownerClassIsQObject) - s << " else "; - s << "if (numArgs < " << minArgs << ") {\n"; - { - Indentation indent(s); - s << "static PyObject *const too_few = " - "Shiboken::String::createStaticString(\"<\");\n" - << "errInfo.reset(too_few);\n" - << "Py_INCREF(errInfo.object());\n" - << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n"; - } - s << '}'; - } + + // Disable argument count checks for QObject constructors to allow for + // passing properties as KW args. + auto *owner = rfunc->ownerClass(); + bool isQObjectConstructor = owner != nullptr && owner->isQObject() + && rfunc->functionType() == AbstractMetaFunction::ConstructorFunction; + + if (usesNamedArguments && !isQObjectConstructor) { + s << "errInfo.reset(Shiboken::checkInvalidArgumentCount(numArgs, " + << minArgs << ", " << maxArgs << "));\n" + << "if (!errInfo.isNull())\n" << indent + << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent; } + const QList invalidArgsLength = overloadData.invalidArgumentLengths(); if (!invalidArgsLength.isEmpty()) { - QStringList invArgsLen; - for (int i : qAsConst(invalidArgsLength)) - invArgsLen << u"numArgs == "_qs + QString::number(i); - if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0)) - s << " else "; - s << "if (" << invArgsLen.join(QLatin1String(" || ")) << ")\n"; - Indentation indent(s); - s << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; + s << "if ("; + for (qsizetype i = 0, size = invalidArgsLength.size(); i < size; ++i) { + if (i) + s << " || "; + s << "numArgs == " << invalidArgsLength.at(i); + } + s << ")\n" << indent + << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent; } - s << "\n\n"; + s << '\n'; QString funcName; if (rfunc->isOperatorOverload()) diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp index bc33d9c95..79a80f3c0 100644 --- a/sources/shiboken6/libshiboken/basewrapper.cpp +++ b/sources/shiboken6/libshiboken/basewrapper.cpp @@ -761,6 +761,22 @@ void setErrorAboutWrongArguments(PyObject *args, const char *funcName, PyObject SetError_Argument(args, funcName, info); } +PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, Py_ssize_t minArgs, Py_ssize_t maxArgs) +{ + PyObject *result = nullptr; + // for seterror_argument(), signature/errorhandler.py + if (numArgs > maxArgs) { + static PyObject *const tooMany = Shiboken::String::createStaticString(">"); + result = tooMany; + Py_INCREF(result); + } else if (numArgs < minArgs) { + static PyObject *const tooFew = Shiboken::String::createStaticString("<"); + result = tooFew; + Py_INCREF(result); + } + return result; +} + class FindBaseTypeVisitor : public HierarchyVisitor { public: diff --git a/sources/shiboken6/libshiboken/basewrapper.h b/sources/shiboken6/libshiboken/basewrapper.h index 3126557c0..682321653 100644 --- a/sources/shiboken6/libshiboken/basewrapper.h +++ b/sources/shiboken6/libshiboken/basewrapper.h @@ -169,6 +169,11 @@ void callCppDestructor(void *cptr) LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject *args, const char *funcName, PyObject *info); +// Return error information object if the argument count is wrong +LIBSHIBOKEN_API PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, + Py_ssize_t minArgs, + Py_ssize_t maxArgs); + namespace ObjectType { /** -- cgit v1.2.3