aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--README.pyside2.md6
-rw-r--r--build_scripts/config.py1
-rw-r--r--build_scripts/main.py12
-rw-r--r--build_scripts/utils.py10
-rw-r--r--build_scripts/wheel_override.py13
-rw-r--r--coin/instructions/common_environment.yaml117
-rw-r--r--coin/instructions/execute_build_instructions.yaml56
-rw-r--r--coin/instructions/execute_license_check.yaml31
-rw-r--r--coin/instructions/execute_test_instructions.yaml39
-rw-r--r--coin/instructions/find_path_to_msvc_compiler.yaml28
-rw-r--r--coin/instructions/relocate_pyside.yaml57
-rw-r--r--coin/module_config.yaml68
-rw-r--r--coin_build_instructions.py61
-rw-r--r--coin_test_instructions.py10
-rw-r--r--dist/changes-5.12.540
-rw-r--r--dist/changes-5.12.629
m---------sources/pyside2-tools0
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core_common.xml6
-rw-r--r--sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml.in1
-rw-r--r--sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport_common.xml1
-rw-r--r--sources/pyside2/PySide2/glue/qtcore.cpp48
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py4
-rw-r--r--sources/pyside2/pyside_version.py2
-rw-r--r--sources/pyside2/tests/QtCore/qsettings_test.py46
-rw-r--r--sources/pyside2/tests/pysidetest/CMakeLists.txt9
-rw-r--r--sources/shiboken2/data/shiboken_helpers.cmake3
-rw-r--r--sources/shiboken2/doc/typesystemvariables.rst2
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp2
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp2
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp94
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp28
-rw-r--r--sources/shiboken2/shiboken_version.py2
-rw-r--r--sources/shiboken2/shibokenmodule/CMakeLists.txt2
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py15
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py135
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py362
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py185
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py15
-rw-r--r--sources/shiboken2/tests/minimalbinding/brace_pattern_test.py121
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttype_test.py8
-rw-r--r--sources/shiboken2/tests/smartbinding/smart_pointer_test.py12
42 files changed, 1279 insertions, 406 deletions
diff --git a/.gitignore b/.gitignore
index b8977159c..c4bc8c8f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,7 +69,7 @@ develop-eggs/
downloads/
eggs/
.eggs/
-lib/
+/lib/
lib64/
parts/
sdist/
diff --git a/README.pyside2.md b/README.pyside2.md
index f1bd8aaa4..94cdd16e3 100644
--- a/README.pyside2.md
+++ b/README.pyside2.md
@@ -69,3 +69,9 @@ our [guidelines](https://wiki.qt.io/Qt_for_Python/Reporting_Bugs).
Check *#qt-pyside*, our official IRC channel on FreeNode,
or contact us via our [mailing list](http://lists.qt-project.org/mailman/listinfo/pyside).
+
+### Licensing
+
+PySide2 is available under both Open Source (LGPLv3/GPLv2) and commercial license.
+Using PyPi is the recommended installation source, because the content of the wheels is valid for both cases.
+For more information, refer to the [Qt Licensing page](https://www.qt.io/licensing/).
diff --git a/build_scripts/config.py b/build_scripts/config.py
index cad4e2f57..25036a65f 100644
--- a/build_scripts/config.py
+++ b/build_scripts/config.py
@@ -174,6 +174,7 @@ class Config(object):
'Environment :: Win32 (MS Windows)',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'License :: Other/Proprietary License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX',
'Operating System :: POSIX :: Linux',
diff --git a/build_scripts/main.py b/build_scripts/main.py
index 4d9f95b14..f853bc899 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -527,7 +527,13 @@ class PysideBuild(_build):
self.py_scripts_dir = py_scripts_dir
if py_libdir is None or not os.path.exists(py_libdir):
if sys.platform == "win32":
- py_libdir = os.path.join(py_prefix, "libs")
+ # For virtual environments on Windows, the py_prefix will contain a path pointing
+ # to it, instead of the system Python installation path.
+ # Since INCLUDEPY contains a path to the system location, we use the same base
+ # directory to define the py_libdir variable.
+ py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
+ if not os.path.isdir(py_libdir):
+ raise DistutilsSetupError("Failed to locate the 'libs' directory")
else:
py_libdir = os.path.join(py_prefix, "lib")
if py_include_dir is None or not os.path.exists(py_include_dir):
@@ -705,7 +711,7 @@ class PysideBuild(_build):
log.info("Creating install folder {}...".format(self.install_dir))
os.makedirs(self.install_dir)
- if not (OPTION_ONLYPACKAGE
+ if (not OPTION_ONLYPACKAGE
and not config.is_internal_shiboken_generator_build_and_part_of_top_level_all()):
# Build extensions
for ext in config.get_buildable_extensions():
@@ -1056,7 +1062,7 @@ class PysideBuild(_build):
OPTION_MACOS_SYSROOT))
else:
latest_sdk_path = run_process_output(['xcrun',
- '--show-sdk-path'])
+ '--sdk', 'macosx', '--show-sdk-path'])
if latest_sdk_path:
latest_sdk_path = latest_sdk_path[0]
cmake_cmd.append("-DCMAKE_OSX_SYSROOT={}".format(
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index b34d37123..85a2f9e36 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -1089,13 +1089,6 @@ def get_python_dict(python_script_path):
"file: {}.".format(python_script_path))
raise
-def install_pip_wheel_package(env_pip):
- # Need to install an unreleased wheel version, due to a bug that
- # will generate a wheel which will not be installable.
- # See https://github.com/pypa/wheel/issues/263
- wheel_url = "git+https://github.com/pypa/wheel.git@fbf3e3ada64d36ca7bb9c1422f5a1ccdba7e4dcf"
- install_pip_package_from_url_specifier(env_pip, wheel_url)
-
def install_pip_package_from_url_specifier(env_pip, url, upgrade=True):
args = [env_pip, "install", url]
if upgrade:
@@ -1148,7 +1141,8 @@ def run_instruction(instruction, error, initial_env=None):
def acceptCITestConfiguration(hostOS, hostOSVer, targetArch, compiler):
# Disable unsupported CI configs for now
# NOTE: String must match with QT CI's storagestruct thrift
- if hostOSVer in ["WinRT_10", "WebAssembly", "Ubuntu_18_04"]:
+ if hostOSVer in ["WinRT_10", "WebAssembly", "Ubuntu_18_04", "Android_ANY"] \
+ or hostOSVer.startswith("SLES_"):
print("Disabled " + hostOSVer + " from Coin configuration")
return False
# With 5.11 CI will create two sets of release binaries, one with msvc 2015 and one with msvc 2017
diff --git a/build_scripts/wheel_override.py b/build_scripts/wheel_override.py
index 3a5c8164b..025b7ebc2 100644
--- a/build_scripts/wheel_override.py
+++ b/build_scripts/wheel_override.py
@@ -157,8 +157,17 @@ class PysideBuildWheel(_bdist_wheel):
else:
abi_tag = str(get_abi_tag()).lower()
tag = (impl, abi_tag, plat_name)
- supported_tags = pep425tags.get_supported(
- supplied_platform=plat_name if self.plat_name_supplied else None)
+ try:
+ supported_tags = pep425tags.get_supported(
+ supplied_platform=plat_name if self.plat_name_supplied else None)
+ except TypeError:
+ # This was breaking the CI, specifically the:
+ # OpenSUSE 15 x86_64 using ICC
+ # Some versions of Python 2.7 require an argument called
+ # 'archive_root' which doesn't exist on 3, so we set it to
+ # 'None' for those version (e.g.: Python 2.7.14)
+ supported_tags = pep425tags.get_supported(None,
+ supplied_platform=plat_name if self.plat_name_supplied else None)
# XXX switch to this alternate implementation for non-pure:
if (self.py_limited_api) or (plat_name in ('manylinux1_x86_64') and sys.version_info[0] == 2):
return tag
diff --git a/coin/instructions/common_environment.yaml b/coin/instructions/common_environment.yaml
new file mode 100644
index 000000000..2c6603334
--- /dev/null
+++ b/coin/instructions/common_environment.yaml
@@ -0,0 +1,117 @@
+type: Group
+instructions:
+ - type: EnvironmentVariable
+ variableName: TARGET_ARCHITECTURE
+ variableValue: amd64
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64
+ - condition: property
+ property: host.os
+ equals_value: Windows
+ - type: EnvironmentVariable
+ variableName: TARGET_ARCHITECTURE
+ variableValue: amd64_x86
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86
+ - condition: property
+ property: host.os
+ equals_value: Windows
+ - type: EnvironmentVariable
+ variableName: CI_TARGET_ARCHITECTURE
+ variableValue: X86_64
+ enable_if:
+ condition: property
+ property: target.arch
+ equals_value: X86_64
+ - type: EnvironmentVariable
+ variableName: CI_TARGET_ARCHITECTURE
+ variableValue: X86
+ enable_if:
+ condition: property
+ property: target.arch
+ equals_value: X86
+ - type: EnvironmentVariable
+ variableName: CI_PACKAGING_FEATURE
+ variableValue: "--packaging"
+ enable_if:
+ condition: property
+ property: features
+ contains_value: Packaging
+ - type: EnvironmentVariable
+ variableName: CI_OS
+ variableValue: "MacOS"
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: MacOS
+ - type: EnvironmentVariable
+ variableName: CI_OS
+ variableValue: "Linux"
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Linux
+ - type: EnvironmentVariable
+ variableName: CI_OS
+ variableValue: "Windows"
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: EnvironmentVariable
+ variableName: MAKEFLAGS
+ variableValue: ""
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: AppendToEnvironmentVariable
+ variableName: PATH
+ variableValue: ;%CI_JOM_PATH%
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: PrependToEnvironmentVariable
+ variableName: PATH
+ variableValue: "\\Users\\qt\\work\\install\\bin;"
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: EnvironmentVariable
+ variableName: ICC64_18_LDLP
+ variableValue: /opt/intel/lib/intel64
+ enable_if:
+ condition: property
+ property: target.compiler
+ equals_value: ICC_18
+ - type: EnvironmentVariable
+ variableName: ICC64_18_PATH # Seems a bit hard to maintain
+ variableValue: /opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:/opt/intel/bin
+ enable_if:
+ condition: property
+ property: target.compiler
+ equals_value: ICC_18
+ - type: AppendToEnvironmentVariable
+ variableName: LD_LIBRARY_PATH
+ variableValue: :/opt/intel/lib/intel64
+ enable_if:
+ condition: property
+ property: target.compiler
+ equals_value: ICC_18
+ - type: AppendToEnvironmentVariable
+ variableName: PATH
+ variableValue: ":{{.Env.ICC64_18_PATH}}"
+ enable_if:
+ condition: property
+ property: target.compiler
+ equals_value: ICC_18
diff --git a/coin/instructions/execute_build_instructions.yaml b/coin/instructions/execute_build_instructions.yaml
new file mode 100644
index 000000000..831783a73
--- /dev/null
+++ b/coin/instructions/execute_build_instructions.yaml
@@ -0,0 +1,56 @@
+type: Group
+instructions:
+ - type: ExecuteCommand
+ command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=ALL"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: MacOS
+ userMessageOnFailure: >
+ Failed to execute build instructions on osx
+ - type: ExecuteCommand
+ command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/home/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=ALL"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Linux
+ userMessageOnFailure: >
+ Failed to execute build instructions on Linux
+ - type: ExecuteCommand
+ command: "c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=BUILD"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ userMessageOnFailure: >
+ Failed to execute build instructions on Windows
+ - type: SignPackage
+ directory: "{{.AgentWorkingDir}}\\pyside"
+ maxTimeInSeconds: 1200
+ maxTimeBetweenOutput: 1200
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}\\pyside\\pyside-setup"
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: ExecuteCommand
+ command: "c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=WHEEL"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ userMessageOnFailure: >
+ Failed to create wheels for Windows
diff --git a/coin/instructions/execute_license_check.yaml b/coin/instructions/execute_license_check.yaml
new file mode 100644
index 000000000..3a78a0aab
--- /dev/null
+++ b/coin/instructions/execute_license_check.yaml
@@ -0,0 +1,31 @@
+type: Group
+instructions:
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}"
+ - type: InstallSourceArchive
+ maxTimeInSeconds: 600
+ maxTimeBetweenOutput: 600
+ project: qt/qtbase
+ ref: 5.14
+ directory: qt/qtbase
+ userMessageOnFailure: >
+ Could not install source archive. Please investigate why.
+ - type: InstallSourceArchive
+ maxTimeInSeconds: 600
+ maxTimeBetweenOutput: 600
+ project: qt/qtqa
+ ref: master
+ directory: qt/qtqa-latest
+ userMessageOnFailure: >
+ Could not install source archive. Please investigate why.
+ - type: EnvironmentVariable
+ variableName: QT_MODULE_TO_TEST
+ variableValue: pyside/pyside-setup
+ userMessageOnFailure: >
+ Failed to set environment variable. This should not happen.
+ - type: ExecuteCommand
+ command: perl qt/qtqa-latest/tests/prebuild/license/tst_licenses.pl
+ maxTimeInSeconds: 7200
+ maxTimeBetweenOutput: 120
+ userMessageOnFailure: >
+ Failed to run license check script.
diff --git a/coin/instructions/execute_test_instructions.yaml b/coin/instructions/execute_test_instructions.yaml
new file mode 100644
index 000000000..87abb476c
--- /dev/null
+++ b/coin/instructions/execute_test_instructions.yaml
@@ -0,0 +1,39 @@
+type: Group
+enable_if:
+ condition: property
+ property: features
+ not_contains_value: LicenseCheck
+instructions:
+ - type: EnvironmentVariable
+ variableName: QTEST_ENVIRONMENT
+ variableValue: "ci"
+ - type: ExecuteCommand
+ command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: MacOS
+ userMessageOnFailure: >
+ Failed to execute test instructions on osx
+ - type: ExecuteCommand
+ command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/home/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Linux
+ userMessageOnFailure: >
+ Failed to execute test instructions on Linux
+ - type: ExecuteCommand
+ command: "c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=\\Users\\qt\\work\\install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 300
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ userMessageOnFailure: >
+ Failed to execute test instructions on 64 bit Windows
diff --git a/coin/instructions/find_path_to_msvc_compiler.yaml b/coin/instructions/find_path_to_msvc_compiler.yaml
new file mode 100644
index 000000000..8f9bed82f
--- /dev/null
+++ b/coin/instructions/find_path_to_msvc_compiler.yaml
@@ -0,0 +1,28 @@
+type: Group
+enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+instructions:
+ - type: EnvironmentVariable
+ variableName: VC_SCRIPT
+ variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2017\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat"
+ enable_if:
+ condition: property
+ property: host.compiler
+ equals_value: MSVC2017
+ - type: EnvironmentVariable
+ variableName: VC_SCRIPT
+ variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2019\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat"
+ enable_if:
+ condition: property
+ property: host.compiler
+ equals_value: MSVC2019
+ - type: WriteFile
+ fileContents: "call \"{{.Env.VC_SCRIPT}}\" {{.Env.TARGET_ARCHITECTURE}} \r\ncmd /c %*"
+ filename: "c:\\users\\qt\\MSVC.bat"
+ fileMode: 420
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
diff --git a/coin/instructions/relocate_pyside.yaml b/coin/instructions/relocate_pyside.yaml
new file mode 100644
index 000000000..afab83c70
--- /dev/null
+++ b/coin/instructions/relocate_pyside.yaml
@@ -0,0 +1,57 @@
+type: Group
+enable_if:
+ condition: property
+ property: features
+ not_contains_value: LicenseCheck
+instructions:
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}/pyside"
+ maxTimeInSeconds: 300
+ maxTimeBetweenOutput: 120
+ userMessageOnFailure: >
+ Failed to change to pyside dir
+ - type: ExecuteCommand
+ command: c:\\users\\qt\\MSVC.bat rd /s /q pyside-setup
+ maxTimeInSeconds: 300
+ maxTimeBetweenOutput: 120
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ userMessageOnFailure: >
+ Failed to remove pyside-setup dir
+ - type: ExecuteCommand
+ command: /bin/rm -rf pyside-setup
+ maxTimeInSeconds: 300
+ maxTimeBetweenOutput: 120
+ enable_if:
+ condition: property
+ property: host.os
+ not_equals_value: Windows
+ userMessageOnFailure: >
+ Failed to remove pyside-setup dir
+ - type: InstallBinaryArchive
+ relativeStoragePath: "{{.Env.MODULE_ARTIFACTS_RELATIVE_STORAGE_PATH}}/artifacts.tar.gz"
+ directory: "pyside"
+ maxTimeInSeconds: 1200
+ maxTimeBetweenOutput: 1200
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}\\pyside\\pyside-setup"
+ maxTimeInSeconds: 7200
+ maxTimeBetweenOutput: 120
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ userMessageOnFailure: >
+ Failed to install binary artifacts
+ - type: ChangeDirectory
+ directory: "{{.AgentWorkingDir}}/pyside/pyside-setup"
+ maxTimeInSeconds: 7200
+ maxTimeBetweenOutput: 120
+ enable_if:
+ condition: property
+ property: host.os
+ not_equals_value: Windows
+ userMessageOnFailure: >
+ Failed to change to pyside-setup dir
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
new file mode 100644
index 000000000..772166fb5
--- /dev/null
+++ b/coin/module_config.yaml
@@ -0,0 +1,68 @@
+version: 2
+accept_configuration:
+ condition: or
+ conditions:
+ - condition: and
+ conditions:
+ - condition: property # No cross compilation
+ property: host.os
+ equals_property: target.os
+ - condition: property # qtnamespace is not supported
+ property: configureArgs
+ not_contains_value: -qtnamespace
+ - condition: property # no-widgets is notsupported
+ property: configureArgs
+ not_contains_value: -no-widgets
+ - condition: property # no-gui is not supported
+ property: configureArgs
+ not_contains_value: -no-gui
+ - condition: property # Following configs are not supported
+ property: target.osVersion
+ not_in_values: [OPENSUSE_13_01, QEMU, WebAssembly, Ubuntu_18_04, SLES_12, SLES_15]
+ - condition: property # MibnGW and msvc2015 are not supported
+ property: target.compiler
+ not_in_values: [Mingw73, MSVC2015]
+ - condition: and
+ conditions:
+ - condition: property
+ property: target.osVersion
+ equals_value: Ubuntu_18_04
+ - condition: property
+ property: features
+ contains_value: LicenseCheck
+
+upload_pyside: &upload_pyside
+ type: Group
+ instructions:
+ - type: UploadArtifact
+ archiveDirectory: "{{.AgentWorkingDir}}\\pyside"
+ transferType: UploadModuleBuildArtifact
+ maxTimeInSeconds: 1200
+ maxTimeBetweenOutput: 1200
+ enable_if:
+ condition: property
+ property: host.os
+ equals_value: Windows
+ - type: UploadArtifact
+ archiveDirectory: "{{.AgentWorkingDir}}/pyside"
+ transferType: UploadModuleBuildArtifact
+ maxTimeInSeconds: 1200
+ maxTimeBetweenOutput: 1200
+ enable_if:
+ condition: property
+ property: host.os
+ not_equals_value: Windows
+
+instructions:
+ LicenseCheck:
+ - !include "{{pyside/pyside-setup}}/execute_license_check.yaml"
+ Build:
+ - !include "{{pyside/pyside-setup}}/common_environment.yaml"
+ - !include "{{pyside/pyside-setup}}/find_path_to_msvc_compiler.yaml"
+ - !include "{{pyside/pyside-setup}}/execute_build_instructions.yaml"
+ - *upload_pyside
+ Test:
+ - !include "{{pyside/pyside-setup}}/common_environment.yaml"
+ - !include "{{pyside/pyside-setup}}/find_path_to_msvc_compiler.yaml"
+ - !include "{{pyside/pyside-setup}}/relocate_pyside.yaml"
+ - !include "{{pyside/pyside-setup}}/execute_test_instructions.yaml"
diff --git a/coin_build_instructions.py b/coin_build_instructions.py
index 9a7d6272c..e35bcda3b 100644
--- a/coin_build_instructions.py
+++ b/coin_build_instructions.py
@@ -39,14 +39,14 @@
from build_scripts.options import has_option
from build_scripts.options import option_value
from build_scripts.utils import install_pip_dependencies
-from build_scripts.utils import install_pip_wheel_package
from build_scripts.utils import get_qtci_virtualEnv
from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
from build_scripts.utils import get_python_dict
-from build_scripts.utils import acceptCITestConfiguration
from build_scripts.utils import get_ci_qmake_path
import os
+import datetime
+import calendar
# Values must match COIN thrift
CI_HOST_OS = option_value("os")
@@ -57,13 +57,18 @@ CI_HOST_OS_VER = option_value("osVer")
CI_ENV_INSTALL_DIR = option_value("instdir")
CI_ENV_AGENT_DIR = option_value("agentdir")
CI_COMPILER = option_value("compiler")
-CI_INTEGRATION_ID = option_value("coinIntegrationId")
+CI_INTEGRATION_ID = option_value("coinIntegrationId") or str(calendar.timegm(datetime.datetime.now().timetuple()))
CI_FEATURES = []
_ci_features = option_value("features")
if _ci_features is not None:
for f in _ci_features.split(', '):
CI_FEATURES.append(f)
CI_RELEASE_CONF = has_option("packaging")
+CI_TEST_PHASE = option_value("phase")
+if CI_TEST_PHASE not in ["ALL", "BUILD", "WHEEL"]:
+ CI_TEST_PHASE = "ALL"
+
+
def get_current_script_path():
""" Returns the absolute path containing this script. """
@@ -96,21 +101,20 @@ def is_snapshot_build():
return True
return False
-def call_setup(python_ver):
+def call_setup(python_ver, phase):
_pExe, _env, env_pip, env_python = get_qtci_virtualEnv(python_ver, CI_HOST_OS, CI_HOST_ARCH, CI_TARGET_ARCH)
- rmtree(_env, True)
- run_instruction(["virtualenv", "-p", _pExe, _env], "Failed to create virtualenv")
- install_pip_dependencies(env_pip, ["pip", "numpy", "setuptools", "sphinx", "six"])
- install_pip_wheel_package(env_pip)
+ if phase in ["BUILD"]:
+ rmtree(_env, True)
+ run_instruction(["virtualenv", "-p", _pExe, _env], "Failed to create virtualenv")
+ install_pip_dependencies(env_pip, ["pip", "numpy", "setuptools", "sphinx", "six", "wheel"])
cmd = [env_python, "-u", "setup.py"]
- if CI_RELEASE_CONF:
- cmd += ["bdist_wheel", "--standalone"]
- else:
- cmd += ["build"]
- qmake_path = get_ci_qmake_path(CI_ENV_INSTALL_DIR, CI_HOST_OS)
- cmd.append(qmake_path)
+ if phase in ["BUILD"]:
+ cmd += ["build", "--standalone", "--skip-packaging"]
+ elif phase in ["WHEEL"] or CI_RELEASE_CONF:
+ cmd += ["bdist_wheel", "--reuse-build", "--standalone", "--skip-cmake", "--skip-make-install", "--only-package"]
+
cmd += ["--build-tests",
"--parallel=4",
"--verbose-build"]
@@ -119,6 +123,9 @@ def call_setup(python_ver):
if is_snapshot_build():
cmd += ["--snapshot-build"]
+ qmake_path = get_ci_qmake_path(CI_ENV_INSTALL_DIR, CI_HOST_OS)
+ cmd.append(qmake_path)
+
# Due to certain older CMake versions generating very long paths
# (at least with CMake 3.6.2) when using the export() function,
# pass the shorter paths option on Windows so we don't hit
@@ -129,25 +136,27 @@ def call_setup(python_ver):
cmd += ["--package-timestamp=" + CI_INTEGRATION_ID]
env = os.environ
- run_instruction(cmd, "Failed to run setup.py", initial_env=env)
+ run_instruction(cmd, "Failed to run setup.py for build", initial_env=env)
-def run_build_instructions():
- if not acceptCITestConfiguration(CI_HOST_OS, CI_HOST_OS_VER, CI_TARGET_ARCH, CI_COMPILER):
- exit()
- # Remove some environment variables that impact cmake
- for env_var in ['CC', 'CXX']:
- if os.environ.get(env_var):
- del os.environ[env_var]
+def run_build_instructions(phase):
# Uses default python, hopefully we have python2 installed on all hosts
# Skip building using Python 2 on Windows, because of different MSVC C runtimes (VS2008 vs VS2015+)
if CI_HOST_OS != "Windows":
- call_setup("")
-
+ call_setup("", phase)
# In case of packaging build, we have to build also python3 wheel
if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]:
- call_setup("3")
+ call_setup("3", phase)
if __name__ == "__main__":
- run_build_instructions()
+ # Remove some environment variables that impact cmake
+ for env_var in ['CC', 'CXX']:
+ if os.environ.get(env_var):
+ del os.environ[env_var]
+
+ if CI_TEST_PHASE in ["ALL", "BUILD"]:
+ run_build_instructions("BUILD")
+
+ if CI_TEST_PHASE in ["ALL", "WHEEL"]:
+ run_build_instructions("WHEEL")
diff --git a/coin_test_instructions.py b/coin_test_instructions.py
index aeedd03e7..a1c634497 100644
--- a/coin_test_instructions.py
+++ b/coin_test_instructions.py
@@ -39,11 +39,9 @@
from build_scripts.options import has_option
from build_scripts.options import option_value
from build_scripts.utils import install_pip_dependencies
-from build_scripts.utils import install_pip_wheel_package
from build_scripts.utils import get_qtci_virtualEnv
from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
-from build_scripts.utils import acceptCITestConfiguration
from build_scripts.utils import get_ci_qmake_path
import os
@@ -68,8 +66,7 @@ def call_testrunner(python_ver, buildnro):
rmtree(_env, True)
run_instruction(["virtualenv", "-p", _pExe, _env], "Failed to create virtualenv")
# Keeping PyInstaller 3.4, because 3.5 seems to have broken our test
- install_pip_dependencies(env_pip, ["pip", "numpy", "PyOpenGL", "setuptools", "six", "pyinstaller==3.4"])
- install_pip_wheel_package(env_pip)
+ install_pip_dependencies(env_pip, ["pip", "numpy", "PyOpenGL", "setuptools", "six", "pyinstaller==3.6", "wheel"])
cmd = [env_python, "testrunner.py", "test",
"--blacklist", "build_history/blacklist.txt",
"--buildno=" + buildnro]
@@ -84,9 +81,6 @@ def call_testrunner(python_ver, buildnro):
run_instruction(cmd, "Error while running wheel_tester.py")
def run_test_instructions():
- if not acceptCITestConfiguration(CI_HOST_OS, CI_HOST_OS_VER, CI_TARGET_ARCH, CI_COMPILER):
- exit()
-
# Remove some environment variables that impact cmake
for env_var in ['CC', 'CXX']:
if os.environ.get(env_var):
@@ -99,7 +93,7 @@ def run_test_instructions():
call_testrunner("", str(testRun))
testRun =+ 1
# We know that second build was with python3
- if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]:
+ if CI_RELEASE_CONF:
call_testrunner("3", str(testRun))
if __name__ == "__main__":
diff --git a/dist/changes-5.12.5 b/dist/changes-5.12.5
new file mode 100644
index 000000000..d463b8324
--- /dev/null
+++ b/dist/changes-5.12.5
@@ -0,0 +1,40 @@
+
+Qt for Python 5.12.5 is a bug-fix release.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qtforpython/
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* PySide2 *
+****************************************************************************
+
+ - [PYSIDE-571] Support the qApp macro in "scriptable application"
+ - [PYSIDE-634] Add support for parameterNames in Signals
+ - [PYSIDE-951] Correct QtPrintSupport dependency
+ - [PYSIDE-1010] Add optional support for types in QSettings::value
+ - [PYSIDE-1020] Fix pyside2-uic to generate correct code for QWebview and QQuickWidget
+ - [PYSIDE-1028] Leave QVariantMap as a name, not a type
+ - [PYSIDE-1029] Fix type name for lookup of QFlags<> converters
+ - [PYSIDE-1032] Use default compiler on macOS
+ - [PYSIDE-1035] Fix pyside2-uic to generate correct code for QTableWidget
+ - [PYSIDE-1066] Fix Xcode sdk value embedded into PySide2 binaries
+
+
+****************************************************************************
+* Shiboken2 *
+****************************************************************************
+
+ - [PYSIDE-1024] shiboken: Generate code for smart pointers only within declaring package
+ - [PYSIDE-1037] shiboken: Allow for "auto" as target of type for CONVERTTOCPP in injected code
+
+
diff --git a/dist/changes-5.12.6 b/dist/changes-5.12.6
new file mode 100644
index 000000000..d1eba40c2
--- /dev/null
+++ b/dist/changes-5.12.6
@@ -0,0 +1,29 @@
+Qt for Python 5.12.6 is a bug-fix release.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qtforpython/
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* PySide2 *
+****************************************************************************
+
+ - [Fixes: PYSIDE-1007] Remove extra ref on QDataStream::setDevice
+ - [Fixes: PYSIDE-1051] Fix heaptype conflict with QtCore.QObject.__new__in Python 2.7
+
+
+****************************************************************************
+* Shiboken2 *
+****************************************************************************
+
+ - No changes
+
diff --git a/sources/pyside2-tools b/sources/pyside2-tools
-Subproject bd27bac457943aab1082ac1c5b3f81ef9574c67
+Subproject 3c402fef54106b65ab9c1df92c39c4626424fdd
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
index 78a731458..20893b658 100644
--- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
+++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
@@ -2541,12 +2541,6 @@
<include file-name="QtCore/QtCore" location="global"/>
</extra-includes>
- <modify-function signature="setDevice(QIODevice*)">
- <modify-argument index="1">
- <parent index="this" action="add"/>
- </modify-argument>
- </modify-function>
-
<!-- ### Replaced by write<TYPE> methods -->
<modify-function signature="operator&gt;&gt;(qint8&amp;)" remove="all"/>
<modify-function signature="operator&gt;&gt;(bool&amp;)" remove="all"/>
diff --git a/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml.in b/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml.in
index 7949b2daa..ff078d19a 100644
--- a/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml.in
+++ b/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml.in
@@ -40,7 +40,6 @@
****************************************************************************/
-->
<typesystem package="PySide2.QtPrintSupport">
- <load-typesystem name="QtGui/typesystem_gui.xml" generate="no"/>
<load-typesystem name="QtWidgets/typesystem_widgets.xml" generate="no"/>
<load-typesystem name="QtPrintSupport/typesystem_printsupport_common.xml" generate="yes"/>
</typesystem>
diff --git a/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport_common.xml b/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport_common.xml
index c11a6e046..487103875 100644
--- a/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport_common.xml
+++ b/sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport_common.xml
@@ -40,6 +40,7 @@
****************************************************************************/
-->
<typesystem package="PySide2.QtPrintSupport">
+ <load-typesystem name="QtWidgets/typesystem_widgets.xml" generate="no"/>
<object-type name="QPageSetupDialog">
<modify-function signature="exec()" rename="exec_" allow-thread="yes"/>
diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp
index 3e1bab97b..a218e433f 100644
--- a/sources/pyside2/PySide2/glue/qtcore.cpp
+++ b/sources/pyside2/PySide2/glue/qtcore.cpp
@@ -57,24 +57,39 @@ bool py2kStrCheck(PyObject *obj)
// @snippet pystring-check
// @snippet qsettings-value
-QVariant out = %CPPSELF.value(%1, %2);
+// If we enter the kwds, means that we have a defaultValue or
+// at least a type.
+// This avoids that we are passing '0' as defaultValue.
+// defaultValue can also be passed as positional argument,
+// not only as keyword.
+QVariant out;
+if (kwds || numArgs > 1)
+ out = %CPPSELF.value(%1, %2);
+else
+ out = %CPPSELF.value(%1);
+
PyTypeObject *typeObj = reinterpret_cast<PyTypeObject*>(%PYARG_3);
if (typeObj) {
if (typeObj == &PyList_Type) {
- QByteArrayList valuesList = out.toByteArray().split(',');
- const int valuesSize = valuesList.size();
- if (valuesSize > 0) {
- PyObject *list = PyList_New(valuesSize);
- for (int i = 0; i < valuesSize; i++) {
- PyObject *item = PyUnicode_FromString(valuesList[i].data());
- PyList_SET_ITEM(list, i, item);
- Py_DECREF(item);
- }
- %PYARG_0 = list;
+ QByteArray out_ba = out.toByteArray();
+ if (!out_ba.isEmpty()) {
+ QByteArrayList valuesList = out_ba.split(',');
+ const int valuesSize = valuesList.size();
+ if (valuesSize > 0) {
+ PyObject *list = PyList_New(valuesSize);
+ for (int i = 0; i < valuesSize; i++) {
+ PyObject *item = PyUnicode_FromString(valuesList[i].data());
+ PyList_SET_ITEM(list, i, item);
+ Py_DECREF(item);
+ }
+ %PYARG_0 = list;
+ } else {
+ %PYARG_0 = %CONVERTTOPYTHON[QVariant](out);
+ }
} else {
- %PYARG_0 = %CONVERTTOPYTHON[QVariant](out);
+ %PYARG_0 = PyList_New(0);
}
} else if (typeObj == &PyBytes_Type) {
QByteArray asByteArray = out.toByteArray();
@@ -94,11 +109,13 @@ if (typeObj) {
} else if (typeObj == &PyFloat_Type) {
float asFloat = out.toFloat();
%PYARG_0 = PyFloat_FromDouble(asFloat);
+ } else if (typeObj == &PyBool_Type) {
+ %PYARG_0 = out.toBool() ? Py_True : Py_False;
}
// TODO: PyDict_Type and PyTuple_Type
}
else {
- if (out == 0)
+ if (!out.isValid())
%PYARG_0 = Py_None;
else
%PYARG_0 = %CONVERTTOPYTHON[QVariant](out);
@@ -1289,7 +1306,7 @@ Shiboken::AutoDecRef emptyTuple(PyTuple_New(0));
PyObject *pyTimer = reinterpret_cast<PyTypeObject *>(Shiboken::SbkType<QTimer>())->tp_new(Shiboken::SbkType<QTimer>(), emptyTuple, 0);
reinterpret_cast<PyTypeObject *>(Shiboken::SbkType<QTimer>())->tp_init(pyTimer, emptyTuple, 0);
-QTimer * timer = %CONVERTTOCPP[QTimer *](pyTimer);
+auto timer = %CONVERTTOCPP[QTimer *](pyTimer);
//XXX /|\ omitting this space crashes shiboken!
Shiboken::AutoDecRef result(
PyObject_CallMethod(pyTimer,
@@ -1484,8 +1501,7 @@ if (PySide::SignalManager::registerMetaMethod(%1, signalName.mid(1).toLatin1().d
if (!PyObject_TypeCheck(%1, PySideSignalInstanceTypeF()))
goto Sbk_%TYPEFunc_%FUNCTION_NAME_TypeError;
PySideSignalInstance *signalInstance = reinterpret_cast<PySideSignalInstance *>(%1);
-QObject * sender = %CONVERTTOCPP[QObject *](PySide::Signal::getObject(signalInstance));
-//XXX /|\ omitting this space crashes shiboken!
+auto sender = %CONVERTTOCPP[QObject *](PySide::Signal::getObject(signalInstance));
QSignalTransition *%0 = %CPPSELF->%FUNCTION_NAME(sender, PySide::Signal::getSignature(signalInstance),%2);
%PYARG_0 = %CONVERTTOPYTHON[QSignalTransition *](%0);
// @snippet qstate-addtransition-2
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
index 294cdc91b..c732227f4 100644
--- a/sources/pyside2/PySide2/support/generate_pyi.py
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -252,6 +252,10 @@ def generate_all_pyi(outpath, options):
from PySide2.support.signature import inspect
from PySide2.support.signature.lib.enum_sig import HintingEnumerator
+ # propagate USE_PEP563 to the mapping module.
+ # Perhaps this can be automated?
+ PySide2.support.signature.mapping.USE_PEP563 = USE_PEP563
+
outpath = outpath or os.path.dirname(PySide2.__file__)
name_list = PySide2.__all__ if options.modules == ["all"] else options.modules
errors = ", ".join(set(name_list) - set(PySide2.__all__))
diff --git a/sources/pyside2/pyside_version.py b/sources/pyside2/pyside_version.py
index e253eb8fb..17a6bb515 100644
--- a/sources/pyside2/pyside_version.py
+++ b/sources/pyside2/pyside_version.py
@@ -39,7 +39,7 @@
major_version = "5"
minor_version = "12"
-patch_version = "4"
+patch_version = "5"
# For example: "a", "b", "rc"
# (which means "alpha", "beta", "release candidate").
diff --git a/sources/pyside2/tests/QtCore/qsettings_test.py b/sources/pyside2/tests/QtCore/qsettings_test.py
index 6d64b0db3..36a4c3c62 100644
--- a/sources/pyside2/tests/QtCore/qsettings_test.py
+++ b/sources/pyside2/tests/QtCore/qsettings_test.py
@@ -55,15 +55,55 @@ class TestQSettings(unittest.TestCase):
def testDefaultValueConversion(self):
settings = QSettings('foo.ini', QSettings.IniFormat)
- r = settings.value('lala', 22)
+ settings.setValue('zero_value', 0)
+ settings.setValue('empty_list', [])
+ settings.setValue('bool1', False)
+ settings.setValue('bool2', True)
+ del settings
+
+ # Loading values already set
+ settings = QSettings('foo.ini', QSettings.IniFormat)
+
+ # Getting value that doesn't exist
+ r = settings.value("variable")
+ self.assertEqual(type(r), type(None))
+
+ # Handling zero value
+ r = settings.value('zero_value')
if py3k.IS_PY3K:
self.assertEqual(type(r), int)
else:
self.assertEqual(type(r), long)
- r = settings.value('lala', 22, type=str)
- self.assertEqual(type(r), str)
+ r = settings.value('zero_value', type=int)
+ self.assertEqual(type(r), int)
+
+ # Empty list
+ r = settings.value('empty_list')
+ self.assertTrue(len(r) == 0)
+ self.assertEqual(type(r), list)
+
+ r = settings.value('empty_list', type=list)
+ self.assertTrue(len(r) == 0)
+ self.assertEqual(type(r), list)
+
+ # Booleans
+ r = settings.value('bool1')
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool2')
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool1', type=bool)
+ self.assertEqual(type(r), bool)
+
+ r = settings.value('bool2', type=int)
+ self.assertEqual(type(r), int)
+
+ r = settings.value('bool2', type=bool)
+ self.assertEqual(type(r), bool)
+ # Not set variable, but with default value
r = settings.value('lala', 22, type=bytes)
self.assertEqual(type(r), bytes)
diff --git a/sources/pyside2/tests/pysidetest/CMakeLists.txt b/sources/pyside2/tests/pysidetest/CMakeLists.txt
index 3c993cf4e..6c100475b 100644
--- a/sources/pyside2/tests/pysidetest/CMakeLists.txt
+++ b/sources/pyside2/tests/pysidetest/CMakeLists.txt
@@ -106,10 +106,17 @@ set_property(TARGET testbinding PROPERTY OUTPUT_NAME "testbinding${SHIBOKEN_PYTH
if(WIN32)
set_property(TARGET testbinding PROPERTY SUFFIX ".pyd")
endif()
+
+if(PYTHON_LIMITED_API)
+ set(TESTBINDING_PYTHON_LIBS ${PYTHON_LIMITED_LIBRARIES})
+else()
+ set(TESTBINDING_PYTHON_LIBS ${PYTHON_LIBRARIES})
+endif()
+
target_link_libraries(testbinding
pysidetest
pyside2
- ${PYTHON_LIBRARIES}
+ ${TESTBINDING_PYTHON_LIBS}
Shiboken2::libshiboken
${Qt5Core_LIBRARIES}
${Qt5Gui_LIBRARIES}
diff --git a/sources/shiboken2/data/shiboken_helpers.cmake b/sources/shiboken2/data/shiboken_helpers.cmake
index f4dd4d5dc..780509f58 100644
--- a/sources/shiboken2/data/shiboken_helpers.cmake
+++ b/sources/shiboken2/data/shiboken_helpers.cmake
@@ -13,8 +13,9 @@ macro(shiboken_check_if_limited_api)
# On other platforms, this result is not used at all.
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ import os
for lib in '${PYTHON_LIBRARIES}'.split(';'):
- if '/' in lib:
+ if '/' in lib and os.path.isfile(lib):
prefix, py = lib.rsplit('/', 1)
if py.startswith('python3'):
print(prefix + '/python3.lib')
diff --git a/sources/shiboken2/doc/typesystemvariables.rst b/sources/shiboken2/doc/typesystemvariables.rst
index b1b9bbfe6..73d4dd12c 100644
--- a/sources/shiboken2/doc/typesystemvariables.rst
+++ b/sources/shiboken2/doc/typesystemvariables.rst
@@ -150,6 +150,8 @@ Variables
since it otherwise would be indistinguishable from the pointer assignment
above.
+ It is possible to use "auto" as type.
+
.. _converttopython:
**%CONVERTTOPYTHON[CPPTYPE]**
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index e36b6edc3..68bcfe508 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -5387,7 +5387,7 @@ void CppGenerator::writeGetattroFunction(QTextStream &s, GeneratorContext &conte
s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl;
s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl;
s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl;
- s << INDENT << " tp->tp_name, PyBytes_AS_STRING(name));" << endl;
+ s << INDENT << " tp->tp_name, Shiboken::String::toCString(name));" << endl;
s << INDENT << "return nullptr;" << endl;
}
s << INDENT << "} else {" << endl;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index e41c91716..34e43a4c7 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -2047,7 +2047,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
QString varName = list.at(1).trimmed();
if (!varType.isEmpty()) {
const QString conversionSignature = conversionType->cppSignature();
- if (varType != conversionSignature)
+ if (varType != QLatin1String("auto") && varType != conversionSignature)
qFatal("%s", qPrintable(msgConversionTypesDiffer(varType, conversionSignature)));
c << getFullTypeName(conversionType) << ' ' << varName;
writeMinimalConstructorExpression(c, conversionType);
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index b9f6735d8..9d233b847 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -92,6 +92,7 @@ static PyType_Slot SbkObjectType_Type_slots[] = {
{Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
{Py_tp_new, reinterpret_cast<void *>(SbkObjectTypeTpNew)},
{Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
+ {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_Type_getsetlist)},
{0, nullptr}
};
static PyType_Spec SbkObjectType_Type_spec = {
@@ -106,7 +107,7 @@ static PyType_Spec SbkObjectType_Type_spec = {
#if PY_VERSION_HEX < 0x03000000
/*****************************************************************************
*
- * PYSIDE-816: Workaround for Python 2.7
+ * PYSIDE-816: Workaround for Python 2.7 for SbkObjectType_TypeF().
*
* This is an add-on for function typeobject.c:tp_new_wrapper from Python 2.7 .
* Problem:
@@ -121,9 +122,16 @@ static PyType_Spec SbkObjectType_Type_spec = {
* The problem is that heap types have this unwanted dependency.
* But we cannot get at static slot_tp_new, and so we have to use
* the original function and patch Py_TPFLAGS_HEAPTYPE away during the call.
+ *
+ * PYSIDE-1051: The same problem holds for all dynamic metatypes generated by
+ * SbkObjectTypeTpNew() and all types generated by
+ * introduceWrapperType() .
+ *
+ * This led to a drastic overhaul of patch_tp_new_wrapper() which now adds
+ * the new wrapper to exactly those types which have the old wrapper.
*/
-static PyCFunction old_tp_new_wrapper = nullptr;
+ternaryfunc old_tp_new_wrapper = nullptr;
static PyObject *
tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
@@ -136,9 +144,9 @@ tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
return ret;
}
-// This is intentionally the new docstring of Python 3.7 .
+// This is intentionally the __new__ docstring of Python 3.7 .
static struct PyMethodDef tp_new_methoddef[] = {
- {"__new__", (PyCFunction)tp_new_wrapper, METH_VARARGS|METH_KEYWORDS,
+ {"__new__", reinterpret_cast<PyCFunction>(tp_new_wrapper), METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n"
"Create and return a new object. "
"See help(type) for accurate signature.")},
@@ -146,43 +154,39 @@ static struct PyMethodDef tp_new_methoddef[] = {
};
static int
-get_old_tp_new_wrapper(void)
-{
- // We get the old tp_new_wrapper from any initialized type.
- PyTypeObject *type = &PyType_Type;
- PyObject *dict = type->tp_dict;
- PyObject *key, *func = nullptr;
- Py_ssize_t pos = 0;
- while (PyDict_Next(dict, &pos, &key, &func)) {
- char *name = PyString_AsString(key);
- if (strcmp(name, "__new__") == 0) {
- break;
+patch_tp_new_wrapper(PyTypeObject *type)
+{
+ /*
+ * The old tp_new_wrapper is added to all types that have tp_new.
+ * We patch that with a version that ignores the heaptype flag.
+ */
+ static PyObject *__new__ = nullptr;
+ if (old_tp_new_wrapper == nullptr) {
+ if ((__new__ = Py_BuildValue("s", "__new__")) == nullptr)
+ return -1;
+ PyObject *func = PyDict_GetItem(PyType_Type.tp_dict, __new__);
+ PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func);
+ old_tp_new_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth);
+ }
+ PyObject *mro = type->tp_mro;
+ Py_ssize_t i, n = PyTuple_GET_SIZE(mro);
+ for (i = 0; i < n; i++) {
+ type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i));
+ PyObject *existing = PyDict_GetItem(type->tp_dict, __new__);
+ if (existing && PyCFunction_Check(existing)
+ && type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
+ auto *pycf_ob = reinterpret_cast<PyCFunctionObject *>(existing);
+ auto existing_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth);
+ if (existing_wrapper == tp_new_wrapper)
+ break;
+ if (existing_wrapper == old_tp_new_wrapper) {
+ PyObject *ob_type = reinterpret_cast<PyObject *>(type);
+ Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type));
+ if (func.isNull() || PyDict_SetItem(type->tp_dict, __new__, func))
+ return -1;
+ }
}
}
- if (func == nullptr)
- return -1;
- PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func);
- old_tp_new_wrapper = pycf_ob->m_ml->ml_meth;
- return 0;
-}
-
-static int
-add_tp_new_wrapper(PyTypeObject *type)
-{
- // get the original tp_new_wrapper
- if (old_tp_new_wrapper == nullptr && get_old_tp_new_wrapper() < 0)
- return -1;
- // initialize tp_dict
- if (type->tp_dict == nullptr)
- type->tp_dict = PyDict_New();
- if (type->tp_dict == nullptr)
- return -1;
- PyObject *ob_type = reinterpret_cast<PyObject *>(type);
- Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type));
- if (func.isNull())
- return -1;
- if (PyDict_SetItemString(type->tp_dict, "__new__", func))
- return -1;
return 0;
}
/*****************************************************************************/
@@ -197,7 +201,7 @@ PyTypeObject *SbkObjectType_TypeF(void)
PepHeapType_SIZE + sizeof(SbkObjectTypePrivate);
type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObjectType_Type_spec));
#if PY_VERSION_HEX < 0x03000000
- if (add_tp_new_wrapper(type) < 0)
+ if (patch_tp_new_wrapper(type) < 0)
return nullptr;
#endif
}
@@ -452,6 +456,11 @@ PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *k
auto *newType = reinterpret_cast<SbkObjectType *>(type_new(metatype, args, kwds));
if (!newType)
return nullptr;
+#if PY_VERSION_HEX < 0x03000000
+ // PYSIDE-1051: The newly created metatype needs the PYSIDE-816 wrapper, too.
+ if (patch_tp_new_wrapper(&newType->type) < 0)
+ return nullptr;
+#endif
Shiboken::ObjectType::initPrivateData(newType);
SbkObjectTypePrivate *sotp = PepType_SOTP(newType);
@@ -842,6 +851,11 @@ introduceWrapperType(PyObject *enclosingObject,
Py_TYPE(heaptype) = SbkObjectType_TypeF();
Py_INCREF(Py_TYPE(heaptype));
auto *type = reinterpret_cast<SbkObjectType *>(heaptype);
+#if PY_VERSION_HEX < 0x03000000
+ // PYSIDE-1051: The newly created type needs the PYSIDE-816 wrapper, too.
+ if (patch_tp_new_wrapper(&type->type) < 0)
+ return nullptr;
+#endif
if (baseType) {
if (baseTypes) {
for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i)
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index e62f861a2..2f080edad 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -187,8 +187,12 @@ _get_class_of_descr(PyObject *ob)
}
static PyObject *
-GetClassOfFunc(PyObject *ob)
+GetClassOrModOf(PyObject *ob)
{
+ /*
+ * Return the type or module of a function or type.
+ * The purpose is finally to use the name of the object.
+ */
if (PyType_Check(ob)) {
// PySide-928: The type case must do refcounting like the others as well.
Py_INCREF(ob);
@@ -202,7 +206,7 @@ GetClassOfFunc(PyObject *ob)
return _get_class_of_descr(ob);
if (Py_TYPE(ob) == &PyWrapperDescr_Type)
return _get_class_of_descr(ob);
- Py_FatalError("unexpected type in GetClassOfFunc");
+ Py_FatalError("unexpected type in GetClassOrModOf");
return nullptr;
}
@@ -227,7 +231,7 @@ compute_name_key(PyObject *ob)
if (PyType_Check(ob))
return GetTypeKey(ob);
Shiboken::AutoDecRef func_name(get_funcname(ob));
- Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(ob)));
+ Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOrModOf(ob)));
return Py_BuildValue("(OO)", type_key.object(), func_name.object());
}
@@ -267,7 +271,7 @@ name_key_to_func(PyObject *ob)
PyObject *ret = PyDict_GetItem(pyside_globals->map_dict, name_key);
if (ret == nullptr) {
// do a lazy initialization
- Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(ob)));
+ Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOrModOf(ob)));
PyObject *type = PyDict_GetItem(pyside_globals->map_dict,
type_key);
if (type == nullptr)
@@ -364,7 +368,7 @@ GetSignature_Function(PyObject *obfunc, const char *modifier)
// make sure that we look into PyCFunction, only...
if (Py_TYPE(obfunc) == PepFunction_TypePtr)
Py_RETURN_NONE;
- Shiboken::AutoDecRef obtype_mod(GetClassOfFunc(obfunc));
+ Shiboken::AutoDecRef obtype_mod(GetClassOrModOf(obfunc));
Shiboken::AutoDecRef type_key(GetTypeKey(obtype_mod));
if (type_key.isNull())
Py_RETURN_NONE;
@@ -674,10 +678,16 @@ handle_doc(PyObject *ob, PyObject *old_descr)
{
init_module_1();
init_module_2();
- Shiboken::AutoDecRef ob_type(GetClassOfFunc(ob));
- auto *type = reinterpret_cast<PyTypeObject *>(ob_type.object());
- if (handle_doc_in_progress || strncmp(type->tp_name, "PySide2.", 8) != 0)
- return PyObject_CallMethod(old_descr, const_cast<char *>("__get__"), const_cast<char *>("(O)"), ob);
+ Shiboken::AutoDecRef ob_type_mod(GetClassOrModOf(ob));
+ const char *name;
+ if (PyModule_Check(ob_type_mod))
+ name = PyModule_GetName(ob_type_mod);
+ else
+ name = reinterpret_cast<PyTypeObject *>(ob_type_mod.object())->tp_name;
+ if (handle_doc_in_progress || name == nullptr
+ || strncmp(name, "PySide2.", 8) != 0)
+ return PyObject_CallMethod(old_descr, const_cast<char *>("__get__"),
+ const_cast<char *>("(O)"), ob);
handle_doc_in_progress++;
PyObject *res = PyObject_CallFunction(
pyside_globals->make_helptext_func,
diff --git a/sources/shiboken2/shiboken_version.py b/sources/shiboken2/shiboken_version.py
index e253eb8fb..17a6bb515 100644
--- a/sources/shiboken2/shiboken_version.py
+++ b/sources/shiboken2/shiboken_version.py
@@ -39,7 +39,7 @@
major_version = "5"
minor_version = "12"
-patch_version = "4"
+patch_version = "5"
# For example: "a", "b", "rc"
# (which means "alpha", "beta", "release candidate").
diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt
index 09731240f..057a995f8 100644
--- a/sources/shiboken2/shibokenmodule/CMakeLists.txt
+++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt
@@ -61,6 +61,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/
"${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/__init__.py" COPYONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/lib/enum_sig.py"
"${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/enum_sig.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/signature/lib/tool.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/files.dir/shibokensupport/signature/lib/tool.py" COPYONLY)
if (PYTHON_VERSION_MAJOR EQUAL 3)
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/files.dir/shibokensupport/backport_inspect.py"
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index c43d6d076..bd827f1ee 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -58,20 +58,7 @@ used literally as strings like "signature", "existence", etc.
from textwrap import dedent
from shibokensupport.signature import inspect
from shibokensupport.signature.mapping import ellipsis
-
-
-class SimpleNamespace(object):
- # From types.rst, because the builtin is implemented in Python 3, only.
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
-
- def __repr__(self):
- keys = sorted(self.__dict__)
- items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
- return "{}({})".format(type(self).__name__, ", ".join(items))
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
+from shibokensupport.signature.lib.tool import SimpleNamespace
class SignatureLayout(SimpleNamespace):
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
new file mode 100644
index 000000000..b34bfb404
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
@@ -0,0 +1,135 @@
+#############################################################################
+##
+## Copyright (C) 2019 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## 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 Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## 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-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+"""
+tool.py
+
+Some useful stuff, see below.
+"""
+
+from textwrap import dedent
+
+
+class SimpleNamespace(object):
+ # From types.rst, because the builtin is implemented in Python 3, only.
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
+
+ def __repr__(self):
+ keys = sorted(self.__dict__)
+ items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
+ return "{}({})".format(type(self).__name__, ", ".join(items))
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+try:
+ from types import SimpleNamespace
+except ImportError:
+ pass
+
+
+def build_brace_pattern(level, separators=""):
+ """
+ Build a brace pattern upto a given depth
+
+ The brace pattern parses any pattern with round, square, curly, or angle
+ brackets. Inside those brackets, any characters are allowed.
+
+ The structure is quite simple and is recursively repeated as needed.
+ When separators are given, the match stops at that separator.
+
+ Reason to use this instead of some Python function:
+ The resulting regex is _very_ fast!
+
+ A faster replacement would be written in C, but this solution is
+ sufficient when the nesting level is not too large.
+
+ Because of the recursive nature of the pattern, the size grows by a factor
+ of 4 at every level, as does the creation time. Up to a level of 6, this
+ is below 10 ms.
+
+ There are other regex engines available which allow recursive patterns,
+ avoiding this problem completely. It might be considered to switch to
+ such an engine if the external module is not a problem.
+ """
+ def escape(str):
+ return "".join("\\" + c for c in str)
+
+ ro, rc = round = "()"
+ so, sc = square = "[]"
+ co, cc = curly = "CD" # we insert "{}", later...
+ ao, ac = angle = "<>"
+ qu, bs = '"', "\\"
+ all = round + square + curly + angle
+ __ = " "
+ ro, rc, so, sc, co, cc, ao, ac, separators, qu, bs, all = map(
+ escape, (ro, rc, so, sc, co, cc, ao, ac, separators, qu, bs, all))
+
+ no_brace_sep_q = r"[^{all}{separators}{qu}{bs}]".format(**locals())
+ no_quote = r"(?: [^{qu}{bs}] | {bs}. )*".format(**locals())
+ pattern = dedent(r"""
+ (
+ (?: {__} {no_brace_sep_q}
+ | {qu} {no_quote} {qu}
+ | {ro} {replacer} {rc}
+ | {so} {replacer} {sc}
+ | {co} {replacer} {cc}
+ | {ao} {replacer} {ac}
+ )*
+ )
+ """)
+ no_braces_q = "[^{all}{qu}{bs}]*".format(**locals())
+ repeated = dedent(r"""
+ {indent} (?: {__} {no_braces_q}
+ {indent} | {qu} {no_quote} {qu}
+ {indent} | {ro} {replacer} {rc}
+ {indent} | {so} {replacer} {sc}
+ {indent} | {co} {replacer} {cc}
+ {indent} | {ao} {replacer} {ac}
+ {indent} )*
+ """)
+ for idx in range(level):
+ pattern = pattern.format(replacer = repeated if idx < level-1 else no_braces_q,
+ indent = idx * " ", **locals())
+ return pattern.replace("C", "{").replace("D", "}")
+
+# eof
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 5f92446cf..36b137104 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -61,24 +61,13 @@ class ellipsis(object):
return "..."
ellipsis = ellipsis()
-StringList = typing.List[str]
-IntList = typing.List[int]
Point = typing.Tuple[float, float]
-PointList = typing.List[Point]
-IntMatrix = typing.List[IntList]
Variant = typing.Any
ModelIndexList = typing.List[int]
QImageCleanupFunction = typing.Callable
+StringList = typing.List[str]
-# First time installing our own Pair type into typing.
-T = TypeVar('T')
-S = TypeVar('S')
-
-class Pair(Generic[T, S]):
- __module__ = "typing"
-
-typing.Pair = Pair
-
+_S = TypeVar("_S")
# Building our own Char type, which is much nicer than
# Char = typing.Union[str, int] # how do I model the limitation to 1 char?
@@ -174,7 +163,12 @@ class _NotCalled(str):
text = self if self.endswith(")") else self + "()"
return eval(text, namespace)
-USE_PEP563 = sys.version_info[:2] >= (3, 7)
+USE_PEP563 = False
+# Note: we cannot know if this feature has been imported.
+# Otherwise it would be "sys.version_info[:2] >= (3, 7)".
+# We *can* eventually inspect sys.modules and look if
+# the calling module has this future statement set,
+# but should we do that?
# Some types are abstract. They just show their name.
@@ -183,10 +177,11 @@ class Virtual(_NotCalled):
# Other types I simply could not find.
class Missing(_NotCalled):
- if not USE_PEP563:
- # The string must be quoted, because the object does not exist.
- def __repr__(self):
- return '{}("{}")'.format(type(self).__name__, self)
+ # The string must be quoted, because the object does not exist.
+ def __repr__(self):
+ if USE_PEP563:
+ return _NotCalled.__repr__(self)
+ return '{}("{}")'.format(type(self).__name__, self)
class Invalid(_NotCalled):
@@ -230,7 +225,7 @@ class Reloader(object):
self.sys_module_count = len(sys.modules)
g = globals()
# PYSIDE-1009: Try to recognize unknown modules in errorhandler.py
- candidates = list(mod_name for mod_name in sys.modules
+ candidates = list(mod_name for mod_name in sys.modules.copy()
if self.module_valid(sys.modules[mod_name]))
for mod_name in candidates:
# 'top' is PySide2 when we do 'import PySide.QtCore'
@@ -260,20 +255,76 @@ type_map = {}
namespace = globals() # our module's __dict__
type_map.update({
+ "bool": bool,
+ "char": Char,
+ "char*": str,
+ "char*const": str,
+ "double": float,
+ "float": float,
+ "int": int,
+ "List": typing.List,
+ "long": int,
+ "PyCallable": typing.Callable,
+ "PyObject": object,
+ "PySequence": typing.Iterable, # important for numpy
+ "PyTypeObject": type,
+ "QChar": Char,
+ "QHash": typing.Dict,
+ "qint16": int,
+ "qint32": int,
+ "qint64": int,
+ "qint8": int,
+ "qintptr": int,
"QList": typing.List,
- "QVector": typing.List,
- "QSet": typing.Set,
- "QPair": Pair,
+ "qlonglong": int,
"QMap": typing.Dict,
+ "QPair": typing.Tuple,
+ "qptrdiff": int,
+ "qreal": float,
+ "QSet": typing.Set,
+ "QString": str,
+ "QStringList": StringList,
+ "quint16": int,
+ "quint32": int,
+ "quint32": int,
+ "quint64": int,
+ "quint8": int,
+ "quintptr": int,
+ "qulonglong": int,
+ "QVariant": Variant,
+ "QVector": typing.List,
+ "real": float,
+ "short": int,
+ "signed char": Char,
+ "signed long": int,
+ "str": str,
+ "true": True,
+ "ULONG_MAX": ulong_max,
+ "unsigned char": Char,
+ "unsigned int": int, # should we define an unsigned type?
+ "unsigned long int": int, # 5.6, RHEL 6.6
+ "unsigned long long": int,
+ "unsigned long": int,
+ "unsigned short int": int, # 5.6, RHEL 6.6
+ "unsigned short": int,
+ "UnsignedShortType": int, # 5.9
+ "void": int, # be more specific?
+ "WId": WId,
+ "zero(bytes)": b"",
+ "zero(Char)": 0,
+ "zero(float)": 0,
+ "zero(int)": 0,
+ "zero(object)": None,
+ "zero(str)": "",
})
# The Shiboken Part
def init_Shiboken():
type_map.update({
+ "PyType": type,
"shiboken2.bool": bool,
"size_t": int,
- "PyType": type,
})
return locals()
@@ -288,36 +339,32 @@ def init_minimal():
def init_sample():
import datetime
type_map.update({
- "double": float,
- "sample.int": int,
+ "char": Char,
"Complex": complex,
- "sample.OddBool": bool,
- "sample.bool": bool,
- "sample.PStr": str,
+ "double": float,
+ "Foo.HANDLE": int,
+ "HANDLE": int,
+ "Null": None,
+ "ObjectType.Identifier": Missing("sample.ObjectType.Identifier"),
"OddBool": bool,
"PStr": str,
- "char": Char,
+ "PyDate": datetime.date,
+ "sample.bool": bool,
"sample.char": Char,
- "sample.Point": Point,
+ "sample.double": float,
+ "sample.int": int,
"sample.ObjectType": object,
- "std.string": str,
- "HANDLE": int,
- "Foo.HANDLE": int,
+ "sample.OddBool": bool,
"sample.Photon.TemplateBase": Missing("sample.Photon.TemplateBase"),
- "ObjectType.Identifier": Missing("sample.ObjectType.Identifier"),
- "zero(HANDLE)": 0,
- "Null": None,
- "zero(sample.ObjectType)": None,
+ "sample.Point": Point,
+ "sample.PStr": str,
+ "sample.unsigned char": Char,
"std.size_t": int,
- 'Str("<unknown>")': "<unknown>",
+ "std.string": str,
+ "ZeroIn": 0,
'Str("<unk")': "<unk",
+ 'Str("<unknown>")': "<unknown>",
'Str("nown>")': "nown>",
- "zero(sample.ObjectModel)": None,
- "sample.unsigned char": Char,
- "sample.double": float,
- "zero(sample.bool)": False,
- "PyDate": datetime.date,
- "ZeroIn": 0,
})
return locals()
@@ -325,15 +372,20 @@ def init_sample():
def init_other():
import numbers
type_map.update({
- "other.Number": numbers.Number,
"other.ExtendsNoImplicitConversion": Missing("other.ExtendsNoImplicitConversion"),
+ "other.Number": numbers.Number,
})
return locals()
def init_smart():
+ # This missing type should be defined in module smart. We cannot set it to Missing()
+ # because it is a container type. Therefore, we supply a surrogate:
+ global SharedPtr
+ class SharedPtr(Generic[_S]):
+ __module__ = "smart"
+ smart.SharedPtr = SharedPtr
type_map.update({
- "smart.SharedPtr": Missing("smart.SharedPtr"), # bad object "SharedPtr<Obj >"
"smart.Smart.Integer2": int,
})
return locals()
@@ -349,131 +401,88 @@ def init_PySide2_QtCore():
except ImportError:
pass
type_map.update({
- "str": str,
- "int": int,
- "QString": str,
- "bool": bool,
- "PyObject": object,
- "void": int, # be more specific?
- "char": Char,
- "'%'": "%",
"' '": " ",
- "false": False,
- "double": float,
+ "'%'": "%",
"'g'": "g",
+ "4294967295UL": 4294967295, # 5.6, RHEL 6.6
+ "CheckIndexOption.NoOption": Instance(
+ "PySide2.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
+ "false": False,
+ "list of QAbstractAnimation": typing.List[PySide2.QtCore.QAbstractAnimation],
+ "list of QAbstractState": typing.List[PySide2.QtCore.QAbstractState],
"long long": int,
- "unsigned int": int, # should we define an unsigned type?
- "Q_NULLPTR": None,
"long": int,
- "float": float,
- "short": int,
- "unsigned long": int,
- "unsigned long long": int,
- "unsigned short": int,
- "QStringList": StringList,
- "QChar": Char,
- "signed char": Char,
- "QVariant": Variant,
- "QVariant.Type": type, # not so sure here...
- "QStringRef": str,
- "QString()": "",
- "QModelIndexList": ModelIndexList,
- "unsigned char": Char,
- "QJsonObject": typing.Dict[str, PySide2.QtCore.QJsonValue],
- "QStringList()": [],
- "ULONG_MAX": ulong_max,
- "quintptr": int,
+ "NULL": None, # 5.6, MSVC
+ "nullptr": None, # 5.9
+ "PyByteArray": bytearray,
+ "PyBytes": bytes,
"PyCallable": typing.Callable,
- "PyTypeObject": type,
+ "PyObject": object,
"PySequence": typing.Iterable, # important for numpy
- "qptrdiff": int,
- "true": True,
- "Qt.HANDLE": int, # be more explicit with some consts?
- "list of QAbstractState": typing.List[PySide2.QtCore.QAbstractState],
- "list of QAbstractAnimation": typing.List[PySide2.QtCore.QAbstractAnimation],
- "QVariant()": Invalid(Variant),
"PySide2.QtCore.bool": bool,
- "QHash": typing.Dict,
- "PySide2.QtCore.QChar": Char,
- "PySide2.QtCore.qreal": float,
+ "PySide2.QtCore.char": StringList, # A 'char **' is a list of strings.
+ "PySide2.QtCore.double": float,
"PySide2.QtCore.float": float,
+ "PySide2.QtCore.int": int,
+ "PySide2.QtCore.int32_t": int, # 5.9
+ "PySide2.QtCore.int64_t": int, # 5.9
+ "PySide2.QtCore.long long": int, # 5.9, MSVC 15
+ "PySide2.QtCore.long": int,
+ "PySide2.QtCore.QCborStreamReader.StringResult": typing.AnyStr,
+ "PySide2.QtCore.QChar": Char,
"PySide2.QtCore.qint16": int,
"PySide2.QtCore.qint32": int,
"PySide2.QtCore.qint64": int,
"PySide2.QtCore.qint8": int,
+ "PySide2.QtCore.qreal": float,
"PySide2.QtCore.QString": str,
"PySide2.QtCore.QStringList": StringList,
- "PySide2.QtCore.QVariant": Variant,
"PySide2.QtCore.quint16": int,
"PySide2.QtCore.quint32": int,
"PySide2.QtCore.quint64": int,
"PySide2.QtCore.quint8": int,
+ "PySide2.QtCore.QUrl.ComponentFormattingOptions":
+ PySide2.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
+ "PySide2.QtCore.QVariant": Variant,
"PySide2.QtCore.short": int,
- "PySide2.QtCore.unsigned short": int,
"PySide2.QtCore.signed char": Char,
"PySide2.QtCore.uchar": Char,
+ "PySide2.QtCore.uint32_t": int, # 5.9
"PySide2.QtCore.unsigned char": Char, # 5.9
- "PySide2.QtCore.long": int,
- "PySide2.QtCore.QUrl.ComponentFormattingOptions":
- PySide2.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
- "QUrl.FormattingOptions(PrettyDecoded)": Instance(
- "QUrl.FormattingOptions(QUrl.PrettyDecoded)"),
- # from 5.9
+ "PySide2.QtCore.unsigned int": int, # 5.9 Ubuntu
+ "PySide2.QtCore.unsigned short": int,
+ "PyTypeObject": type,
+ "PyUnicode": typing.Text,
+ "Q_NULLPTR": None,
+ "QChar": Char,
"QDir.Filters(AllEntries | NoDotAndDotDot)": Instance(
"QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot)"),
- "NULL": None, # 5.6, MSVC
"QDir.SortFlags(Name | IgnoreCase)": Instance(
"QDir.SortFlags(QDir.Name | QDir.IgnoreCase)"),
- "PyBytes": bytes,
- "PyByteArray": bytearray,
- "PyUnicode": typing.Text,
- "signed long": int,
- "PySide2.QtCore.int": int,
- "PySide2.QtCore.char": StringList, # A 'char **' is a list of strings.
- "unsigned long int": int, # 5.6, RHEL 6.6
- "unsigned short int": int, # 5.6, RHEL 6.6
- "4294967295UL": 4294967295, # 5.6, RHEL 6.6
- "PySide2.QtCore.int32_t": int, # 5.9
- "PySide2.QtCore.int64_t": int, # 5.9
- "UnsignedShortType": int, # 5.9
- "nullptr": None, # 5.9
- "uint64_t": int, # 5.9
- "PySide2.QtCore.uint32_t": int, # 5.9
- "PySide2.QtCore.unsigned int": int, # 5.9 Ubuntu
- "PySide2.QtCore.long long": int, # 5.9, MSVC 15
- "QGenericArgument(nullptr)": ellipsis, # 5.10
- "QModelIndex()": Invalid("PySide2.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
"QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
"QGenericArgument()": ellipsis,
"QGenericArgument(0)": ellipsis,
"QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
+ "QGenericArgument(nullptr)": ellipsis, # 5.10
"QGenericArgument(Q_NULLPTR)": ellipsis,
- "zero(PySide2.QtCore.QObject)": None,
- "zero(PySide2.QtCore.QThread)": None,
- "zero(quintptr)": 0,
- "zero(str)": "",
- "zero(int)": 0,
- "zero(PySide2.QtCore.QState)": None,
- "zero(PySide2.QtCore.bool)": False,
- "zero(PySide2.QtCore.int)": 0,
- "zero(void)": None,
- "zero(long long)": 0,
- "zero(PySide2.QtCore.QAbstractItemModel)": None,
- "zero(PySide2.QtCore.QJsonParseError)": None,
- "zero(double)": 0.0,
- "zero(PySide2.QtCore.qint64)": 0,
- "zero(PySide2.QtCore.QTextCodec.ConverterState)": None,
- "zero(long long)": 0,
- "zero(QImageCleanupFunction)": None,
- "zero(unsigned int)": 0,
- "zero(PySide2.QtCore.QPoint)": Default("PySide2.QtCore.QPoint"),
- "zero(unsigned char)": 0,
- "zero(PySide2.QtCore.QEvent.Type)": None,
- "CheckIndexOption.NoOption": Instance(
- "PySide2.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
+ "QHash": typing.Dict,
+ "QJsonObject": typing.Dict[str, PySide2.QtCore.QJsonValue],
+ "QModelIndex()": Invalid("PySide2.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
+ "QModelIndexList": ModelIndexList,
+ "qptrdiff": int,
+ "QString": str,
+ "QString()": "",
+ "QStringList": StringList,
+ "QStringList()": [],
+ "QStringRef": str,
+ "Qt.HANDLE": int, # be more explicit with some consts?
+ "quintptr": int,
+ "QUrl.FormattingOptions(PrettyDecoded)": Instance(
+ "QUrl.FormattingOptions(QUrl.PrettyDecoded)"),
+ "QVariant": Variant,
+ "QVariant()": Invalid(Variant),
+ "QVariant.Type": type, # not so sure here...
"QVariantMap": typing.Dict[str, Variant],
- "PySide2.QtCore.QCborStreamReader.StringResult": typing.AnyStr,
- "PySide2.QtCore.double": float,
})
try:
type_map.update({
@@ -488,29 +497,21 @@ def init_PySide2_QtCore():
def init_PySide2_QtGui():
from PySide2.QtGui import QPageLayout, QPageSize # 5.12 macOS
type_map.update({
- "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
- "USHRT_MAX": ushort_max,
"0.0f": 0.0,
"1.0f": 1.0,
- "uint32_t": int,
- "uint8_t": int,
- "int32_t": int,
"GL_COLOR_BUFFER_BIT": GL_COLOR_BUFFER_BIT,
"GL_NEAREST": GL_NEAREST,
- "WId": WId,
+ "int32_t": int,
+ "PySide2.QtCore.uint8_t": int, # macOS 5.9
+ "PySide2.QtGui.QGenericMatrix": Missing("PySide2.QtGui.QGenericMatrix"),
"PySide2.QtGui.QPlatformSurface": int, # a handle
"QList< QTouchEvent.TouchPoint >()": [], # XXX improve?
"QPixmap()": Default("PySide2.QtGui.QPixmap"), # can't create without qApp
- "PySide2.QtCore.uint8_t": int, # macOS 5.9
- "zero(uint32_t)": 0,
- "zero(PySide2.QtGui.QWindow)": None,
- "zero(PySide2.QtGui.QOpenGLContext)": None,
- "zero(PySide2.QtGui.QRegion)": None,
- "zero(PySide2.QtGui.QPaintDevice)": None,
- "zero(PySide2.QtGui.QTextLayout.FormatRange)": None,
- "zero(PySide2.QtGui.QTouchDevice)": None,
- "zero(PySide2.QtGui.QScreen)": None,
- "PySide2.QtGui.QGenericMatrix": Missing("PySide2.QtGui.QGenericMatrix"),
+ "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
+ "uint32_t": int,
+ "uint8_t": int,
+ "USHRT_MAX": ushort_max,
+ "WId": WId,
})
return locals()
@@ -521,28 +522,15 @@ def init_PySide2_QtWidgets():
type_map.update({
"QMessageBox.StandardButtons(Yes | No)": Instance(
"QMessageBox.StandardButtons(QMessageBox.Yes | QMessageBox.No)"),
+ "QVector< int >()": [],
"QWidget.RenderFlags(DrawWindowBackground | DrawChildren)": Instance(
"QWidget.RenderFlags(QWidget.DrawWindowBackground | QWidget.DrawChildren)"),
+ "SH_Default": QStyleHintReturn.SH_Default,
+ "SO_Complex": QStyleOptionComplex.SO_Complex,
+ "SO_Default": QStyleOption.SO_Default,
"static_cast<Qt.MatchFlags>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance(
"Qt.MatchFlags(Qt.MatchExactly | Qt.MatchCaseSensitive)"),
- "QVector< int >()": [],
- "WId": WId,
- # from 5.9
"Type": PySide2.QtWidgets.QListWidgetItem.Type,
- "SO_Default": QStyleOption.SO_Default,
- "SH_Default": QStyleHintReturn.SH_Default,
- "SO_Complex": QStyleOptionComplex.SO_Complex,
- "zero(PySide2.QtWidgets.QWidget)": None,
- "zero(PySide2.QtWidgets.QGraphicsItem)": None,
- "zero(PySide2.QtCore.QEvent)": None,
- "zero(PySide2.QtWidgets.QStyleOption)": None,
- "zero(PySide2.QtWidgets.QStyleHintReturn)": None,
- "zero(PySide2.QtWidgets.QGraphicsLayoutItem)": None,
- "zero(PySide2.QtWidgets.QListWidget)": None,
- "zero(PySide2.QtGui.QKeySequence)": None,
- "zero(PySide2.QtWidgets.QAction)": None,
- "zero(PySide2.QtWidgets.QUndoCommand)": None,
- "zero(WId)": 0,
})
return locals()
@@ -559,9 +547,6 @@ def init_PySide2_QtSql():
def init_PySide2_QtNetwork():
type_map.update({
"QMultiMap": MultiMap,
- "zero(unsigned short)": 0,
- "zero(PySide2.QtCore.QIODevice)": None,
- "zero(QList)": [],
})
return locals()
@@ -569,8 +554,8 @@ def init_PySide2_QtNetwork():
def init_PySide2_QtXmlPatterns():
from PySide2.QtXmlPatterns import QXmlName
type_map.update({
+ "QXmlName.NamespaceCode": Missing("PySide2.QtXmlPatterns.QXmlName.NamespaceCode"),
"QXmlName.PrefixCode": Missing("PySide2.QtXmlPatterns.QXmlName.PrefixCode"),
- "QXmlName.NamespaceCode": Missing("PySide2.QtXmlPatterns.QXmlName.NamespaceCode")
})
return locals()
@@ -588,39 +573,31 @@ def init_PySide2_QtMultimedia():
def init_PySide2_QtOpenGL():
type_map.update({
- "GLuint": int,
+ "GLbitfield": int,
"GLenum": int,
+ "GLfloat": float, # 5.6, MSVC 15
"GLint": int,
- "GLbitfield": int,
+ "GLuint": int,
"PySide2.QtOpenGL.GLint": int,
"PySide2.QtOpenGL.GLuint": int,
- "GLfloat": float, # 5.6, MSVC 15
- "zero(PySide2.QtOpenGL.QGLContext)": None,
- "zero(GLenum)": 0,
- "zero(PySide2.QtOpenGL.QGLWidget)": None,
})
return locals()
def init_PySide2_QtQml():
type_map.update({
- "QJSValueList()": [],
"PySide2.QtQml.bool volatile": bool,
- # from 5.9
+ "QJSValueList()": [],
"QVariantHash()": typing.Dict[str, Variant], # XXX sorted?
- "zero(PySide2.QtQml.QQmlContext)": None,
- "zero(PySide2.QtQml.QQmlEngine)": None,
})
return locals()
def init_PySide2_QtQuick():
type_map.update({
- "PySide2.QtQuick.QSharedPointer": int,
"PySide2.QtCore.uint": int,
+ "PySide2.QtQuick.QSharedPointer": int,
"T": int,
- "zero(PySide2.QtQuick.QQuickItem)": None,
- "zero(GLuint)": 0,
})
return locals()
@@ -638,13 +615,6 @@ def init_PySide2_QtTest():
})
return locals()
-# from 5.9
-def init_PySide2_QtWebEngineWidgets():
- type_map.update({
- "zero(PySide2.QtWebEngineWidgets.QWebEnginePage.FindFlags)": 0,
- })
- return locals()
-
# from 5.6, MSVC
def init_PySide2_QtWinExtras():
type_map.update({
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 72ca35757..6109bceee 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -47,6 +47,8 @@ import keyword
import functools
from shibokensupport.signature.mapping import (type_map, update_mapping,
namespace, typing, _NotCalled)
+from shibokensupport.signature.lib.tool import (SimpleNamespace,
+ build_brace_pattern)
_DEBUG = False
LIST_KEYWORDS = False
@@ -78,6 +80,23 @@ def dprint(*args, **kw):
pprint.pprint(arg)
sys.stdout.flush()
+
+_cache = {}
+
+def _parse_arglist(argstr):
+ # The following is a split re. The string is broken into pieces which are
+ # between the recognized strings. Because the re has groups, both the
+ # strings and the separators are returned, where the strings are not
+ # interesting at all: They are just the commata.
+ key = "_parse_arglist"
+ if key not in _cache:
+ regex = build_brace_pattern(level=3, separators=",")
+ _cache[key] = re.compile(regex, flags=re.VERBOSE)
+ split = _cache[key].split
+ # Note: this list is interspersed with "," and surrounded by ""
+ return [x.strip() for x in split(argstr) if x.strip() not in ("", ",")]
+
+
def _parse_line(line):
line_re = r"""
((?P<multi> ([0-9]+)) : )? # the optional multi-index
@@ -86,38 +105,9 @@ def _parse_line(line):
( -> (?P<returntype> .*) )? # the optional return type
$
"""
- ret = re.match(line_re, line, re.VERBOSE).groupdict()
- arglist = ret["arglist"]
- # The following is a split re. The string is broken into pieces which are
- # between the recognized strings. Because the re has groups, both the
- # strings and the delimiters are returned, where the strings are not
- # interesting at all: They are just the commata.
- # Note that it is necessary to put the characters with special handling in
- # the first group (comma, brace, angle bracket).
- # Then they are not recognized there, and we can handle them differently
- # in the following expressions.
- arglist = list(x.strip() for x in re.split(r"""
- (
- (?: # inner group is not capturing
- [^,()<>] # no commas or braces or angle brackets
- |
- \(
- (?:
- [^()]* # or one brace pair
- |
- \(
- [^()]* # or doubls nested pair
- \)
- )*
- \)
- |
- < # or one angle bracket pair
- [^<>]*
- >
- )+ # longest possible span
- ) # this list is interspersed with "," and surrounded by ""
- """, arglist, flags=re.VERBOSE)
- if x.strip() not in ("", ","))
+ ret = SimpleNamespace(**re.match(line_re, line, re.VERBOSE).groupdict())
+ argstr = ret.arglist
+ arglist = _parse_arglist(argstr)
args = []
for arg in arglist:
name, ann = arg.split(":")
@@ -131,15 +121,16 @@ def _parse_line(line):
else:
tup = name, ann
args.append(tup)
- ret["arglist"] = args
- multi = ret["multi"]
+ ret.arglist = args
+ multi = ret.multi
if multi is not None:
- ret["multi"] = int(multi)
- funcname = ret["funcname"]
+ ret.multi = int(multi)
+ funcname = ret.funcname
parts = funcname.split(".")
if parts[-1] in keyword.kwlist:
- ret["funcname"] = funcname + "_"
- return ret
+ ret.funcname = funcname + "_"
+ return vars(ret)
+
def make_good_value(thing, valtype):
try:
@@ -153,6 +144,7 @@ def make_good_value(thing, valtype):
except Exception:
pass
+
def try_to_guess(thing, valtype):
if "." not in thing and "(" not in thing:
text = "{}.{}".format(valtype, thing)
@@ -172,9 +164,13 @@ def try_to_guess(thing, valtype):
return ret
return None
+
def _resolve_value(thing, valtype, line):
if thing in ("0", "None") and valtype:
- thing = "zero({})".format(valtype)
+ if valtype.startswith("PySide2."):
+ return None
+ name = type_map[valtype].__name__
+ thing = "zero({})".format(name)
if thing in type_map:
return type_map[thing]
res = make_good_value(thing, valtype)
@@ -192,40 +188,88 @@ def _resolve_value(thing, valtype, line):
""".format(thing, line), RuntimeWarning)
return thing
+
def _resolve_arraytype(thing, line):
- thing = thing[:-2]
- if thing.endswith("[]"):
+ search = re.search(r"\[(\d*)\]$", thing)
+ thing = thing[:search.start()]
+ if thing.endswith("]"):
thing = _resolve_arraytype(thing, line)
- # this mapping is in shiboken
- thing = "QList[" + thing + "]"
+ if search.group(1):
+ # concrete array, use a tuple
+ nelem = int(search.group(1))
+ thing = ", ".join([thing] * nelem)
+ thing = "Tuple[" + thing + "]"
+ else:
+ thing = "QList[" + thing + "]"
return thing
+
def to_string(thing):
if isinstance(thing, str):
return thing
if hasattr(thing, "__name__"):
- dot = "." in str(type(thing))
+ dot = "." in str(thing)
return thing.__module__ + "." + thing.__name__ if dot else thing.__name__
# Note: This captures things from the typing module:
return str(thing)
-def _resolve_type(thing, line):
- if thing.endswith("[]"):
- thing = _resolve_arraytype(thing, line)
+
+matrix_pattern = "PySide2.QtGui.QGenericMatrix"
+
+# The matrix patch is borrowed from the future (extracted).
+# It will work when the parser recognizes matrices.
+def handle_matrix(arg):
+ n, m, typstr = tuple(map(lambda x:x.strip(), arg.split(",")))
+ assert typstr == "float"
+ result = "PySide2.QtGui.QMatrix{n}x{m}".format(**locals())
+ return eval(result, namespace)
+
+
+debugging_aid = """
+from inspect import currentframe
+
+def lno(level):
+ lineno = currentframe().f_back.f_lineno
+ spaces = level * " "
+ return "{lineno}{spaces}".format(**locals())
+"""
+
+
+def _resolve_type(thing, line, level):
+ # Capture total replacements, first. Happens in
+ # "PySide2.QtCore.QCborStreamReader.StringResult[PySide2.QtCore.QByteArray]"
+ if thing in type_map:
+ return type_map[thing]
+ # Now the nested structures are handled.
if "[" in thing:
+ # handle primitive arrays
+ if re.search(r"\[\d*\]$", thing):
+ thing = _resolve_arraytype(thing, line)
# Handle a container return type. (see PYSIDE-921 in cppgenerator.cpp)
contr, thing = re.match(r"(.*?)\[(.*?)\]$", thing).groups()
- contr = to_string(_resolve_type(contr, line))
- thing = to_string(_resolve_type(thing, line))
+ # Special case: Handle the generic matrices.
+ if contr == matrix_pattern:
+ return handle_matrix(thing)
+ contr = _resolve_type(contr, line, level+1)
+ if isinstance(contr, _NotCalled):
+ raise SystemError("Container types must exist:", repr(contr))
+ contr = to_string(contr)
+ pieces = []
+ for part in _parse_arglist(thing):
+ part = _resolve_type(part, line, level+1)
+ if isinstance(part, _NotCalled):
+ # fix the tag (i.e. "Missing") by repr
+ part = repr(part)
+ pieces.append(to_string(part))
+ thing = ", ".join(pieces)
result = "{contr}[{thing}]".format(**locals())
- if not isinstance(thing, _NotCalled):
- result = eval(result, namespace)
- return result
+ return eval(result, namespace)
return _resolve_value(thing, None, line)
+
def calculate_props(line):
- res = _parse_line(line)
- arglist = res["arglist"]
+ parsed = SimpleNamespace(**_parse_line(line.strip()))
+ arglist = parsed.arglist
annotations = {}
_defaults = []
for idx, tup in enumerate(arglist):
@@ -236,27 +280,33 @@ def calculate_props(line):
ann = 'NULL' # maps to None
tup = name, ann
arglist[idx] = tup
- annotations[name] = _resolve_type(ann, line)
+ annotations[name] = _resolve_type(ann, line, 0)
if len(tup) == 3:
default = _resolve_value(tup[2], ann, line)
_defaults.append(default)
defaults = tuple(_defaults)
- returntype = res["returntype"]
+ returntype = parsed.returntype
if returntype is not None:
- annotations["return"] = _resolve_type(returntype, line)
- props = {}
- props["defaults"] = defaults
- props["kwdefaults"] = {}
- props["annotations"] = annotations
- props["varnames"] = varnames = tuple(tup[0] for tup in arglist)
- funcname = res["funcname"]
- props["fullname"] = funcname
+ annotations["return"] = _resolve_type(returntype, line, 0)
+ props = SimpleNamespace()
+ props.defaults = defaults
+ props.kwdefaults = {}
+ 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"] = res["multi"]
- return props
+ props.name = shortname
+ props.multi = parsed.multi
+ return vars(props)
+
def fixup_multilines(lines):
+ """
+ Multilines can collapse when certain distinctions between C++ types
+ vanish after mapping to Python.
+ This function fixes this by re-computing multiline-ness.
+ """
res = []
multi_lines = []
for line in lines:
@@ -280,6 +330,7 @@ def fixup_multilines(lines):
res.append(line)
return res
+
def pyside_type_init(type_key, sig_strings):
dprint()
dprint("Initialization of type key '{}'".format(type_key))
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
index dba8f8c77..786a84ecb 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/typing27.py
@@ -1996,6 +1996,21 @@ class DefaultDict(collections.defaultdict, MutableMapping[KT, VT]):
return _generic_new(collections.defaultdict, cls, *args, **kwds)
+############################
+# Insertion by CT 2019-02-21
+#
+class OrderedDict(collections.OrderedDict, MutableMapping[KT, VT]):
+ __slots__ = ()
+ __extra__ = collections.OrderedDict
+
+ def __new__(cls, *args, **kwds):
+ if cls._gorg is OrderedDict:
+ return collections.OrderedDict(*args, **kwds)
+ return _generic_new(collections.OrderedDict, cls, *args, **kwds)
+#
+############################
+
+
class Counter(collections.Counter, Dict[T, int]):
__slots__ = ()
__extra__ = collections.Counter
diff --git a/sources/shiboken2/tests/minimalbinding/brace_pattern_test.py b/sources/shiboken2/tests/minimalbinding/brace_pattern_test.py
new file mode 100644
index 000000000..89df998e8
--- /dev/null
+++ b/sources/shiboken2/tests/minimalbinding/brace_pattern_test.py
@@ -0,0 +1,121 @@
+#############################################################################
+##
+## Copyright (C) 2019 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## 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 Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## 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-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import absolute_import, print_function
+
+import re
+import sys
+import os
+
+import shiboken2
+type.__signature__ # trigger bootstrap
+
+from shibokensupport.signature.lib.tool import build_brace_pattern
+import unittest
+
+"""
+This test tests the brace pattern from signature.lib.tool
+against a slower reference implementation.
+The pattern is crucial, because it is used heavily in signature.parser .
+"""
+
+# A slow reference parser for braces and strings
+def check(s):
+ open, close = "[{(<", "]})>"
+ escape, quote = "\\", '"'
+ instring = blind = False
+ stack = []
+ for c in s:
+ if instring:
+ if blind:
+ blind = False
+ elif c == escape:
+ blind = True
+ elif c == quote:
+ instring = False
+ stack.pop()
+ continue
+ if c in open:
+ stack.append(c)
+ elif c in close:
+ pos = close.index(c)
+ if ((len(stack) > 0) and
+ (open[pos] == stack[len(stack)-1])):
+ stack.pop()
+ else:
+ return False
+ elif c == escape:
+ return False
+ elif c == quote:
+ instring = True
+ stack.append(c)
+ return len(stack) == 0
+
+
+class TestBracePattern(unittest.TestCase):
+ tests = [
+ (r'{[]{()}}', True),
+ (r'[{}{})(]', False),
+ (r'[{}{} ")(" ]', True),
+ (r'[{}{} ")(\" ]', False),
+ (r'[{}{} ")(\" ]"]', True),
+ (r'a < b ( c [ d { "} \"\"}" } ] ) >', True),
+ (r'a < b ( c [ d { } ] ) >', True),
+ (r'a < b ( c [ d { "huh" } ] ) >', True),
+ (r'a < b ( c [ d { "huh\" \" \\\"" } ] ) >', True),
+ ]
+
+ def test_checkfunc(self):
+ for test, result in self.tests:
+ if result:
+ self.assertTrue(check(test))
+ else:
+ self.assertFalse(check(test))
+
+ def test_the_brace_pattern(self):
+ func = re.compile(build_brace_pattern(5) + "$", re.VERBOSE).match
+ for test, result in self.tests:
+ if result:
+ self.assertTrue(func(test))
+ else:
+ self.assertFalse(func(test))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/objecttype_test.py b/sources/shiboken2/tests/samplebinding/objecttype_test.py
index bda14c69c..f1a06c2b1 100644
--- a/sources/shiboken2/tests/samplebinding/objecttype_test.py
+++ b/sources/shiboken2/tests/samplebinding/objecttype_test.py
@@ -118,5 +118,13 @@ class ObjectTypeTest(unittest.TestCase):
self.assertLess(abs(before - after), 5)
+ def testInvalidProperty(self):
+ o = ObjectType()
+ try:
+ o.typo
+ self.assertFail()
+ except AttributeError as error:
+ self.assertEqual(error.args[0], "'sample.ObjectType' object has no attribute 'typo'")
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
index e07856e61..e1883c7cc 100644
--- a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
+++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py
@@ -175,5 +175,17 @@ class SmartPointerTests(unittest.TestCase):
self.assertEqual(len(ptrToObjList), 0)
self.assertEqual(objCount(), 1)
+ def testInvalidParameter(self):
+ # Create Obj.
+ o = Obj()
+ # Create a shared pointer to an Obj together with an Obj.
+ ptrToObj = o.giveSharedPtrToObj()
+ try:
+ ptrToObj.typo
+ self.assertFail()
+ except AttributeError as error:
+ self.assertEqual(error.args[0], "'smart.SharedPtr_Obj' object has no attribute 'typo'")
+
+
if __name__ == '__main__':
unittest.main()