aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-03-06 07:58:51 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-03-06 12:43:06 +0100
commitdf7c72e63c6b7aecee156db2eff726bcfb89977e (patch)
treeb9cecf87e2cd75d11813cd06ef1f2a5ab28384de /sources/pyside2
parente621f81115cec5089f30755e09b9a59ece39660c (diff)
parentf3139399b273fdf405f20cba32a08262cd933d6e (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Diffstat (limited to 'sources/pyside2')
-rw-r--r--sources/pyside2/CMakeLists.txt85
-rw-r--r--sources/pyside2/PySide2/CMakeLists.txt5
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml3
-rw-r--r--sources/pyside2/PySide2/__init__.py.in7
-rw-r--r--sources/pyside2/PySide2/_config.py.in11
-rw-r--r--sources/pyside2/PySide2/typesystem_templates.xml6
-rw-r--r--sources/pyside2/doc/inheritance_diagram.py87
-rw-r--r--sources/pyside2/doc/pysideversion.rst18
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp59
-rw-r--r--sources/pyside2/pyside_version.py49
-rw-r--r--sources/pyside2/tests/QtWidgets/qvalidator_test.py27
-rw-r--r--sources/pyside2/tests/pysidetest/version_test.py6
-rw-r--r--sources/pyside2/tests/signals/signal_signature_test.py40
13 files changed, 310 insertions, 93 deletions
diff --git a/sources/pyside2/CMakeLists.txt b/sources/pyside2/CMakeLists.txt
index b16bcb55e..4db611f0d 100644
--- a/sources/pyside2/CMakeLists.txt
+++ b/sources/pyside2/CMakeLists.txt
@@ -21,6 +21,27 @@ else()
find_package(PythonLibs 2.6)
endif()
+set(PYSIDE_VERSION_FILE_PATH "${CMAKE_SOURCE_DIR}/pyside_version.py")
+set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
+ ${PYSIDE_VERSION_FILE_PATH}
+)
+execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} "${PYSIDE_VERSION_FILE_PATH}"
+ OUTPUT_VARIABLE PYSIDE_VERSION_OUTPUT
+ ERROR_VARIABLE PYSIDE_VERSION_OUTPUT_ERROR
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+if (NOT PYSIDE_VERSION_OUTPUT)
+ message(FATAL_ERROR "Could not identify PySide2 version. Error: ${PYSIDE_VERSION_OUTPUT_ERROR}")
+endif()
+
+list(GET PYSIDE_VERSION_OUTPUT 0 BINDING_API_MAJOR_VERSION)
+list(GET PYSIDE_VERSION_OUTPUT 1 BINDING_API_MINOR_VERSION)
+list(GET PYSIDE_VERSION_OUTPUT 2 BINDING_API_MICRO_VERSION)
+# a - alpha, b - beta, rc - rc
+list(GET PYSIDE_VERSION_OUTPUT 3 BINDING_API_PRE_RELEASE_VERSION_TYPE)
+# the number of the pre release (alpha1, beta3, rc7, etc.)
+list(GET PYSIDE_VERSION_OUTPUT 4 BINDING_API_PRE_RELEASE_VERSION)
+
macro(get_python_extension_suffix)
# Result of imp.get_suffixes() depends on the platform, but generally looks something like:
# [('.cpython-34m-x86_64-linux-gnu.so', 'rb', 3), ('.cpython-34m.so', 'rb', 3),
@@ -161,19 +182,15 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
set(BINDING_NAME PySide2)
-set(BINDING_API_MAJOR_VERSION "2")
-set(BINDING_API_MINOR_VERSION "0")
-set(BINDING_API_MICRO_VERSION "0")
-set(BINDING_API_RELEASE_LEVEL "alpha") # alpha, beta, rc, or final
-set(BINDING_API_SERIAL 0) # leave as 0 when release level is final
-set(BINDING_API_VERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}" CACHE STRING "PySide version" FORCE)
+
+set(BINDING_API_VERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}" CACHE STRING "PySide2 version" FORCE)
set(PYSIDE_SO_VERSION ${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION})
-if (BINDING_API_RELEASE_LEVEL STREQUAL "final")
+if (BINDING_API_PRE_RELEASE_VERSION_TYPE STREQUAL "")
set(BINDING_API_VERSION_FULL "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}"
- CACHE STRING "PySide version [full]" FORCE)
+ CACHE STRING "PySide2 version [full]" FORCE)
else()
- set(BINDING_API_VERSION_FULL "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}~${BINDING_API_RELEASE_LEVEL}${BINDING_API_SERIAL}"
- CACHE STRING "PySide version [full]" FORCE)
+ set(BINDING_API_VERSION_FULL "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}~${BINDING_API_PRE_RELEASE_VERSION_TYPE}${BINDING_API_PRE_RELEASE_VERSION}"
+ CACHE STRING "PySide2 version [full]" FORCE)
endif()
string(TIMESTAMP PYSIDE_BUILD_DATE "%Y-%m-%dT%H:%M:%S+00:00" UTC)
@@ -181,6 +198,19 @@ if (PYSIDE_BUILD_DATE)
set(PYSIDE_BUILD_DATE "__build_date__ = '${PYSIDE_BUILD_DATE}'")
endif()
+if (PYSIDE_SETUP_PY_PACKAGE_VERSION)
+ set(PYSIDE_SETUP_PY_PACKAGE_VERSION_ASSIGNMENT "__setup_py_package_version__ = '${PYSIDE_SETUP_PY_PACKAGE_VERSION}'")
+ set(FINAL_PACKAGE_VERSION ${PYSIDE_SETUP_PY_PACKAGE_VERSION})
+else()
+ set(FINAL_PACKAGE_VERSION ${BINDING_API_VERSION_FULL})
+endif()
+
+if (PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP)
+ set(PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT "__setup_py_package_timestamp__ = '${PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP}'")
+else()
+ set(PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT "__setup_py_package_timestamp__ = ''")
+endif()
+
find_package(Git)
if(GIT_FOUND)
# Check if current source folder is inside a git repo, so that commit information can be
@@ -222,11 +252,6 @@ if(GIT_FOUND)
endif()
endif()
-# Used by setup.py to know which symlink to resolve and copy in to the final package, in order to
-# avoid resolving all symlinks and thus copying unnecessary duplicate files.
-set(config_py_shiboken_library_version "")
-set(config_py_pyside_library_version "")
-
include(PySideModules)
macro(COLLECT_MODULE_IF_FOUND shortname)
@@ -316,7 +341,7 @@ if(WIN32)
list(APPEND ALL_OPTIONAL_MODULES AxContainer)
endif()
list(APPEND ALL_OPTIONAL_MODULES WebChannel WebEngineWidgets WebKit WebKitWidgets WebSockets)
-if (Qt5Core_VERSION VERSION_GREATER 5.9.3 AND Qt5Core_VERSION VERSION_LESS 5.10.0) # Depending on fixes in Qt3D
+if (Qt5Core_VERSION VERSION_GREATER 5.9.3) # Depending on fixes in Qt3D
list(APPEND ALL_OPTIONAL_MODULES 3DCore 3DRender 3DInput 3DLogic 3DAnimation 3DExtras)
endif()
@@ -372,8 +397,6 @@ endif()
# Define supported Qt Version
set(SUPPORTED_QT_VERSION "${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}")
-set(BINDING_VERSION ${BINDING_API_VERSION}.${QT_VERSION_MAJOR}.${QT_VERSION_MINOR})
-
# uninstall target
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
@@ -382,16 +405,6 @@ add_custom_target(uninstall "${CMAKE_COMMAND}"
-P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
-set(ARCHIVE_NAME pyside-qt${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}+${BINDING_API_VERSION_FULL})
-add_custom_target(dist
- COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" &&
- git log > "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}/ChangeLog" &&
- git archive --prefix=${ARCHIVE_NAME}/ HEAD --format=tar --output="${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" &&
- tar -C "${CMAKE_BINARY_DIR}" --owner=root --group=root -r "${ARCHIVE_NAME}/ChangeLog" -f "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" &&
- bzip2 -f9 "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" &&
- echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2.\n"
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
-
if (NOT PYTHON_SITE_PACKAGES)
execute_process(
COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} -c "if True:
@@ -424,6 +437,22 @@ else()
message(STATUS "PySide will be generated using the protected hack!")
endif()
+# Build with Address sanitizer enabled if requested. This may break things, so use at your own risk.
+if (SANITIZE_ADDRESS AND NOT MSVC)
+ # Currently this does not check that the clang / gcc version used supports Address sanitizer,
+ # so once again, use at your own risk.
+ add_compile_options("-fsanitize=address" "-g" "-fno-omit-frame-pointer")
+ # We need to add the sanitize address option to all linked executables / shared libraries
+ # so that proper sanitizer symbols are linked in.
+ #
+ # Note that when running tests, you may need to set an additional environment variable
+ # in set_tests_properties for shiboken2 / pyside tests, or exported in your shell. Address
+ # sanitizer will tell you what environment variable needs to be exported. For example:
+ # export DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/Toolchains/
+ # ./XcodeDefault.xctoolchain/usr/lib/clang/8.1.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib
+ set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_STANDARD_LIBRARIES} -fsanitize=address")
+endif()
+
add_subdirectory(libpyside)
find_package(Qt5Designer)
if(Qt5UiTools_FOUND AND Qt5Designer_FOUND)
diff --git a/sources/pyside2/PySide2/CMakeLists.txt b/sources/pyside2/PySide2/CMakeLists.txt
index 21db337e9..971d0a9ef 100644
--- a/sources/pyside2/PySide2/CMakeLists.txt
+++ b/sources/pyside2/PySide2/CMakeLists.txt
@@ -10,6 +10,9 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in"
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/_config.py.in"
"${CMAKE_CURRENT_BINARY_DIR}/_config.py" @ONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../pyside_version.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/_git_pyside_version.py" @ONLY)
+
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/__init__.py"
"${CMAKE_CURRENT_BINARY_DIR}/support/__init__.py" COPYONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/__init__.py"
@@ -69,6 +72,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/__init__.py"
DESTINATION "${PYTHON_SITE_PACKAGES}/${BINDING_NAME}${pyside2_SUFFIX}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_config.py"
DESTINATION "${PYTHON_SITE_PACKAGES}/${BINDING_NAME}${pyside2_SUFFIX}")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_git_pyside_version.py"
+ DESTINATION "${PYTHON_SITE_PACKAGES}/${BINDING_NAME}${pyside2_SUFFIX}")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_templates.xml
DESTINATION share/PySide2${pyside_SUFFIX}/typesystems)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyside2_global.h
diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
index 12b0f3115..0f6d48968 100644
--- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
+++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
@@ -1731,6 +1731,9 @@
<modify-argument index="return">
<replace-type modified-type="QString"/>
</modify-argument>
+ <inject-code class="native" position="end">
+ <insert-template name="return_QString_native"/>
+ </inject-code>
<inject-code class="target" position="end">
<insert-template name="return_QString"/>
</inject-code>
diff --git a/sources/pyside2/PySide2/__init__.py.in b/sources/pyside2/PySide2/__init__.py.in
index 92e52a81a..4ce266b69 100644
--- a/sources/pyside2/PySide2/__init__.py.in
+++ b/sources/pyside2/PySide2/__init__.py.in
@@ -1,14 +1,17 @@
__all__ = list("Qt" + body for body in
"@all_module_shortnames@"
.split(";"))
-__version__ = "@BINDING_API_VERSION_FULL@"
-__version_info__ = (@BINDING_API_MAJOR_VERSION@, @BINDING_API_MINOR_VERSION@, @BINDING_API_MICRO_VERSION@, "@BINDING_API_RELEASE_LEVEL@", @BINDING_API_SERIAL@)
+__version__ = "@FINAL_PACKAGE_VERSION@"
+__version_info__ = (@BINDING_API_MAJOR_VERSION@, @BINDING_API_MINOR_VERSION@, @BINDING_API_MICRO_VERSION@, "@BINDING_API_PRE_RELEASE_VERSION_TYPE@", @BINDING_API_PRE_RELEASE_VERSION@)
@PYSIDE_BUILD_DATE@
@PYSIDE_BUILD_COMMIT_DATE@
@PYSIDE_BUILD_COMMIT_HASH@
@PYSIDE_BUILD_COMMIT_HASH_DESCRIBED@
+# Timestamp used for snapshot build, which is part of snapshot package version.
+@PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT@
+
def _setupQtDirectories():
import sys
import os
diff --git a/sources/pyside2/PySide2/_config.py.in b/sources/pyside2/PySide2/_config.py.in
index db8a17210..6f8d022dc 100644
--- a/sources/pyside2/PySide2/_config.py.in
+++ b/sources/pyside2/PySide2/_config.py.in
@@ -4,3 +4,14 @@ built_modules = list(name for name in
shiboken_library_soversion = str(@SHIBOKEN_SO_VERSION@)
pyside_library_soversion = str(@PYSIDE_SO_VERSION@)
+
+version = "@FINAL_PACKAGE_VERSION@"
+version_info = (@BINDING_API_MAJOR_VERSION@, @BINDING_API_MINOR_VERSION@, @BINDING_API_MICRO_VERSION@, "@BINDING_API_PRE_RELEASE_VERSION_TYPE@", @BINDING_API_PRE_RELEASE_VERSION@)
+
+@PYSIDE_BUILD_DATE@
+@PYSIDE_BUILD_COMMIT_DATE@
+@PYSIDE_BUILD_COMMIT_HASH@
+@PYSIDE_BUILD_COMMIT_HASH_DESCRIBED@
+
+# Timestamp used for snapshot build, which is part of snapshot package version.
+@PYSIDE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT@
diff --git a/sources/pyside2/PySide2/typesystem_templates.xml b/sources/pyside2/PySide2/typesystem_templates.xml
index 1715c0253..11a384263 100644
--- a/sources/pyside2/PySide2/typesystem_templates.xml
+++ b/sources/pyside2/PySide2/typesystem_templates.xml
@@ -286,6 +286,12 @@
<template name="return_QString">
%PYARG_0 = %CONVERTTOPYTHON[QString](%1);
</template>
+ <template name="return_QString_native">
+ if (%ISCONVERTIBLE[QString](%PYARG_0))
+ %1 = %CONVERTTOCPP[QString](%PYARG_0);
+ else
+ qWarning("%TYPE::%FUNCTION_NAME: Argument is not convertible to unicode.");
+ </template>
<template name="return_tuple_QValidator_QString_int">
%BEGIN_ALLOW_THREADS
diff --git a/sources/pyside2/doc/inheritance_diagram.py b/sources/pyside2/doc/inheritance_diagram.py
index a7f376ccd..038c22f29 100644
--- a/sources/pyside2/doc/inheritance_diagram.py
+++ b/sources/pyside2/doc/inheritance_diagram.py
@@ -52,15 +52,38 @@ from docutils.parsers.rst import directives
from sphinx.ext.graphviz import render_dot_html, render_dot_latex
from sphinx.util.compat import Directive
-
-class_sig_re = re.compile(r'''^([\w.]*\.)? # module names
- (\w+) \s* $ # class/final module name
- ''', re.VERBOSE)
-
-
class InheritanceException(Exception):
pass
+# When passed something like:
+# PySide2.QtCore.QStateMachine.SignalEvent
+# try to import the underlying module and return a
+# handle to the object. In a loop, import
+# PySide2.QtCore.QStateMachine.SignalEvent
+# PySide2.QtCore.QStateMachine
+# PySide2.QtCore
+# until the import succeeds and walk up the attributes
+# to obtain the object
+
+def importClassOrModule(name):
+ components = name.split('.')
+ for i in range(len(components), 0, -1):
+ importPath = '.'.join(components[: i])
+ try:
+ __import__(importPath)
+ except ImportError:
+ continue
+ if i == len(components):
+ return sys.modules[importPath]
+ remaining = components[i :]
+ cls = sys.modules[importPath]
+ for component in remaining:
+ try:
+ cls = getattr(cls, component)
+ except Exception: # No such attribute
+ return None
+ return cls
+ return None
class InheritanceGraph(object):
"""
@@ -86,38 +109,13 @@ class InheritanceGraph(object):
"""
Import a class using its fully-qualified *name*.
"""
- try:
- path, base = class_sig_re.match(name).groups()
- except (AttributeError, ValueError):
- raise InheritanceException('Invalid class or module %r specified '
- 'for inheritance diagram' % name)
-
- fullname = (path or '') + base
- path = (path and path.rstrip('.') or '')
-
- # two possibilities: either it is a module, then import it
- try:
- __import__(fullname)
- todoc = sys.modules[fullname]
- except ImportError:
- # else it is a class, then import the module
- if not path:
- if currmodule:
- # try the current module
- path = currmodule
- else:
- raise InheritanceException(
- 'Could not import class %r specified for '
- 'inheritance diagram' % base)
- try:
- __import__(path)
- todoc = getattr(sys.modules[path], base)
- except (ImportError, AttributeError):
- raise InheritanceException(
- 'Could not import class or module %r specified for '
- 'inheritance diagram' % (path + '.' + base))
-
- # If a class, just return it
+ todoc = importClassOrModule(name)
+ if not todoc and currmodule is not None:
+ todoc = importClassOrModule(currmodule + '.' + name)
+ if not todoc:
+ moduleStr = '(module {})'.format(currmodule) if currmodule else ''
+ raise InheritanceException('Could not import class {} specified for '
+ 'inheritance diagram {}.'.format(name, moduleStr))
if inspect.isclass(todoc):
return [todoc]
elif inspect.ismodule(todoc):
@@ -167,7 +165,7 @@ class InheritanceGraph(object):
for cls in classes:
recurse(cls)
- return all_classes.values()
+ return list(all_classes.values())
def class_name(self, cls, parts=0):
"""Given a class object, return a fully-qualified name.
@@ -200,8 +198,8 @@ class InheritanceGraph(object):
'shape': 'box',
'fontsize': 10,
'height': 0.25,
- 'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, '
- 'Arial, Helvetica, sans',
+ 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, '
+ 'Arial, Helvetica, sans"',
'style': '"setlinewidth(0.5)"',
}
default_edge_attrs = {
@@ -314,7 +312,8 @@ class InheritanceDiagram(Directive):
def get_graph_hash(node):
- return md5(node['content'] + str(node['parts'])).hexdigest()[-10:]
+ hashString = node['content'] + str(node['parts'])
+ return md5(hashString.encode('utf-8')).hexdigest()[-10:]
def html_visit_inheritance_diagram(self, node):
@@ -336,7 +335,7 @@ def html_visit_inheritance_diagram(self, node):
urls[child['reftitle']] = '#' + child.get('refid')
dotcode = graph.generate_dot(name, urls, env=self.builder.env)
- render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance',
+ render_dot_html(self, node, dotcode, {}, 'inheritance', 'inheritance',
alt='Inheritance diagram of ' + node['content'])
raise nodes.SkipNode
@@ -352,7 +351,7 @@ def latex_visit_inheritance_diagram(self, node):
dotcode = graph.generate_dot(name, env=self.builder.env,
graph_attrs={'size': '"6.0,6.0"'})
- render_dot_latex(self, node, dotcode, [], 'inheritance')
+ render_dot_latex(self, node, dotcode, {}, 'inheritance')
raise nodes.SkipNode
diff --git a/sources/pyside2/doc/pysideversion.rst b/sources/pyside2/doc/pysideversion.rst
index 3bcebe0da..5ad308c1e 100644
--- a/sources/pyside2/doc/pysideversion.rst
+++ b/sources/pyside2/doc/pysideversion.rst
@@ -1,31 +1,31 @@
Getting PySide and Qt version
*****************************
-PySide exports their version numbers among the version of Qt used to compile PySide in a pythonnic way, you can check it using the variables:
+PySide exports their version numbers among the version of Qt used to compile PySide in a pythonic way, you can check it using the variables:
::
- import PySide
+ import PySide2.QtCore
# Prints PySide version
# e.g. 1.0.2
- print PySide.__version__
+ print(PySide2.__version__)
# Gets a tuple with each version component
# e.g. (1, 0, 2, 'final', 1)
- print PySide.__version_info__
+ print(PySide2.__version_info__)
# Prints the Qt version used to compile PySide
- # e.g. "4.7.2"
- print PySide2.QtCore.__version__
+ # e.g. "5.11.0"
+ print(PySide2.QtCore.__version__)
# Gets a tuple with each version components of Qt used to compile PySide
- # e.g. (4, 7, 2)
- print PySide2.QtCore.__version_info__
+ # e.g. (5, 11, 0)
+ print(PySide2.QtCore.__version_info__)
Note that the Qt version used to compile PySide may differ from the version used to run PySide, to get the current running Qt version you can do:
::
- print PySide2.QtCore.qVersion()
+ print(PySide2.QtCore.qVersion())
diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp
index 04b1cf1f4..a901d10af 100644
--- a/sources/pyside2/libpyside/pysidesignal.cpp
+++ b/sources/pyside2/libpyside/pysidesignal.cpp
@@ -413,11 +413,64 @@ PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
sourceWalk = reinterpret_cast<PySideSignalInstance*>(sourceWalk->d->next);
}
} else {
- //try the first signature
+ // Check signature of the slot (method or function) to match signal
+ int slotArgs = -1;
+ bool useSelf = false;
+ bool isMethod = PyMethod_Check(slot);
+ bool isFunction = PyFunction_Check(slot);
+ bool matchedSlot = false;
+
+ QByteArray functionName;
+ PySideSignalInstance *it = source;
+
+ if (isMethod || isFunction) {
+ PyObject *function = isMethod ? PyMethod_GET_FUNCTION(slot) : slot;
+ PyCodeObject *objCode = reinterpret_cast<PyCodeObject *>(PyFunction_GET_CODE(function));
+ PyFunctionObject *function_obj = reinterpret_cast<PyFunctionObject *>(function);
+ functionName = Shiboken::String::toCString(function_obj->func_name);
+ useSelf = isMethod;
+ slotArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+ if (useSelf)
+ slotArgs -= 1;
+
+ // Get signature args
+ bool isShortCircuit = false;
+ int signatureArgs = 0;
+ QStringList argsSignature;
+
+ argsSignature = PySide::Signal::getArgsFromSignature(it->d->signature,
+ &isShortCircuit);
+ signatureArgs = argsSignature.length();
+
+ // Iterate the possible types of connection for this signal and compare
+ // it with slot arguments
+ if (signatureArgs != slotArgs) {
+ while (it->d->next != nullptr) {
+ it = it->d->next;
+ argsSignature = PySide::Signal::getArgsFromSignature(it->d->signature,
+ &isShortCircuit);
+ signatureArgs = argsSignature.length();
+ if (signatureArgs == slotArgs) {
+ matchedSlot = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // Adding references to pyArgs
PyList_Append(pyArgs, source->d->source);
- Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(source->d->signature));
- PyList_Append(pyArgs, signature);
+ if (matchedSlot) {
+ // If a slot matching the same number of arguments was found,
+ // include signature to the pyArgs
+ Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(it->d->signature));
+ PyList_Append(pyArgs, signature);
+ } else {
+ // Try the first by default if the slot was not found
+ Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(source->d->signature));
+ PyList_Append(pyArgs, signature);
+ }
PyList_Append(pyArgs, slot);
match = true;
}
diff --git a/sources/pyside2/pyside_version.py b/sources/pyside2/pyside_version.py
new file mode 100644
index 000000000..3a678cd14
--- /dev/null
+++ b/sources/pyside2/pyside_version.py
@@ -0,0 +1,49 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of PySide2.
+##
+## $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$
+##
+#############################################################################
+
+major_version = "5"
+minor_version = "11"
+patch_version = "0"
+pre_release_version_type = "a" # e.g. "a", "b", "rc".
+pre_release_version = "1" # e.g "1", "2", (which means "beta1", "beta2", if type is "b")
+
+if __name__ == '__main__':
+ # Used by CMake.
+ print('{0};{1};{2};{3};{4}'.format(major_version, minor_version, patch_version,
+ pre_release_version_type, pre_release_version))
diff --git a/sources/pyside2/tests/QtWidgets/qvalidator_test.py b/sources/pyside2/tests/QtWidgets/qvalidator_test.py
index 951d6b2b0..dd5eaadb3 100644
--- a/sources/pyside2/tests/QtWidgets/qvalidator_test.py
+++ b/sources/pyside2/tests/QtWidgets/qvalidator_test.py
@@ -29,38 +29,49 @@
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
+from PySide2.QtTest import *
import unittest
from helper import UsesQApplication
class MyValidator1(QValidator):
- def fixUp(self, input):
+ def fixup(self, input):
return "fixed"
def validate(self, input, pos):
return (QValidator.Acceptable, "fixed", 1)
class MyValidator2(QValidator):
- def fixUp(self, input):
+ def fixup(self, input):
return "fixed"
def validate(self, input, pos):
return (QValidator.Acceptable, "fixed")
class MyValidator3(QValidator):
- def fixUp(self, input):
+ def fixup(self, input):
return "fixed"
def validate(self, input, pos):
return (QValidator.Acceptable,)
class MyValidator4(QValidator):
- def fixUp(self, input):
+ def fixup(self, input):
return "fixed"
def validate(self, input, pos):
return QValidator.Acceptable
+class MyValidator5(QValidator):
+ def validate(self, input, pos):
+ if input.islower():
+ return (QValidator.Intermediate, input, pos)
+ else:
+ return (QValidator.Acceptable, input, pos)
+
+ def fixup(self, input):
+ return "22"
+
class QValidatorTest(UsesQApplication):
def testValidator1(self):
line = QLineEdit()
@@ -110,5 +121,13 @@ class QValidatorTest(UsesQApplication):
self.assertEqual(line.text(), "foo")
self.assertEqual(line.cursorPosition(), 3)
+ def testValidator5(self):
+ line = QLineEdit()
+ line.show()
+ line.setValidator(MyValidator5())
+ line.setText("foo")
+ QTest.keyClick(line, Qt.Key_Return)
+ self.assertEqual(line.text(), "22")
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside2/tests/pysidetest/version_test.py b/sources/pyside2/tests/pysidetest/version_test.py
index 5901a56c1..01e88dbc6 100644
--- a/sources/pyside2/tests/pysidetest/version_test.py
+++ b/sources/pyside2/tests/pysidetest/version_test.py
@@ -33,8 +33,10 @@ from PySide2 import __version_info__, __version__, QtCore
class CheckForVariablesTest(unittest.TestCase):
def testVesions(self):
- self.assertTrue(__version_info__ >= (1, 0, 0))
- self.assertTrue(__version_info__ < (99, 99, 99))
+ version_tuple = (__version_info__[0], __version_info__[1], __version_info__[2])
+ self.assertTrue(version_tuple >= (1, 0, 0))
+
+ self.assertTrue(version_tuple < (99, 99, 99))
self.assertTrue(__version__)
self.assertTrue(QtCore.__version_info__ >= (4, 5, 0))
diff --git a/sources/pyside2/tests/signals/signal_signature_test.py b/sources/pyside2/tests/signals/signal_signature_test.py
index 349619aac..e94c1722d 100644
--- a/sources/pyside2/tests/signals/signal_signature_test.py
+++ b/sources/pyside2/tests/signals/signal_signature_test.py
@@ -34,7 +34,11 @@ import unittest
from PySide2.QtCore import *
from helper import UsesQCoreApplication
+called = False
+name = "Old"
class Obj(QObject):
+ dummySignalArgs = Signal(str)
+ numberSignal = Signal(int)
def __init__(self):
QObject.__init__(self)
self.signal = ''
@@ -42,8 +46,20 @@ class Obj(QObject):
def connectNotify(self, signal):
self.signal = signal
+ @staticmethod
+ def static_method():
+ global called
+ called = True
+
+ @staticmethod
+ def static_method_args(arg="default"):
+ global name
+ name = arg
+
def callback(arg=None):
pass
+def callback_empty():
+ pass
class TestConnectNotifyWithNewStyleSignals(UsesQCoreApplication):
'''Test case for signal signature received by QObject::connectNotify().'''
@@ -65,12 +81,34 @@ class TestConnectNotifyWithNewStyleSignals(UsesQCoreApplication):
def testNewStyle(self):
sender = Obj()
- sender.destroyed.connect(callback)
+ sender.destroyed.connect(callback_empty)
self.assertEqual(sender.signal.methodSignature(), 'destroyed()')
sender.destroyed[QObject].connect(callback)
self.assertEqual(sender.signal.methodSignature(), 'destroyed(QObject*)')
+ def testStaticSlot(self):
+ global called
+ sender = Obj()
+ sender.connect(sender, SIGNAL("dummySignal()"), Obj.static_method)
+ sender.emit(SIGNAL("dummySignal()"))
+ self.assertTrue(called)
+
+
+ def testStaticSlotArgs(self):
+ global name
+ sender = Obj()
+ sender.dummySignalArgs.connect(Obj.static_method_args)
+ sender.dummySignalArgs[str].emit("New")
+ self.assertEqual(name, "New")
+
+ def testLambdaSlot(self):
+ sender = Obj()
+ sender.numberSignal[int].connect(lambda x: 42)
+ with self.assertRaises(IndexError):
+ sender.numberSignal[str].emit("test")
+
+
if __name__ == '__main__':
unittest.main()