diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ef1190..6563441 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,27 @@ -cmake_minimum_required(VERSION 2.8.3) +cmake_minimum_required(VERSION 3.5) project(python_qt_binding) -find_package(catkin REQUIRED) -catkin_package(CFG_EXTRAS python_qt_binding-extras.cmake) +find_package(ament_cmake REQUIRED) +find_package(ament_cmake_python REQUIRED) -catkin_python_setup() +ament_python_install_package(${PROJECT_NAME} + PACKAGE_DIR src/${PROJECT_NAME}) install(FILES cmake/shiboken_helper.cmake cmake/sip_configure.py cmake/sip_helper.cmake - DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/cmake) + DESTINATION share/${PROJECT_NAME}/cmake) + +if(BUILD_TESTING) + find_package(ament_cmake_pytest REQUIRED) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() + + ament_add_pytest_test(python_qt_binding test + APPEND_ENV PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR} + TIMEOUT 90 +) +endif() + +ament_package() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5fb68cc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +Any contribution that you make to this repository will +be under the BSD license. +[license](https://opensource.org/licenses/BSD-3-Clause): diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..713c7ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/python_qt_binding-extras.cmake.em b/cmake/python_qt_binding-extras.cmake.em deleted file mode 100644 index a11da30..0000000 --- a/cmake/python_qt_binding-extras.cmake.em +++ /dev/null @@ -1,7 +0,0 @@ -@[if DEVELSPACE]@ -# location of cmake files in develspace -set(python_qt_binding_EXTRAS_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/cmake") -@[else]@ -# location of cmake files in installspace -set(python_qt_binding_EXTRAS_DIR "${python_qt_binding_DIR}") -@[end if]@ diff --git a/cmake/sip_configure.py b/cmake/sip_configure.py index ed7aa7c..1d8d8e6 100644 --- a/cmake/sip_configure.py +++ b/cmake/sip_configure.py @@ -5,8 +5,8 @@ import subprocess import sys -import sipconfig from PyQt5 import QtCore +import sipconfig class Configuration(sipconfig.Configuration): @@ -73,6 +73,7 @@ def __init__(self): # Run SIP to generate the code. Note that we tell SIP where to find the qt # module's specification files using the -I flag. + cmd = [ config.sip_bin, '-c', build_dir, diff --git a/cmake/sip_helper.cmake b/cmake/sip_helper.cmake index ce76008..d73cf29 100644 --- a/cmake/sip_helper.cmake +++ b/cmake/sip_helper.cmake @@ -7,7 +7,6 @@ set(__PYTHON_QT_BINDING_SIP_HELPER_DIR ${CMAKE_CURRENT_LIST_DIR}) set(Python_ADDITIONAL_VERSIONS "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") find_package(PythonInterp "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" REQUIRED) -assert(PYTHON_EXECUTABLE) find_package(PythonLibs "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" REQUIRED) find_program(SIP_EXECUTABLE sip) @@ -99,11 +98,11 @@ if(${CMAKE_VERSION} VERSION_LESS 2.8.3) # first set all result variables to empty/FALSE foreach(arg_name ${_singleArgNames} ${_multiArgNames}) set(${prefix}_${arg_name}) - endforeach(arg_name) + endforeach() foreach(option ${_optionNames}) set(${prefix}_${option} FALSE) - endforeach(option) + endforeach() set(${prefix}_UNPARSED_ARGUMENTS) @@ -124,9 +123,9 @@ if(${CMAKE_VERSION} VERSION_LESS 2.8.3) elseif("${insideValues}" STREQUAL "MULTI") list(APPEND ${prefix}_${currentArgName} ${currentArg}) endif() - else(insideValues) + else() list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) - endif(insideValues) + endif() else() if(NOT ${optionIndex} EQUAL -1) set(${prefix}_${currentArg} TRUE) @@ -142,15 +141,15 @@ if(${CMAKE_VERSION} VERSION_LESS 2.8.3) endif() endif() - endforeach(currentArg) + endforeach() # propagate the result variables to the caller: foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) - endforeach(arg_name) + endforeach() set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) - endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs) + endfunction() endif() # diff --git a/package.xml b/package.xml index 09b8929..09fcdc5 100644 --- a/package.xml +++ b/package.xml @@ -1,10 +1,10 @@ - + python_qt_binding 0.3.4 This stack provides Python bindings for Qt. - There are two providers: pyside and pyqt. PySide is released under - the LGPL. PyQt is released under the GPL. + There are two providers: pyside and pyqt. PySide2 is available under + the GPL, LGPL and a commercial license. PyQt is released under the GPL. Both the bindings and tools to build bindings are included from each available provider. For PySide, it is called "Shiboken". For PyQt, @@ -21,16 +21,22 @@ Dave Hershberger Dorian Scholz Dirk Thomas + Stephen Brawner - catkin + ament_cmake - rosbuild qtbase5-dev - python-qt5-bindings + python3-qt5-bindings - python-qt5-bindings + python3-qt5-bindings + ament_cmake_pytest + ament_lint_auto + ament_flake8 + ament_pep257 + python3-pytest + - + ament_cmake diff --git a/src/python_qt_binding/QtBindingHelper.py b/src/python_qt_binding/QtBindingHelper.py deleted file mode 100644 index 4145d81..0000000 --- a/src/python_qt_binding/QtBindingHelper.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of the TU Darmstadt nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -from __future__ import print_function - -print( - 'Deprecation warning: the "python_qt_binding.QtBindingHelper" module is deprecated and will be removed in the near future.') -print('Replace your usage of QtBindingHelper with import statements like:') -print(' from python_qt_binding.QtCore import QObject') -print(' from python_qt_binding import QtGui, loadUi') diff --git a/src/python_qt_binding/__init__.py b/src/python_qt_binding/__init__.py index 536a3f9..1e209de 100644 --- a/src/python_qt_binding/__init__.py +++ b/src/python_qt_binding/__init__.py @@ -52,9 +52,13 @@ """ import sys -from .binding_helper import loadUi, QT_BINDING, QT_BINDING_MODULES, QT_BINDING_VERSION # @UnusedImport -# register all binding modules as sub modules of this package (python_qt_binding) for easy importing +from python_qt_binding.binding_helper import loadUi # noqa: F401 +from python_qt_binding.binding_helper import QT_BINDING # noqa: F401 +from python_qt_binding.binding_helper import QT_BINDING_MODULES +from python_qt_binding.binding_helper import QT_BINDING_VERSION # noqa: F401 + +# register binding modules as sub modules of this package (python_qt_binding) for easy importing for module_name, module in QT_BINDING_MODULES.items(): sys.modules[__name__ + '.' + module_name] = module setattr(sys.modules[__name__], module_name, module) diff --git a/src/python_qt_binding/binding_helper.py b/src/python_qt_binding/binding_helper.py index e84cf2f..53b65f8 100644 --- a/src/python_qt_binding/binding_helper.py +++ b/src/python_qt_binding/binding_helper.py @@ -236,7 +236,8 @@ def createWidget(self, class_name, parent=None, name=''): loader = CustomUiLoader(baseinstance, custom_widgets) - # instead of passing the custom widgets, they should be registered using QUiLoader.registerCustomWidget(), + # instead of passing the custom widgets, they should be registered using + # QUiLoader.registerCustomWidget(), # but this does not work in PySide 1.0.6: it simply segfaults... # loader = CustomUiLoader(baseinstance) # custom_widgets = custom_widgets or {} @@ -253,6 +254,8 @@ def createWidget(self, class_name, parent=None, name=''): def loadUi(uifile, baseinstance=None, custom_widgets=None): """ + Load a provided UI file chosen Python Qt 5 binding. + @type uifile: str @param uifile: Absolute path of .ui file @type baseinstance: QWidget diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_flake8.py b/test/test_flake8.py new file mode 100644 index 0000000..eff8299 --- /dev/null +++ b/test/test_flake8.py @@ -0,0 +1,23 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc = main(argv=[]) + assert rc == 0, 'Found errors' diff --git a/test/test_imports.py b/test/test_imports.py new file mode 100644 index 0000000..92ba3ca --- /dev/null +++ b/test/test_imports.py @@ -0,0 +1,33 @@ +# Copyright 2018, PickNik Consulting +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def test_import_qtcore(): + from python_qt_binding import QtCore + assert QtCore is not None + + +def test_import_qtgui(): + from python_qt_binding import QtGui + assert QtGui is not None + + +def test_import_qtwidgets(): + from python_qt_binding import QtWidgets + assert QtWidgets is not None + + +def test_import_qtobject(): + from python_qt_binding.QtCore import QObject + assert QObject is not None diff --git a/test/test_pep257.py b/test/test_pep257.py new file mode 100644 index 0000000..b234a38 --- /dev/null +++ b/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings'