From 78a7f442162d3f0a3c6ce8f2016ee48baa9fdb7b Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Fri, 6 Aug 2021 13:06:07 +0200 Subject: [PATCH 01/10] Added Conan support - Added a conanfile.py for dependency manager Conan - Updated gitignore for cmake-build-* - Use find_package Python3 since we're now using CMake 3.13 - Allow setting Python_VERSION to specify an exact Python version (3.8 default) --- .gitignore | 2 + CMakeLists.txt | 20 +++++--- CPackConfig.cmake | 4 +- cmake/UraniumPluginInstall.cmake | 18 +++----- cmake/UraniumTests.cmake | 4 +- conanfile.py | 79 ++++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 conanfile.py diff --git a/.gitignore b/.gitignore index 4577e1cb59..eb7f1cb783 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ resources/.DS_Store #Common plug-ins plugins/UraniumExample*Plugin +/cmake-build-debug/ +/cmake-build-release/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e64f48cfb..18575a46b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ project(uranium NONE) -cmake_minimum_required(VERSION 3.6) +cmake_minimum_required(VERSION 3.13) message(STATUS ${CMAKE_MODULE_PATH}) @@ -10,19 +10,25 @@ include(UraniumTranslationTools) include(GNUInstallDirs) -find_package(PythonInterp 3 REQUIRED) +if(NOT DEFINED Python_VERSION) + set(Python_VERSION + 3.8 + CACHE STRING "Python Version" FORCE) + message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") +endif() +find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS Interpreter) -message("Using python version ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") +message("Using Python version ${Python3_VERSION}") # # Checks using pylint # Note that we use exit 0 here to not mark the build as a failure on check failure # In addition, the specified pylint configuration uses the spellchecker plugin. This required python-enchant to be installed. add_custom_target(check) -add_custom_command(TARGET check POST_BUILD COMMAND "PYTHONPATH=${CMAKE_SOURCE_DIR}" ${PYTHON_EXECUTABLE} -m pylint --rcfile=${CMAKE_SOURCE_DIR}/pylint.cfg UM --msg-template=\"{path}:{line}: [{msg_id}({symbol}) , {obj}] {msg}\" > ${CMAKE_BINARY_DIR}/pylint.log || exit 0 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_custom_command(TARGET check POST_BUILD COMMAND "PYTHONPATH=${CMAKE_SOURCE_DIR}" ${Python3_EXECUTABLE} -m pylint --rcfile=${CMAKE_SOURCE_DIR}/pylint.cfg UM --msg-template=\"{path}:{line}: [{msg_id}({symbol}) , {obj}] {msg}\" > ${CMAKE_BINARY_DIR}/pylint.log || exit 0 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) # # Check using Mypy add_custom_target(typecheck) -add_custom_command(TARGET typecheck POST_BUILD COMMAND ${PYTHON_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_custom_command(TARGET typecheck POST_BUILD COMMAND ${Python3_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) # # Tests include(UraniumTests) @@ -49,9 +55,9 @@ CREATE_TRANSLATION_TARGETS() if(EXISTS /etc/debian_version) - install(DIRECTORY UM DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}/dist-packages) + install(DIRECTORY UM DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}/dist-packages) else() - install(DIRECTORY UM DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) + install(DIRECTORY UM DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages) endif() install(FILES ${CMAKE_SOURCE_DIR}/cmake/UraniumTranslationTools.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules/ ) diff --git a/CPackConfig.cmake b/CPackConfig.cmake index b104d646a3..874df96190 100644 --- a/CPackConfig.cmake +++ b/CPackConfig.cmake @@ -7,7 +7,7 @@ set(CPACK_PACKAGE_VERSION_PATCH 93) set(CPACK_GENERATOR "DEB;RPM") set(RPM_REQUIRES - "python3 >= 3.5.0" + "python3 >= ${Python3_VERSION}" "python3-qt5 >= 5.6.0" "qt5-qtquickcontrols >= 5.6.0" "arcus >= 15.05.90" @@ -16,7 +16,7 @@ string(REPLACE ";" "," RPM_REQUIRES "${RPM_REQUIRES}") set(CPACK_RPM_PACKAGE_REQUIRES ${RPM_REQUIRES}) set(DEB_DEPENDS - "python3 (>= 3.5.0)" + "python3 (>= ${Python3_VERSION})" "python3-pyqt5 (>= 5.6.0)" "python3-pyqt5.qtopengl (>= 5.6.0)" "python3-pyqt5.qtquick (>= 5.6.0)" diff --git a/cmake/UraniumPluginInstall.cmake b/cmake/UraniumPluginInstall.cmake index e170024ef7..8915286dba 100644 --- a/cmake/UraniumPluginInstall.cmake +++ b/cmake/UraniumPluginInstall.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # UraniumPluginInstall.cmake is released under the terms of the LGPLv3 or higher. # @@ -10,17 +10,13 @@ # # FIXME: Remove the code for CMake <3.12 once we have switched over completely. -# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3 -# module is copied from the CMake repository here so in CMake <3.12 we can still use it. -if(${CMAKE_VERSION} VERSION_LESS 3.12) - # Use FindPythonInterp and FindPythonLibs for CMake <3.12 - find_package(PythonInterp 3 REQUIRED) - - set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE}) -else() - # Use FindPython3 for CMake >=3.12 - find_package(Python3 REQUIRED COMPONENTS Interpreter) +if(NOT DEFINED Python_VERSION) + set(Python_VERSION + 3.8 + CACHE STRING "Python Version" FORCE) + message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") endif() +find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS Interpreter) # Options or configuration variables set(UM_NO_INSTALL_PLUGINS "" CACHE STRING "A list of plugins that should not be installed, separated with ';' or ','.") diff --git a/cmake/UraniumTests.cmake b/cmake/UraniumTests.cmake index 332b24c0f5..effde8dad3 100644 --- a/cmake/UraniumTests.cmake +++ b/cmake/UraniumTests.cmake @@ -32,7 +32,7 @@ function(uranium_add_test) add_test( NAME ${_NAME} - COMMAND ${PYTHON_EXECUTABLE} -m pytest --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY} + COMMAND ${Python3_EXECUTABLE} -m pytest --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY} ) set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT LANG=C) set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT "PYTHONPATH=${_PYTHONPATH}") @@ -52,5 +52,5 @@ endforeach() #Add code style test. add_test( NAME "code-style" - COMMAND ${PYTHON_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${Python3_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) \ No newline at end of file diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000000..ceeff9b652 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,79 @@ +import os +import pathlib + +from conans import ConanFile, tools +from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake + + +class UraniumConan(ConanFile): + name = "Uranium" + version = "4.10.0" + license = "LGPL-3.0" + author = "Ultimaker B.V." + url = "https://github.com/Ultimaker/uranium" + description = "A Python framework for building Desktop applications." + topics = ("conan", "python", "pyqt5", "qt", "3d-graphics", "3d-models", "python-framework") + settings = "os", "compiler", "build_type", "arch" + exports = "LICENSE" + options = { + "python_version": "ANY" + } + default_options = { + "python_version": "3.8" + } + scm = { + "type": "git", + "subfolder": ".", + "url": "auto", + "revision": "auto" + } + + def configure(self): + self.options["Arcus"].python_version = self.options.python_version + + def build_requirements(self): + self.build_requires("cmake/[>=3.16.2]") + + def requirements(self): + self.requires(f"Arcus/4.10.0@ultimaker/testing") + + def generate(self): + cmake = CMakeDeps(self) + cmake.generate() + + tc = CMakeToolchain(self) + tc.variables["Python_VERSION"] = self.options.python_version + tc.generate() + + _cmake = None + + def configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + self._cmake.configure() + return self._cmake + + def build(self): + cmake = self.configure_cmake() + cmake.build() + + def package(self): + cmake = self.configure_cmake() + cmake.install() + self.copy("*", src = os.path.join(self.package_folder, "lib", f"python{self.options.python_version}", + "site-packages"), dst = "site-packages") + self.copy("*", src = os.path.join(self.package_folder, "lib", "uranium"), dst = "site-packages") + self.copy("*.cmake", src = os.path.join(self.package_folder, "share"), dst = "cmake", keep_path=False) + tools.rmdir(os.path.join(self.package_folder, "lib")) + + def package_info(self): + if self.in_local_cache: + self.user_info.URANIUM_CMAKE_PATH = str(os.path.join(self.package_folder, "cmake")) + self.runenv_info.prepend_path("PYTHONPATH", os.path.join(self.package_folder, "site-packages")) + else: + self.user_info.URANIUM_CMAKE_PATH = str(os.path.join(str(pathlib.Path(__file__).parent.absolute()), "cmake")) + self.runenv_info.prepend_path("PYTHONPATH", str(pathlib.Path(__file__).parent.absolute())) + + def package_id(self): + self.info.header_only() From b504fd6eec76deda4d917c961e2cc99b6e2c920b Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 10 Aug 2021 17:02:36 +0200 Subject: [PATCH 02/10] Simplified recipe This is basically a header only recipe and can be seen as a pure Python package. just copying the UM, plugins and resources should be enough --- conanfile.py | 45 ++++++--------------------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/conanfile.py b/conanfile.py index ceeff9b652..33e52cdc02 100644 --- a/conanfile.py +++ b/conanfile.py @@ -15,12 +15,9 @@ class UraniumConan(ConanFile): topics = ("conan", "python", "pyqt5", "qt", "3d-graphics", "3d-models", "python-framework") settings = "os", "compiler", "build_type", "arch" exports = "LICENSE" - options = { - "python_version": "ANY" - } - default_options = { - "python_version": "3.8" - } + exports_sources = "plugins/*", "resources/*", "UM/*" + no_copy_source = True + scm = { "type": "git", "subfolder": ".", @@ -28,44 +25,14 @@ class UraniumConan(ConanFile): "revision": "auto" } - def configure(self): - self.options["Arcus"].python_version = self.options.python_version - - def build_requirements(self): - self.build_requires("cmake/[>=3.16.2]") - def requirements(self): self.requires(f"Arcus/4.10.0@ultimaker/testing") - def generate(self): - cmake = CMakeDeps(self) - cmake.generate() - - tc = CMakeToolchain(self) - tc.variables["Python_VERSION"] = self.options.python_version - tc.generate() - - _cmake = None - - def configure_cmake(self): - if self._cmake: - return self._cmake - self._cmake = CMake(self) - self._cmake.configure() - return self._cmake - - def build(self): - cmake = self.configure_cmake() - cmake.build() - def package(self): - cmake = self.configure_cmake() - cmake.install() - self.copy("*", src = os.path.join(self.package_folder, "lib", f"python{self.options.python_version}", - "site-packages"), dst = "site-packages") - self.copy("*", src = os.path.join(self.package_folder, "lib", "uranium"), dst = "site-packages") + self.copy("*", src = os.path.join(self.source_folder, "plugins"), dst = os.path.join("site-packages", "plugins")) + self.copy("*", src = os.path.join(self.source_folder, "resources"), dst = os.path.join("site-packages", "resources")) + self.copy("*", src = os.path.join(self.source_folder, "UM"), dst = os.path.join("site-packages", "UM")) self.copy("*.cmake", src = os.path.join(self.package_folder, "share"), dst = "cmake", keep_path=False) - tools.rmdir(os.path.join(self.package_folder, "lib")) def package_info(self): if self.in_local_cache: From 97e6bc9e326242088ef812b869c196d321ab48f1 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 10 Aug 2021 18:53:51 +0200 Subject: [PATCH 03/10] Set Arcus python_version Although Uranium isn't compiled its dependency Arcus is. Since Arcus is also used by CuraEngine. Setting the version here should ensure that they same python version is used by both. --- conanfile.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 33e52cdc02..b4058f273c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -17,7 +17,12 @@ class UraniumConan(ConanFile): exports = "LICENSE" exports_sources = "plugins/*", "resources/*", "UM/*" no_copy_source = True - + options = { + "python_version": "ANY" + } + default_options = { + "python_version": "3.8" + } scm = { "type": "git", "subfolder": ".", @@ -25,6 +30,9 @@ class UraniumConan(ConanFile): "revision": "auto" } + def configure(self): + self.options["Arcus"].python_version = self.options.python_version + def requirements(self): self.requires(f"Arcus/4.10.0@ultimaker/testing") From 457c97cd6ceb64fcf8d7ef59f4f38b45c0cea4cd Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 10 Aug 2021 23:31:30 +0200 Subject: [PATCH 04/10] Never us Apple Frameworks --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18575a46b7..f3a5c7f3a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ if(NOT DEFINED Python_VERSION) CACHE STRING "Python Version" FORCE) message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") endif() +if(APPLE) + set(Python3_FIND_FRAMEWORK NEVER) +endif() find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS Interpreter) message("Using Python version ${Python3_VERSION}") From 36f6dc3afdd384091d69d777f5c87fcf534e01ac Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Mon, 30 Aug 2021 14:10:03 +0200 Subject: [PATCH 05/10] Safely convert message image sources to QUrls Some messages may already provide a QUrl as the image source. In such cases, Cura would crash because the `QUrl.fromLocalFile()` expects a string and not a QUrl as input. This is now accounted for to make sure that in the image source will not be converted to QUrl again. CURA-8500 --- UM/Qt/Bindings/VisibleMessagesModel.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/UM/Qt/Bindings/VisibleMessagesModel.py b/UM/Qt/Bindings/VisibleMessagesModel.py index 8deb40b430..3c7b1f66c8 100644 --- a/UM/Qt/Bindings/VisibleMessagesModel.py +++ b/UM/Qt/Bindings/VisibleMessagesModel.py @@ -56,7 +56,7 @@ def addMessage(self, message): "actions": self.createActionsModel(message.getActions()), "dismissable": message.isDismissable(), "title": message.getTitle(), - "image_source": QUrl.fromLocalFile(message.getImageSource()), + "image_source": self.getImageSourceAsQUrl(message.getImageSource()), "image_caption": message.getImageCaption(), "option_text": message.getOptionText(), "option_state": message.getOptionState(), @@ -66,6 +66,14 @@ def addMessage(self, message): message.textChanged.connect(self._onMessageTextChanged) message.progressChanged.connect(self._onMessageProgress) + @staticmethod + def getImageSourceAsQUrl(image_source): + if type(image_source) is str: + return QUrl.fromLocalFile(image_source) + elif type(image_source) is QUrl: + return image_source + return QUrl.fromLocalFile("") + def createActionsModel(self, actions): model = ListModel() model.addRoleName(self.IDRole, "action_id") From ce52a5b15feee64d0c8e60cef844b2c8ecc84ae4 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 31 Aug 2021 12:05:41 +0200 Subject: [PATCH 06/10] add typing to getImageSourceAsQUrl As suggested by @nallath Co-authored-by: Jaime van Kessel --- UM/Qt/Bindings/VisibleMessagesModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UM/Qt/Bindings/VisibleMessagesModel.py b/UM/Qt/Bindings/VisibleMessagesModel.py index 3c7b1f66c8..c4f9da91bb 100644 --- a/UM/Qt/Bindings/VisibleMessagesModel.py +++ b/UM/Qt/Bindings/VisibleMessagesModel.py @@ -67,7 +67,7 @@ def addMessage(self, message): message.progressChanged.connect(self._onMessageProgress) @staticmethod - def getImageSourceAsQUrl(image_source): + def getImageSourceAsQUrl(image_source: Union[QUrl, str]) -> QUrl: if type(image_source) is str: return QUrl.fromLocalFile(image_source) elif type(image_source) is QUrl: From 1599aaa12de59fd8f8042b48a91ce21c491d36a6 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 31 Aug 2021 12:58:19 +0200 Subject: [PATCH 07/10] Import union from typing CURA-8500 --- UM/Qt/Bindings/VisibleMessagesModel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UM/Qt/Bindings/VisibleMessagesModel.py b/UM/Qt/Bindings/VisibleMessagesModel.py index c4f9da91bb..fa7fb43f6f 100644 --- a/UM/Qt/Bindings/VisibleMessagesModel.py +++ b/UM/Qt/Bindings/VisibleMessagesModel.py @@ -1,5 +1,6 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Uranium is released under the terms of the LGPLv3 or higher. +from typing import Union from PyQt5.QtCore import Qt, QUrl From 40f5e31b333f158b0a58b95cfe72518e6348418b Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 8 Sep 2021 11:15:58 +0200 Subject: [PATCH 08/10] Bump up to 4.11 --- conanfile.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/conanfile.py b/conanfile.py index b4058f273c..5dcbde523f 100644 --- a/conanfile.py +++ b/conanfile.py @@ -7,22 +7,18 @@ class UraniumConan(ConanFile): name = "Uranium" - version = "4.10.0" + version = "4.11.0" license = "LGPL-3.0" author = "Ultimaker B.V." url = "https://github.com/Ultimaker/uranium" description = "A Python framework for building Desktop applications." topics = ("conan", "python", "pyqt5", "qt", "3d-graphics", "3d-models", "python-framework") settings = "os", "compiler", "build_type", "arch" + revision_mode = "scm" + build_policy = "missing" exports = "LICENSE" exports_sources = "plugins/*", "resources/*", "UM/*" no_copy_source = True - options = { - "python_version": "ANY" - } - default_options = { - "python_version": "3.8" - } scm = { "type": "git", "subfolder": ".", @@ -30,11 +26,9 @@ class UraniumConan(ConanFile): "revision": "auto" } - def configure(self): - self.options["Arcus"].python_version = self.options.python_version - def requirements(self): - self.requires(f"Arcus/4.10.0@ultimaker/testing") + self.requires(f"Python/3.8.10@python/testing") + self.requires(f"Arcus/4.11.0@ultimaker/testing") def package(self): self.copy("*", src = os.path.join(self.source_folder, "plugins"), dst = os.path.join("site-packages", "plugins")) From ce4ce940ffddc57c20b168419b0f0e9bbc868479 Mon Sep 17 00:00:00 2001 From: jelle Spijker Date: Wed, 8 Sep 2021 13:51:38 +0200 Subject: [PATCH 09/10] Build Arcus static on Windows --- conanfile.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conanfile.py b/conanfile.py index 5dcbde523f..434cc4e199 100644 --- a/conanfile.py +++ b/conanfile.py @@ -26,6 +26,9 @@ class UraniumConan(ConanFile): "revision": "auto" } + def configure(self): + self.options["Arcus"].shared = self.settings.os != "Windows" + def requirements(self): self.requires(f"Python/3.8.10@python/testing") self.requires(f"Arcus/4.11.0@ultimaker/testing") From ddd0abd1221d397450af8dd97a6747fc6e3c45c7 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Mon, 1 Nov 2021 09:17:35 +0100 Subject: [PATCH 10/10] Bumped up Uranium version to 4.12 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 434cc4e199..3e7ad6aaed 100644 --- a/conanfile.py +++ b/conanfile.py @@ -7,7 +7,7 @@ class UraniumConan(ConanFile): name = "Uranium" - version = "4.11.0" + version = "4.12.0" license = "LGPL-3.0" author = "Ultimaker B.V." url = "https://github.com/Ultimaker/uranium"