diff options
Diffstat (limited to 'sources')
27 files changed, 406 insertions, 192 deletions
diff --git a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml index 2cbe490aa..c3b800454 100644 --- a/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml +++ b/sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml @@ -62,7 +62,7 @@ of the `.ui` file. (Remember that `duck punching virtual methods is an invitation for your own demise! - <http://www.pyside.org/docs/shiboken/wordsofadvice.html#duck-punching-and-virtual-methods>`_) + <https://doc.qt.io/qtforpython/shiboken2/wordsofadvice.html#duck-punching-and-virtual-methods>`_) Let's see an obvious example. If you want to create a new widget it's probable you'll end up overriding :class:`~PySide2.QtGui.QWidget`'s :meth:`~PySide2.QtGui.QWidget.paintEvent` method. diff --git a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml index c2c36d60f..a41a27c33 100644 --- a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml +++ b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml @@ -610,7 +610,13 @@ <include file-name="QPair" location="global"/> </extra-includes> </object-type> - <object-type name="QGraphicsItemGroup"/> + <object-type name="QGraphicsItemGroup"> + <modify-function signature="addToGroup(QGraphicsItem*)"> + <modify-argument index="1"> + <parent index="this" action="add"/> + </modify-argument> + </modify-function> + </object-type> <object-type name="QGraphicsLineItem"/> <object-type name="QGraphicsPathItem"/> <object-type name="QGraphicsPixmapItem"> diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp index 629484458..6259724c3 100644 --- a/sources/pyside2/PySide2/glue/qtcore.cpp +++ b/sources/pyside2/PySide2/glue/qtcore.cpp @@ -965,13 +965,33 @@ if (PyIndex_Check(_key)) { // @snippet qbytearray-msetitem // @snippet qbytearray-bufferprotocol -#if PY_VERSION_HEX < 0x03000000 - +extern "C" { // QByteArray buffer protocol functions // see: http://www.python.org/dev/peps/pep-3118/ -extern "C" { +static int SbkQByteArray_getbufferproc(PyObject* obj, Py_buffer *view, int flags) +{ + if (!view || !Shiboken::Object::isValid(obj)) + return -1; + + QByteArray* cppSelf = %CONVERTTOCPP[QByteArray*](obj); + view->obj = obj; + view->buf = reinterpret_cast<void*>(cppSelf->data()); + view->len = cppSelf->size(); + view->readonly = 0; + view->itemsize = 1; + view->format = const_cast<char*>("c"); + view->ndim = 1; + view->shape = NULL; + view->strides = &view->itemsize; + view->suboffsets = NULL; + view->internal = NULL; + + Py_XINCREF(obj); + return 0; +} +#if PY_VERSION_HEX < 0x03000000 static Py_ssize_t SbkQByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp) { if (lenp) @@ -993,12 +1013,18 @@ PyBufferProcs SbkQByteArrayBufferProc = { /*bf_getreadbuffer*/ &SbkQByteArray_readbufferproc, /*bf_getwritebuffer*/ (writebufferproc) &SbkQByteArray_readbufferproc, /*bf_getsegcount*/ &SbkQByteArray_segcountproc, - /*bf_getcharbuffer*/ (charbufferproc) &SbkQByteArray_readbufferproc + /*bf_getcharbuffer*/ (charbufferproc) &SbkQByteArray_readbufferproc, + /*bf_getbuffer*/ (getbufferproc)SbkQByteArray_getbufferproc, }; +#else -} +static PyBufferProcs SbkQByteArrayBufferProc = { + /*bf_getbuffer*/ (getbufferproc)SbkQByteArray_getbufferproc, + /*bf_releasebuffer*/ (releasebufferproc)0, +}; #endif +} // @snippet qbytearray-bufferprotocol // @snippet qbytearray-operatorplus-1 @@ -1110,8 +1136,14 @@ if (PyBytes_Check(%PYARG_1)) { // @snippet qbytearray-py3 #if PY_VERSION_HEX < 0x03000000 - Shiboken::SbkType<QByteArray>()->tp_as_buffer = &SbkQByteArrayBufferProc; - Shiboken::SbkType<QByteArray>()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; +Shiboken::SbkType<QByteArray>()->tp_as_buffer = &SbkQByteArrayBufferProc; +Shiboken::SbkType<QByteArray>()->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; +#else +#ifdef Py_LIMITED_API +PepType_AS_BUFFER(Shiboken::SbkType<QByteArray>()) = &SbkQByteArrayBufferProc; +#else +Shiboken::SbkType<QByteArray>()->tp_as_buffer = &SbkQByteArrayBufferProc; +#endif #endif // @snippet qbytearray-py3 diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py index 21ef841fe..a92ee76f0 100644 --- a/sources/pyside2/PySide2/support/generate_pyi.py +++ b/sources/pyside2/PySide2/support/generate_pyi.py @@ -53,13 +53,6 @@ import re import subprocess import argparse import glob -# PYSIDE-953: Use a newer contextlib for Python 3.5 -skip_creation = False -if sys.version_info[:2] == (3, 5): - try: - import PySide2.support.signature # gets new contextlib - except: - skip_creation = True from contextlib import contextmanager from textwrap import dedent @@ -279,9 +272,6 @@ def single_process(lockdir): def generate_all_pyi(outpath, options): - if skip_creation: - logger.warn("Sorry, we cannot create .pyi files with Python 3.5 while PySide") - logger.warn(" is not installed. Please run it by hand!") ps = os.pathsep if options.sys_path: # make sure to propagate the paths from sys_path to subprocesses diff --git a/sources/pyside2/doc/CMakeLists.txt b/sources/pyside2/doc/CMakeLists.txt index eb5200e85..b5bde885a 100644 --- a/sources/pyside2/doc/CMakeLists.txt +++ b/sources/pyside2/doc/CMakeLists.txt @@ -28,6 +28,8 @@ configure_file("pyside-config.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/pyside-con file(READ "${pyside2_BINARY_DIR}/pyside2_global.h" docHeaderContents) file(READ "typesystem_doc.xml.in" typeSystemDocXmlContents) +set(HAS_WEBENGINE_WIDGETS 0) + foreach(moduleIn ${all_module_shortnames}) string(TOLOWER "${moduleIn}" lowerModuleIn) set(docConf "${CMAKE_CURRENT_LIST_DIR}/qtmodules/pyside-qt${lowerModuleIn}.qdocconf.in") @@ -45,6 +47,7 @@ foreach(moduleIn ${all_module_shortnames}) set(modules Multimedia "${moduleIn}") elseif ("${moduleIn}" STREQUAL "WebEngineWidgets") set(modules WebEngine WebEngineCore "${moduleIn}") + set(HAS_WEBENGINE_WIDGETS 1) else() set(modules "${moduleIn}") endif() diff --git a/sources/pyside2/doc/conf.py.in b/sources/pyside2/doc/conf.py.in index 99b74deef..33f408354 100644 --- a/sources/pyside2/doc/conf.py.in +++ b/sources/pyside2/doc/conf.py.in @@ -18,7 +18,8 @@ import sys, os # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@') sys.path.append('@pyside_BINARY_DIR@') -sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/../../../examples/webenginewidgets/tabbedbrowser') +if @HAS_WEBENGINE_WIDGETS@: + sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/../../../examples/webenginewidgets/tabbedbrowser') # -- General configuration ----------------------------------------------------- @@ -170,3 +171,5 @@ html_show_sourcelink = False # Link to the shiboken2 sphinx project to enable linking # between the two projects. intersphinx_mapping = {'shiboken2': ('shiboken2','@CMAKE_BINARY_DIR@/../shiboken2/doc/html/objects.inv')} + +add_module_names = False diff --git a/sources/pyside2/tests/registry/init_platform.py b/sources/pyside2/tests/registry/init_platform.py index 6031dd2ad..a324c36a2 100644 --- a/sources/pyside2/tests/registry/init_platform.py +++ b/sources/pyside2/tests/registry/init_platform.py @@ -55,8 +55,7 @@ shiboken and pysidetest projects. import sys import os import re -# PYSIDE-953: Use a newer contextlib for Python 3.5 -# from contextlib import contextmanager +from contextlib import contextmanager from textwrap import dedent script_dir = os.path.normpath(os.path.join(__file__, *".. .. .. .. ..".split())) @@ -118,9 +117,6 @@ sys.path[:0] = [os.path.join(shiboken_build_dir, "shibokenmodule"), pyside_build_dir] import PySide2 -# PYSIDE-953: Use a newer contextlib for Python 3.5 -import PySide2.support.signature # new contextlib -from contextlib import contextmanager all_modules = list("PySide2." + x for x in PySide2.__all__) diff --git a/sources/pyside2/tests/support/voidptr_test.py b/sources/pyside2/tests/support/voidptr_test.py index 330788c63..c04022489 100644 --- a/sources/pyside2/tests/support/voidptr_test.py +++ b/sources/pyside2/tests/support/voidptr_test.py @@ -38,9 +38,21 @@ class PySide2Support(unittest.TestCase): # a C++ object, a wrapped Shiboken Object type, # an object implementing the Python Buffer interface, # or another VoidPtr object. - ba = QByteArray(b"Hello world") - voidptr = VoidPtr(ba) - self.assertIsInstance(voidptr, shiboken.VoidPtr) + + # Original content + b = b"Hello world" + ba = QByteArray(b) + vp = VoidPtr(ba, ba.size()) + self.assertIsInstance(vp, shiboken.VoidPtr) + + # Create QByteArray from voidptr byte interpretation + nba = QByteArray.fromRawData(vp.toBytes()) + # Compare original bytes to toBytes() + self.assertTrue(b, vp.toBytes()) + # Compare original with new QByteArray data + self.assertTrue(b, nba.data()) + # Convert original and new to str + self.assertTrue(str(b), str(nba)) if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 37ff3b72c..0b11b1666 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1840,34 +1840,27 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM return result; } -bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func, - const FunctionModelItem &functionItem, - int i) -{ - if (i < 0 || i >= func->arguments().size()) { - qCWarning(lcShiboken).noquote() - << msgCannotSetArrayUsage(func->minimalSignature(), i, - QLatin1String("Index out of range.")); - return false; - } - AbstractMetaType *metaType = func->arguments().at(i)->type(); - if (metaType->indirections() == 0) { - qCWarning(lcShiboken).noquote() - << msgCannotSetArrayUsage(func->minimalSignature(), i, - QLatin1String("Type does not have indirections.")); - return false; - } - TypeInfo elementType = functionItem->arguments().at(i)->type(); - elementType.setIndirections(elementType.indirections() - 1); - AbstractMetaType *element = translateType(elementType); - if (element == nullptr) { - qCWarning(lcShiboken).noquote() - << msgCannotSetArrayUsage(func->minimalSignature(), i, - QLatin1String("Cannot translate element type ") + elementType.toString()); - return false; +// Apply the <array> modifications of the arguments +static bool applyArrayArgumentModifications(const FunctionModificationList &functionMods, + AbstractMetaFunction *func, + QString *errorMessage) +{ + for (const FunctionModification &mod : functionMods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.array) { + const int i = argMod.index - 1; + if (i < 0 || i >= func->arguments().size()) { + *errorMessage = msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Index out of range.")); + return false; + } + if (!func->arguments().at(i)->type()->applyArrayModification(errorMessage)) { + *errorMessage = msgCannotSetArrayUsage(func->minimalSignature(), i, *errorMessage); + return false; + } + } + } } - metaType->setArrayElementType(element); - metaType->setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern); return true; } @@ -2109,11 +2102,10 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio if (!metaArguments.isEmpty()) { fixArgumentNames(metaFunction, functionMods); - for (const FunctionModification &mod : functionMods) { - for (const ArgumentModification &argMod : mod.argument_mods) { - if (argMod.array) - setArrayArgumentType(metaFunction, functionItem, argMod.index - 1); - } + QString errorMessage; + if (!applyArrayArgumentModifications(functionMods, metaFunction, &errorMessage)) { + qCWarning(lcShiboken, "While traversing %s: %s", + qPrintable(className), qPrintable(errorMessage)); } } @@ -2744,6 +2736,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, { QVector<TypeInfo> targs = info.instantiations(); QVector<AbstractMetaType *> templateTypes; + QString errorMessage; if (subclass->isTypeDef()) { subclass->setHasCloneOperator(templateClass->hasCloneOperator()); @@ -2876,6 +2869,13 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, te->addFunctionModification(mod); } + + if (!applyArrayArgumentModifications(f->modifications(subclass), f.data(), + &errorMessage)) { + qCWarning(lcShiboken, "While specializing %s (%s): %s", + qPrintable(subclass->name()), qPrintable(templateClass->name()), + qPrintable(errorMessage)); + } subclass->addFunction(f.take()); } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 226d6defd..185dd0e30 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -156,8 +156,6 @@ public: AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); void setInclude(TypeEntry *te, const QString &fileName) const; void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); - bool setArrayArgumentType(AbstractMetaFunction *func, - const FunctionModelItem &functionItem, int i); void fillAddedFunctions(AbstractMetaClass *metaClass); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index a10a15b08..95f8048cd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -207,6 +207,35 @@ AbstractMetaType *AbstractMetaType::copy() const return cpy; } +// For applying the <array> function argument modification: change into a type +// where "int *" becomes "int[]". +bool AbstractMetaType::applyArrayModification(QString *errorMessage) +{ + if (m_pattern == AbstractMetaType::NativePointerAsArrayPattern) { + *errorMessage = QLatin1String("<array> modification already applied."); + return false; + } + if (m_arrayElementType != nullptr) { + QTextStream(errorMessage) << "The type \"" << cppSignature() + << "\" is an array of " << m_arrayElementType->name() << '.'; + return false; + } + if (m_indirections.isEmpty()) { + QTextStream(errorMessage) << "The type \"" << cppSignature() + << "\" does not have indirections."; + return false; + } + // Element type to be used for ArrayHandle<>, strip constness. + auto elementType = copy(); + elementType->m_indirections.pop_front(); + elementType->setConstant(false); + elementType->setVolatile(false); + elementType->decideUsagePattern(); + m_arrayElementType = elementType; + setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern); + return true; +} + AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const { AbstractMetaTypeCList result; @@ -1256,6 +1285,8 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const d << " [userAdded]"; if (m_explicit) d << " [explicit]"; + if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) + d << " [deprecated]"; if (m_pointerOperator) d << " [operator->]"; if (m_isCallOperator) @@ -2608,6 +2639,8 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) d << '"' << ac->fullName() << '"'; if (ac->attributes() & AbstractMetaAttributes::FinalCppClass) d << " [final]"; + if (ac->attributes().testFlag(AbstractMetaAttributes::Deprecated)) + d << " [deprecated]"; if (ac->m_baseClass) d << ", inherits \"" << ac->m_baseClass->name() << '"'; if (ac->m_templateBaseClass) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 074adbe00..9d36706ac 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -488,6 +488,7 @@ public: QString cppSignature() const; AbstractMetaType *copy() const; + bool applyArrayModification(QString *errorMessage); const TypeEntry *typeEntry() const { diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 36a75c599..96d0bb5fd 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -46,8 +46,6 @@ extern const char *TARGET_CONVERSION_RULE_FLAG; extern const char *NATIVE_CONVERSION_RULE_FLAG; -class Indentor; - class AbstractMetaType; QT_BEGIN_NAMESPACE class QDebug; diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h index cdf6d89b3..04840427f 100644 --- a/sources/shiboken2/generator/generator.h +++ b/sources/shiboken2/generator/generator.h @@ -29,6 +29,7 @@ #ifndef GENERATOR_H #define GENERATOR_H +#include "indentor.h" #include <abstractmetalang_typedefs.h> #include <typedatabase_typedefs.h> #include <dependency.h> @@ -54,7 +55,6 @@ QT_END_NAMESPACE class PrimitiveTypeEntry; class ContainerTypeEntry; -class Indentor; QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor); void verifyDirectoryFor(const QString &file); @@ -417,41 +417,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options) typedef QSharedPointer<Generator> GeneratorPtr; typedef QVector<GeneratorPtr> Generators; -/** -* Utility class to store the identation level, use it in a QTextStream. -*/ -class Indentor -{ -public: - Indentor() : indent(0) {} - int indent; -}; - -/** -* Class that use the RAII idiom to set and unset the identation level. -*/ -class Indentation -{ -public: - Indentation(Indentor &indentor) : indentor(indentor) - { - indentor.indent++; - } - ~Indentation() - { - indentor.indent--; - } - -private: - Indentor &indentor; -}; - -inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor) -{ - for (int i = 0; i < indentor.indent; ++i) - s << " "; - return s; -} - #endif // GENERATOR_H diff --git a/sources/shiboken2/generator/indentor.h b/sources/shiboken2/generator/indentor.h new file mode 100644 index 000000000..111259f12 --- /dev/null +++ b/sources/shiboken2/generator/indentor.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 INDENTOR_H +#define INDENTOR_H + +#include <QtCore/QTextStream> + +/** +* Utility class to store the indentation level, use it in a QTextStream. +*/ + +template <int tabWidth> +class IndentorBase +{ +public: + int total() const { return tabWidth * indent; } + + int indent = 0; +}; + +using Indentor = IndentorBase<4>; +using Indentor1 = IndentorBase<1>; + +/** +* Class that use the RAII idiom to set and unset the indentation level. +*/ + +template <int tabWidth> +class IndentationBase +{ +public: + using Indentor = IndentorBase<tabWidth>; + + IndentationBase(Indentor &indentor, int count = 1) : m_count(count), indentor(indentor) + { + indentor.indent += m_count; + } + + ~IndentationBase() + { + indentor.indent -= m_count; + } + +private: + const int m_count; + Indentor &indentor; +}; + +using Indentation = IndentationBase<4>; + +template <int tabWidth> +inline QTextStream &operator <<(QTextStream &s, const IndentorBase<tabWidth> &indentor) +{ + for (int i = 0, total = indentor.total(); i < total; ++i) + s << ' '; + return s; +} + +#endif // GENERATOR_H diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index c194c0ea4..9410bc158 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -55,6 +55,13 @@ static inline QString briefAttribute() { return QStringLiteral("brief"); } static inline QString none() { return QStringLiteral("None"); } +static void stripPythonQualifiers(QString *s) +{ + const int lastSep = s->lastIndexOf(QLatin1Char('.')); + if (lastSep != -1) + s->remove(0, lastSep + 1); +} + static bool shouldSkip(const AbstractMetaFunction* func) { // Constructors go to separate section @@ -167,12 +174,33 @@ static QTextStream &ensureEndl(QTextStream &s) return s; } -static void formatSince(QTextStream &s, const char *what, const TypeEntry *te) +static inline QVersionNumber versionOf(const TypeEntry *te) { - if (te && te->version() > QVersionNumber(0, 0)) { - s << ".. note:: This " << what << " was introduced in Qt " - << te->version().toString() << '.' << endl; + if (te) { + const auto version = te->version(); + if (!version.isNull() && version > QVersionNumber(0, 0)) + return version; } + return QVersionNumber(); +} + +struct rstVersionAdded +{ + explicit rstVersionAdded(const QVersionNumber &v) : m_version(v) {} + + const QVersionNumber m_version; +}; + +static QTextStream &operator<<(QTextStream &s, const rstVersionAdded &v) +{ + s << ".. versionadded:: "<< v.m_version.toString() << "\n\n"; + return s; +} + +static QByteArray rstDeprecationNote(const char *what) +{ + return QByteArrayLiteral(".. note:: This ") + + what + QByteArrayLiteral(" is deprecated.\n\n"); } // RST anchor string: Anything else but letters, numbers, '_' or '.' replaced by '-' @@ -1013,22 +1041,19 @@ static QString fixLinkText(const QtXmlToSphinx::LinkContext *linkContext, || linkContext->type == QtXmlToSphinx::LinkContext::Reference) { return linktext; } - // For the language reference documentation, clear the link text if it matches - // the function/class/enumeration name. - linktext.replace(QLatin1String("::"), QLatin1String(".")); + // For the language reference documentation, strip the module name. + // Clear the link text if that matches the function/class/enumeration name. + const int lastSep = linktext.lastIndexOf(QLatin1String("::")); + if (lastSep != -1) + linktext.remove(0, lastSep + 2); + else + stripPythonQualifiers(&linktext); if (linkContext->linkRef == linktext) return QString(); if ((linkContext->type & QtXmlToSphinx::LinkContext::FunctionMask) != 0 && (linkContext->linkRef + QLatin1String("()")) == linktext) { return QString(); } - const QStringRef item = linkContext->linkRef.splitRef(QLatin1Char('.')).constLast(); - if (item == linktext) - return QString(); - if ((linkContext->type & QtXmlToSphinx::LinkContext::FunctionMask) != 0 - && (item + QLatin1String("()")) == linktext) { - return QString(); - } return linktext; } @@ -1576,7 +1601,11 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex writeInheritedByList(s, metaClass, classes()); - formatSince(s, "class", metaClass->typeEntry()); + const auto version = versionOf(metaClass->typeEntry()); + if (!version.isNull()) + s << rstVersionAdded(version); + if (metaClass->attributes().testFlag(AbstractMetaAttributes::Deprecated)) + s << rstDeprecationNote("class"); writeFunctionList(s, metaClass); @@ -1608,7 +1637,7 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex else s << ".. method:: "; - writeFunction(s, true, metaClass, func); + writeFunction(s, metaClass, func); } writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass, 0); @@ -1697,7 +1726,9 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas for (AbstractMetaEnum *en : enums) { s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; writeFormattedText(s, en->documentation(), cppClass); - formatSince(s, "enum", en->typeEntry()); + const auto version = versionOf(en->typeEntry()); + if (!version.isNull()) + s << rstVersionAdded(version); } } @@ -1717,7 +1748,6 @@ void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppCla void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* cppClass) { static const QString sectionTitle = QLatin1String(".. class:: "); - static const QString sectionTitleSpace = QString(sectionTitle.size(), QLatin1Char(' ')); AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible); for (int i = lst.size() - 1; i >= 0; --i) { @@ -1728,14 +1758,23 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* bool first = true; QHash<QString, AbstractMetaArgument*> arg_map; + IndentorBase<1> indent1; + indent1.indent = INDENT.total(); for (AbstractMetaFunction *func : qAsConst(lst)) { + s << indent1; if (first) { first = false; s << sectionTitle; - } else { - s << sectionTitleSpace; + indent1.indent += sectionTitle.size(); } - writeFunction(s, false, cppClass, func); + s << functionSignature(cppClass, func) << "\n\n"; + + const auto version = versionOf(func->typeEntry()); + if (!version.isNull()) + s << indent1 << rstVersionAdded(version); + if (func->attributes().testFlag(AbstractMetaAttributes::Deprecated)) + s << indent1 << rstDeprecationNote("constructor"); + const AbstractMetaArgumentList &arguments = func->arguments(); for (AbstractMetaArgument *arg : arguments) { if (!arg_map.contains(arg->name())) { @@ -1747,7 +1786,7 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* s << endl; for (QHash<QString, AbstractMetaArgument*>::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { - Indentation indentation(INDENT); + Indentation indentation(INDENT, 2); writeParameterType(s, cppClass, it.value()); } @@ -1910,7 +1949,7 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, return didSomething; } -void QtDocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +QString QtDocGenerator::functionSignature(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) { QString className; if (!func->isConstructor()) @@ -1922,23 +1961,25 @@ void QtDocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaCl if (!funcName.startsWith(className)) funcName = className + funcName; - s << funcName << "(" << parseArgDocStyle(cppClass, func) << ")"; + return funcName + QLatin1Char('(') + parseArgDocStyle(cppClass, func) + + QLatin1Char(')'); } QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, const AbstractMetaClass* cppClass) { QString strType; - if (type->name() == QLatin1String("QString")) { + const QString name = type->name(); + if (name == QLatin1String("QString")) { strType = QLatin1String("unicode"); - } else if (type->name() == QLatin1String("QVariant")) { + } else if (name == QLatin1String("QVariant")) { strType = QLatin1String("object"); - } else if (type->name() == QLatin1String("QStringList")) { + } else if (name == QLatin1String("QStringList")) { strType = QLatin1String("list of strings"); - } else if (type->isConstant() && type->name() == QLatin1String("char") && type->indirections() == 1) { + } else if (type->isConstant() && name == QLatin1String("char") && type->indirections() == 1) { strType = QLatin1String("str"); - } else if (type->name().startsWith(QLatin1String("unsigned short"))) { + } else if (name.startsWith(QLatin1String("unsigned short"))) { strType = QLatin1String("int"); - } else if (type->name().startsWith(QLatin1String("unsigned "))) { // uint and ulong + } else if (name.startsWith(QLatin1String("unsigned "))) { // uint and ulong strType = QLatin1String("long"); } else if (type->isContainer()) { QString strType = translateType(type, cppClass, Options(ExcludeConst) | ExcludeReference); @@ -1962,7 +2003,7 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, cons refTag = QLatin1String("attr"); else refTag = QLatin1String("class"); - strType = QLatin1Char(':') + refTag + QLatin1String(":`") + type->fullName() + QLatin1Char('`'); + strType = QLatin1Char(':') + refTag + QLatin1String(":`") + name + QLatin1Char('`'); } return strType; } @@ -1976,8 +2017,6 @@ void QtDocGenerator::writeParameterType(QTextStream& s, const AbstractMetaClass* void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func) { - Indentation indentation(INDENT); - s << endl; const AbstractMetaArgumentList &funcArgs = func->arguments(); for (AbstractMetaArgument *arg : funcArgs) { @@ -2009,22 +2048,25 @@ void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractM s << endl; } -void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +void QtDocGenerator::writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, + const AbstractMetaFunction* func) { - writeFunctionSignature(s, cppClass, func); - s << endl; - - formatSince(s, "method", func->typeEntry()); + s << functionSignature(cppClass, func) << "\n\n"; - if (writeDoc) { - s << endl; + { + Indentation indentation(INDENT); writeFunctionParametersType(s, cppClass, func); - s << endl; - writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); - if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) - writeFormattedText(s, func->documentation(), cppClass); - writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); + const auto version = versionOf(func->typeEntry()); + if (!version.isNull()) + s << INDENT << rstVersionAdded(version); + if (func->attributes().testFlag(AbstractMetaAttributes::Deprecated)) + s << INDENT << rstDeprecationNote("function"); } + + writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); + if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) + writeFormattedText(s, func->documentation(), cppClass); + writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); } static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4) @@ -2159,7 +2201,7 @@ void QtDocGenerator::writeModuleDocumentation() Documentation moduleDoc = m_docParser->retrieveModuleDocumentation(it.key()); if (moduleDoc.format() == Documentation::Native) { QString context = it.key(); - context.remove(0, context.lastIndexOf(QLatin1Char('.')) + 1); + stripPythonQualifiers(&context); QtXmlToSphinx x(this, moduleDoc.value(), context); s << x; } else { diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index 5545de9a9..43345716d 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -239,8 +239,9 @@ private: void writeFields(QTextStream &s, const AbstractMetaClass *cppClass); void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + QString functionSignature(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + void writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, + const AbstractMetaFunction* func); void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func); void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index f2112e34f..86a632e78 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -2091,10 +2091,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s, QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry()); s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG << ')' << endl; { - Indentation indent1(INDENT); - Indentation indent2(INDENT); - Indentation indent3(INDENT); - Indentation indent4(INDENT); + Indentation indent1(INDENT, 4); s << INDENT << "&& !" << checkFunc << "self);" << endl; } s << INDENT << "if (isReverse)" << endl; @@ -5536,7 +5533,7 @@ bool CppGenerator::finishGeneration() if (usePySideExtensions()) { s << "void cleanTypesAttributes(void) {" << endl; s << INDENT << "if (PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03060000)" << endl; - s << INDENT << " return; // testbinding crashes in Python 3.5 when hasattr touches types!" << endl; + s << INDENT << " return; // PYSIDE-953: testbinding crashes in Python 3.5 when hasattr touches types!" << endl; s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {" << endl; { Indentation indentation(INDENT); diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index a95603754..6a85bf7ef 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -30,6 +30,7 @@ #include <reporthandler.h> #include <graph.h> #include "overloaddata.h" +#include "indentor.h" #include "shibokengenerator.h" #include <QtCore/QDir> @@ -857,13 +858,14 @@ static inline QString toHtml(QString s) QString OverloadData::dumpGraph() const { - QString indent(4, QLatin1Char(' ')); + Indentor INDENT; + Indentation indent(INDENT); QString result; QTextStream s(&result); if (m_argPos == -1) { const AbstractMetaFunction* rfunc = referenceFunction(); s << "digraph OverloadedFunction {" << endl; - s << indent << "graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];" << endl; + s << INDENT << "graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];" << endl; // Shows all function signatures s << "legend [fontsize=9 fontname=freemono shape=rect label=\""; @@ -878,7 +880,7 @@ QString OverloadData::dumpGraph() const s << "\"];" << endl; // Function box title - s << indent << '"' << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 "; + s << INDENT << '"' << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 "; s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">"; s << "<tr><td bgcolor=\"black\" align=\"center\" cellpadding=\"6\" colspan=\"2\"><font color=\"white\">"; if (rfunc->ownerClass()) @@ -931,14 +933,14 @@ QString OverloadData::dumpGraph() const s << "</table>> ];" << endl; for (const OverloadData *pd : m_nextOverloadData) - s << indent << '"' << rfunc->name() << "\" -> " << pd->dumpGraph(); + s << INDENT << '"' << rfunc->name() << "\" -> " << pd->dumpGraph(); s << "}" << endl; } else { QString argId = QLatin1String("arg_") + QString::number(quintptr(this)); s << argId << ';' << endl; - s << indent << '"' << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 "; + s << INDENT << '"' << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 "; s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">"; // Argument box title @@ -982,7 +984,7 @@ QString OverloadData::dumpGraph() const s << "</table>>];" << endl; for (const OverloadData *pd : m_nextOverloadData) - s << indent << argId << " -> " << pd->dumpGraph(); + s << INDENT << argId << " -> " << pd->dumpGraph(); } return result; } diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index 61a097771..cd00a1482 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -167,8 +167,11 @@ _get_class_of_descr(PyObject *ob) static PyObject * GetClassOfFunc(PyObject *ob) { - if (PyType_Check(ob)) + if (PyType_Check(ob)) { + // PySide-928: The type case must do refcounting like the others as well. + Py_INCREF(ob); return ob; + } if (PyType_IsSubtype(Py_TYPE(ob), &PyCFunction_Type)) return _get_class_of_cf(ob); if (Py_TYPE(ob) == PepStaticMethod_TypePtr) @@ -535,6 +538,10 @@ error: static int _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) { + /* + * This function pre-fills all fields of the new gsp. We then + * insert the changed values. + */ PyGetSetDef *gsp = type->tp_getset; if (gsp != nullptr) { for (; gsp->name != NULL; gsp++) { @@ -542,7 +549,7 @@ _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) new_gsp->set = gsp->set; new_gsp->doc = gsp->doc; new_gsp->closure = gsp->closure; - return 1; + return 1; // success } } } diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp index a306f7a9d..e55ccfab5 100644 --- a/sources/shiboken2/libshiboken/voidptr.cpp +++ b/sources/shiboken2/libshiboken/voidptr.cpp @@ -95,13 +95,6 @@ int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) sbkSelf->size = sbkOther->size; sbkSelf->isWritable = sbkOther->isWritable; } - // Shiboken::Object wrapper. - else if (Shiboken::Object::checkType(addressObject)) { - SbkObject *sbkOther = reinterpret_cast<SbkObject *>(addressObject); - sbkSelf->cptr = sbkOther->d->cptr[0]; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0 ? true : false; - } // Python buffer interface. else if (PyObject_CheckBuffer(addressObject)) { Py_buffer bufferView; @@ -111,26 +104,41 @@ int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) return 0; sbkSelf->cptr = bufferView.buf; - sbkSelf->size = bufferView.len; + sbkSelf->size = bufferView.len > 0 ? bufferView.len : size; sbkSelf->isWritable = bufferView.readonly > 0 ? false : true; // Release the buffer. PyBuffer_Release(&bufferView); } + // Shiboken::Object wrapper. + else if (Shiboken::Object::checkType(addressObject)) { + SbkObject *sbkOther = reinterpret_cast<SbkObject *>(addressObject); + sbkSelf->cptr = sbkOther->d->cptr[0]; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; + } // An integer representing an address. else { - void *cptr = PyLong_AsVoidPtr(addressObject); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "Creating a VoidPtr object requires an address of a C++ object, " - "a wrapped Shiboken Object type, " - "an object implementing the Python Buffer interface, " - "or another VoidPtr object."); - return -1; + if (addressObject == Py_None) { + sbkSelf->cptr = nullptr; + sbkSelf->size = 0; + sbkSelf->isWritable = false; + } + + else { + void *cptr = PyLong_AsVoidPtr(addressObject); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "Creating a VoidPtr object requires an address of a C++ object, " + "a wrapped Shiboken Object type, " + "an object implementing the Python Buffer interface, " + "or another VoidPtr object."); + return -1; + } + sbkSelf->cptr = cptr; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; } - sbkSelf->cptr = cptr; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0 ? true : false; } return 0; @@ -174,6 +182,24 @@ PyObject *SbkVoidPtrObject_int(PyObject *v) return PyLong_FromVoidPtr(sbkObject->cptr); } +PyObject *toBytes(PyObject *self, PyObject *args) +{ + SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); + if (sbkObject->size < 0) { + PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set."); + return nullptr; + } + PyObject *bytes = PyBytes_FromStringAndSize(reinterpret_cast<const char*>(sbkObject->cptr), + sbkObject->size); + Py_XINCREF(bytes); + return bytes; +} + +static struct PyMethodDef SbkVoidPtrObject_methods[] = { + {"toBytes", toBytes, METH_NOARGS}, + {0} +}; + static Py_ssize_t SbkVoidPtrObject_length(PyObject *v) { SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); @@ -233,6 +259,7 @@ static PyType_Slot SbkVoidPtrType_slots[] = { {Py_tp_init, (void *)SbkVoidPtrObject_init}, {Py_tp_new, (void *)SbkVoidPtrObject_new}, {Py_tp_dealloc, (void *)object_dealloc}, + {Py_tp_methods, (void *)SbkVoidPtrObject_methods}, {0, 0} }; static PyType_Spec SbkVoidPtrType_spec = { diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index 952d31994..b37d0c941 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -70,10 +70,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/__init__.py" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/enum_sig.py" "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/enum_sig.py" COPYONLY) if (PYTHON_VERSION_MAJOR EQUAL 3) - if (PYTHON_VERSION_MINOR EQUAL 5) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/contextlib36.py" - "${CMAKE_CURRENT_BINARY_DIR}/support/signature/contextlib36.py" COPYONLY) - endif() else() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/backport_inspect.py" "${CMAKE_CURRENT_BINARY_DIR}/support/signature/backport_inspect.py" COPYONLY) diff --git a/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py b/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py index ef18beb67..cdd84f9be 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py +++ b/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py @@ -49,7 +49,7 @@ you are changing messages (what I did, of course :-) . import os -patched_modules = "backport_inspect typing27 contextlib36" +patched_modules = "backport_inspect typing27" offending_words = { "behavio""ur": "behavior", diff --git a/sources/shiboken2/shibokenmodule/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/loader.py index 749229c3b..458759845 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/support/signature/loader.py @@ -158,10 +158,6 @@ with ensure_import_support(): import typing import inspect inspect.formatannotation = formatannotation - if sys.version_info[:2] == (3, 5): - # PYSIDE-953: Use a newer contextlib. - from support.signature import contextlib36 as contextlib - sys.modules["contextlib"] = contextlib else: import inspect namespace = inspect.__dict__ diff --git a/sources/shiboken2/tests/libsample/nontypetemplate.h b/sources/shiboken2/tests/libsample/nontypetemplate.h index 4e2100626..5a9e670c6 100644 --- a/sources/shiboken2/tests/libsample/nontypetemplate.h +++ b/sources/shiboken2/tests/libsample/nontypetemplate.h @@ -37,6 +37,7 @@ template <int Size> class IntArray { public: + explicit IntArray(const int *data) { std::copy(data, data + Size, m_array); } explicit IntArray(int v) { std::fill(m_array, m_array + Size, v); } int sum() const { return std::accumulate(m_array, m_array + Size, int(0)); } diff --git a/sources/shiboken2/tests/samplebinding/nontypetemplate_test.py b/sources/shiboken2/tests/samplebinding/nontypetemplate_test.py index 9adfa2441..a7a4da72b 100644 --- a/sources/shiboken2/tests/samplebinding/nontypetemplate_test.py +++ b/sources/shiboken2/tests/samplebinding/nontypetemplate_test.py @@ -28,6 +28,14 @@ ## ############################################################################# +hasNumPy = False + +try: + import numpy + hasNumPy = True +except ImportError: + pass + import unittest from sample import IntArray2, IntArray3 @@ -40,5 +48,12 @@ class NonTypeTemplateTest(unittest.TestCase): array3 = IntArray3(5) self.assertEqual(array3.sum(), 15) + def testArrayInitializer(self): + if not hasNumPy: + return + array3 = IntArray3(numpy.array([1, 2, 3], dtype = 'int32')) + self.assertEqual(array3.sum(), 6) + + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 9b967fc53..78ceaab43 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -521,8 +521,17 @@ </value-type> <value-type name="IntArray" generate="no"/> - <value-type name="IntArray2"/> - <value-type name="IntArray3"/> + <value-type name="IntArray2"> + <modify-function signature="IntArray2(const int*)"> + <modify-argument index="1"><array/></modify-argument> + </modify-function> + </value-type> + + <value-type name="IntArray3"> + <modify-function signature="IntArray3(const int*)"> + <modify-argument index="1"><array/></modify-argument> + </modify-function> + </value-type> <enum-type name="OverloadedFuncEnum"/> <!-- BUG: |