aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-05-17 20:31:52 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-05-18 13:15:10 +0000
commit06dd32d94cfc452b2d199d525455af6397f77f3a (patch)
treea87bd84b3c9361b39bd92de664c8bb0788a57044
parentba04130a9ece05644f35ebda12d319e86d71d020 (diff)
shiboken6: Introduce a struct for PyMethodDef
Instead of passing a maximum number of entries to write, add a data structure for PyMethodDef and pass lists of it. Task-number: PYSIDE-1202 Task-number: PYSIDE-1905 Change-Id: I110413aaedaf959aeac2c87f8fe0334f940a793d Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit ac9619647cf3cb94d57fac4daf955ad541beacb4) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/shiboken6/ApiExtractor/CMakeLists.txt1
-rw-r--r--sources/shiboken6/ApiExtractor/pymethoddefentry.cpp66
-rw-r--r--sources/shiboken6/ApiExtractor/pymethoddefentry.h53
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp74
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h10
5 files changed, 152 insertions, 52 deletions
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt
index db3916982..83f55360f 100644
--- a/sources/shiboken6/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt
@@ -27,6 +27,7 @@ messages.cpp
modifications.cpp
predefined_templates.cpp
propertyspec.cpp
+pymethoddefentry.cpp
reporthandler.cpp
sourcelocation.cpp
typeparser.cpp
diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp
new file mode 100644
index 000000000..770a8291a
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pymethoddefentry.h"
+#include "textstream.h"
+
+#include <QtCore/QDebug>
+
+TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e)
+{
+ s << "{\"" << e.name << "\", reinterpret_cast<PyCFunction>("
+ << e.function << "), ";
+ if (e.methFlags.isEmpty()) {
+ s << '0';
+ } else {
+ for (qsizetype i = 0, size = e.methFlags.size(); i < size; ++i) {
+ if (i)
+ s << '|';
+ s << e.methFlags.at(i);
+ }
+ }
+ s << '}';
+ return s;
+}
+
+TextStream &operator<<(TextStream &s, const PyMethodDefEntries &entries)
+{
+ for (const auto &e : entries)
+ s << e << ",\n";
+ return s;
+}
+
+QDebug operator<<(QDebug debug, const PyMethodDefEntry &e)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "PyMethodDefEntry(\"" << e.name << "\", " << e.function
+ << ", " << e.methFlags << ')';
+ return debug;
+}
diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.h b/sources/shiboken6/ApiExtractor/pymethoddefentry.h
new file mode 100644
index 000000000..1a0a0e0af
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYMETHODDEFENTRY_H
+#define PYMETHODDEFENTRY_H
+
+#include <QtCore/QByteArrayList>
+#include <QtCore/QString>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+class TextStream;
+
+struct PyMethodDefEntry
+{
+ QString name;
+ QString function;
+ QByteArrayList methFlags; // "METH_O" etc.
+};
+
+using PyMethodDefEntries = QList<PyMethodDefEntry>;
+
+TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e);
+TextStream &operator<<(TextStream &s, const PyMethodDefEntries &e);
+
+QDebug operator<<(QDebug debug, const PyMethodDefEntry &e);
+
+#endif // PYMETHODDEFENTRY_H
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 3f1c72988..64d99ef74 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -35,6 +35,7 @@
#include "pytypenames.h"
#include "fileout.h"
#include "overloaddata.h"
+#include "pymethoddefentry.h"
#include <abstractmetaenum.h>
#include <abstractmetafield.h>
#include <abstractmetafunction.h>
@@ -631,13 +632,14 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
// a separate PyMethodDef entry is written which is referenced
// in the PyMethodDef list and later in getattro() for handling
// the non-static case.
+ const auto defEntries = methodDefinitionEntries(overloadData);
if (OverloadData::hasStaticAndInstanceFunctions(overloads)) {
QString methDefName = cpythonMethodDefinitionName(rfunc);
- smd << "static PyMethodDef " << methDefName << " = " << indent;
- writeMethodDefinitionEntries(smd, overloadData, 1);
- smd << outdent << ";\n\n";
+ smd << "static PyMethodDef " << methDefName << " = " << indent
+ << defEntries.constFirst() << outdent << ";\n\n";
}
- writeMethodDefinition(md, overloadData);
+ if (!m_tpFuncs.contains(rfunc->name()))
+ md << defEntries;
}
}
const QString methodsDefinitions = md.toString();
@@ -929,7 +931,7 @@ void CppGenerator::writeMethodWrapper(TextStream &s, TextStream &definitionStrea
OverloadData overloadData(overloads, api());
writeMethodWrapper(s, overloadData, classContext);
writeSignatureInfo(signatureStream, overloadData);
- writeMethodDefinition(definitionStream, overloadData);
+ definitionStream << methodDefinitionEntries(overloadData);
}
void CppGenerator::writeCacheResetNative(TextStream &s, const GeneratorContext &classContext)
@@ -5277,68 +5279,48 @@ void CppGenerator::writeSmartPointerRichCompareFunction(TextStream &s,
writeRichCompareFunctionFooter(s, baseName);
}
-QString CppGenerator::methodDefinitionParameters(const OverloadData &overloadData) const
+// Return a flag combination for PyMethodDef
+QByteArrayList CppGenerator::methodDefinitionParameters(const OverloadData &overloadData) const
{
const bool usePyArgs = overloadData.pythonFunctionWrapperUsesListOfArguments();
- const auto func = overloadData.referenceFunction();
int min = overloadData.minArgs();
int max = overloadData.maxArgs();
- QString result;
- QTextStream s(&result);
- s << "reinterpret_cast<PyCFunction>("
- << cpythonFunctionName(func) << "), ";
+ QByteArrayList result;
if ((min == max) && (max < 2) && !usePyArgs) {
- if (max == 0)
- s << "METH_NOARGS";
- else
- s << "METH_O";
+ result.append(max == 0 ? QByteArrayLiteral("METH_NOARGS")
+ : QByteArrayLiteral("METH_O"));
} else {
- s << "METH_VARARGS";
+ result.append(QByteArrayLiteral("METH_VARARGS"));
if (overloadData.hasArgumentWithDefaultValue())
- s << "|METH_KEYWORDS";
+ result.append(QByteArrayLiteral("METH_KEYWORDS"));
}
// METH_STATIC causes a crash when used for global functions (also from
// invisible namespaces).
- auto ownerClass = func->ownerClass();
+ auto *ownerClass = overloadData.referenceFunction()->ownerClass();
if (ownerClass
&& !invisibleTopNamespaces().contains(const_cast<AbstractMetaClass *>(ownerClass))) {
if (overloadData.hasStaticFunction())
- s << "|METH_STATIC";
+ result.append(QByteArrayLiteral("METH_STATIC"));
if (overloadData.hasClassMethod())
- s << "|METH_CLASS";
+ result.append(QByteArrayLiteral("METH_CLASS"));
}
return result;
}
-void CppGenerator::writeMethodDefinitionEntries(TextStream &s,
- const OverloadData &overloadData,
- qsizetype maxEntries) const
+QList<PyMethodDefEntry>
+ CppGenerator::methodDefinitionEntries(const OverloadData &overloadData) const
{
- const QStringList names = overloadData.referenceFunction()->definitionNames();
- const QString parameters = methodDefinitionParameters(overloadData);
- const qsizetype count = maxEntries > 0
- ? qMin(names.size(), maxEntries) : names.size();
- for (qsizetype i = 0; i < count; ++i) {
- if (i)
- s << ",\n";
- s << "{\"" << names.at(i) << "\", " << parameters << '}';
- }
-}
-void CppGenerator::writeMethodDefinition(TextStream &s,
- const OverloadData &overloadData) const
-{
- const auto func = overloadData.referenceFunction();
- if (m_tpFuncs.contains(func->name()))
- return;
+ const QStringList names = overloadData.referenceFunction()->definitionNames();
+ const QString funcName = cpythonFunctionName(overloadData.referenceFunction());
+ const QByteArrayList parameters = methodDefinitionParameters(overloadData);
- if (OverloadData::hasStaticAndInstanceFunctions(overloadData.overloads())) {
- s << cpythonMethodDefinitionName(func);
- } else {
- writeMethodDefinitionEntries(s, overloadData);
- }
- s << ',' << '\n';
+ QList<PyMethodDefEntry> result;
+ result.reserve(names.size());
+ for (const auto &name : names)
+ result.append({name, funcName, parameters});
+ return result;
}
// Format the type signature of a function parameter
@@ -6391,7 +6373,7 @@ bool CppGenerator::finishGeneration()
writeMethodWrapper(s_globalFunctionImpl, overloadData, classContext);
writeSignatureInfo(signatureStream, overloadData);
- writeMethodDefinition(s_globalFunctionDef, overloadData);
+ s_globalFunctionDef << methodDefinitionEntries(overloadData);
}
AbstractMetaClassCList classesWithStaticFields;
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index 6b1df070a..92b712dc3 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -37,6 +37,7 @@
class OverloadDataNode;
class OverloadDataRootNode;
+struct PyMethodDefEntry;
/**
* The CppGenerator generate the implementations of C++ bindings classes.
@@ -380,12 +381,9 @@ private:
void writeClassDefinition(TextStream &s,
const AbstractMetaClass *metaClass,
const GeneratorContext &classContext);
- QString methodDefinitionParameters(const OverloadData &overloadData) const;
- void writeMethodDefinitionEntries(TextStream &s,
- const OverloadData &overloadData,
- qsizetype maxEntries = -1) const;
- void writeMethodDefinition(TextStream &s,
- const OverloadData &overloadData) const;
+ QByteArrayList methodDefinitionParameters(const OverloadData &overloadData) const;
+ QList<PyMethodDefEntry> methodDefinitionEntries(const OverloadData &overloadData) const;
+
void writeSignatureInfo(TextStream &s, const OverloadData &overloads) const;
QString signatureParameter(const AbstractMetaArgument &arg) const;
/// Writes the implementation of all methods part of python sequence protocol