Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--requirements-coin.txt4
-rw-r--r--requirements.txt6
-rw-r--r--sources/pyside-tools/pyside_tool.py27
-rw-r--r--sources/pyside-tools/requirements-android.txt1
-rw-r--r--sources/pyside6/libpyside/pysidevariantutils.cpp8
-rw-r--r--sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py8
-rw-r--r--sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py2
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion.h3
-rw-r--r--sources/shiboken6/ApiExtractor/smartpointertypeentry.h5
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp19
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp8
-rw-r--r--sources/shiboken6/cmake/ShibokenHelpers.cmake25
-rw-r--r--sources/shiboken6/doc/typesystem_conversionrule.rst15
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst3
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp91
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h10
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp11
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp6
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h2
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py1
-rw-r--r--sources/shiboken6/tests/smartbinding/std_optional_test.py9
-rw-r--r--sources/shiboken6/tests/smartbinding/typesystem_smart.xml13
-rw-r--r--testing/wheel_tester.py6
24 files changed, 204 insertions, 91 deletions
diff --git a/requirements-coin.txt b/requirements-coin.txt
index 5ee2bac0d..a5dabc834 100644
--- a/requirements-coin.txt
+++ b/requirements-coin.txt
@@ -1,5 +1,5 @@
-pip>=24.2
-setuptools==72.1.0
+pip>=25
+setuptools==78.1.0
importlib_metadata>=6
importlib_resources>=5.10.2
packaging>=24
diff --git a/requirements.txt b/requirements.txt
index ad4c91813..feb5a01aa 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
# Build dependencies
-setuptools==72.1.0
-packaging==24.1
-build==1.2.1
+setuptools==78.1.0
+packaging==24.2
+build==1.2.2.post1
wheel==0.43.0
distro==1.9.0; sys_platform == 'linux'
patchelf==0.17.2; sys_platform == 'linux'
diff --git a/sources/pyside-tools/pyside_tool.py b/sources/pyside-tools/pyside_tool.py
index 887f2bdda..5c009859d 100644
--- a/sources/pyside-tools/pyside_tool.py
+++ b/sources/pyside-tools/pyside_tool.py
@@ -198,6 +198,18 @@ def metaobjectdump():
pyside_script_wrapper("metaobjectdump.py")
+def _check_requirements(requirements_file):
+ """Check if all required packages are installed."""
+ missing_packages = []
+ with open(requirements_file, 'r', encoding='UTF-8') as file:
+ for line in file:
+ # versions
+ package = line.strip().split('==')[0]
+ if not importlib.util.find_spec(package):
+ missing_packages.append(line.strip())
+ return missing_packages
+
+
def project():
pyside_script_wrapper("project.py")
@@ -220,12 +232,15 @@ def android_deploy():
file=sys.stderr)
else:
android_requirements_file = Path(__file__).parent / "requirements-android.txt"
- with open(android_requirements_file, 'r', encoding='UTF-8') as file:
- while line := file.readline():
- dependent_package = line.rstrip()
- if not bool(importlib.util.find_spec(dependent_package)):
- command = [sys.executable, "-m", "pip", "install", dependent_package]
- subprocess.run(command)
+ if android_requirements_file.exists():
+ missing_packages = _check_requirements(android_requirements_file)
+ if missing_packages:
+ print("The following packages are required but not installed:")
+ for package in missing_packages:
+ print(f" - {package}")
+ print("Please install them using:")
+ print(f" pip install -r {android_requirements_file}")
+ sys.exit(1)
pyside_script_wrapper("android_deploy.py")
diff --git a/sources/pyside-tools/requirements-android.txt b/sources/pyside-tools/requirements-android.txt
index 9ed5d8427..1a247f6c1 100644
--- a/sources/pyside-tools/requirements-android.txt
+++ b/sources/pyside-tools/requirements-android.txt
@@ -1,3 +1,4 @@
jinja2
pkginfo
tqdm
+packaging==24.1
diff --git a/sources/pyside6/libpyside/pysidevariantutils.cpp b/sources/pyside6/libpyside/pysidevariantutils.cpp
index 7dbfb3afc..729557919 100644
--- a/sources/pyside6/libpyside/pysidevariantutils.cpp
+++ b/sources/pyside6/libpyside/pysidevariantutils.cpp
@@ -125,8 +125,12 @@ QMetaType resolveMetaType(PyTypeObject *type)
// PYSIDE-1887, PYSIDE-86: Skip QObject base class of QGraphicsObject;
// it needs to use always QGraphicsItem as a QVariant type for
// QGraphicsItem::itemChange() to work.
- if (qstrcmp(typeName, "QGraphicsObject*") == 0)
- ++i;
+ if (qstrcmp(typeName, "QGraphicsObject*") == 0 && size > 1) {
+ auto *firstBaseType = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, 0));
+ const char *firstBaseTypeName = Shiboken::ObjectType::getOriginalName(firstBaseType);
+ if (firstBaseTypeName != nullptr && qstrcmp(firstBaseTypeName, "QObject*") == 0)
+ ++i;
+ }
for ( ; i < size; ++i) {
auto baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, i));
const QMetaType derived = resolveMetaType(baseType);
diff --git a/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
index 91b405aaf..7ae29d1f7 100644
--- a/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
+++ b/sources/pyside6/tests/QtWidgets/qgraphicsobjectreimpl_test.py
@@ -53,8 +53,16 @@ class QGraphicsObjectReimpl(UsesQApplication):
# See also PYSIDE-1887, PYSIDE-3069
gobjA = GObjA()
gobjA.setParentItem(w)
+ print(gobjA.parentItem())
self.assertIs(type(w), type(gobjA.parentItem()))
+ # PYSIDE-3115: QVariant conversion of the parent
+ # (Python class inheriting QGraphicsObject).
+ parentA = GObjA()
+ gobjA = GObjA()
+ gobjA.setParentItem(parentA)
+ self.assertIs(type(parentA), type(gobjA.parentItem()))
+
gobjB = GObjB()
gobjB.setParentItem(w)
self.assertIs(type(w), type(gobjB.parentItem()))
diff --git a/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
index 120c54af3..14330726a 100644
--- a/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
+++ b/sources/pyside6/tests/tools/pyside6-android-deploy/test_pyside6_android_deploy.py
@@ -36,7 +36,7 @@ class DeployTestBase(unittest.TestCase):
android_requirements_file = pyside_tools / "requirements-android.txt"
with open(android_requirements_file, 'r', encoding='UTF-8') as file:
while line := file.readline():
- dependent_package = line.rstrip()
+ dependent_package = line.rstrip().split('==')[0]
if not bool(importlib.util.find_spec(dependent_package)):
command = [sys.executable, "-m", "pip", "install", dependent_package]
subprocess.run(command)
diff --git a/sources/shiboken6/ApiExtractor/customconversion.cpp b/sources/shiboken6/ApiExtractor/customconversion.cpp
index 4cfd1b974..b022cd692 100644
--- a/sources/shiboken6/ApiExtractor/customconversion.cpp
+++ b/sources/shiboken6/ApiExtractor/customconversion.cpp
@@ -5,6 +5,7 @@
#include "containertypeentry.h"
#include "customtypenentry.h"
#include "primitivetypeentry.h"
+#include "smartpointertypeentry.h"
#include "valuetypeentry.h"
#include <QtCore/qdebug.h>
@@ -95,6 +96,11 @@ QString TargetToNativeConversion::sourceTypeName() const
QString TargetToNativeConversion::sourceTypeCheck() const
{
+ return m_sourceTypeCheck;
+}
+
+QString TargetToNativeConversion::sourceTypeCheckFallback() const
+{
if (!m_sourceTypeCheck.isEmpty())
return m_sourceTypeCheck;
@@ -108,6 +114,10 @@ QString TargetToNativeConversion::sourceTypeCheck() const
}
}
+ if (m_sourceTypeName == "Py_None"_L1 || m_sourceTypeName == "PyNone"_L1)
+ return "%in == Py_None"_L1;
+ if (m_sourceTypeName == "SbkObject"_L1)
+ return "Shiboken::Object::checkType(%in)"_L1;
return {};
}
@@ -139,6 +149,8 @@ CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &t
return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion();
if (type->isValue())
return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion();
+ if (type->isSmartPointer())
+ return std::static_pointer_cast<const SmartPointerTypeEntry>(type)->customConversion();
return {};
}
diff --git a/sources/shiboken6/ApiExtractor/customconversion.h b/sources/shiboken6/ApiExtractor/customconversion.h
index a75178846..9125d6705 100644
--- a/sources/shiboken6/ApiExtractor/customconversion.h
+++ b/sources/shiboken6/ApiExtractor/customconversion.h
@@ -25,7 +25,10 @@ public:
void setSourceType(const TypeEntryCPtr &sourceType);
bool isCustomType() const;
QString sourceTypeName() const;
+ // Check as specified in the type system
QString sourceTypeCheck() const;
+ // Check with fallback bases on sourceType
+ QString sourceTypeCheckFallback() const;
QString conversion() const;
void setConversion(const QString &conversion);
diff --git a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
index d704210f7..7b67647b9 100644
--- a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
+++ b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
@@ -5,6 +5,7 @@
#define SMARTPOINTERTYPEENTRY_H
#include "complextypeentry.h"
+#include "customconversion_typedefs.h"
class SmartPointerTypeEntryPrivate;
@@ -51,6 +52,10 @@ public:
QString getTargetName(const AbstractMetaType &metaType) const;
+ bool hasCustomConversion() const;
+ void setCustomConversion(const CustomConversionPtr &customConversion);
+ CustomConversionPtr customConversion() const;
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index 0820150f8..46e88291d 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -2154,6 +2154,7 @@ public:
QString m_resetMethod;
SmartPointerTypeEntry::Instantiations m_instantiations;
TypeEntryCList m_excludedInstantiations;
+ CustomConversionPtr m_customConversion;
TypeSystem::SmartPointerType m_smartPointerType;
};
@@ -2306,6 +2307,24 @@ QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) c
return fixSmartPointerName(name);
}
+bool SmartPointerTypeEntry::hasCustomConversion() const
+{
+ S_D(const SmartPointerTypeEntry);
+ return bool(d->m_customConversion);
+}
+
+void SmartPointerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
+{
+ S_D(SmartPointerTypeEntry);
+ d->m_customConversion = customConversion;
+}
+
+CustomConversionPtr SmartPointerTypeEntry::customConversion() const
+{
+ S_D(const SmartPointerTypeEntry);
+ return d->m_customConversion;
+}
+
// ----------------- NamespaceTypeEntry
class NamespaceTypeEntryPrivate : public ComplexTypeEntryPrivate
{
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index 8b2ad08de..7ae25e48c 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -2348,9 +2348,10 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
if (topElement != StackElement::ModifyArgument
&& topElement != StackElement::ValueTypeEntry
&& topElement != StackElement::PrimitiveTypeEntry
- && topElement != StackElement::ContainerTypeEntry) {
+ && topElement != StackElement::ContainerTypeEntry
+ && topElement != StackElement::SmartPointerTypeEntry) {
m_error = u"Conversion rules can only be specified for argument modification, "
- "value-type, primitive-type or container-type conversion."_s;
+ "value-type, primitive-type, or container-type or smartpointer-type conversion."_s;
return false;
}
@@ -2415,6 +2416,9 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion);
else if (top->entry->isValue())
std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion);
+ else if (top->entry->isSmartPointer())
+ std::static_pointer_cast<SmartPointerTypeEntry>(top->entry)->setCustomConversion(customConversion);
+
customConversionsForReview.append(customConversion);
return true;
}
diff --git a/sources/shiboken6/cmake/ShibokenHelpers.cmake b/sources/shiboken6/cmake/ShibokenHelpers.cmake
index bcaf31e89..c6414b2ca 100644
--- a/sources/shiboken6/cmake/ShibokenHelpers.cmake
+++ b/sources/shiboken6/cmake/ShibokenHelpers.cmake
@@ -869,28 +869,9 @@ endfunction()
# Get path to libclang.dll/libclang.so depending on the platform
macro(find_libclang)
- if(CMAKE_HOST_WIN32)
- set(libclang_directory_suffix "bin")
- set(libclang_suffix ".dll")
- else()
- set(libclang_directory_suffix "lib")
- if(CMAKE_HOST_APPLE)
- set(libclang_suffix ".dylib")
- else()
- set(libclang_suffix ".so")
- endif()
- endif()
-
- set(libclang_lib_dir "")
- if(DEFINED ENV{LLVM_INSTALL_DIR})
- set(libclang_lib_dir "$ENV{LLVM_INSTALL_DIR}/${libclang_directory_suffix}")
- elseif(DEFINED ENV{CLANG_INSTALL_DIR})
- set(libclang_lib_dir "$ENV{CLANG_INSTALL_DIR}/${libclang_directory_suffix}")
- else()
- message(WARNING
- "Couldn't find libclang${libclang_suffix} "
- "You will likely need to add it manually to PATH to ensure the build succeeds.")
- endif()
+ find_package(Clang CONFIG REQUIRED)
+ get_target_property(libclang_location libclang LOCATION)
+ get_filename_component(libclang_lib_dir "${libclang_location}" DIRECTORY)
endmacro()
# Allow setting a shiboken debug level from the the build system or from the environment
diff --git a/sources/shiboken6/doc/typesystem_conversionrule.rst b/sources/shiboken6/doc/typesystem_conversionrule.rst
index cee45bfb3..f6ce18345 100644
--- a/sources/shiboken6/doc/typesystem_conversionrule.rst
+++ b/sources/shiboken6/doc/typesystem_conversionrule.rst
@@ -12,9 +12,13 @@ The **conversion-rule** tag specifies how a **primitive-type**, a **container-ty
or a **value-type** may be converted to and from the native C++ language types to the
target language types (see also :ref:`user-defined-type-conversion`).
-It is a child of the :ref:`container-type`, :ref:`primitive-type` or
-:ref:`value-type` and may contain :ref:`native-to-target` or
-:ref:`native-to-target` child nodes.
+It may be a child of the :ref:`container-type` and :ref:`primitive-type` nodes,
+where conversions have to be provided for both directions using the
+:ref:`native-to-target` and :ref:`target-to-native` child nodes.
+
+It may also appear as a child of :ref:`value-type` or :ref:`smart-pointer-type`
+where additional conversions from other target language types can be provided
+using the :ref:`target-to-native` child node.
.. code-block:: xml
@@ -70,8 +74,9 @@ an input value an does what's needed to convert it to the output value.
</conversion-rule>
Use the replace node to modify the template code.
-Notice that the generator must provide type system variables for the input
-and output values and types, namely **%in**, **%out**, **%INTYPE** and
+Notice that the generator provides type system variables for the input
+and output values and types (see :ref:`converter_variables_and_functions`).
+The most important ones are **%in**, **%out**, **%INTYPE** and
**%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
**%INTYPE_#**, should be replaced by the types used in the container template
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 60ac5c6d9..798ef5719 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -729,7 +729,8 @@ The ``smart pointer`` type node indicates that the given class is a smart pointe
and requires inserting calls to **getter** to access the pointeee.
Currently, the usage is limited to function return values.
**ref-count-method** specifies the name of the method used to do reference counting.
-It is a child of the :ref:`typesystem_details` node or other type nodes.
+It is a child of the :ref:`typesystem_details` node or other type nodes
+and may contain :ref:`conversion-rule` nodes.
The *optional* attribute **instantiations** specifies for which instantiations
of the smart pointer wrappers will be generated (comma-separated list).
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 539094075..29603bd97 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -2120,6 +2120,24 @@ void CppGenerator::writeCustomConverterRegister(TextStream &s,
}
}
+void CppGenerator::writeTemplateCustomConverterRegister(TextStream &s,
+ const AbstractMetaType &type,
+ QString converter)
+{
+ auto customConversion = CustomConversion::getCustomConversion(type.typeEntry());
+ if (!customConversion || customConversion->targetToNativeConversions().isEmpty())
+ return;
+ if (converter.isEmpty())
+ converter = converterVar;
+ const QString typeName = fixedCppTypeName(type);
+ for (const auto &conv : customConversion->targetToNativeConversions()) {
+ const QString &sourceTypeName = conv.sourceTypeName();
+ QString toCpp = pythonToCppFunctionName(sourceTypeName, typeName);
+ QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName);
+ writeAddPythonToCppConversion(s, converter, toCpp, isConv);
+ }
+}
+
void CppGenerator::writeContainerConverterFunctions(TextStream &s,
const AbstractMetaType &containerType) const
{
@@ -3577,14 +3595,7 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// Python to C++ convertible check function.
- QString typeCheck = toNative.sourceTypeCheck();
- if (typeCheck.isEmpty()) {
- QString pyTypeName = toNative.sourceTypeName();
- if (pyTypeName == u"Py_None" || pyTypeName == u"PyNone")
- typeCheck = u"%in == Py_None"_s;
- else if (pyTypeName == u"SbkObject")
- typeCheck = u"Shiboken::Object::checkType(%in)"_s;
- }
+ QString typeCheck = toNative.sourceTypeCheckFallback();
if (typeCheck.isEmpty()) {
if (!toNative.sourceType() || toNative.sourceType()->isPrimitive()) {
QString m;
@@ -3595,33 +3606,47 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
typeCheck = u"PyObject_TypeCheck(%in, "_s
+ cpythonTypeNameExt(toNative.sourceType()) + u')';
}
- typeCheck.replace(u"%in"_s, u"pyIn"_s);
- processCodeSnip(typeCheck, targetType->qualifiedCppName());
+ processTypeCheckCodeSnip(typeCheck, targetType->qualifiedCppName());
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
}
-void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const AbstractMetaType &containerType) const
+void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
+ const AbstractMetaType &templateType) const
{
- Q_ASSERT(containerType.typeEntry()->isContainer());
- const auto cte = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
- const auto customConversion = cte->customConversion();
- for (const auto &conv : customConversion->targetToNativeConversions())
- writePythonToCppConversionFunction(s, containerType, conv);
+ const auto customConversion = CustomConversion::getCustomConversion(templateType.typeEntry());
+ if (customConversion) {
+ const auto &conversions = customConversion->targetToNativeConversions();
+ for (const auto &conv : conversions)
+ writePythonToCppConversionFunction(s, templateType, conv);
+ }
}
void CppGenerator::writePythonToCppConversionFunction(TextStream &s,
- const AbstractMetaType &containerType,
+ const AbstractMetaType &templateType,
const TargetToNativeConversion &conv) const
{
+ // Python to C++ convertible check function.
+ QString typeName = fixedCppTypeName(templateType);
+ // Check fallback is too broad for containers that need elements of same type
+ QString typeCheck = templateType.isContainer()
+ ? conv.sourceTypeCheck() : conv.sourceTypeCheckFallback();
+ if (typeCheck.isEmpty()) {
+ typeCheck = cpythonCheckFunction(templateType);
+ if (typeCheck.isEmpty())
+ typeCheck = u"false"_s;
+ else
+ typeCheck = typeCheck + u"pyIn)"_s;
+ }
+
// Python to C++ conversion function.
- QString cppTypeName = getFullTypeNameWithoutModifiers(containerType);
+ QString cppTypeName = getFullTypeNameWithoutModifiers(templateType);
QString code = conv.conversion();
const QString line = u"auto &cppOutRef = *reinterpret_cast<"_s
+ cppTypeName + u" *>(cppOut);"_s;
CodeSnipAbstract::prependCode(&code, line);
- for (qsizetype i = 0; i < containerType.instantiations().size(); ++i) {
- const AbstractMetaType &type = containerType.instantiations().at(i);
- QString typeName = getFullTypeName(type);
+ for (qsizetype i = 0; i < templateType.instantiations().size(); ++i) {
+ const AbstractMetaType &type = templateType.instantiations().at(i);
+ QString instTypeName = getFullTypeName(type);
// Containers of opaque containers are not handled here.
const auto generatorArg = GeneratorArgument::fromMetaType(type);
if (generatorArg.indirections > 0 && !type.generateOpaqueContainer()) {
@@ -3635,23 +3660,19 @@ void CppGenerator::writePythonToCppConversionFunction(TextStream &s,
rightCode.replace(varName, u'*' + varName);
code.replace(pos, code.size() - pos, rightCode);
}
- typeName.append(u" *"_s);
+ instTypeName.append(" *"_L1);
}
- code.replace(u"%OUTTYPE_"_s + QString::number(i), typeName);
+ const QString var = "%OUTTYPE_"_L1 + QString::number(i);
+ code.replace(var, instTypeName);
+ typeCheck.replace(var, instTypeName);
}
code.replace(u"%OUTTYPE"_s, cppTypeName);
code.replace(u"%in"_s, u"pyIn"_s);
code.replace(u"%out"_s, u"cppOutRef"_s);
- QString typeName = fixedCppTypeName(containerType);
const QString &sourceTypeName = conv.sourceTypeName();
writePythonToCppFunction(s, code, sourceTypeName, typeName);
- // Python to C++ convertible check function.
- QString typeCheck = cpythonCheckFunction(containerType);
- if (typeCheck.isEmpty())
- typeCheck = u"false"_s;
- else
- typeCheck = typeCheck + u"pyIn)"_s;
+ processTypeCheckCodeSnip(typeCheck, typeName); // needs %OUTTYPE_[n]
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, typeName, typeCheck);
s << '\n';
}
@@ -4438,8 +4459,7 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
s << '&' << targetTypeName << "_Type";
}
- const QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, targetTypeName) << ");\n";
+ s << ", " << cppToPythonFunctionName(fixedCppTypeName(type), targetTypeName) << ");\n";
s << registerConverterName(cppSignature, converter);
if (usePySideExtensions() && cppSignature.startsWith("const "_L1)
@@ -4448,12 +4468,7 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
s << registerConverterName(underlyingType, converter);
}
- for (const auto &conv : typeEntry->customConversion()->targetToNativeConversions()) {
- const QString &sourceTypeName = conv.sourceTypeName();
- QString toCpp = pythonToCppFunctionName(sourceTypeName, typeName);
- QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName);
- writeAddPythonToCppConversion(s, converter, toCpp, isConv);
- }
+ writeTemplateCustomConverterRegister(s, type, converter);
auto typedefItPair = api.typedefTargetToName().equal_range(type.cppSignature());
if (typedefItPair.first != typedefItPair.second) {
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index 0cf204234..1a192f8fd 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -114,6 +114,9 @@ private:
static void writeCustomConverterRegister(TextStream &s,
const CustomConversionPtr &customConversion,
const QString &converterVar);
+ static void writeTemplateCustomConverterRegister(TextStream &s,
+ const AbstractMetaType &type,
+ QString converter = {});
void writeContainerConverterFunctions(TextStream &s,
const AbstractMetaType &containerType) const;
@@ -361,12 +364,13 @@ private:
const TargetToNativeConversion &toNative,
const TypeEntryCPtr &targetType) const;
- /// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
+ /// Writes a pair of Python to C++ conversion and check functions for instantiated
+ /// template (smart pointer/container types).
void writePythonToCppConversionFunctions(TextStream &s,
- const AbstractMetaType &containerType) const;
+ const AbstractMetaType &templateType) const;
void writePythonToCppConversionFunction(TextStream &s,
- const AbstractMetaType &containerType,
+ const AbstractMetaType &templateType,
const TargetToNativeConversion &conv) const;
static void writeAddPythonToCppConversion(TextStream &s, const QString &converterVar,
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
index 48c4ed5d2..1d3280e36 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
@@ -232,13 +232,16 @@ void CppGenerator::generateSmartPointerClass(TextStream &s,
void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
const AbstractMetaType &smartPointerType) const
{
+ auto smartPointerTypeEntry =
+ std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
+
+ if (smartPointerTypeEntry->hasCustomConversion())
+ writePythonToCppConversionFunctions(s, smartPointerType);
+
const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
if (baseClasses.isEmpty())
return;
- auto smartPointerTypeEntry =
- std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
-
// TODO: Missing conversion to smart pointer pointer type:
s << "// Register smartpointer conversion for all derived classes\n";
@@ -290,6 +293,8 @@ void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s,
writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
};
+ writeTemplateCustomConverterRegister(s, type);
+
const auto classes = findSmartPointeeBaseClasses(api(), type);
if (classes.isEmpty())
return;
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index 5c67f20f0..872076754 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -1387,6 +1387,12 @@ void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorConte
processCodeSnip(code, context.effectiveClassName());
}
+void ShibokenGenerator::processTypeCheckCodeSnip(QString &code, const QString &context) const
+{
+ code.replace("%in"_L1, "pyIn"_L1);
+ processCodeSnip(code, context);
+}
+
void ShibokenGenerator::processCodeSnip(QString &code) const
{
// replace "toPython" converters
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index 045581ed6..c0f388871 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -161,6 +161,8 @@ protected:
void processCodeSnip(QString &code) const;
void processCodeSnip(QString &code, const QString &context) const;
void processClassCodeSnip(QString &code, const GeneratorContext &context) const;
+ /// Replaces variables in a custom conversion type check snippet
+ void processTypeCheckCodeSnip(QString &code, const QString &context) const;
/**
* Verifies if any of the function's code injections makes a call
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 2bb3c9a87..84cb15feb 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -509,6 +509,7 @@ def init_PySide6_QtCore():
"PySide6.QtCore.QUrl.ComponentFormattingOptions":
PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
"PyUnicode": typing.Text,
+ "QByteArray": typing.Union[PySide6.QtCore.QByteArray, bytes, bytearray, memoryview],
"QByteArrayView": PySide6.QtCore.QByteArray,
"Q_NULLPTR": None,
"QCalendar.Unspecified": PySide6.QtCore.QCalendar.Unspecified,
diff --git a/sources/shiboken6/tests/smartbinding/std_optional_test.py b/sources/shiboken6/tests/smartbinding/std_optional_test.py
index cd97facfa..9e8bc8d47 100644
--- a/sources/shiboken6/tests/smartbinding/std_optional_test.py
+++ b/sources/shiboken6/tests/smartbinding/std_optional_test.py
@@ -26,6 +26,15 @@ def integer_from_value(v):
class StdOptionalTests(unittest.TestCase):
+ def testConversionFromInt(self):
+ """PYSIDE-3107: Test whether a parameter taking a 'std::optional<int>'
+ accepts 'int'."""
+ b = StdOptionalTestBench()
+ b.setOptionalInt(43)
+ self.assertEqual(b.optionalInt().value(), 43)
+ b.setOptionalInt(None)
+ self.assertFalse(b.optionalInt().has_value())
+
def testCInt(self):
b = StdOptionalTestBench()
ci = b.optionalInt()
diff --git a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
index 14b181b61..4024036fa 100644
--- a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
+++ b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
@@ -50,6 +50,19 @@
value-check-method="has_value"
instantiations="Integer,int">
<include file-name="optional" location="global"/>
+ <!-- PYSIDE-3107: Generic rule constructing std::optional<T>' from 'T'. -->
+ <conversion-rule>
+ <target-to-native>
+ <add-conversion type="Py_None">
+ SBK_UNUSED(pyIn)
+ %out = std::nullopt;
+ </add-conversion>
+ <add-conversion type="InstType" check="%CHECKTYPE[%OUTTYPE_0](%in)">
+ %OUTTYPE_0 v = %CONVERTTOCPP[%OUTTYPE_0](%in);
+ %out = %OUTTYPE(v);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
</smart-pointer-type>
</namespace-type>
diff --git a/testing/wheel_tester.py b/testing/wheel_tester.py
index 0f6fb04ff..e5b47ffc1 100644
--- a/testing/wheel_tester.py
+++ b/testing/wheel_tester.py
@@ -84,10 +84,10 @@ def package_prefix_names():
# Note: shiboken6_generator is not needed for compile_using_nuitka,
# but building modules with cmake needs it.
if NEW_WHEELS:
- return ["shiboken6", "shiboken6_generator", "PySide6_Essentials", "PySide6_Addons",
- "PySide6"]
+ return ["shiboken6", "shiboken6_generator", "pyside6_essentials", "pyside6_addons",
+ "pyside6"]
else:
- return ["shiboken6", "shiboken6_generator", "PySide6"]
+ return ["shiboken6", "shiboken6_generator", "pyside6"]
def clean_egg_info():