From 8471ae7a61b61597d89ac5c28d3cd6e133a47400 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 16 Mar 2021 08:27:19 +0100 Subject: Write conversions as typing.Union[] Extract all implicit conversions and write them as typing.Union[]. The optional_replacer was fixed, build_brace_pattern needed a separator to be able to continue. Missing mappings are added. Task-number: PYSIDE-1520 Change-Id: I2d8e4e7b8f1586036cc3ec9cf469a27e693e7312 Reviewed-by: Christian Tismer Reviewed-by: Qt CI Bot --- sources/pyside6/PySide6/support/generate_pyi.py | 2 +- .../shiboken6/generator/shiboken/cppgenerator.cpp | 61 +++++++++++++++++----- .../shiboken6/generator/shiboken/cppgenerator.h | 1 + .../shibokensupport/signature/lib/tool.py | 4 +- .../files.dir/shibokensupport/signature/mapping.py | 4 +- .../tests/minimalbinding/brace_pattern_test.py | 2 +- 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/sources/pyside6/PySide6/support/generate_pyi.py b/sources/pyside6/PySide6/support/generate_pyi.py index 2810d37e5..233bc9142 100644 --- a/sources/pyside6/PySide6/support/generate_pyi.py +++ b/sources/pyside6/PySide6/support/generate_pyi.py @@ -120,7 +120,7 @@ class Formatter(Writer): # I tried hard to replace typing.Optional by a simple override, but # this became _way_ too much. # See also the comment in layout.py . - brace_pat = build_brace_pattern(3) + brace_pat = build_brace_pattern(3, ",") pattern = fr"\b Union \s* \[ \s* {brace_pat} \s*, \s* NoneType \s* \]" replace = r"Optional[\1]" optional_searcher = re.compile(pattern, flags=re.VERBOSE) diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index f6b0f47c5..ed16deca8 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -4944,6 +4944,50 @@ void CppGenerator::writeMethodDefinition(TextStream &s, const AbstractMetaFuncti s << ',' << '\n'; } +// Format the type signature of a function parameter +QString CppGenerator::signatureParameter(const AbstractMetaArgument &arg) const +{ + QString result; + QTextStream s(&result); + + auto metaType = arg.type(); + if (auto viewOn = metaType.viewOn()) + metaType = *viewOn; + s << arg.name() << ':'; + + QStringList signatures(metaType.pythonSignature()); + + // Implicit conversions (C++): Check for converting constructors + // "QColor(Qt::GlobalColor)" or conversion operators + const AbstractMetaFunctionCList conversions = + api().implicitConversions(metaType); + for (const auto &f : conversions) { + if (f->isConstructor() && !f->arguments().isEmpty()) + signatures << f->arguments().constFirst().type().pythonSignature(); + else if (f->isConversionOperator()) + signatures << f->ownerClass()->fullName(); + } + + const qsizetype size = signatures.size(); + if (size > 1) + s << "typing.Union["; + for (qsizetype i = 0; i < size; ++i) { + if (i > 0) + s << ", "; + s << signatures.at(i); + } + if (size > 1) + s << ']'; + + if (!arg.defaultValueExpression().isEmpty()) { + s << '='; + QString e = arg.defaultValueExpression(); + e.replace(QLatin1String("::"), QLatin1String(".")); + s << e; + } + return result; +} + void CppGenerator::writeSignatureInfo(TextStream &s, const AbstractMetaFunctionCList &overloads) const { OverloadData overloadData(overloads, api()); @@ -4959,20 +5003,9 @@ void CppGenerator::writeSignatureInfo(TextStream &s, const AbstractMetaFunctionC // Toplevel functions like `PySide6.QtCore.QEnum` are always self-less. if (!(f->isStatic()) && f->ownerClass()) args << QLatin1String("self"); - const AbstractMetaArgumentList &arguments = f->arguments(); - for (const AbstractMetaArgument &arg : arguments) { - auto metaType = arg.type(); - if (auto viewOn = metaType.viewOn()) - metaType = *viewOn; - QString strArg = metaType.pythonSignature(); - if (!arg.defaultValueExpression().isEmpty()) { - strArg += QLatin1Char('='); - QString e = arg.defaultValueExpression(); - e.replace(QLatin1String("::"), QLatin1String(".")); - strArg += e; - } - args << arg.name() + QLatin1Char(':') + strArg; - } + for (const AbstractMetaArgument &arg : f->arguments()) + args.append(signatureParameter(arg)); + // mark the multiple signatures as such, to make it easier to generate different code if (multiple) s << idx-- << ':'; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 9c3cf6dca..3e230fa11 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -296,6 +296,7 @@ private: qsizetype maxEntries = -1) const; void writeMethodDefinition(TextStream &s, const AbstractMetaFunctionCList &overloads) const; void writeSignatureInfo(TextStream &s, const AbstractMetaFunctionCList &overloads) const; + QString signatureParameter(const AbstractMetaArgument &arg) const; /// Writes the implementation of all methods part of python sequence protocol void writeSequenceMethods(TextStream &s, const AbstractMetaClass *metaClass, diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py index 268142db8..66d68ad92 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py @@ -68,7 +68,7 @@ except ImportError: pass -def build_brace_pattern(level, separators=""): +def build_brace_pattern(level, separators): """ Build a brace pattern upto a given depth @@ -92,6 +92,8 @@ def build_brace_pattern(level, separators=""): avoiding this problem completely. It might be considered to switch to such an engine if the external module is not a problem. """ + assert type(separators) is str + def escape(txt): return "".join("\\" + c for c in txt) diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index 2f4104945..177f4f179 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -430,7 +430,7 @@ def init_smart(): # The PySide Part def init_PySide6_QtCore(): - from PySide6.QtCore import Qt, QUrl, QDir + from PySide6.QtCore import Qt, QUrl, QDir, QKeyCombination from PySide6.QtCore import QRect, QSize, QPoint, QLocale, QByteArray from PySide6.QtCore import QMarginsF # 5.9 try: @@ -551,7 +551,7 @@ def init_PySide6_QtSql(): def init_PySide6_QtNetwork(): - from PySide6.QtNetwork import QNetworkRequest + from PySide6.QtNetwork import QNetworkRequest, QHostAddress best_structure = typing.OrderedDict if getattr(typing, "OrderedDict", None) else typing.Dict type_map.update({ "QMultiMap[PySide6.QtNetwork.QSsl.AlternativeNameEntryType, QString]": diff --git a/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py index 842cb93e2..e036eafb9 100644 --- a/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py +++ b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py @@ -112,7 +112,7 @@ class TestBracePattern(unittest.TestCase): self.assertFalse(check(test)) def test_the_brace_pattern(self): - func = re.compile(build_brace_pattern(5) + "$", re.VERBOSE).match + func = re.compile(build_brace_pattern(5, ",") + "$", re.VERBOSE).match for test, result in self.tests: if result: self.assertTrue(func(test)) -- cgit v1.2.3