From e1bc5d0f74ac31361ba07ea78cc351222177d363 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 5 Jul 2018 11:25:22 +0200 Subject: [PATCH 01/26] fix typing --- plugins/CuraEngineBackend/StartSliceJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 78dd4eafd2..237c1f2dda 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -234,8 +234,8 @@ class StartSliceJob(Job): if has_model_with_disabled_extruders: self.setResult(StartJobResult.ObjectsWithDisabledExtruder) - associated_disabled_extruders = [str(c) for c in sorted([int(p) + 1 for p in associated_disabled_extruders])] - self.setMessage(", ".join(associated_disabled_extruders)) + associated_disabled_extruders_message = [str(c) for c in sorted([int(p) + 1 for p in associated_disabled_extruders])] + self.setMessage(", ".join(associated_disabled_extruders_message)) return # There are cases when there is nothing to slice. This can happen due to one at a time slicing not being From 50da6d517634a875ec47d0162a15594e47342ffb Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 11:36:36 +0200 Subject: [PATCH 02/26] Fix some code-style --- plugins/CuraEngineBackend/CuraEngineBackend.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index e7dca2ae3e..c6784d87bc 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -69,8 +69,8 @@ class CuraEngineBackend(QObject, Backend): break self._application = CuraApplication.getInstance() #type: CuraApplication - self._multi_build_plate_model = None #type: MultiBuildPlateModel - self._machine_error_checker = None #type: MachineErrorChecker + self._multi_build_plate_model = None #type: Optional[MultiBuildPlateModel] + self._machine_error_checker = None #type: Optional[MachineErrorChecker] if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") @@ -328,6 +328,9 @@ class CuraEngineBackend(QObject, Backend): if job.getResult() == StartJobResult.SettingError: if self._application.platformActivity: + if not self._global_container_stack: + Logger.log("w", "Global container stack not assigned to CuraEngineBackend!") + return extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) error_keys = [] #type: List[str] for extruder in extruders: From 1aac301f75ceb51bcb480d8721651a070eda11b9 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 11:46:21 +0200 Subject: [PATCH 03/26] additional code style fixes --- plugins/CuraEngineBackend/CuraEngineBackend.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index c6784d87bc..d3c9077d9b 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -120,7 +120,7 @@ class CuraEngineBackend(QObject, Backend): self._engine_is_fresh = True #type: bool # Is the newly started engine used before or not? self._backend_log_max_lines = 20000 #type: int # Maximum number of lines to buffer - self._error_message = None #type: Message # Pop-up message that shows errors. + self._error_message = None #type: Optional[Message] # Pop-up message that shows errors. self._last_num_objects = defaultdict(int) #type: Dict[int, int] # Count number of objects to see if there is something changed self._postponed_scene_change_sources = [] #type: List[SceneNode] # scene change is postponed (by a tool) @@ -145,7 +145,9 @@ class CuraEngineBackend(QObject, Backend): self._multi_build_plate_model = self._application.getMultiBuildPlateModel() self._application.getController().activeViewChanged.connect(self._onActiveViewChanged) - self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged) + + if self._multi_build_plate_model: + self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged) self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() @@ -412,7 +414,8 @@ class CuraEngineBackend(QObject, Backend): # Notify the user that it's now up to the backend to do it's job self.backendStateChange.emit(BackendState.Processing) - Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time ) + if self._slice_start_time: + Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time ) ## Determine enable or disable auto slicing. Return True for enable timer and False otherwise. # It disables when @@ -622,7 +625,8 @@ class CuraEngineBackend(QObject, Backend): gcode_list[index] = replaced self._slicing = False - Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time ) + if self._slice_start_time: + Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time ) Logger.log("d", "Number of models per buildplate: %s", dict(self._numObjectsPerBuildPlate())) # See if we need to process the sliced layers job. @@ -834,6 +838,9 @@ class CuraEngineBackend(QObject, Backend): self._change_timer.start() def _extruderChanged(self) -> None: + if not self._multi_build_plate_model: + Logger.log("w", "CuraEngineBackend does not have multi_build_plate_model assigned!") + return for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): if build_plate_number not in self._build_plates_to_be_sliced: self._build_plates_to_be_sliced.append(build_plate_number) From 6f20b9219d76648903aa8028c4e2ae85d346ebfb Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 11:57:13 +0200 Subject: [PATCH 04/26] code style fixes --- plugins/CuraEngineBackend/CuraEngineBackend.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index d3c9077d9b..4fc1381d2a 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -366,6 +366,9 @@ class CuraEngineBackend(QObject, Backend): if not stack: continue for key in stack.getErrorKeys(): + if not self._global_container_stack: + Logger.log("e", "CuraEngineBackend does not have global_container_stack assigned.") + continue definition = cast(DefinitionContainerInterface, self._global_container_stack.getBottom()).findDefinitions(key = key) if not definition: Logger.log("e", "When checking settings for errors, unable to find definition for key {key} in per-object stack.".format(key = key)) @@ -489,7 +492,8 @@ class CuraEngineBackend(QObject, Backend): build_plate_changed.add(source_build_plate_number) - build_plate_changed.discard(None) + # TODO: Commented out for code tests, discard() only takes 'int', and no explanation exists for this line + # build_plate_changed.discard(None) build_plate_changed.discard(-1) # object not on build plate if not build_plate_changed: return @@ -583,9 +587,10 @@ class CuraEngineBackend(QObject, Backend): # # \param message The protobuf message containing sliced layer data. def _onOptimizedLayerMessage(self, message: Arcus.PythonMessage) -> None: - if self._start_slice_job_build_plate not in self._stored_optimized_layer_data: - self._stored_optimized_layer_data[self._start_slice_job_build_plate] = [] - self._stored_optimized_layer_data[self._start_slice_job_build_plate].append(message) + if self._start_slice_job_build_plate: + if self._start_slice_job_build_plate not in self._stored_optimized_layer_data: + self._stored_optimized_layer_data[self._start_slice_job_build_plate] = [] + self._stored_optimized_layer_data[self._start_slice_job_build_plate].append(message) ## Called when a progress message is received from the engine. # From 07e92ead0b6100a4fd518fd4008536f0774ebb0a Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 15:20:38 +0200 Subject: [PATCH 05/26] last fixes for CuraEngineBackend --- plugins/CuraEngineBackend/CuraEngineBackend.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 4fc1381d2a..26a2399567 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -21,6 +21,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.SettingInstance import SettingInstance #For typing. from UM.Tool import Tool #For typing. +from UM.Mesh.MeshData import MeshData #For typing. from cura.CuraApplication import CuraApplication from cura.Settings.ExtruderManager import ExtruderManager @@ -62,7 +63,7 @@ class CuraEngineBackend(QObject, Backend): if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError("There is something wrong with your Linux installation.") - for pathdir in os.getenv("PATH").split(os.pathsep): + for pathdir in cast(str, os.getenv("PATH")).split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath @@ -485,9 +486,8 @@ class CuraEngineBackend(QObject, Backend): else: # we got a single scenenode if not source.callDecoration("isGroup"): - if source.getMeshData() is None: - return - if source.getMeshData().getVertices() is None: + meshData = source.getMeshData(); + if meshData and meshData.getVertices() is None: return build_plate_changed.add(source_build_plate_number) @@ -670,7 +670,7 @@ class CuraEngineBackend(QObject, Backend): ## Creates a new socket connection. def _createSocket(self, protocol_file: str = None) -> None: if not protocol_file: - protocol_file = os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")) + protocol_file = os.path.abspath(os.path.join(str(PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "Cura.proto")) super()._createSocket(protocol_file) self._engine_is_fresh = True From 9ec5770a1c2f64c50aee6a279645320e5bff8fe0 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 15:31:08 +0200 Subject: [PATCH 06/26] Fixes for StartSliceJob --- plugins/CuraEngineBackend/StartSliceJob.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 237c1f2dda..8f31e8cd0a 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -5,7 +5,7 @@ import numpy from string import Formatter from enum import IntEnum import time -from typing import Any, Dict, List, Optional, Set +from typing import Any, cast, Dict, List, Optional, Set import re import Arcus #For typing. @@ -114,7 +114,7 @@ class StartSliceJob(Job): self.setResult(StartJobResult.Error) return - stack = CuraApplication.getInstance().getGlobalContainerStack() + stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) if not stack: self.setResult(StartJobResult.Error) return @@ -216,12 +216,11 @@ class StartSliceJob(Job): if temp_list: object_groups.append(temp_list) - extruders_enabled = {position: stack.isEnabled for position, stack in CuraApplication.getInstance().getGlobalContainerStack().extruders.items()} + extruders_enabled = {position: stack.isEnabled for position, extruder in stack.extruders.items()} filtered_object_groups = [] has_model_with_disabled_extruders = False associated_disabled_extruders = set() for group in object_groups: - stack = CuraApplication.getInstance().getGlobalContainerStack() skip_group = False for node in group: extruder_position = node.callDecoration("getActiveExtruderPosition") @@ -325,11 +324,11 @@ class StartSliceJob(Job): # \param default_extruder_nr Stack nr to use when no stack nr is specified, defaults to the global stack def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str: if not self._all_extruders_settings: - global_stack = CuraApplication.getInstance().getGlobalContainerStack() + global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) # NB: keys must be strings for the string formatter self._all_extruders_settings = { - "-1": self._buildReplacementTokens(global_stack) + "-1": self._buildReplacementTokens(cast(ContainerStack, global_stack)) } for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): From 2f8debc985d0425da4244f5bc2284f20b28bc6f2 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 15:45:48 +0200 Subject: [PATCH 07/26] Fixes for FlavorParser --- plugins/GCodeReader/FlavorParser.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index 05f40b41e7..ead527a61f 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -286,7 +286,9 @@ class FlavorParser: self._cancelled = False # We obtain the filament diameter from the selected extruder to calculate line widths global_stack = CuraApplication.getInstance().getGlobalContainerStack() - self._filament_diameter = global_stack.extruders[str(self._extruder_number)].getProperty("material_diameter", "value") + + if global_stack: + self._filament_diameter = global_stack.extruders[str(self._extruder_number)].getProperty("material_diameter", "value") scene_node = CuraSceneNode() From d0c68f8e947da1858331a2094c361afa89fa8dc6 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 15:46:16 +0200 Subject: [PATCH 08/26] Fixes for WindowsRemovableDrivePlugin --- .../WindowsRemovableDrivePlugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py index 7a3e1ab5c1..51b6a70b7a 100644 --- a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py +++ b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py @@ -11,7 +11,7 @@ from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") # Ignore windows error popups. Fixes the whole "Can't open drive X" when user has an SD card reader. -ctypes.windll.kernel32.SetErrorMode(1) +ctypes.windll.kernel32.SetErrorMode(1) #type: ignore # WinAPI Constants that we need # Hardcoded here due to stupid WinDLL stuff that does not give us access to these values. @@ -29,7 +29,7 @@ OPEN_EXISTING = 3 # [CodeStyle: Windows Enum value] # Setup the DeviceIoControl function arguments and return type. # See ctypes documentation for details on how to call C functions from python, and why this is important. -ctypes.windll.kernel32.DeviceIoControl.argtypes = [ +ctypes.windll.kernel32.DeviceIoControl.argtypes = [ #type: ignore wintypes.HANDLE, # _In_ HANDLE hDevice wintypes.DWORD, # _In_ DWORD dwIoControlCode wintypes.LPVOID, # _In_opt_ LPVOID lpInBuffer @@ -39,7 +39,7 @@ ctypes.windll.kernel32.DeviceIoControl.argtypes = [ ctypes.POINTER(wintypes.DWORD), # _Out_opt_ LPDWORD lpBytesReturned wintypes.LPVOID # _Inout_opt_ LPOVERLAPPED lpOverlapped ] -ctypes.windll.kernel32.DeviceIoControl.restype = wintypes.BOOL +ctypes.windll.kernel32.DeviceIoControl.restype = wintypes.BOOL #type: ignore ## Removable drive support for windows From cfae634061fbfedb6b75355fcf122e9c5ec04b25 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 15:54:21 +0200 Subject: [PATCH 09/26] Fixes for SliceInfo --- plugins/SliceInfoPlugin/SliceInfo.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index fe17af89eb..aad1b5005d 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -16,7 +16,7 @@ from UM.i18n import i18nCatalog from UM.Logger import Logger from UM.PluginRegistry import PluginRegistry from UM.Qt.Duration import DurationFormat - +from typing import cast from .SliceInfoJob import SliceInfoJob @@ -81,9 +81,10 @@ class SliceInfo(QObject, Extension): @pyqtSlot(result = str) def getExampleData(self) -> str: if self._example_data_content is None: - file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "example_data.json") - with open(file_path, "r", encoding = "utf-8") as f: - self._example_data_content = f.read() + file_path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "example_data.json") + if file_path: + with open(file_path, "r", encoding = "utf-8") as f: + self._example_data_content = f.read() return self._example_data_content @pyqtSlot(bool) From 85be9cea07ec564171f09ff30334d5fe723f06c2 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 16:06:37 +0200 Subject: [PATCH 10/26] Fixes for Toolbox --- plugins/Toolbox/src/Toolbox.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 0d0060e48c..d3b9b37bc6 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -6,7 +6,7 @@ import json import os import tempfile import platform -from typing import List +from typing import cast, List from PyQt5.QtCore import QUrl, QObject, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply @@ -229,10 +229,14 @@ class Toolbox(QObject, Extension): # Apply enabled/disabled state to installed plugins self.enabledChanged.emit() - def _createDialog(self, qml_name: str) -> Optional[QObject]: + def _createDialog(self, qml_name: str) -> QObject: Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name) - path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "resources", "qml", qml_name) + path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "resources", "qml", qml_name) + if not path: + raise Exception("Failed to create toolbox QML path") dialog = self._application.createQmlComponent(path, {"toolbox": self}) + if not dialog: + raise Exception("Failed to create toolbox dialog") return dialog From 3321b23925c0cd756efbae343fc028f13b4d7e87 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 16:31:56 +0200 Subject: [PATCH 11/26] Fixes for UM3NetworkPrinting --- .../ClusterUM3OutputDevice.py | 19 +++++++++++++------ .../UM3NetworkPrinting/DiscoverUM3Action.py | 8 ++++++-- plugins/UM3NetworkPrinting/SendMaterialJob.py | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index 8b3ceb7809..6a5da04429 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, cast, Set, Tuple, Union +from typing import Any, cast, Optional, Set, Tuple, Union from UM.FileHandler.FileHandler import FileHandler from UM.FileHandler.FileWriter import FileWriter #To choose based on the output file mode (text vs. binary). @@ -9,6 +9,7 @@ from UM.FileHandler.WriteFileJob import WriteFileJob #To call the file writer as from UM.Logger import Logger from UM.Settings.ContainerRegistry import ContainerRegistry from UM.i18n import i18nCatalog +from UM.Mesh.MeshWriter import MeshWriter # For typing from UM.Message import Message from UM.Qt.Duration import Duration, DurationFormat from UM.OutputDevice import OutputDeviceError #To show that something went wrong when writing. @@ -103,8 +104,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): else: file_formats = CuraApplication.getInstance().getMeshFileHandler().getSupportedFileTypesWrite() + global_stack = CuraApplication.getInstance().getGlobalContainerStack() #Create a list from the supported file formats string. - machine_file_formats = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("file_formats").split(";") + if global_stack: + machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";") machine_file_formats = [file_type.strip() for file_type in machine_file_formats] #Exception for UM3 firmware version >=4.4: UFP is now supported and should be the preferred file format. if "application/x-ufp" not in machine_file_formats and self.printerType == "ultimaker3" and Version(self.firmwareVersion) >= Version("4.4"): @@ -126,6 +129,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): writer = CuraApplication.getInstance().getMeshFileHandler().getWriterByMimeType(cast(str, preferred_format["mime_type"])) #This function pauses with the yield, waiting on instructions on which printer it needs to print with. + if not writer: + Logger.log("e", "Missing file or mesh writer!") + return self._sending_job = self._sendPrintJob(writer, preferred_format, nodes) self._sending_job.send(None) #Start the generator. @@ -168,7 +174,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): # \param preferred_format A dictionary containing some information about # what format to write to. This is necessary to create the correct buffer # types and file extension and such. - def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]): + def _sendPrintJob(self, writer: MeshWriter, preferred_format: Dict, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( @@ -205,14 +211,14 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): yield #To prevent having to catch the StopIteration exception. def _sendPrintJobWaitOnWriteJobFinished(self, job: WriteFileJob) -> None: - self._write_job_progress_message.hide() + if self._write_job_progress_message: + self._write_job_progress_message.hide() self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0, dismissable = False, progress = -1, title = i18n_catalog.i18nc("@info:title", "Sending Data")) self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), icon = None, description = "") self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered) self._progress_message.show() - parts = [] target_printer, preferred_format, stream = self._dummy_lambdas @@ -249,7 +255,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self.activePrinterChanged.emit() def _onPostPrintJobFinished(self, reply: QNetworkReply) -> None: - self._progress_message.hide() + if self._progress_message: + self._progress_message.hide() self._compressing_gcode = False self._sending_gcode = False diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.py b/plugins/UM3NetworkPrinting/DiscoverUM3Action.py index c51092ed98..988559a3f5 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.py +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.py @@ -3,7 +3,7 @@ import os.path import time -from typing import Optional +from typing import cast, Optional from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject @@ -170,7 +170,11 @@ class DiscoverUM3Action(MachineAction): Logger.log("d", "Creating additional ui components for UM3.") # Create networking dialog - path = os.path.join(PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"), "UM3InfoComponents.qml") + path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")), "UM3InfoComponents.qml") + if not path: + Logger.log("w", "Could not get QML path for UM3 network printing UI.") + return + self.__additional_components_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) if not self.__additional_components_view: Logger.log("w", "Could not create ui components for UM3.") diff --git a/plugins/UM3NetworkPrinting/SendMaterialJob.py b/plugins/UM3NetworkPrinting/SendMaterialJob.py index 02b5b68393..0ac38843a1 100644 --- a/plugins/UM3NetworkPrinting/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/SendMaterialJob.py @@ -23,7 +23,7 @@ if TYPE_CHECKING: # # This way it won't freeze up the interface while sending those materials. class SendMaterialJob(Job): - def __init__(self, device: "ClusterUM3OutputDevice"): + def __init__(self, device: "ClusterUM3OutputDevice") -> None: super().__init__() self.device = device #type: ClusterUM3OutputDevice From b6364b28044b5267c032eb5e4789752f2f75305f Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 5 Jul 2018 16:35:57 +0200 Subject: [PATCH 12/26] Fixes for X3DReader --- plugins/X3DReader/X3DReader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/X3DReader/X3DReader.py b/plugins/X3DReader/X3DReader.py index 44a2f1443a..f529f76509 100644 --- a/plugins/X3DReader/X3DReader.py +++ b/plugins/X3DReader/X3DReader.py @@ -42,7 +42,8 @@ class X3DReader(MeshReader): def __init__(self) -> None: super().__init__() self._supported_extensions = [".x3d"] - self._namespaces = {} + # TODO: Remove after testing because it appears to be unused + # self._namespaces = {} # Main entry point # Reads the file, returns a SceneNode (possibly with nested ones), or None From 2c291e02bed5d27cd64005b95e49a1fe387d3f95 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 6 Jul 2018 10:54:24 +0200 Subject: [PATCH 13/26] Revert "Fixes for StartSliceJob" This reverts commit 9ec5770a1c2f64c50aee6a279645320e5bff8fe0. --- plugins/CuraEngineBackend/StartSliceJob.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 8f31e8cd0a..237c1f2dda 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -5,7 +5,7 @@ import numpy from string import Formatter from enum import IntEnum import time -from typing import Any, cast, Dict, List, Optional, Set +from typing import Any, Dict, List, Optional, Set import re import Arcus #For typing. @@ -114,7 +114,7 @@ class StartSliceJob(Job): self.setResult(StartJobResult.Error) return - stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) + stack = CuraApplication.getInstance().getGlobalContainerStack() if not stack: self.setResult(StartJobResult.Error) return @@ -216,11 +216,12 @@ class StartSliceJob(Job): if temp_list: object_groups.append(temp_list) - extruders_enabled = {position: stack.isEnabled for position, extruder in stack.extruders.items()} + extruders_enabled = {position: stack.isEnabled for position, stack in CuraApplication.getInstance().getGlobalContainerStack().extruders.items()} filtered_object_groups = [] has_model_with_disabled_extruders = False associated_disabled_extruders = set() for group in object_groups: + stack = CuraApplication.getInstance().getGlobalContainerStack() skip_group = False for node in group: extruder_position = node.callDecoration("getActiveExtruderPosition") @@ -324,11 +325,11 @@ class StartSliceJob(Job): # \param default_extruder_nr Stack nr to use when no stack nr is specified, defaults to the global stack def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str: if not self._all_extruders_settings: - global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) + global_stack = CuraApplication.getInstance().getGlobalContainerStack() # NB: keys must be strings for the string formatter self._all_extruders_settings = { - "-1": self._buildReplacementTokens(cast(ContainerStack, global_stack)) + "-1": self._buildReplacementTokens(global_stack) } for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): From 8e7399c442278cdc118b1c98bfd86593171e2708 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 6 Jul 2018 10:56:09 +0200 Subject: [PATCH 14/26] Add correct typing --- plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index 185430f3f3..c6e384a987 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -178,7 +178,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): # \param preferred_format A dictionary containing some information about # what format to write to. This is necessary to create the correct buffer # types and file extension and such. - def _sendPrintJob(self, writer: MeshWriter, preferred_format: Dict, nodes: List[SceneNode]): + def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( From c6b290e1e5fa3d2b496a98b4916b6acc1a39464d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 6 Jul 2018 11:03:32 +0200 Subject: [PATCH 15/26] Fix broken slicing --- plugins/CuraEngineBackend/StartSliceJob.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 237c1f2dda..afa26a444e 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -5,7 +5,7 @@ import numpy from string import Formatter from enum import IntEnum import time -from typing import Any, Dict, List, Optional, Set +from typing import Any, cast, Dict, List, Optional, Set import re import Arcus #For typing. @@ -216,12 +216,15 @@ class StartSliceJob(Job): if temp_list: object_groups.append(temp_list) - extruders_enabled = {position: stack.isEnabled for position, stack in CuraApplication.getInstance().getGlobalContainerStack().extruders.items()} + global_stack = CuraApplication.getInstance().getGlobalContainerStack() + if not global_stack: + return + extruders_enabled = {position: stack.isEnabled for position, stack in global_stack.extruders.items()} filtered_object_groups = [] has_model_with_disabled_extruders = False associated_disabled_extruders = set() for group in object_groups: - stack = CuraApplication.getInstance().getGlobalContainerStack() + stack = global_stack skip_group = False for node in group: extruder_position = node.callDecoration("getActiveExtruderPosition") @@ -325,7 +328,7 @@ class StartSliceJob(Job): # \param default_extruder_nr Stack nr to use when no stack nr is specified, defaults to the global stack def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str: if not self._all_extruders_settings: - global_stack = CuraApplication.getInstance().getGlobalContainerStack() + global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) # NB: keys must be strings for the string formatter self._all_extruders_settings = { From 1483571fda2ad158633ab506e377c6f8cb6701bf Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 6 Jul 2018 11:14:10 +0200 Subject: [PATCH 16/26] Show verbose msg when cmake test fails on Jenkins --- Jenkinsfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 83104aea18..ff4558625a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,10 @@ parallel_nodes(['linux && cura', 'windows && cura']) { timeout(time: 2, unit: "HOURS") { + + environment { + CTEST_OUTPUT_ON_FAILURE = '1' + } + // Prepare building stage('Prepare') { // Ensure we start with a clean build directory. From c7b7521a30e047175aa591733f8308869633d59b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 6 Jul 2018 11:21:54 +0200 Subject: [PATCH 17/26] WIP: Use shell to run make test on Jenkins --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index ff4558625a..29b2bef670 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -33,7 +33,8 @@ parallel_nodes(['linux && cura', 'windows && cura']) { // Try and run the unit tests. If this stage fails, we consider the build to be "unstable". stage('Unit Test') { try { - make('test') + //make('test') + sh "CTEST_OUTPUT_ON_FAILURE=1 make test" } catch(e) { currentBuild.result = "UNSTABLE" } From c3cd6f8052d53e8f0ef6acf944784707633140e8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 6 Jul 2018 11:24:54 +0200 Subject: [PATCH 18/26] Restore Jenkinsfile --- Jenkinsfile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 29b2bef670..de62b7ed5a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,10 +1,6 @@ parallel_nodes(['linux && cura', 'windows && cura']) { timeout(time: 2, unit: "HOURS") { - environment { - CTEST_OUTPUT_ON_FAILURE = '1' - } - // Prepare building stage('Prepare') { // Ensure we start with a clean build directory. @@ -33,8 +29,7 @@ parallel_nodes(['linux && cura', 'windows && cura']) { // Try and run the unit tests. If this stage fails, we consider the build to be "unstable". stage('Unit Test') { try { - //make('test') - sh "CTEST_OUTPUT_ON_FAILURE=1 make test" + make('test') } catch(e) { currentBuild.result = "UNSTABLE" } From ac0192f01f72c859effe05ae7ce9dc7a536d9220 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 9 Jul 2018 11:29:25 +0200 Subject: [PATCH 19/26] Improve fixes --- plugins/CuraEngineBackend/CuraEngineBackend.py | 10 +++++++--- plugins/SliceInfoPlugin/SliceInfo.py | 10 +++++++--- plugins/Toolbox/src/Toolbox.py | 2 +- plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py | 7 +++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 26a2399567..60436a3ef2 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -486,8 +486,8 @@ class CuraEngineBackend(QObject, Backend): else: # we got a single scenenode if not source.callDecoration("isGroup"): - meshData = source.getMeshData(); - if meshData and meshData.getVertices() is None: + mesh_data = source.getMeshData() + if mesh_data and mesh_data.getVertices() is None: return build_plate_changed.add(source_build_plate_number) @@ -670,7 +670,11 @@ class CuraEngineBackend(QObject, Backend): ## Creates a new socket connection. def _createSocket(self, protocol_file: str = None) -> None: if not protocol_file: - protocol_file = os.path.abspath(os.path.join(str(PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "Cura.proto")) + plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) + if not plugin_path: + Logger.log("e", "Could not get plugin path!", self.getPluginId()) + return + protocol_file = os.path.abspath(os.path.join(plugin_path, "Cura.proto")) super()._createSocket(protocol_file) self._engine_is_fresh = True diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index aad1b5005d..2e9e557c4a 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -16,7 +16,7 @@ from UM.i18n import i18nCatalog from UM.Logger import Logger from UM.PluginRegistry import PluginRegistry from UM.Qt.Duration import DurationFormat -from typing import cast +from typing import cast, Optional from .SliceInfoJob import SliceInfoJob @@ -79,9 +79,13 @@ class SliceInfo(QObject, Extension): return dialog @pyqtSlot(result = str) - def getExampleData(self) -> str: + def getExampleData(self) -> Optional[str]: if self._example_data_content is None: - file_path = os.path.join(cast(str, PluginRegistry.getInstance().getPluginPath(self.getPluginId())), "example_data.json") + plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) + if not plugin_path: + Logger.log("e", "Could not get plugin path!", self.getPluginId()) + return None + file_path = os.path.join(plugin_path, "example_data.json") if file_path: with open(file_path, "r", encoding = "utf-8") as f: self._example_data_content = f.read() diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 762e7027fb..7c2605e5e0 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -234,7 +234,7 @@ class Toolbox(QObject, Extension): # Apply enabled/disabled state to installed plugins self.enabledChanged.emit() - def _createDialog(self, qml_name: str) -> QObject: + def _createDialog(self, qml_name: str) -> Optional[QObject]: Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name) plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) if not plugin_path: diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index c6e384a987..b58601db46 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -106,8 +106,11 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): global_stack = CuraApplication.getInstance().getGlobalContainerStack() #Create a list from the supported file formats string. - if global_stack: - machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";") + if not global_stack: + Logger.log("e", "Missing global stack!") + return; + + machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";") machine_file_formats = [file_type.strip() for file_type in machine_file_formats] #Exception for UM3 firmware version >=4.4: UFP is now supported and should be the preferred file format. if "application/x-ufp" not in machine_file_formats and self.printerType == "ultimaker3" and Version(self.firmwareVersion) >= Version("4.4"): From 413965a0ee549c1ff215141a34e123c07229a947 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 9 Jul 2018 11:51:53 +0200 Subject: [PATCH 20/26] Fighting muscle memory --- plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index b58601db46..84e0a66170 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -108,7 +108,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): #Create a list from the supported file formats string. if not global_stack: Logger.log("e", "Missing global stack!") - return; + return machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";") machine_file_formats = [file_type.strip() for file_type in machine_file_formats] From 8dab2a6696431aa6fd70644e3490e1bc79e3f23c Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 9 Jul 2018 15:33:41 +0200 Subject: [PATCH 21/26] Do not attempt to discard changed build plates --- plugins/CuraEngineBackend/CuraEngineBackend.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 60436a3ef2..b893640939 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -492,9 +492,6 @@ class CuraEngineBackend(QObject, Backend): build_plate_changed.add(source_build_plate_number) - # TODO: Commented out for code tests, discard() only takes 'int', and no explanation exists for this line - # build_plate_changed.discard(None) - build_plate_changed.discard(-1) # object not on build plate if not build_plate_changed: return From 5e30fdf0fe140f599fb19534d2373d25c2756fe7 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 9 Jul 2018 15:54:54 +0200 Subject: [PATCH 22/26] Make sure searchPath is always a string --- run_mypy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run_mypy.py b/run_mypy.py index 2a2c72dbbe..43196fa7f1 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -5,6 +5,8 @@ import subprocess # A quick Python implementation of unix 'where' command. def where(exeName, searchPath=os.getenv("PATH")): + if searchPath is None: + searchPath = "" paths = searchPath.split(";" if sys.platform == "win32" else ":") for path in paths: candidatePath = os.path.join(path, exeName) From 1a32e90cd0276fadd29574c1412a0de3c5fbca5e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 9 Jul 2018 16:13:40 +0200 Subject: [PATCH 23/26] WIP: Fix run_mypy.py for Windows --- run_mypy.py | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/run_mypy.py b/run_mypy.py index 43196fa7f1..66118b36fd 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -1,18 +1,20 @@ -#!env python +#!/usr/bin/env python import os import sys import subprocess + # A quick Python implementation of unix 'where' command. -def where(exeName, searchPath=os.getenv("PATH")): - if searchPath is None: - searchPath = "" - paths = searchPath.split(";" if sys.platform == "win32" else ":") +def where(exe_name: str, search_path: str = os.getenv("PATH")) -> str: + if search_path is None: + search_path = "" + paths = search_path.split(";" if sys.platform == "win32" else ":") for path in paths: - candidatePath = os.path.join(path, exeName) - if os.path.exists(candidatePath): - return candidatePath - return None + candidate_path = os.path.join(path, exe_name) + if os.path.exists(candidate_path): + return candidate_path + return "" + def findModules(path): result = [] @@ -21,6 +23,7 @@ def findModules(path): result.append(entry.name) return result + def main(): # Find Uranium via the PYTHONPATH var uraniumUMPath = where("UM", os.getenv("PYTHONPATH")) @@ -28,16 +31,16 @@ def main(): uraniumUMPath = os.path.join("..", "Uranium") uraniumPath = os.path.dirname(uraniumUMPath) - mypyPathParts = [".", os.path.join(".", "plugins"), os.path.join(".", "plugins", "VersionUpgrade"), - uraniumPath, os.path.join(uraniumPath, "stubs")] + mypy_path_parts = [".", os.path.join(".", "plugins"), os.path.join(".", "plugins", "VersionUpgrade"), + uraniumPath, os.path.join(uraniumPath, "stubs")] if sys.platform == "win32": - os.putenv("MYPYPATH", ";".join(mypyPathParts)) + os.putenv("MYPYPATH", ";".join(mypy_path_parts)) else: - os.putenv("MYPYPATH", ":".join(mypyPathParts)) + os.putenv("MYPYPATH", ":".join(mypy_path_parts)) # Mypy really needs to be run via its Python script otherwise it can't find its data files. - mypyExe = where("mypy.bat" if sys.platform == "win32" else "mypy") - mypyModule = os.path.join(os.path.dirname(mypyExe), "mypy") + mypy_exe = where("mypy.exe" if sys.platform == "win32" else "mypy") + mypy_module = os.path.join(os.path.dirname(mypy_exe), "mypy") plugins = findModules("plugins") plugins.sort() @@ -46,11 +49,14 @@ def main(): for mod in mods: print("------------- Checking module {mod}".format(**locals())) - result = subprocess.run([sys.executable, mypyModule, "-p", mod, "--ignore-missing-imports"]) + result = subprocess.run([sys.executable, mypy_module, "-p", mod, "--ignore-missing-imports"]) if result.returncode != 0: print("\nModule {mod} failed checking. :(".format(**locals())) return 1 else: print("\n\nDone checking. All is good.") return 0 -sys.exit(main()) + + +if __name__ == "__main__": + sys.exit(main()) From 08249a8b0648cad518c93b7ebbe7973d15aea487 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 9 Jul 2018 16:18:43 +0200 Subject: [PATCH 24/26] WIP: Fix run_mypy.py for Windows --- run_mypy.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/run_mypy.py b/run_mypy.py index 66118b36fd..3b75ecd2eb 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -39,8 +39,9 @@ def main(): os.putenv("MYPYPATH", ":".join(mypy_path_parts)) # Mypy really needs to be run via its Python script otherwise it can't find its data files. - mypy_exe = where("mypy.exe" if sys.platform == "win32" else "mypy") - mypy_module = os.path.join(os.path.dirname(mypy_exe), "mypy") + mypy_exe_name = "mypy.exe" if sys.platform == "win32" else "mypy" + mypy_exe_dir = where(mypy_exe_name) + mypy_module = os.path.join(os.path.dirname(mypy_exe_dir), mypy_exe_name) plugins = findModules("plugins") plugins.sort() @@ -49,7 +50,10 @@ def main(): for mod in mods: print("------------- Checking module {mod}".format(**locals())) - result = subprocess.run([sys.executable, mypy_module, "-p", mod, "--ignore-missing-imports"]) + if sys.platform == "win32": + result = subprocess.run([mypy_module, "-p", mod, "--ignore-missing-imports"]) + else: + result = subprocess.run([sys.executable, mypy_module, "-p", mod, "--ignore-missing-imports"]) if result.returncode != 0: print("\nModule {mod} failed checking. :(".format(**locals())) return 1 From de551ccf51916358927a2183bf223be58e23da9e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 9 Jul 2018 16:22:59 +0200 Subject: [PATCH 25/26] WIP: Fix run_mypy on Windows via cmake --- run_mypy.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/run_mypy.py b/run_mypy.py index 3b75ecd2eb..27f07cd281 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -8,12 +8,24 @@ import subprocess def where(exe_name: str, search_path: str = os.getenv("PATH")) -> str: if search_path is None: search_path = "" - paths = search_path.split(";" if sys.platform == "win32" else ":") - for path in paths: + paths = search_path.split(os.pathsep) + result = "" + print(" -> sys.executable location: %s" % sys.executable) + sys_exec_dir = os.path.dirname(sys.executable) + root_dir = os.path.dirname(sys_exec_dir) + paths += [sys_exec_dir, + os.path.join(root_dir, "bin"), + os.path.join(root_dir, "scripts"), + ] + paths = set(paths) + + for path in sorted(paths): + print(" -> Searching %s" % path) candidate_path = os.path.join(path, exe_name) if os.path.exists(candidate_path): - return candidate_path - return "" + result = candidate_path + break + return result def findModules(path): @@ -42,6 +54,8 @@ def main(): mypy_exe_name = "mypy.exe" if sys.platform == "win32" else "mypy" mypy_exe_dir = where(mypy_exe_name) mypy_module = os.path.join(os.path.dirname(mypy_exe_dir), mypy_exe_name) + print("Found mypy exe path: %s" % mypy_exe_dir) + print("Found mypy module path: %s" % mypy_module) plugins = findModules("plugins") plugins.sort() From d709650def1d82845b9eb7034600e27101033a06 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 10 Jul 2018 11:04:17 +0200 Subject: [PATCH 26/26] Try to ignore _process variable --- plugins/CuraEngineBackend/CuraEngineBackend.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index b893640939..2b3c2b29f8 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -249,7 +249,7 @@ class CuraEngineBackend(QObject, Backend): if self._application.getPrintInformation() and build_plate_to_be_sliced == active_build_plate: self._application.getPrintInformation().setToZeroPrintInformation(build_plate_to_be_sliced) - if self._process is None: + if self._process is None: # type: ignore self._createSocket() self.stopSlicing() self._engine_is_fresh = False # Yes we're going to use the engine @@ -287,12 +287,12 @@ class CuraEngineBackend(QObject, Backend): if self._application.getUseExternalBackend(): return - if self._process is not None: + if self._process is not None: # type: ignore Logger.log("d", "Killing engine process") try: - self._process.terminate() - Logger.log("d", "Engine process is killed. Received return code %s", self._process.wait()) - self._process = None + self._process.terminate() # type: ignore + Logger.log("d", "Engine process is killed. Received return code %s", self._process.wait()) # type: ignore + self._process = None # type: ignore except Exception as e: # terminating a process that is already terminating causes an exception, silently ignore this. Logger.log("d", "Exception occurred while trying to kill the engine %s", str(e)) @@ -786,9 +786,9 @@ class CuraEngineBackend(QObject, Backend): # We should reset our state and start listening for new connections. def _onBackendQuit(self) -> None: if not self._restart: - if self._process: - Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait()) - self._process = None + if self._process: # type: ignore + Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait()) # type: ignore + self._process = None # type: ignore ## Called when the global container stack changes def _onGlobalStackChanged(self) -> None: