aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build_scripts/main.py84
-rw-r--r--examples/samplebinding/README.md13
-rw-r--r--examples/samplebinding/bindings.xml1
-rw-r--r--examples/samplebinding/main.py2
-rw-r--r--examples/samplebinding/truck.cpp5
-rw-r--r--examples/samplebinding/truck.h2
-rw-r--r--sources/pyside2/doc/CMakeLists.txt152
-rw-r--r--sources/pyside2/doc/conf.py.in8
-rw-r--r--sources/pyside2/libpyside/feature_select.cpp32
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h5
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.cpp3
-rw-r--r--sources/shiboken2/doc/CMakeLists.txt3
-rw-r--r--sources/shiboken2/generator/indentor.h14
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp22
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp185
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp6
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp3
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.cpp2
-rw-r--r--sources/shiboken2/libshiboken/sbkstaticstrings.h2
-rw-r--r--sources/shiboken2/libshiboken/signature/signature.cpp3
-rw-r--r--sources/shiboken2/libshiboken/signature/signature_helper.cpp73
-rw-r--r--sources/shiboken2/libshiboken/signature/signature_p.h1
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py5
-rw-r--r--sources/shiboken2/tests/libother/otherobjecttype.cpp2
-rw-r--r--sources/shiboken2/tests/libother/otherobjecttype.h3
-rw-r--r--sources/shiboken2/tests/libsample/removednamespaces.h10
-rw-r--r--sources/shiboken2/tests/libsample/samplenamespace.h19
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.h4
-rw-r--r--sources/shiboken2/tests/samplebinding/CMakeLists.txt2
-rw-r--r--sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py20
-rw-r--r--sources/shiboken2/tests/samplebinding/namespace_test.py20
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml6
33 files changed, 422 insertions, 293 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py
index 8aeabcd63..c7761e2dc 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -119,6 +119,7 @@ from distutils.spawn import find_executable
from distutils.command.build import build as _build
from distutils.command.build_ext import build_ext as _build_ext
from distutils.util import get_platform
+from distutils.cmd import Command
from setuptools import Extension
from setuptools.command.install import install as _install
@@ -1023,6 +1024,9 @@ class PysideBuild(_build):
log.info("Output format will be qthelp")
cmake_cmd.append("-DDOC_OUTPUT_FORMAT=qthelp")
+ # Build the whole documentation (rst + API) by default
+ cmake_cmd.append("-DFULLDOCSBUILD=1")
+
if not OPTION["SKIP_CMAKE"]:
log.info("Configuring module {} ({})...".format(extension, module_src_dir))
if run_process(cmake_cmd) != 0:
@@ -1273,6 +1277,83 @@ class PysideBuild(_build):
log.info("Patched rpath to '$ORIGIN/' (Linux) or "
"updated rpath (OS/X) in {}.".format(srcpath))
+class PysideRstDocs(Command):
+ description = "Build .rst documentation only"
+ user_options = []
+ def initialize_options(self):
+ log.info("-- This build process will not include the API documentation."
+ "API documentation requires a full build of pyside/shiboken.")
+ self.skip = False
+ if config.is_internal_shiboken_generator_build():
+ self.skip = True
+ if not self.skip:
+ self.name = config.package_name().lower()
+ self.doc_dir = os.path.join(config.setup_script_dir, "sources")
+ self.doc_dir = os.path.join(self.doc_dir, self.name)
+ self.doc_dir = os.path.join(self.doc_dir, "doc")
+ try:
+ # Check if sphinx is installed to proceed.
+ import sphinx
+ if self.name == "shiboken2":
+ log.info("-- Generating Shiboken documentation")
+ log.info("-- Documentation directory: 'html/pyside2/shiboken2/'")
+ elif self.name == "pyside2":
+ log.info("-- Generating PySide documentation")
+ log.info("-- Documentation directory: 'html/pyside2/'")
+ except ImportError:
+ raise DistutilsSetupError("Sphinx not found - aborting")
+ self.html_dir = "html"
+
+ # creating directories html/pyside2/shiboken2
+ try:
+ if not os.path.isdir(self.html_dir):
+ os.mkdir(self.html_dir)
+ if self.name == "shiboken2":
+ out_pyside = os.path.join(self.html_dir, "pyside2")
+ if not os.path.isdir(out_pyside):
+ os.mkdir(out_pyside)
+ out_shiboken = os.path.join(out_pyside, "shiboken2")
+ if not os.path.isdir(out_shiboken):
+ os.mkdir(out_shiboken)
+ self.out_dir = out_shiboken
+ # We know that on the shiboken step, we already created the
+ # 'pyside2' directory
+ elif self.name == "pyside2":
+ self.out_dir = os.path.join(self.html_dir, "pyside2")
+ except:
+ raise DistutilsSetupError("Error while creating directories for {}".format(self.doc_dir))
+
+ def run(self):
+ if not self.skip:
+ cmake_cmd = [OPTION["CMAKE"]]
+ cmake_cmd += [
+ "-S", self.doc_dir,
+ "-B", self.out_dir,
+ "-DDOC_OUTPUT_FORMAT=html",
+ "-DFULLDOCSBUILD=0",
+ ]
+ if run_process(cmake_cmd) != 0:
+ raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
+
+ if self.name == "pyside2":
+ self.sphinx_src = os.path.join(self.out_dir, "rst")
+ elif self.name == "shiboken2":
+ self.sphinx_src = self.out_dir
+
+ sphinx_cmd = ["sphinx-build",
+ "-b", "html",
+ "-c", self.sphinx_src,
+ self.doc_dir,
+ self.out_dir
+ ]
+ if run_process(sphinx_cmd) != 0:
+ raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
+ # Last message
+ if not self.skip and self.name == "pyside2":
+ log.info("-- The documentation was built. Check html/pyside2/index.html")
+
+ def finalize_options(self):
+ pass
cmd_class_dict = {
'build': PysideBuild,
@@ -1281,7 +1362,8 @@ cmd_class_dict = {
'bdist_egg': PysideBdistEgg,
'develop': PysideDevelop,
'install': PysideInstall,
- 'install_lib': PysideInstallLib
+ 'install_lib': PysideInstallLib,
+ 'build_rst_docs': PysideRstDocs,
}
if wheel_module_exists:
params = {}
diff --git a/examples/samplebinding/README.md b/examples/samplebinding/README.md
index 85e96ddbe..e84d1eff4 100644
--- a/examples/samplebinding/README.md
+++ b/examples/samplebinding/README.md
@@ -62,6 +62,19 @@ and the `clone()` and `addIcecreamFlavor(Icecream*)` need additional
info about who owns the parameter objects when passing them across
language boundaries (in this case C++ will delete the objects).
+The `Truck` has getters and setters for the string `arrivalMessage`.
+In the type system file, we declare this to be a property in Python:
+
+```
+<property type="std::string" name="arrivalMessage" get="getArrivalMessage" set="setArrivalMessage"/>
+```
+
+It can then be used in a more pythonic way:
+
+```
+special_truck.arrivalMessage = "A new SPECIAL icecream truck has arrived!\n"
+```
+
After shiboken generates the C++ code and CMake makes an extension
module from the code, the types can be accessed in Python simply by
importing them using the original C++ names.
diff --git a/examples/samplebinding/bindings.xml b/examples/samplebinding/bindings.xml
index f08243694..9be9f1afa 100644
--- a/examples/samplebinding/bindings.xml
+++ b/examples/samplebinding/bindings.xml
@@ -70,6 +70,7 @@
<value-type name="Truck">
<!-- Same ownership caveat applies here. -->
+ <property type="std::string" name="arrivalMessage" get="getArrivalMessage" set="setArrivalMessage"/>
<modify-function signature="addIcecreamFlavor(Icecream*)">
<modify-argument index="1">
<define-ownership owner="c++"/>
diff --git a/examples/samplebinding/main.py b/examples/samplebinding/main.py
index bd1d10b8e..dc727c5d8 100644
--- a/examples/samplebinding/main.py
+++ b/examples/samplebinding/main.py
@@ -92,7 +92,7 @@ if __name__ == '__main__':
del truck
print("")
- special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n")
+ special_truck.arrivalMessage = "A new SPECIAL icecream truck has arrived!\n"
special_truck.arrive()
special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream"))
special_truck.printAvailableFlavors()
diff --git a/examples/samplebinding/truck.cpp b/examples/samplebinding/truck.cpp
index 6e24bdc87..056abfcd6 100644
--- a/examples/samplebinding/truck.cpp
+++ b/examples/samplebinding/truck.cpp
@@ -114,6 +114,11 @@ void Truck::setArrivalMessage(const std::string &message)
m_arrivalMessage = message;
}
+std::string Truck::getArrivalMessage() const
+{
+ return m_arrivalMessage;
+}
+
bool Truck::deliver() const
{
std::random_device rd;
diff --git a/examples/samplebinding/truck.h b/examples/samplebinding/truck.h
index 02e304a82..3f213f9ac 100644
--- a/examples/samplebinding/truck.h
+++ b/examples/samplebinding/truck.h
@@ -71,7 +71,9 @@ public:
void leave() const;
void setLeaveOnDestruction(bool value);
+
void setArrivalMessage(const std::string &message);
+ std::string getArrivalMessage() const;
private:
void clearFlavors();
diff --git a/sources/pyside2/doc/CMakeLists.txt b/sources/pyside2/doc/CMakeLists.txt
index d84bd073f..73b90c059 100644
--- a/sources/pyside2/doc/CMakeLists.txt
+++ b/sources/pyside2/doc/CMakeLists.txt
@@ -16,84 +16,90 @@ set(TS_ROOT "${ROOT}/PySide2")
file(REMOVE ${CMAKE_CURRENT_LIST_DIR}/pyside.qdocconf ${CMAKE_CURRENT_LIST_DIR}/pyside.qdocconf.in)
-# For Qt modules that are part of the documentation build:
-# - Configure the module docconf file
-# - Write shiboken header consisting of pyside2_global.h and module includes
-# - Build include path for qdoc for shiboken
-
-# The last element of the include list is the mkspec directory containing qplatformdefs.h
-list(GET Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS -1 mkspecInclude)
-configure_file("pyside-config.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf" @ONLY)
-
-file(READ "${pyside2_BINARY_DIR}/pyside2_global.h" docHeaderContents)
-file(READ "typesystem_doc.xml.in" typeSystemDocXmlContents)
-
+set(SHIBOKEN_INTERSPHINX_FILE "${ROOT}/pyside2/shiboken2/objects.inv")
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")
- if(EXISTS "${docConf}")
- string(REGEX REPLACE "(^.*)\.in" "\\1" OUTFILE ${docConf})
- get_filename_component(BASENAME ${OUTFILE} NAME)
- configure_file(${docConf} "${CMAKE_CURRENT_LIST_DIR}/qtmodules/${BASENAME}" @ONLY)
- file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/qtmodules/${BASENAME}\n")
- # Handle docconf files in Qt that contain multiple modules
- if ("${moduleIn}" STREQUAL "3DExtras")
- set(modules 3DCore 3DRender 3DInput 3DLogic 3DAnimation "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "QuickWidgets")
- set(modules Qml Quick "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "MultimediaWidgets")
- set(modules Multimedia "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "WebEngineWidgets")
- set(modules WebEngine WebEngineCore "${moduleIn}")
- set(HAS_WEBENGINE_WIDGETS 1)
- else()
- set(modules "${moduleIn}")
- endif()
- foreach(module ${modules})
- string(TOLOWER "${module}" lowerModule)
- # -- @TODO fix this for macOS frameworks.
- file(APPEND "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf"
- " -I ${QT_INCLUDE_DIR}Qt${module} \\\n"
- " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION} \\\n"
- " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION}/Qt${module} \\\n")
-
- if (${moduleIn} STREQUAL "X11Extras")
- set(globalHeader "QX11Info")
+set(SKIP_SPHINX_WARNINGS 1)
+if (FULLDOCSBUILD)
+ set(SKIP_SPHINX_WARNINGS 0)
+ set(SHIBOKEN_INTERSPHINX_FILE "${CMAKE_BINARY_DIR}/doc/html/shiboken2/doc/html/objects.inv")
+ # For Qt modules that are part of the documentation build:
+ # - Configure the module docconf file
+ # - Write shiboken header consisting of pyside2_global.h and module includes
+ # - Build include path for qdoc for shiboken
+
+ # The last element of the include list is the mkspec directory containing qplatformdefs.h
+ list(GET Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS -1 mkspecInclude)
+ configure_file("pyside-config.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf" @ONLY)
+
+ file(READ "${pyside2_BINARY_DIR}/pyside2_global.h" docHeaderContents)
+ file(READ "typesystem_doc.xml.in" typeSystemDocXmlContents)
+
+
+ foreach(moduleIn ${all_module_shortnames})
+ string(TOLOWER "${moduleIn}" lowerModuleIn)
+ set(docConf "${CMAKE_CURRENT_LIST_DIR}/qtmodules/pyside-qt${lowerModuleIn}.qdocconf.in")
+ if(EXISTS "${docConf}")
+ string(REGEX REPLACE "(^.*)\.in" "\\1" OUTFILE ${docConf})
+ get_filename_component(BASENAME ${OUTFILE} NAME)
+ configure_file(${docConf} "${CMAKE_CURRENT_LIST_DIR}/qtmodules/${BASENAME}" @ONLY)
+ file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/qtmodules/${BASENAME}\n")
+ # Handle docconf files in Qt that contain multiple modules
+ if ("${moduleIn}" STREQUAL "3DExtras")
+ set(modules 3DCore 3DRender 3DInput 3DLogic 3DAnimation "${moduleIn}")
+ elseif ("${moduleIn}" STREQUAL "QuickWidgets")
+ set(modules Qml Quick "${moduleIn}")
+ elseif ("${moduleIn}" STREQUAL "MultimediaWidgets")
+ set(modules Multimedia "${moduleIn}")
+ elseif ("${moduleIn}" STREQUAL "WebEngineWidgets")
+ set(modules WebEngine WebEngineCore "${moduleIn}")
+ set(HAS_WEBENGINE_WIDGETS 1)
else()
- set(globalHeader "Qt${module}")
+ set(modules "${moduleIn}")
endif()
- set(docHeaderContents "${docHeaderContents}\n#include <Qt${module}/${globalHeader}>")
- set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n<load-typesystem name=\"Qt${module}/typesystem_${lowerModule}.xml\" generate=\"yes\"/>")
- endforeach()
- endif()
-endforeach()
+ foreach(module ${modules})
+ string(TOLOWER "${module}" lowerModule)
+ # -- @TODO fix this for macOS frameworks.
+ file(APPEND "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf"
+ " -I ${QT_INCLUDE_DIR}Qt${module} \\\n"
+ " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION} \\\n"
+ " -I ${QT_INCLUDE_DIR}Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION}/Qt${module} \\\n")
+
+ if (${moduleIn} STREQUAL "X11Extras")
+ set(globalHeader "QX11Info")
+ else()
+ set(globalHeader "Qt${module}")
+ endif()
+ set(docHeaderContents "${docHeaderContents}\n#include <Qt${module}/${globalHeader}>")
+ set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n<load-typesystem name=\"Qt${module}/typesystem_${lowerModule}.xml\" generate=\"yes\"/>")
+ endforeach()
+ endif()
+ endforeach()
-#Appending the additional qdocconf that describes the pyside-examples
-#doc project.
-configure_file("qtmodules/pyside-examples.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/qtmodules/pyside-examples.qdocconf" @ONLY)
-file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/qtmodules/pyside-examples.qdocconf\n")
+ #Appending the additional qdocconf that describes the pyside-examples
+ #doc project.
+ configure_file("qtmodules/pyside-examples.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/qtmodules/pyside-examples.qdocconf" @ONLY)
+ file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/qtmodules/pyside-examples.qdocconf\n")
-set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n</typesystem>\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml" "${typeSystemDocXmlContents}")
+ set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n</typesystem>\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml" "${typeSystemDocXmlContents}")
-set(docHeader "${pyside2_BINARY_DIR}/qdoc.h")
-file(WRITE ${docHeader} "${docHeaderContents}")
+ set(docHeader "${pyside2_BINARY_DIR}/qdoc.h")
+ file(WRITE ${docHeader} "${docHeaderContents}")
+ configure_file("pyside.qdocconf.in" "pyside.qdocconf" @ONLY)
-configure_file("pyside.qdocconf.in" "pyside.qdocconf" @ONLY)
-set(QDOC_TYPESYSTEM_PATH "${pyside2_SOURCE_DIR}${PATH_SEP}${pyside2_BINARY_DIR}")
+ set(QDOC_TYPESYSTEM_PATH "${pyside2_SOURCE_DIR}${PATH_SEP}${pyside2_BINARY_DIR}")
-add_custom_target(qdoc
- # Use dummy Qt version information, QDoc needs it but has no effect on WebXML output
- COMMAND ${CMAKE_COMMAND} -E env BUILDDIR=${CMAKE_CURRENT_LIST_DIR}/src QT_INSTALL_DOCS=${QT_SRC_DIR}/doc
- QT_VERSION=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
- QT_VER=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}
- QT_VERSION_TAG=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
- qdoc pyside.qdocconf -single-exec -installdir ${DOC_DATA_DIR} -outputdir ${DOC_DATA_DIR}
- COMMENT "Running qdoc against Qt source code..."
- SOURCE "pyside.qdocconf")
+ add_custom_target(qdoc
+ # Use dummy Qt version information, QDoc needs it but has no effect on WebXML output
+ COMMAND ${CMAKE_COMMAND} -E env BUILDDIR=${CMAKE_CURRENT_LIST_DIR}/src QT_INSTALL_DOCS=${QT_SRC_DIR}/doc
+ QT_VERSION=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
+ QT_VER=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}
+ QT_VERSION_TAG=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
+ qdoc pyside.qdocconf -single-exec -installdir ${DOC_DATA_DIR} -outputdir ${DOC_DATA_DIR}
+ COMMENT "Running qdoc against Qt source code..."
+ SOURCE "pyside.qdocconf")
+endif()
# conditional tag for sphinx build
#string(JOIN "_" SPHINX_TAG ${DOC_OUTPUT_FORMAT} "format")
@@ -168,9 +174,11 @@ add_custom_target("licensedocrsts"
COMMENT "Creating 3rdparty license documentation..."
)
-add_dependencies(apidoc docrsts licensedocrsts)
-add_dependencies(licensedocrsts docrsts)
-add_dependencies(docrsts qdoc)
+if (FULLDOCSBUILD)
+ add_dependencies(apidoc docrsts licensedocrsts)
+ add_dependencies(licensedocrsts docrsts)
+ add_dependencies(docrsts qdoc)
+endif()
#install files
add_custom_target(apidocinstall
diff --git a/sources/pyside2/doc/conf.py.in b/sources/pyside2/doc/conf.py.in
index e37abcb24..ae1bc6455 100644
--- a/sources/pyside2/doc/conf.py.in
+++ b/sources/pyside2/doc/conf.py.in
@@ -175,10 +175,16 @@ html_show_sourcelink = False
# Link to the shiboken2 sphinx project to enable linking
# between the two projects.
-intersphinx_mapping = {'shiboken2': ('shiboken2','@CMAKE_BINARY_DIR@/doc/html/shiboken2/doc/html/objects.inv')}
+intersphinx_mapping = {'shiboken2': ('shiboken2','@SHIBOKEN_INTERSPHINX_FILE@')}
add_module_names = False
+# Skip some warnings when building the documentation with
+# 'build_rst_docs' due to the lack of qdoc generated files, in charge
+# of sphinx modules (autodoc) and references.
+if @SKIP_SPHINX_WARNINGS@:
+ suppress_warnings = ["autodoc", "autodoc.import_object", "ref.ref"]
+
# -- Options for qthelp output ---------------------------------------------------
qthelp_theme = 'pysidedocs_qthelp'
diff --git a/sources/pyside2/libpyside/feature_select.cpp b/sources/pyside2/libpyside/feature_select.cpp
index a1ba76251..b26810add 100644
--- a/sources/pyside2/libpyside/feature_select.cpp
+++ b/sources/pyside2/libpyside/feature_select.cpp
@@ -546,40 +546,17 @@ static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, in
// Feature 0x02: Use true properties instead of getters and setters
//
-static PyObject *createProperty(PyObject *getter, PyObject *setter, PyObject *doc)
+static PyObject *createProperty(PyObject *getter, PyObject *setter)
{
assert(getter != nullptr);
if (setter == nullptr)
setter = Py_None;
- PyObject *deleter = Py_None;
PyObject *prop = PyObject_CallObject(reinterpret_cast<PyObject *>(&PyProperty_Type), nullptr);
- AutoDecRef args(Py_BuildValue("OOOO", getter, setter, deleter, doc));
+ AutoDecRef args(Py_BuildValue("OO", getter, setter));
PyProperty_Type.tp_init(prop, args, nullptr);
return prop;
}
-static PyObject *calcPropDocString(PyTypeObject *type, PyObject *getterName, PyObject *setterName)
-{
- // To calculate the docstring, we need the __doc__ attribute of the original
- // getter and setter. We temporatily switch back to no features. This
- // might change when we have full signature support for features.
- auto hold = type->tp_dict;
- moveToFeatureSet(type, fast_id_array[0]);
- auto dict = type->tp_dict;
- auto getter = PyDict_GetItem(dict, getterName);
- auto setter = setterName ? PyDict_GetItem(dict, setterName) : nullptr;
- PyObject *buf = PyObject_GetAttr(getter, PyMagicName::doc());
- type->tp_dict = hold;
-
- if (setter == nullptr)
- return buf;
- AutoDecRef nl(Py_BuildValue("s", "\n"));
- AutoDecRef wdoc(PyObject_GetAttr(setter, PyMagicName::doc()));
- String::concat(&buf, nl);
- String::concat(&buf, wdoc);
- return buf;
-}
-
static QStringList parseFields(const char *propstr)
{
/*
@@ -639,10 +616,7 @@ static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, in
if (setter != nullptr && Py_TYPE(setter) != PepMethodDescr_TypePtr)
continue;
- PyObject *doc_read = make_snake_case(fields[1], false);
- PyObject *doc_write(haveWrite ? make_snake_case(fields[2], false) : nullptr);
- AutoDecRef doc(calcPropDocString(type, doc_read, doc_write));
- AutoDecRef PyProperty(createProperty(getter, setter, doc));
+ AutoDecRef PyProperty(createProperty(getter, setter));
if (PyProperty.isNull())
return false;
if (PyDict_SetItem(prop_dict, name, PyProperty) < 0)
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index 466464807..648c792b3 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -1413,10 +1413,7 @@ public:
AbstractMetaField *findField(const QString &name) const;
- AbstractMetaEnumList enums() const
- {
- return m_enums;
- }
+ const AbstractMetaEnumList &enums() const { return m_enums; }
void setEnums(const AbstractMetaEnumList &enums)
{
m_enums = enums;
diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.cpp b/sources/shiboken2/ApiExtractor/doxygenparser.cpp
index da6e32fba..cf152720e 100644
--- a/sources/shiboken2/ApiExtractor/doxygenparser.cpp
+++ b/sources/shiboken2/ApiExtractor/doxygenparser.cpp
@@ -199,8 +199,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
}
//Enums
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *meta_enum : enums) {
+ for (AbstractMetaEnum *meta_enum : metaClass->enums()) {
QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef[@kind=\"enum\"]/name[text()=\"")
+ meta_enum->name() + QLatin1String("\"]/..");
QString doc = getDocumentation(xquery, query, DocModificationList());
diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp
index 40c04a403..d439b3fd5 100644
--- a/sources/shiboken2/ApiExtractor/qtdocparser.cpp
+++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp
@@ -285,8 +285,7 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
}
#endif
// Enums
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *meta_enum : enums) {
+ for (AbstractMetaEnum *meta_enum : metaClass->enums()) {
query.clear();
QTextStream(&query) << classQuery << "/enum[@name=\""
<< meta_enum->name() << "\"]/description";
diff --git a/sources/shiboken2/doc/CMakeLists.txt b/sources/shiboken2/doc/CMakeLists.txt
index 399dbba7a..5f59bfbf0 100644
--- a/sources/shiboken2/doc/CMakeLists.txt
+++ b/sources/shiboken2/doc/CMakeLists.txt
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.16)
+if(FULLDOCSBUILD EQUAL 0)
+ project(shiboken2_doc)
+endif()
find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.")
if (SPHINX)
diff --git a/sources/shiboken2/generator/indentor.h b/sources/shiboken2/generator/indentor.h
index 111259f12..3dcec85b6 100644
--- a/sources/shiboken2/generator/indentor.h
+++ b/sources/shiboken2/generator/indentor.h
@@ -82,4 +82,18 @@ inline QTextStream &operator <<(QTextStream &s, const IndentorBase<tabWidth> &in
return s;
}
+template <int tabWidth>
+const char *indent(IndentorBase<tabWidth> &indentor)
+{
+ ++indentor.indent;
+ return "";
+}
+
+template <int tabWidth>
+const char *outdent(IndentorBase<tabWidth> &indentor)
+{
+ --indentor.indent;
+ return "";
+}
+
#endif // GENERATOR_H
diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
index 1a7c195b4..282da6eca 100644
--- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
@@ -1762,8 +1762,7 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas
{
static const QString section_title = QLatin1String(".. attribute:: ");
- const AbstractMetaEnumList &enums = cppClass->enums();
- for (AbstractMetaEnum *en : enums) {
+ for (AbstractMetaEnum *en : cppClass->enums()) {
s << section_title << cppClass->fullName() << '.' << en->name() << Qt::endl << Qt::endl;
writeFormattedText(s, en->documentation().value(), cppClass);
const auto version = versionOf(en->typeEntry());
@@ -2248,18 +2247,13 @@ void QtDocGenerator::writeModuleDocumentation()
writeFancyToc(s, it.value());
- s << INDENT << ".. container:: hide\n\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << ".. toctree::\n";
- Indentation deeperIndentation(INDENT);
- s << INDENT << ":maxdepth: 1\n\n";
- for (const QString &className : qAsConst(it.value()))
- s << INDENT << className << Qt::endl;
- s << Qt::endl << Qt::endl;
- }
-
- s << "Detailed Description\n--------------------\n\n";
+ s << INDENT << ".. container:: hide\n\n" << indent(INDENT)
+ << INDENT << ".. toctree::\n" << indent(INDENT)
+ << INDENT << ":maxdepth: 1\n\n";
+ for (const QString &className : qAsConst(it.value()))
+ s << INDENT << className << Qt::endl;
+ s << "\n\n" << outdent(INDENT) << outdent(INDENT)
+ << "Detailed Description\n--------------------\n\n";
// module doc is always wrong and C++istic, so go straight to the extra directory!
QFile moduleDoc(m_extraSectionDir + QLatin1Char('/') + moduleName.mid(lastIndex + 1) + QLatin1String(".rst"));
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 75633c072..8e9b480cc 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -1011,11 +1011,8 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s,
s << INDENT << "Shiboken::GilState gil;\n";
// Get out of virtual method call if someone already threw an error.
- s << INDENT << "if (PyErr_Occurred())\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << returnStatement << '\n';
- }
+ s << INDENT << "if (PyErr_Occurred())\n" << indent(INDENT)
+ << INDENT << returnStatement << '\n' << outdent(INDENT);
//PYSIDE-1019: Add info about properties.
int propFlag = 0;
@@ -1035,16 +1032,13 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s,
s << INDENT << "static const char *funcName = \"" << propStr << funcName << "\";\n";
s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR
<< "(Shiboken::BindingManager::instance().getOverride(this, nameCache, funcName));\n";
- s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "gil.release();\n";
- if (useOverrideCaching(func->ownerClass()))
- s << INDENT << "m_PyMethodCache[" << cacheIndex << "] = true;\n";
- writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
- returnStatement);
- }
- s << INDENT << "}\n\n"; //WS
+ s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n"
+ << indent(INDENT) << INDENT << "gil.release();\n";
+ if (useOverrideCaching(func->ownerClass()))
+ s << INDENT << "m_PyMethodCache[" << cacheIndex << "] = true;\n";
+ writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
+ returnStatement);
+ s << outdent(INDENT) << INDENT << "}\n\n"; //WS
writeConversionRule(s, func, TypeSystem::TargetLangCode);
@@ -1193,15 +1187,14 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s,
}
if (invalidateReturn) {
- s << INDENT << "if (invalidateArg0)\n";
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ".object());\n";
+ s << INDENT << "if (invalidateArg0)\n" << indent(INDENT)
+ << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR
+ << ".object());\n" << outdent(INDENT);
}
for (int argIndex : qAsConst(invalidateArgs)) {
- s << INDENT << "if (invalidateArg" << argIndex << ")\n";
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS << ", ";
- s << (argIndex - 1) << "));\n";
+ s << INDENT << "if (invalidateArg" << argIndex << ")\n" << indent(INDENT)
+ << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS
+ << ", " << (argIndex - 1) << "));\n" << outdent(INDENT);
}
@@ -1861,30 +1854,20 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
}
if (metaClass->isAbstract()) {
- s << INDENT << "if (type == myType) {\n";
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError,\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "\"'" << metaClass->qualifiedCppName();
- }
- s << "' represents a C++ abstract class and cannot be instantiated\");\n";
- s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
- }
- s << INDENT<< "}\n\n";
+ s << INDENT << "if (type == myType) {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_NotImplementedError,\n" << indent(INDENT)
+ << INDENT << "\"'" << metaClass->qualifiedCppName()
+ << "' represents a C++ abstract class and cannot be instantiated\");\n" << outdent(INDENT)
+ << INDENT << returnStatement(m_currentErrorCode) << '\n' << outdent(INDENT)
+ << INDENT<< "}\n\n";
}
if (metaClass->baseClassNames().size() > 1) {
- if (!metaClass->isAbstract()) {
- s << INDENT << "if (type != myType) {\n";
- }
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::ObjectType::copyMultipleInheritance(type, myType);\n";
- }
if (!metaClass->isAbstract())
- s << INDENT<< "}\n\n";
+ s << INDENT << "if (type != myType)\n" << indent(INDENT);
+ s << INDENT << "Shiboken::ObjectType::copyMultipleInheritance(type, myType);\n";
+ if (!metaClass->isAbstract())
+ s << outdent(INDENT) << '\n';
}
writeMethodWrapperPreamble(s, overloadData, classContext);
@@ -1931,11 +1914,9 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
s << Qt::endl << INDENT << "// QObject setup\n";
s << INDENT << "PySide::Signal::updateSourceObject(self);\n";
s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties\n";
- s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
- }
+ s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, "
+ << argNamesSet.count() << "))\n" << indent(INDENT)
+ << INDENT << returnStatement(m_currentErrorCode) << '\n' << outdent(INDENT);
}
// Constructor code injections, position=end
@@ -2203,7 +2184,8 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
Q_ASSERT(!(cppSelfAsReference && hasStaticOverload));
const AbstractMetaClass *metaClass = context.metaClass();
- bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers();
+ bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers()
+ && !metaClass->attributes().testFlag(AbstractMetaAttributes::FinalCppClass);
Q_ASSERT(!useWrapperClass || context.useWrapper());
QString className;
if (!context.forSmartPointer()) {
@@ -2919,14 +2901,11 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
int numRemovedArgs = OverloadData::numberOfRemovedArguments(func);
- s << INDENT << "if (!PyErr_Occurred()) {\n";
- {
- Indentation indentation(INDENT);
- writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs);
- if (!func->isConstructor())
- writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
- }
- s << INDENT << "}\n";
+ s << INDENT << "if (!PyErr_Occurred()) {\n" << indent(INDENT);
+ writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs);
+ if (!func->isConstructor())
+ writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
+ s << outdent(INDENT) << INDENT << "}\n";
}
QString CppGenerator::cppToPythonFunctionName(const QString &sourceTypeName, QString targetTypeName)
@@ -3506,14 +3485,16 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
+ QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
if (func->isConstant()) {
if (avoidProtectedHack()) {
+ auto ownerClass = func->ownerClass();
mc << "const_cast<const ::";
- if (func->ownerClass()->hasProtectedMembers()) {
+ if (ownerClass->hasProtectedMembers()
+ && !ownerClass->attributes().testFlag(AbstractMetaAttributes::FinalCppClass)) {
// PYSIDE-500: Need a special wrapper cast when inherited
- const QString selfWrapCast = func->ownerClass() == func->implementingClass()
+ const QString selfWrapCast = ownerClass == func->implementingClass()
? QLatin1String(CPP_SELF_VAR)
- : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass())
+ : QLatin1String("reinterpret_cast<") + wrapperName(ownerClass)
+ QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
- mc << wrapperName(func->ownerClass());
+ mc << wrapperName(ownerClass);
mc << " *>(" << selfWrapCast << ")->";
}
else {
@@ -4555,26 +4536,20 @@ void CppGenerator::writeSetterFunctionPreamble(QTextStream &s, const QString &na
writeCppSelfDefinition(s, context);
- s << INDENT << "if (pyIn == " << NULL_PTR << ") {\n";
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'";
- s << name << "' may not be deleted\");\n";
- s << INDENT << "return -1;\n";
- }
- s << INDENT << "}\n";
+ s << INDENT << "if (pyIn == " << NULL_PTR << ") {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"
+ << name << "' may not be deleted\");\n"
+ << INDENT << "return -1;\n"
+ << outdent(INDENT) << INDENT << "}\n";
s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};\n";
s << INDENT << "if (!";
writeTypeCheck(s, type, QLatin1String("pyIn"), isNumber(type->typeEntry()));
- s << ") {\n";
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '";
- s << name << "', '" << type->name() << "' or convertible type expected\");\n";
- s << INDENT << "return -1;\n";
- }
- s << INDENT<< "}\n\n";
+ s << ") {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"
+ << name << "', '" << type->name() << "' or convertible type expected\");\n"
+ << INDENT << "return -1;\n"
+ << outdent(INDENT) << INDENT<< "}\n\n";
}
void CppGenerator::writeSetterFunction(QTextStream &s,
@@ -5430,8 +5405,7 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, const Generat
}
}
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *metaEnum : enums) {
+ for (AbstractMetaEnum *metaEnum : metaClass->enums()) {
if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) {
for (const QString &name : qAsConst(nameVariants))
s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");\n";
@@ -5752,7 +5726,7 @@ bool CppGenerator::finishGeneration()
QString signaturesString;
QTextStream signatureStream(&signaturesString);
- Indentation indent(INDENT);
+ Indentation indentation(INDENT);
const auto functionGroups = getGlobalFunctionGroups();
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
@@ -5877,19 +5851,13 @@ bool CppGenerator::finishGeneration()
s << "void cleanTypesAttributes(void) {\n";
s << INDENT << "if (PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03060000)\n";
s << INDENT << " return; // PYSIDE-953: testbinding crashes in Python 3.5 when hasattr touches types!\n";
- s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject *pyType = reinterpret_cast<PyObject *>(" << cppApiVariableName() << "[i]);\n";
- s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"staticMetaObject\"));\n";
- s << INDENT << "if (pyType && PyObject_HasAttr(pyType, attrName))\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject_SetAttr(pyType, attrName, Py_None);\n";
- }
- }
- s << INDENT << "}\n";
- s << "}\n";
+ s << INDENT << "for (int i = 0, imax = SBK_" << moduleName()
+ << "_IDX_COUNT; i < imax; i++) {\n" << indent(INDENT)
+ << INDENT << "PyObject *pyType = reinterpret_cast<PyObject *>(" << cppApiVariableName() << "[i]);\n"
+ << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"staticMetaObject\"));\n"
+ << INDENT << "if (pyType && PyObject_HasAttr(pyType, attrName))\n" << indent(INDENT)
+ << INDENT << "PyObject_SetAttr(pyType, attrName, Py_None);\n" << outdent(INDENT)
+ << outdent(INDENT) << INDENT << "}\n" << "}\n";
}
s << "// Global functions ";
@@ -6003,19 +5971,15 @@ bool CppGenerator::finishGeneration()
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode);
for (const QString &requiredModule : requiredModules) {
- s << INDENT << "{\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));\n";
- s << INDENT << "if (requiredModule.isNull())\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "return SBK_MODULE_INIT_ERROR;\n";
- }
- s << INDENT << cppApiVariableName(requiredModule) << " = Shiboken::Module::getTypes(requiredModule);\n";
- s << INDENT << convertersVariableName(requiredModule) << " = Shiboken::Module::getTypeConverters(requiredModule);\n";
- }
- s << INDENT << "}\n\n";
+ s << INDENT << "{\n" << indent(INDENT)
+ << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));\n"
+ << INDENT << "if (requiredModule.isNull())\n" << indent(INDENT)
+ << INDENT << "return SBK_MODULE_INIT_ERROR;\n" << outdent(INDENT)
+ << INDENT << cppApiVariableName(requiredModule)
+ << " = Shiboken::Module::getTypes(requiredModule);\n"
+ << INDENT << convertersVariableName(requiredModule)
+ << " = Shiboken::Module::getTypeConverters(requiredModule);\n" << outdent(INDENT)
+ << INDENT << "}\n\n";
}
int maxTypeIndex = getMaxTypeIndex() + instantiatedSmartPointers().size();
@@ -6088,13 +6052,10 @@ bool CppGenerator::finishGeneration()
s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n";
s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n";
- s << Qt::endl << INDENT << "if (PyErr_Occurred()) {\n";
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyErr_Print();\n";
- s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n";
- }
- s << INDENT << "}\n";
+ s << '\n' << INDENT << "if (PyErr_Occurred()) {\n" << indent(INDENT)
+ << INDENT << "PyErr_Print();\n"
+ << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n"
+ << outdent(INDENT) << INDENT << "}\n";
// module inject-code target/end
if (!snips.isEmpty())
diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
index 7826e350a..1fdd89af8 100644
--- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
@@ -343,8 +343,7 @@ void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMet
if (!typeEntry->generateCode() || !NamespaceTypeEntry::isVisibleScope(typeEntry))
return;
writeTypeIndexValueLine(s, metaClass->typeEntry());
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (const AbstractMetaEnum *metaEnum : enums) {
+ for (const AbstractMetaEnum *metaEnum : metaClass->enums()) {
if (metaEnum->isPrivate())
continue;
writeTypeIndexValueLine(s, metaEnum->typeEntry());
@@ -503,8 +502,7 @@ bool HeaderGenerator::finishGeneration()
const TypeEntry *classType = metaClass->typeEntry();
includes << classType->include();
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (const AbstractMetaEnum *cppEnum : enums) {
+ for (const AbstractMetaEnum *cppEnum : metaClass->enums()) {
if (cppEnum->isAnonymous() || cppEnum->isPrivate())
continue;
EnumTypeEntry *enumType = cppEnum->typeEntry();
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 825965b92..1f91609bd 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -339,8 +339,7 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi
Q_ASSERT(metaClass);
// if a scope is not to be generated, collect its enums into the parent scope
if (!NamespaceTypeEntry::isVisibleScope(metaClass->typeEntry())) {
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *metaEnum : enums) {
+ for (AbstractMetaEnum *metaEnum : metaClass->enums()) {
if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode()
&& !enumList.contains(metaEnum)) {
enumList.append(metaEnum);
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
index 672be4009..5559d58d6 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp
@@ -56,6 +56,8 @@ STATIC_STRING_IMPL(dumps, "dumps")
STATIC_STRING_IMPL(fget, "fget")
STATIC_STRING_IMPL(fset, "fset")
STATIC_STRING_IMPL(loads, "loads")
+STATIC_STRING_IMPL(multi, "multi")
+STATIC_STRING_IMPL(name, "name")
STATIC_STRING_IMPL(result, "result")
STATIC_STRING_IMPL(value, "value")
STATIC_STRING_IMPL(values, "values")
diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h
index 09e22b395..b72fa989b 100644
--- a/sources/shiboken2/libshiboken/sbkstaticstrings.h
+++ b/sources/shiboken2/libshiboken/sbkstaticstrings.h
@@ -55,6 +55,8 @@ LIBSHIBOKEN_API PyObject *fset();
LIBSHIBOKEN_API PyObject *f_code();
LIBSHIBOKEN_API PyObject *f_lineno();
LIBSHIBOKEN_API PyObject *loads();
+LIBSHIBOKEN_API PyObject *multi();
+LIBSHIBOKEN_API PyObject *name();
LIBSHIBOKEN_API PyObject *result();
LIBSHIBOKEN_API PyObject *value();
LIBSHIBOKEN_API PyObject *values();
diff --git a/sources/shiboken2/libshiboken/signature/signature.cpp b/sources/shiboken2/libshiboken/signature/signature.cpp
index 76a71b00b..085d751aa 100644
--- a/sources/shiboken2/libshiboken/signature/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature/signature.cpp
@@ -343,6 +343,9 @@ PyObject *PySide_BuildSignatureProps(PyObject *type_key)
empty_dict = PyDict_New();
return empty_dict;
}
+ // PYSIDE-1019: Build snake case versions of the functions.
+ if (insert_snake_case_variants(dict) < 0)
+ return nullptr;
// We replace the arguments by the result dict.
if (PyDict_SetItem(pyside_globals->arg_dict, type_key, dict) < 0)
return nullptr;
diff --git a/sources/shiboken2/libshiboken/signature/signature_helper.cpp b/sources/shiboken2/libshiboken/signature/signature_helper.cpp
index 7e92a9861..2b360c786 100644
--- a/sources/shiboken2/libshiboken/signature/signature_helper.cpp
+++ b/sources/shiboken2/libshiboken/signature/signature_helper.cpp
@@ -150,6 +150,28 @@ static PyObject *compute_name_key(PyObject *ob)
return Py_BuildValue("(OO)", type_key.object(), func_name.object());
}
+static PyObject *_func_with_new_name(PyTypeObject *type,
+ PyMethodDef *meth,
+ const char *new_name)
+{
+ /*
+ * Create a function with a lower case name.
+ * Note: This is similar to feature_select's methodWithNewName,
+ * but does not create a descriptor.
+ * XXX Maybe we can get rid of this, completely?
+ */
+ auto obtype = reinterpret_cast<PyObject *>(type);
+ int len = strlen(new_name);
+ auto name = new char[len + 1];
+ strcpy(name, new_name);
+ auto new_meth = new PyMethodDef;
+ new_meth->ml_name = name;
+ new_meth->ml_meth = meth->ml_meth;
+ new_meth->ml_flags = meth->ml_flags;
+ new_meth->ml_doc = meth->ml_doc;
+ return PyCFunction_NewEx(new_meth, obtype, nullptr);
+}
+
static int build_name_key_to_func(PyObject *obtype)
{
auto *type = reinterpret_cast<PyTypeObject *>(obtype);
@@ -167,6 +189,17 @@ static int build_name_key_to_func(PyObject *obtype)
|| PyDict_SetItem(pyside_globals->map_dict, name_key, func) < 0)
return -1;
}
+ // PYSIDE-1019: Now we repeat the same for snake case names.
+ meth = type->tp_methods;
+ for (; meth->ml_name != nullptr; meth++) {
+ const char *name = String::toCString(String::getSnakeCaseName(meth->ml_name, true));
+ AutoDecRef func(_func_with_new_name(type, meth, name));
+ AutoDecRef func_name(get_funcname(func));
+ AutoDecRef name_key(Py_BuildValue("(OO)", type_key.object(), func_name.object()));
+ if (func.isNull() || name_key.isNull()
+ || PyDict_SetItem(pyside_globals->map_dict, name_key, func) < 0)
+ return -1;
+ }
return 0;
}
@@ -198,6 +231,46 @@ PyObject *name_key_to_func(PyObject *ob)
return ret;
}
+static PyObject *_build_new_entry(PyObject *new_name, PyObject *value)
+{
+ PyObject *new_value = PyDict_Copy(value);
+ PyObject *multi = PyDict_GetItem(value, PyName::multi());
+ if (multi != nullptr && Py_TYPE(multi) == &PyList_Type) {
+ ssize_t len = PyList_Size(multi);
+ AutoDecRef list(PyList_New(len));
+ if (list.isNull())
+ return nullptr;
+ for (int idx = 0; idx < len; ++idx) {
+ auto multi_entry = PyList_GetItem(multi, idx);
+ auto dup = PyDict_Copy(multi_entry);
+ if (PyDict_SetItem(dup, PyName::name(), new_name) < 0)
+ return nullptr;
+ if (PyList_SetItem(list, idx, dup) < 0)
+ return nullptr;
+ }
+ if (PyDict_SetItem(new_value, PyName::multi(), list) < 0)
+ return nullptr;
+ } else {
+ if (PyDict_SetItem(new_value, PyName::name(), new_name) < 0)
+ return nullptr;
+ }
+ return new_value;
+}
+
+int insert_snake_case_variants(PyObject *dict)
+{
+ AutoDecRef snake_dict(PyDict_New());
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ AutoDecRef name(String::getSnakeCaseName(key, true));
+ AutoDecRef new_value(_build_new_entry(name, value));
+ if (PyDict_SetItem(snake_dict, name, new_value) < 0)
+ return -1;
+ }
+ return PyDict_Merge(dict, snake_dict, 0);
+}
+
PyObject *_get_class_of_cf(PyObject *ob_cf)
{
PyObject *selftype = PyCFunction_GET_SELF(ob_cf);
diff --git a/sources/shiboken2/libshiboken/signature/signature_p.h b/sources/shiboken2/libshiboken/signature/signature_p.h
index 9444f3e9b..ef7846472 100644
--- a/sources/shiboken2/libshiboken/signature/signature_p.h
+++ b/sources/shiboken2/libshiboken/signature/signature_p.h
@@ -95,6 +95,7 @@ PyObject *pyside_tp_get___doc__(PyObject *tp);
PyObject *_get_qualname(PyObject *ob);
int add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr);
PyObject *name_key_to_func(PyObject *ob);
+int insert_snake_case_variants(PyObject *dict);
PyObject *_get_class_of_cf(PyObject *ob_cf);
PyObject *_get_class_of_sm(PyObject *ob_sm);
PyObject *_get_class_of_descr(PyObject *ob);
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 8a814114a..20c791cc1 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -349,7 +349,6 @@ def calculate_props(line):
props.annotations = annotations
props.varnames = varnames = tuple(tup[0] for tup in arglist)
funcname = parsed.funcname
- props.fullname = funcname
shortname = funcname[funcname.rindex(".")+1:]
props.name = shortname
props.multi = parsed.multi
@@ -366,7 +365,6 @@ def fix_variables(props, line):
if retvar and isinstance(retvar, (ResultVariable, ArrayLikeVariable)):
# Special case: a ResultVariable which is the result will always be an array!
annos["return"] = retvar = typing.List[retvar.type]
- fullname = props.fullname
varnames = list(props.varnames)
defaults = list(props.defaults)
diff = len(varnames) - len(defaults)
@@ -456,8 +454,7 @@ def pyside_type_init(type_key, sig_strings):
multi_props.append(props)
if multi > 0:
continue
- fullname = props.pop("fullname")
- multi_props = {"multi": multi_props, "fullname": fullname}
+ multi_props = {"multi": multi_props}
ret[shortname] = multi_props
dprint(multi_props)
multi_props = []
diff --git a/sources/shiboken2/tests/libother/otherobjecttype.cpp b/sources/shiboken2/tests/libother/otherobjecttype.cpp
index 1f782ecd8..c7778e7c9 100644
--- a/sources/shiboken2/tests/libother/otherobjecttype.cpp
+++ b/sources/shiboken2/tests/libother/otherobjecttype.cpp
@@ -40,7 +40,7 @@ int OtherObjectType::enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum valu
return static_cast<int>(value);
}
-int OtherObjectType::enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value)
+int OtherObjectType::enumAsIntForInvisibleNamespace(RemovedNamespace1::RemovedNamespace1_Enum value)
{
return static_cast<int>(value);
}
diff --git a/sources/shiboken2/tests/libother/otherobjecttype.h b/sources/shiboken2/tests/libother/otherobjecttype.h
index efd394347..a9362c370 100644
--- a/sources/shiboken2/tests/libother/otherobjecttype.h
+++ b/sources/shiboken2/tests/libother/otherobjecttype.h
@@ -36,13 +36,14 @@
#include "objecttype.h"
#include "collector.h"
#include "samplenamespace.h"
+#include "removednamespaces.h"
class LIBOTHER_API OtherObjectType : public ObjectType
{
public:
static int enumAsInt(SampleNamespace::SomeClass::PublicScopedEnum value);
- static int enumAsIntForInvisibleNamespace(Invisible::EnumOnNamespace value);
+ static int enumAsIntForInvisibleNamespace(RemovedNamespace1::RemovedNamespace1_Enum value);
};
diff --git a/sources/shiboken2/tests/libsample/removednamespaces.h b/sources/shiboken2/tests/libsample/removednamespaces.h
index c9732f8a6..9ad798bf7 100644
--- a/sources/shiboken2/tests/libsample/removednamespaces.h
+++ b/sources/shiboken2/tests/libsample/removednamespaces.h
@@ -34,10 +34,18 @@
namespace RemovedNamespace1
{
-enum RemovedNamespace1_Enum { RemovedNamespace1_Enum_Value0 };
+enum RemovedNamespace1_Enum { RemovedNamespace1_Enum_Value0 = 0,
+ RemovedNamespace1_Enum_Value1 = 1 };
enum { RemovedNamespace1_AnonymousEnum_Value0 };
+struct ObjectOnInvisibleNamespace
+{
+ bool exists() const { return true; }
+ static int toInt(RemovedNamespace1_Enum e) { return static_cast<int>(e); }
+ static ObjectOnInvisibleNamespace consume(const ObjectOnInvisibleNamespace &other) { return other; }
+};
+
namespace RemovedNamespace2
{
diff --git a/sources/shiboken2/tests/libsample/samplenamespace.h b/sources/shiboken2/tests/libsample/samplenamespace.h
index 0d418de16..5fe269c5e 100644
--- a/sources/shiboken2/tests/libsample/samplenamespace.h
+++ b/sources/shiboken2/tests/libsample/samplenamespace.h
@@ -41,25 +41,6 @@ enum {
AnonymousGlobalEnum_Value1
};
-// Invisible namespace
-namespace Invisible
-{
-
-enum EnumOnNamespace {
- Option1 = 1,
- Option2 = 2,
- Option3 = 3
-};
-
-struct ObjectOnInvisibleNamespace
-{
- bool exists() const { return true; }
- static int toInt(EnumOnNamespace e) { return static_cast<int>(e); }
- static ObjectOnInvisibleNamespace consume(const ObjectOnInvisibleNamespace &other) { return other; }
-};
-
-};
-
namespace SampleNamespace
{
diff --git a/sources/shiboken2/tests/libsample/virtualmethods.h b/sources/shiboken2/tests/libsample/virtualmethods.h
index 4937fab0d..4b2d25805 100644
--- a/sources/shiboken2/tests/libsample/virtualmethods.h
+++ b/sources/shiboken2/tests/libsample/virtualmethods.h
@@ -108,6 +108,10 @@ public:
virtual const Str & returnConstRef() const;
+protected:
+ // PYSIDE-1388: Protected hack with final classes (see VirtualFinalDaughter).
+ void protectedMethod() {}
+
private:
Str m_name;
int m_left;
diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
index ad52565ad..6bbfdb5bc 100644
--- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
@@ -97,6 +97,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/rectf_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/reference_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/referentmodelindex_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/toberenamedvalue_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/removednamespace1_objectoninvisiblenamespace_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/renameduser_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/sample_wrapper.cpp
@@ -127,7 +128,6 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/filter_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/data_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/intersection_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/union_wrapper.cpp
-${CMAKE_CURRENT_BINARY_DIR}/sample/invisible_objectoninvisiblenamespace_wrapper.cpp
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sample-binding.txt.in"
diff --git a/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py
index 4b0866c4e..168a609dc 100644
--- a/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py
+++ b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py
@@ -38,15 +38,33 @@ from shiboken_paths import init_paths
init_paths()
import sample
+from shiboken_test_helper import objectFullname
+
class TestEnumFromRemovedNamespace(unittest.TestCase):
def testEnumPromotedToGlobal(self):
sample.RemovedNamespace1_Enum
- sample.RemovedNamespace1_Enum_Value0
+ self.assertEqual(sample.RemovedNamespace1_Enum_Value0, 0)
+ self.assertEqual(sample.RemovedNamespace1_Enum_Value1, 1)
sample.RemovedNamespace1_AnonymousEnum_Value0
sample.RemovedNamespace2_Enum
sample.RemovedNamespace2_Enum_Value0
+ def testNames(self):
+ # Test if invisible namespace does not appear on type name
+ self.assertEqual(objectFullname(sample.RemovedNamespace1_Enum),
+ "sample.RemovedNamespace1_Enum")
+ self.assertEqual(objectFullname(sample.ObjectOnInvisibleNamespace),
+ "sample.ObjectOnInvisibleNamespace")
+
+ # Function arguments
+ signature = sample.ObjectOnInvisibleNamespace.toInt.__signature__
+ self.assertEqual(objectFullname(signature.parameters['e'].annotation),
+ "sample.RemovedNamespace1_Enum")
+ signature = sample.ObjectOnInvisibleNamespace.consume.__signature__
+ self.assertEqual(objectFullname(signature.parameters['other'].annotation),
+ "sample.ObjectOnInvisibleNamespace")
+
def testEnumPromotedToUpperNamespace(self):
sample.UnremovedNamespace
sample.UnremovedNamespace.RemovedNamespace3_Enum
diff --git a/sources/shiboken2/tests/samplebinding/namespace_test.py b/sources/shiboken2/tests/samplebinding/namespace_test.py
index 8171e0e43..807e7bfc9 100644
--- a/sources/shiboken2/tests/samplebinding/namespace_test.py
+++ b/sources/shiboken2/tests/samplebinding/namespace_test.py
@@ -43,20 +43,15 @@ from sample import *
from shiboken_test_helper import objectFullname
+# For tests of invisible namespaces, see
+# enumfromremovednamespace_test.py / removednamespaces.h
+
+
class TestVariablesUnderNamespace(unittest.TestCase):
def testIt(self):
self.assertEqual(SampleNamespace.variableInNamespace, 42)
-class TestEnumUnderNamespace(unittest.TestCase):
- def testInvisibleNamespace(self):
- o1 = EnumOnNamespace.Option1
- self.assertEqual(o1, 1)
- def testTpNames(self):
- self.assertEqual(objectFullname(EnumOnNamespace), "sample.EnumOnNamespace")
- self.assertEqual(str(EnumOnNamespace.Option1),
- "sample.EnumOnNamespace.Option1")
-
class TestClassesUnderNamespace(unittest.TestCase):
def testIt(self):
c1 = SampleNamespace.SomeClass()
@@ -87,14 +82,7 @@ class TestClassesUnderNamespace(unittest.TestCase):
"sample.SampleNamespace.InValue")
self.assertEqual(objectFullname(SampleNamespace.enumAsInt.__signature__.parameters['value'].annotation),
"sample.SampleNamespace.SomeClass.PublicScopedEnum")
- self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.toInt.__signature__.parameters['e'].annotation),
- "sample.EnumOnNamespace")
- # Test if enum on namespace that was marked as not gerenated does not appear on type name
- self.assertEqual(objectFullname(ObjectOnInvisibleNamespace),
- "sample.ObjectOnInvisibleNamespace")
- self.assertEqual(objectFullname(ObjectOnInvisibleNamespace.consume.__signature__.parameters['other'].annotation),
- "sample.ObjectOnInvisibleNamespace")
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
index fdddb80f2..e4963721b 100644
--- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
@@ -536,11 +536,6 @@
<enum-type identified-by-value="AnonymousGlobalEnum_Value0"/>
- <namespace-type name="Invisible" visible="no">
- <enum-type name="EnumOnNamespace" />
- <value-type name="ObjectOnInvisibleNamespace" />
- </namespace-type>
-
<namespace-type name="SampleNamespace">
<enum-type name="Option"/>
<enum-type name="InValue"/>
@@ -603,6 +598,7 @@
<namespace-type name="RemovedNamespace1" visible='false'>
<enum-type name="RemovedNamespace1_Enum" />
+ <value-type name="ObjectOnInvisibleNamespace" />
<namespace-type name="RemovedNamespace2" visible='false'>
<enum-type name="RemovedNamespace2_Enum" />
</namespace-type>