From 388de8cedde4ced1e417f91e25f505c1291e4119 Mon Sep 17 00:00:00 2001 From: Julien Cabieces Date: Mon, 11 Dec 2023 10:18:23 +0100 Subject: [PATCH] Fix sip tests --- scripts/sip_include.sh | 79 +-- ...ed.sip => sipifyheader.expected_pyqt5.sip} | 0 .../sipify/sipifyheader.expected_pyqt6.sip | 466 ++++++++++++++++++ tests/code_layout/sipify/sipifyheader.h | 2 +- tests/code_layout/sipify/test_sip_include.sh | 30 +- tests/code_layout/sipify/test_sipfiles.sh | 30 +- tests/code_layout/sipify/test_sipify.sh | 22 +- 7 files changed, 557 insertions(+), 72 deletions(-) rename tests/code_layout/sipify/{sipifyheader.expected.sip => sipifyheader.expected_pyqt5.sip} (100%) create mode 100644 tests/code_layout/sipify/sipifyheader.expected_pyqt6.sip diff --git a/scripts/sip_include.sh b/scripts/sip_include.sh index 1f201bbfbeb..f4cc9e41c07 100755 --- a/scripts/sip_include.sh +++ b/scripts/sip_include.sh @@ -38,49 +38,50 @@ else fi sources=(HDRS MOC_HDRS SRCS) -for module in "${modules[@]}"; do - file=${DIR}/python/${module}/${module}_auto.sip - echo "Creating python/${module}/${module}_auto.sip" - echo "// Include auto-generated SIP files" > $file +for root_dir in python python/PyQt6; do + for module in "${modules[@]}"; do + file=${DIR}/$root_dir/${module}/${module}_auto.sip + echo "Creating $root_dir/${module}/${module}_auto.sip" + echo "// Include auto-generated SIP files" > $file - headers=$( - for source in "${sources[@]}"; do - echo "QGIS_${module^^}_${source}" - ${GP}sed -r -n -e "/^\s*set\s*\(QGIS_${module^^}_${source}/,/\)\$/{ /^\s*set\s*\(QGIS_${module^^}_${source}/d; /\)\$/d; p; }" src/${module}/CMakeLists.txt | \ - ${GP}sed -r -e '/\.cc?$/d' `# remove c and cc extensions` \ - -e 's/\.cpp$/.h/' `# rename cpp file as headers` \ - -e '/^\s*\$\{CMAKE_(CURRENT_)?BINARY_DIR\}/d' \ - -e '/^\s*#/d' `# remove commented lines` \ - -e 's/\$\{.*\}//g' `# remove CMake variable append` \ - -e 's/^\s+//' `# remove leading spaces` \ - -e '/^\s*$/d' `# remove blank lines` - done | cat -n | sort -uk2 | sort -nk1 | cut -f2- # remove duplicated lines without sorting - ) - for header in ${headers}; do - if [ ! -f src/${module}/$header ]; then - # if no header, no sip file! - #echo "src/${module}/$header not found" - continue - fi - if ! grep -xq -E '^(#define +)?SIP_NO_FILE' src/${module}/${header}; then - sip=$(${GP}sed -r 's/(.*)\.h$/\1.sip/' <<< ${header}) - if_cond=$(grep -x -E '^(#define +)?SIP_IF_MODULE\((.*)\)$' src/${module}/${header} | \ - ${GP}sed -r -e 's/(#define +)?SIP_IF_MODULE\((.*)\)/%If (\2)/') - if [[ -n $if_cond ]]; then - echo "$if_cond" >> $file + headers=$( + for source in "${sources[@]}"; do + echo "QGIS_${module^^}_${source}" + ${GP}sed -r -n -e "/^\s*set\s*\(QGIS_${module^^}_${source}/,/\)\$/{ /^\s*set\s*\(QGIS_${module^^}_${source}/d; /\)\$/d; p; }" src/${module}/CMakeLists.txt | \ + ${GP}sed -r -e '/\.cc?$/d' `# remove c and cc extensions` \ + -e 's/\.cpp$/.h/' `# rename cpp file as headers` \ + -e '/^\s*\$\{CMAKE_(CURRENT_)?BINARY_DIR\}/d' \ + -e '/^\s*#/d' `# remove commented lines` \ + -e 's/\$\{.*\}//g' `# remove CMake variable append` \ + -e 's/^\s+//' `# remove leading spaces` \ + -e '/^\s*$/d' `# remove blank lines` + done | cat -n | sort -uk2 | sort -nk1 | cut -f2- # remove duplicated lines without sorting + ) + for header in ${headers}; do + if [ ! -f src/${module}/$header ]; then + # if no header, no sip file! + #echo "src/${module}/$header not found" + continue fi - if [[ "$sip" == [0-9]* ]]; then - # unfortunately SIP parser does not accept relative paths starting with a number - # so "%Include 3d/xxxx.sip" is a syntax error but everything works with "%Include ./3d/xxxx.sip" - sip="./$sip" + if ! grep -xq -E '^(#define +)?SIP_NO_FILE' src/${module}/${header}; then + sip=$(${GP}sed -r 's/(.*)\.h$/\1.sip/' <<< ${header}) + if_cond=$(grep -x -E '^(#define +)?SIP_IF_MODULE\((.*)\)$' src/${module}/${header} | \ + ${GP}sed -r -e 's/(#define +)?SIP_IF_MODULE\((.*)\)/%If (\2)/') + if [[ -n $if_cond ]]; then + echo "$if_cond" >> $file + fi + if [[ "$sip" == [0-9]* ]]; then + # unfortunately SIP parser does not accept relative paths starting with a number + # so "%Include 3d/xxxx.sip" is a syntax error but everything works with "%Include ./3d/xxxx.sip" + sip="./$sip" + fi + echo "%Include auto_generated/$sip" >> $file + if [[ -n $if_cond ]]; then + echo "%End" >> $file + fi fi - echo "%Include auto_generated/$sip" >> $file - if [[ -n $if_cond ]]; then - echo "%End" >> $file - fi - fi + done done done - popd > /dev/null diff --git a/tests/code_layout/sipify/sipifyheader.expected.sip b/tests/code_layout/sipify/sipifyheader.expected_pyqt5.sip similarity index 100% rename from tests/code_layout/sipify/sipifyheader.expected.sip rename to tests/code_layout/sipify/sipifyheader.expected_pyqt5.sip diff --git a/tests/code_layout/sipify/sipifyheader.expected_pyqt6.sip b/tests/code_layout/sipify/sipifyheader.expected_pyqt6.sip new file mode 100644 index 00000000000..bd302ca0d15 --- /dev/null +++ b/tests/code_layout/sipify/sipifyheader.expected_pyqt6.sip @@ -0,0 +1,466 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * tests/code_layout/sipify/sipifyheader.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ +class QgsSettingsEntryEnumFlag_settingsDigitizingDefaultSnapType +{ +%TypeHeaderCode +#include "sipifyheader.h" +#include "qgssettingsentry.h" +typedef QgsSettingsEntryEnumFlag QgsSettingsEntryEnumFlag_settingsDigitizingDefaultSnapType; +%End + public: + QgsSettingsEntryEnumFlag_settingsDigitizingDefaultSnapType( const QString &key, QgsSettings::Section section, const Qgis::SnappingType &defaultValue, const QString &description = QString() ); + QString key( const QString &dynamicKeyPart = QString() ) const; + Qgis::SnappingType value( const QString &dynamicKeyPart = QString(), bool useDefaultValueOverride = false, const Qgis::SnappingType &defaultValueOverride = Qgis::SnappingType() ) const; +}; + + + +%ModuleHeaderCode +#include +#include +%End + + + + + + + + +typedef qint64 QgsFeatureId; + +typedef QSet QgsFeatureIds; +typedef QMap> QgsChangedAttributesMap; +typedef QMap > QgsChangedAttributesMap; +typedef QMap> QgsChangedAttributesMap; + +typedef QVector QgsSuperClass; + +%MappedType QgsSuperClass +{ + // The annotations are modified by astyle (these will be fixed by sipify.pl) +%TypeHeaderCode +#include +%End + +%ConvertFromTypeCode + // Create the list. + PyObject *l; + return l; +%End +} + + +typedef QtClass QtClassQVariantBase; + +class QgsSipifyHeader : QtClassQVariantBase +{ +%Docstring(signature="appended") +Documentation goes here + +Here's some comment mentioning another class :py:class:`QgsAutoAwesomemater`.makeAwesome. + +.. note:: + + some other note + +.. versionadded:: 3.0 +%End + +%TypeHeaderCode +#include "sipifyheader.h" +#include "qtclass.h" +typedef QtClass QtClassQVariantBase; +%End +%ConvertToSubClassCode + if ( sipCpp->headerType() == QgsSipifyHeader::Special ) + sipType = sipType_QgsSpecialSipifyHeader; + else + sipType = sipType_QgsStandardSipifyHeader; +%End + public: + enum MyEnum /BaseType=IntFlag/ + { + Success, + NoSuccess, + ImaginarySuccess, + RecursiveSuccess, + SuccessCombination, + PythonName /PyName=DifferentName/, + MonkeyName, + }; + typedef QFlags Flags; + + + enum OneLiner { Success, NoSuccess }; + + private: + void makePrivate( int a ); + + public: + void publicMethodBetween1(); + + private: + void makePrivateMultiline( int a, + int b ); + public: + void publicMethodBetween2(); + + private: + bool makePrivateMultilineImpl( int a, + int b ); + public: + const QgsSettingsEntryEnumFlag_settingsDigitizingDefaultSnapType settingsDigitizingDefaultSnapType; + + struct Data + { + Data( QgsMapLayer *layer, Qstring name ); + + QString mName; + int mCount; + QgsMapLayer *mLayer; + QList contextMenuActions; + }; + + static const int MONTHS; + + explicit QgsSipifyHeader(); +%Docstring +A constructor with definition in header +%End + + QgsSipifyHeader( QWidget *parent /TransferThis/ = 0 ); +%Docstring +A classic constructor with arguments +%End + + QgsSipifyHeader( bool a = true ); +%Docstring +A constructor with no empty `()` +%End + + QgsSipifyHeader( QList a, const Issues &b = Issues::weDontHaveIssues(), QgsClass *b = 0 ); +%Docstring +A constructor with some special character types +%End + + Constructor(); + + virtual ~Destructor(); + + Constructor( const QString &name, + bool optional = false, + const QVariant &defaultValue = QVariant() ); + + QgsSipifyHeader(); +%Docstring +Default constructor +%End + + + bool operator==( const QgsSipifyHeader other ); + + void multilineMethod( const QgsPointXY &startPoint, + QgsFeatureId featureId, + QgsVectorLayer *vl, + Qgis::SnappingType snap_to ) const; +%Docstring +A multiline method signature +%End + + + void nonAnnotatedMethodFollowingSkip(); + + + virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) /Factory/; +%Docstring +Factory annotation +%End + + SomeObject *createAnother() /Factory/; + + virtual SomeObject *createAnother2() /Factory/; + + void LongDocStringMethod(); +%Docstring +My long doc string +is not very interesting! +%End + + void LongDocStringMethodWithBrief(); +%Docstring +some brief +My long doc ``string`` +is not very interesting! +Here's some comment mentioning another class :py:class:`QgsAutoAwesomemater`.makeLessAwesome. +%End + + MyPointer *pointerReturnValue(); +%Docstring +I return a pointer. If something bad happens, I return ``None``. + +:return: pointer to something cool +%End + + bool isOKwithErrMesg( QString &ErrMsg /Out/ ); + + void InOutParam( bool &ok = true /In,Out/ ); + + void setDiagramRenderer( QgsDiagramRenderer *r /Transfer/ ); + + void differentDefaultValue( bool defaultValue = false , QWidget *parent = 0, QString msg = "hello" ); + + void differentType( QList & list ); + + void complexDefaultValueAndType( QList>> list = QList>> ); +%Docstring +complex default value and type (i.e. containing commas) should be given as a string with single quotes +%End + + int inlineKeyWordShouldNotAppear(); + + QString labelForRange( double lower, double upper ) const /PyName=labelForLowerUpper/; + + void setComposition( QgsComposition *c /KeepReference/ ); + + void removeProxyFactory( QNetworkProxyFactory *factory /TransferBack/ ); + + bool removeFunctionBody( const QList &list, QgsVectorLayer *vl, Some::Thing _part = -1 /*default =-1*/ ); + + + void multilineBodyAndDefinition( const QList &list, + QgsVectorLayer *vl, + Some::Thing _part = -1 /*default =-1*/ ); + + QgsRaster::RasterBuildPyramids buildPyramidsFlag() const; +%Docstring +Removing function body with namespaced return value +%End + + virtual const QgsLayerMetadata &metadata() const; +%Docstring +Removing function body with virtual const reference +%End + + bool myMultiLineBody(); +%Docstring +Mulitline body +%End + + + virtual int overriddenProperty(); + + virtual int overrideWithoutVirtual(); + + + virtual void overrideWithoutVirtualMultLine( const QList &list1, + const QList &list2 ); + + QString returnTypeString() const; + + double returnTypeDouble() const; + + QList< QgsAnnotation * > returnTypeList(); + + QVector< QgsAnnotation > returnTypeVector(); + + QStringList returnTypeStringList(); + + QSet returnTypeSet(); + + This shouldBeIncluded; + + static QString invokableMethod(); + + bool initializedMember; + + struct PublicStruct + { + explicit PublicStruct( int _part = -1, int _ring = -1, int _vertex = -1, VertexType _type = SegmentVertex ); + + bool isValid( const QgsAbstractGeometry *geom ) const; + + int part; + int ring; + int vertex; + VertexType type; + } + + class PublicMembersWithValue +{ + +%TypeHeaderCode +#include "sipifyheader.h" +%End + public: + + double snappedDistanceAlongCurve; + double snappedHeight; + }; + + void combinedAnnotations() /Factory,PyName=otherName/; + void multiAnnotationArg( SomeClass **object /Out,TransferBack/, int &another /Out/ ); + + void simple(); +%Docstring +remove argument +%End + void method(); + void test(); + void avoidIntersections( const QList &avoidIntersectionsLayers ); + + void position(); + void position( bool keep ); + void position( bool keep, bool keep ); + void position( bool keep ); + + void method( bool superArg = test ); + void method( bool myArg1, + bool superArg2 = test, // hola + bool myArg3 ); + + + static SIP_PYLIST changeReturnType( QVector *resultTree = 0, QVector &resultCost = 0 ); + + Whatever &operator[]( int i ) /Factory/; +%MethodCode + .... +%End + + void ZshouldBeShown(); + + void methodCodeWithMultiLineDef(); +%MethodCode + if ( QgsWkbTypes::flatType( a0 ) != QgsWkbTypes::Point ) + { + multiLineDef( PyExc_ValueError, + QString( "%1 is not nice" ).arg( QgsWkbTypes::displayString( a0 ) ).toUtf8().constData() ); + } + else + { + sipCpp = new sipQgsPoint( a0, a1, a2, a3, a4 ); + } +%End + + protected: + bool thisShouldBeListed(); + + + private: + void privateMethodSIPRUNareShown(); + public: + void FallBackToPublic(); + + private: + void ShowThisPrivateOne(); +}; + +class ClassWithPrivateInheritanceOnly /Abstract/ +{ +%Docstring(signature="appended") +Documentation goes here +%End + +%TypeHeaderCode +#include "sipifyheader.h" +%End + public: + explicit ClassWithPrivateInheritanceOnly(); +%Docstring +A constructor with definition in header on several lines +%End +}; + + +class AbstractClass /Abstract/ +{ +%Docstring(signature="appended") +Documentation goes here +%End + +%TypeHeaderCode +#include "sipifyheader.h" +%End + public: + explicit AbstractClass(); +%Docstring +A constructor +%End + +}; + +QFlags operator|(QgsSipifyHeader::MyEnum f1, QFlags f2); + + + +typedef QgsTemplate QgsTemplateSomethingBase; + +class TemplateInheritance1 : QgsTemplateSomethingBase +{ + +%TypeHeaderCode +#include "sipifyheader.h" +#include "qgstemplate.h" +typedef QgsTemplate QgsTemplateSomethingBase; +%End +} +class TemplateInheritance2 +{ + +%TypeHeaderCode +#include "sipifyheader.h" +%End +} + +typedef QgsTemplate QgsTemplateSomethingBase; + +class TemplateInheritance3 : QgsTemplateSomethingBase, SomethingElse +{ + +%TypeHeaderCode +#include "sipifyheader.h" +#include "qgstemplate.h" +typedef QgsTemplate QgsTemplateSomethingBase; +%End +} +class TemplateInheritance4 : SomethingElse1, SomethingElse2 +{ + +%TypeHeaderCode +#include "sipifyheader.h" +%End +} +class TemplateInheritance5 : SomethingElse +{ + +%TypeHeaderCode +#include "sipifyheader.h" +%End +} + +typedef YourSuperTemplate YourSuperTemplateAbcDefGhiBase; + +class TemplateInheritance6 : SomethingElse, YourSuperTemplateAbcDefGhiBase +{ + +%TypeHeaderCode +#include "sipifyheader.h" +#include "yoursupertemplate.h" +typedef YourSuperTemplate YourSuperTemplateAbcDefGhiBase; +%End +} + + +/************************************************************************ + * This file has been generated automatically from * + * * + * tests/code_layout/sipify/sipifyheader.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/tests/code_layout/sipify/sipifyheader.h b/tests/code_layout/sipify/sipifyheader.h index 56a83824432..32e29e0a547 100644 --- a/tests/code_layout/sipify/sipifyheader.h +++ b/tests/code_layout/sipify/sipifyheader.h @@ -107,7 +107,7 @@ class CORE_EXPORT QgsSipifyHeader : public QtClass, private Ui::QgsBas public: //! This is an enum - enum MyEnum + enum MyEnum : int { Success = 0, //!< Edit operation was successful NoSuccess = 1, //!< Edit operation resulted in an empty geometry diff --git a/tests/code_layout/sipify/test_sip_include.sh b/tests/code_layout/sipify/test_sip_include.sh index e81af576b75..3cd287c802e 100755 --- a/tests/code_layout/sipify/test_sip_include.sh +++ b/tests/code_layout/sipify/test_sip_include.sh @@ -8,23 +8,27 @@ REV=$(git -C ${srcdir} log -n1 --pretty=%H) pushd ${DIR} > /dev/null || exit code=0 -modules=(core gui analysis server) -for module in "${modules[@]}"; do - cp python/${module}/${module}_auto.sip python/${module}/${module}_auto.sip.$REV.bak +modules=(3d core gui analysis server) +for root_dir in python python/PyQt6; do + for module in "${modules[@]}"; do + cp $root_dir/${module}/${module}_auto.sip $root_dir/${module}/${module}_auto.sip.$REV.bak + done done ./scripts/sip_include.sh -for module in "${modules[@]}"; do - outdiff=$(diff python/${module}/${module}_auto.sip python/${module}/${module}_auto.sip.$REV.bak) - if [[ -n $outdiff ]]; then - echo -e " *** SIP include file for \x1B[33m${module}\x1B[0m not up to date." - echo "$outdiff" - code=1 - mv python/${module}/${module}_auto.sip.$REV.bak python/${module}/${module}_auto.sip - else - rm python/${module}/${module}_auto.sip.$REV.bak - fi +for root_dir in python python/PyQt6; do + for module in "${modules[@]}"; do + outdiff=$(diff $root_dir/${module}/${module}_auto.sip $root_dir/${module}/${module}_auto.sip.$REV.bak) + if [[ -n $outdiff ]]; then + echo -e " *** SIP include file for \x1B[33m${module}\x1B[0m not up to date." + echo "$outdiff" + code=1 + mv $root_dir/${module}/${module}_auto.sip.$REV.bak $root_dir/${module}/${module}_auto.sip + else + rm $root_dir/${module}/${module}_auto.sip.$REV.bak + fi + done done if [[ code -eq 1 ]]; then diff --git a/tests/code_layout/sipify/test_sipfiles.sh b/tests/code_layout/sipify/test_sipfiles.sh index c013ed32c62..c6ef19bdb35 100755 --- a/tests/code_layout/sipify/test_sipfiles.sh +++ b/tests/code_layout/sipify/test_sipfiles.sh @@ -14,37 +14,43 @@ fi pushd ${DIR} > /dev/null || exit -modules=(core gui analysis server) +modules=(3d core gui analysis server) code=0 -for module in "${modules[@]}"; do - while read -r sipfile; do +for root_dir in python python/PyQt6; do + + if [[ $root_dir == "python/PyQt6" ]]; then + IS_QT6="--qt6" + fi + + for module in "${modules[@]}"; do + while read -r sipfile; do header=$(${GP}sed -E 's@(.*)\.sip@src/\1.h@; s@auto_generated/@@' <<< $sipfile) pyfile=$(${GP}sed -E 's@([^\/]+\/)*([^\/]+)\.sip@\2.py@;' <<< $sipfile) if [ ! -f $header ]; then echo "*** Missing header: $header for sipfile $sipfile" else - outdiff=$(./scripts/sipify.pl -p python/${module}/auto_additions/${pyfile}.temp $header | diff python/$sipfile.in -) + outdiff=$(./scripts/sipify.pl $IS_QT6 -p $root_dir/${module}/auto_additions/${pyfile}.temp $header | diff $root_dir/$sipfile.in -) if [[ -n "$outdiff" ]]; then - echo " *** SIP file not up to date: $sipfile" + echo " *** SIP file not up to date: $root_dir/$sipfile" echo " $outdiff " code=1 fi - if [[ -f python/${module}/auto_additions/${pyfile}.temp ]]; then - outdiff2=$(diff python/${module}/auto_additions/${pyfile} python/${module}/auto_additions/${pyfile}.temp) + if [[ -f $root_dir/${module}/auto_additions/${pyfile}.temp ]]; then + outdiff2=$(diff $root_dir/${module}/auto_additions/${pyfile} $root_dir/${module}/auto_additions/${pyfile}.temp) if [[ -n "$outdiff2" ]]; then - echo " *** Python addition file not up to date: $sipfile" + echo " *** Python addition file not up to date: $root_dir/$sipfile" echo " $outdiff2 " code=1 fi fi fi - done < <( - ${GP}sed -n -r "s@^%Include auto_generated/(.*\.sip)@${module}/auto_generated/\1@p" python/${module}/${module}_auto.sip - ) + done < <( + ${GP}sed -n -r "s@^%Include auto_generated/(.*\.sip)@${module}/auto_generated/\1@p" $root_dir/${module}/${module}_auto.sip + ) + done done - popd > /dev/null || exit exit $code diff --git a/tests/code_layout/sipify/test_sipify.sh b/tests/code_layout/sipify/test_sipify.sh index a878889fb4f..7467894a3de 100755 --- a/tests/code_layout/sipify/test_sipify.sh +++ b/tests/code_layout/sipify/test_sipify.sh @@ -7,11 +7,19 @@ srcdir=$(dirname $0)/../../ DIR=$(git -C ${srcdir} rev-parse --show-toplevel) pushd ${DIR} > /dev/null || exit -outdiff=$(./scripts/sipify.pl tests/code_layout/sipify/sipifyheader.h | diff tests/code_layout/sipify/sipifyheader.expected.sip -) -popd > /dev/null || exit +for pyqt_version in 5 6; do -if [[ $outdiff ]]; then - echo " *** sipify.pl did not output expected file" - echo "$outdiff" - exit 1 -fi + if [[ $pyqt_version == 6 ]]; then + IS_QT6="--qt6" + fi + + outdiff=$(./scripts/sipify.pl $IS_QT6 tests/code_layout/sipify/sipifyheader.h | diff tests/code_layout/sipify/sipifyheader.expected_pyqt$pyqt_version.sip -) + + if [[ $outdiff ]]; then + echo " *** sipify.pl did not output expected file" + echo "$outdiff" + popd > /dev/null || exit + exit 1 + fi +done +popd > /dev/null || exit