Merge remote-tracking branch 'origin/master'

This commit is contained in:
Nino van Hooff 2020-06-23 14:47:01 +02:00
commit 2e0489c509
18 changed files with 138 additions and 36 deletions

13
.github/no-response.yml vendored Normal file
View File

@ -0,0 +1,13 @@
# Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 14
# Label requiring a response
responseRequiredLabel: 'Status: Needs Info'
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Please reach out if you have or find the answers we need so
that we can investigate further.

View File

@ -80,8 +80,11 @@ class Arrange:
# After scaling (like up to 0.1 mm) the node might not have points # After scaling (like up to 0.1 mm) the node might not have points
if not points.size: if not points.size:
continue continue
try:
shape_arr = ShapeArray.fromPolygon(points, scale = scale) shape_arr = ShapeArray.fromPolygon(points, scale = scale)
except ValueError:
Logger.logException("w", "Unable to create polygon")
continue
arranger.place(0, 0, shape_arr) arranger.place(0, 0, shape_arr)
# If a build volume was set, add the disallowed areas # If a build volume was set, add the disallowed areas

View File

@ -31,7 +31,6 @@ class AutoSave:
self._change_timer.timeout.connect(self._onTimeout) self._change_timer.timeout.connect(self._onTimeout)
self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged) self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
self._onGlobalStackChanged() self._onGlobalStackChanged()
self._triggerTimer()
def _triggerTimer(self, *args: Any) -> None: def _triggerTimer(self, *args: Any) -> None:
if not self._saving: if not self._saving:

View File

@ -215,6 +215,16 @@ class CrashHandler:
locale.getdefaultlocale()[0] locale.getdefaultlocale()[0]
self.data["locale_cura"] = self.cura_locale self.data["locale_cura"] = self.cura_locale
try:
from cura.CuraApplication import CuraApplication
plugins = CuraApplication.getInstance().getPluginRegistry()
self.data["plugins"] = {
plugin_id: plugins.getMetaData(plugin_id)["plugin"]["version"]
for plugin_id in plugins.getInstalledPlugins() if not plugins.isBundledPlugin(plugin_id)
}
except:
self.data["plugins"] = {"[FAILED]": "0.0.0"}
crash_info = "<b>" + catalog.i18nc("@label Cura version number", "Cura version") + ":</b> " + str(self.cura_version) + "<br/>" crash_info = "<b>" + catalog.i18nc("@label Cura version number", "Cura version") + ":</b> " + str(self.cura_version) + "<br/>"
crash_info += "<b>" + catalog.i18nc("@label", "Cura language") + ":</b> " + str(self.cura_locale) + "<br/>" crash_info += "<b>" + catalog.i18nc("@label", "Cura language") + ":</b> " + str(self.cura_locale) + "<br/>"
crash_info += "<b>" + catalog.i18nc("@label", "OS language") + ":</b> " + str(self.data["locale_os"]) + "<br/>" crash_info += "<b>" + catalog.i18nc("@label", "OS language") + ":</b> " + str(self.data["locale_os"]) + "<br/>"
@ -238,6 +248,8 @@ class CrashHandler:
scope.set_tag("locale_cura", self.cura_locale) scope.set_tag("locale_cura", self.cura_locale)
scope.set_tag("is_enterprise", ApplicationMetadata.IsEnterpriseVersion) scope.set_tag("is_enterprise", ApplicationMetadata.IsEnterpriseVersion)
scope.set_context("plugins", self.data["plugins"])
scope.set_user({"id": str(uuid.getnode())}) scope.set_user({"id": str(uuid.getnode())})
return group return group

View File

@ -756,7 +756,6 @@ class CuraApplication(QtApplication):
if not hasattr(sys, "frozen"): if not hasattr(sys, "frozen"):
self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins")) self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))
self._plugin_registry.loadPlugin("ConsoleLogger") self._plugin_registry.loadPlugin("ConsoleLogger")
self._plugin_registry.loadPlugin("CuraEngineBackend")
self._plugin_registry.loadPlugins() self._plugin_registry.loadPlugins()

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from copy import deepcopy from copy import deepcopy
@ -119,9 +119,9 @@ class CuraSceneNode(SceneNode):
self._aabb = None self._aabb = None
if self._mesh_data: if self._mesh_data:
self._aabb = self._mesh_data.getExtents(self.getWorldTransformation()) self._aabb = self._mesh_data.getExtents(self.getWorldTransformation())
else: # If there is no mesh_data, use a boundingbox that encompasses the local (0,0,0) else: # If there is no mesh_data, use a bounding box that encompasses the local (0,0,0)
position = self.getWorldPosition() position = self.getWorldPosition()
self._aabb = AxisAlignedBox(minimum=position, maximum=position) self._aabb = AxisAlignedBox(minimum = position, maximum = position)
for child in self.getAllChildren(): for child in self.getAllChildren():
if child.callDecoration("isNonPrintingMesh"): if child.callDecoration("isNonPrintingMesh"):

View File

@ -60,6 +60,8 @@ class CuraContainerStack(ContainerStack):
import cura.CuraApplication #Here to prevent circular imports. import cura.CuraApplication #Here to prevent circular imports.
self.setMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) self.setMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion)
self.setDirty(False)
# This is emitted whenever the containersChanged signal from the ContainerStack base class is emitted. # This is emitted whenever the containersChanged signal from the ContainerStack base class is emitted.
pyqtContainersChanged = pyqtSignal() pyqtContainersChanged = pyqtSignal()

View File

@ -32,6 +32,8 @@ class ExtruderStack(CuraContainerStack):
self.propertiesChanged.connect(self._onPropertiesChanged) self.propertiesChanged.connect(self._onPropertiesChanged)
self.setDirty(False)
enabledChanged = pyqtSignal() enabledChanged = pyqtSignal()
@override(ContainerStack) @override(ContainerStack)

View File

@ -55,6 +55,8 @@ class GlobalStack(CuraContainerStack):
# properties. So we need to tie them together like this. # properties. So we need to tie them together like this.
self.metaDataChanged.connect(self.configuredConnectionTypesChanged) self.metaDataChanged.connect(self.configuredConnectionTypesChanged)
self.setDirty(False)
extrudersChanged = pyqtSignal() extrudersChanged = pyqtSignal()
configuredConnectionTypesChanged = pyqtSignal() configuredConnectionTypesChanged = pyqtSignal()

View File

@ -738,14 +738,15 @@ class MachineManager(QObject):
containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id) containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id)
for container in containers: for container in containers:
CuraContainerRegistry.getInstance().removeContainer(container["id"]) CuraContainerRegistry.getInstance().removeContainer(container["id"])
machine_stack = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", name = machine_id)[0] machine_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", name = machine_id)
CuraContainerRegistry.getInstance().removeContainer(machine_stack.definitionChanges.getId()) if machine_stacks:
CuraContainerRegistry.getInstance().removeContainer(machine_stacks[0].definitionChanges.getId())
CuraContainerRegistry.getInstance().removeContainer(machine_id) CuraContainerRegistry.getInstance().removeContainer(machine_id)
# If the printer that is being removed is a network printer, the hidden printers have to be also removed # If the printer that is being removed is a network printer, the hidden printers have to be also removed
group_id = metadata.get("group_id", None) group_id = metadata.get("group_id", None)
if group_id: if group_id:
metadata_filter = {"group_id": group_id} metadata_filter = {"group_id": group_id, "hidden": True}
hidden_containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter) hidden_containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
if hidden_containers: if hidden_containers:
# This reuses the method and remove all printers recursively # This reuses the method and remove all printers recursively
@ -1368,7 +1369,6 @@ class MachineManager(QObject):
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self.switchPrinterType(configuration.printerType) self.switchPrinterType(configuration.printerType)
disabled_used_extruder_position_set = set()
extruders_to_disable = set() extruders_to_disable = set()
# If an extruder that's currently used to print a model gets disabled due to the syncing, we need to show # If an extruder that's currently used to print a model gets disabled due to the syncing, we need to show
@ -1377,8 +1377,8 @@ class MachineManager(QObject):
for extruder_configuration in configuration.extruderConfigurations: for extruder_configuration in configuration.extruderConfigurations:
# We support "" or None, since the cloud uses None instead of empty strings # We support "" or None, since the cloud uses None instead of empty strings
extruder_has_hotend = extruder_configuration.hotendID and extruder_configuration.hotendID != "" extruder_has_hotend = extruder_configuration.hotendID not in ["", None]
extruder_has_material = extruder_configuration.material.guid and extruder_configuration.material.guid != "" extruder_has_material = extruder_configuration.material.guid not in [None, "", "00000000-0000-0000-0000-000000000000"]
# If the machine doesn't have a hotend or material, disable this extruder # If the machine doesn't have a hotend or material, disable this extruder
if not extruder_has_hotend or not extruder_has_material: if not extruder_has_hotend or not extruder_has_material:
@ -1396,7 +1396,6 @@ class MachineManager(QObject):
self._global_container_stack.extruderList[int(position)].setEnabled(False) self._global_container_stack.extruderList[int(position)].setEnabled(False)
need_to_show_message = True need_to_show_message = True
disabled_used_extruder_position_set.add(int(position))
else: else:
machine_node = ContainerTree.getInstance().machines.get(self._global_container_stack.definition.getId()) machine_node = ContainerTree.getInstance().machines.get(self._global_container_stack.definition.getId())
@ -1427,7 +1426,7 @@ class MachineManager(QObject):
# Show human-readable extruder names such as "Extruder Left", "Extruder Front" instead of "Extruder 1, 2, 3". # Show human-readable extruder names such as "Extruder Left", "Extruder Front" instead of "Extruder 1, 2, 3".
extruder_names = [] extruder_names = []
for extruder_position in sorted(disabled_used_extruder_position_set): for extruder_position in sorted(extruders_to_disable):
extruder_stack = self._global_container_stack.extruderList[int(extruder_position)] extruder_stack = self._global_container_stack.extruderList[int(extruder_position)]
extruder_name = extruder_stack.definition.getName() extruder_name = extruder_stack.definition.getName()
extruder_names.append(extruder_name) extruder_names.append(extruder_name)

View File

@ -67,4 +67,4 @@ cmake3 \
-DBUILD_TESTS=ON \ -DBUILD_TESTS=ON \
.. ..
make make
ctest3 --output-on-failure -T Test ctest3 -j4 --output-on-failure -T Test

View File

@ -651,7 +651,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._container_registry.addContainer(global_stack) self._container_registry.addContainer(global_stack)
else: else:
# Find the machine # Find the machine
global_stack = self._container_registry.findContainerStacks(name = self._machine_info.name, type = "machine")[0] global_stacks = self._container_registry.findContainerStacks(name = self._machine_info.name, type = "machine")
if not global_stacks:
message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tag <filename>!", "Project file <filename>{0}</filename> is made using profiles that are unknown to this version of Ultimaker Cura.", file_name))
message.show()
self.setWorkspaceName("")
return [], {}
global_stack = global_stacks[0]
extruder_stacks = self._container_registry.findContainerStacks(machine = global_stack.getId(), extruder_stacks = self._container_registry.findContainerStacks(machine = global_stack.getId(),
type = "extruder_train") type = "extruder_train")
extruder_stack_dict = {stack.getMetaDataEntry("position"): stack for stack in extruder_stacks} extruder_stack_dict = {stack.getMetaDataEntry("position"): stack for stack in extruder_stacks}

View File

@ -204,10 +204,11 @@ class PauseAtHeight(Script):
"""Get the X and Y values for a layer (will be used to get X and Y of the layer after the pause).""" """Get the X and Y values for a layer (will be used to get X and Y of the layer after the pause)."""
lines = layer.split("\n") lines = layer.split("\n")
for line in lines: for line in lines:
if self.getValue(line, "X") is not None and self.getValue(line, "Y") is not None: if line.startswith(("G0", "G1", "G2", "G3")):
x = self.getValue(line, "X") if self.getValue(line, "X") is not None and self.getValue(line, "Y") is not None:
y = self.getValue(line, "Y") x = self.getValue(line, "X")
return x, y y = self.getValue(line, "Y")
return x, y
return 0, 0 return 0, 0
def execute(self, data: List[str]) -> List[str]: def execute(self, data: List[str]) -> List[str]:

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2020 Ultimaker B.V.
# Toolbox is released under the terms of the LGPLv3 or higher. # Toolbox is released under the terms of the LGPLv3 or higher.
import json import json
@ -232,7 +232,7 @@ class Toolbox(QObject, Extension):
"licenseModel": self._license_model "licenseModel": self._license_model
}) })
if not dialog: if not dialog:
raise Exception("Failed to create Marketplace dialog") return None
return dialog return dialog
def _convertPluginMetadata(self, plugin_data: Dict[str, Any]) -> Optional[Dict[str, Any]]: def _convertPluginMetadata(self, plugin_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:

View File

@ -31,6 +31,7 @@ class CloudOutputDeviceManager:
""" """
META_CLUSTER_ID = "um_cloud_cluster_id" META_CLUSTER_ID = "um_cloud_cluster_id"
META_HOST_GUID = "host_guid"
META_NETWORK_KEY = "um_network_key" META_NETWORK_KEY = "um_network_key"
SYNC_SERVICE_NAME = "CloudOutputDeviceManager" SYNC_SERVICE_NAME = "CloudOutputDeviceManager"
@ -113,13 +114,18 @@ class CloudOutputDeviceManager:
all_clusters = {c.cluster_id: c for c in clusters} # type: Dict[str, CloudClusterResponse] all_clusters = {c.cluster_id: c for c in clusters} # type: Dict[str, CloudClusterResponse]
online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse] online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse]
# Add the new printers in Cura. If a printer was previously added and is rediscovered, set its metadata to # Add the new printers in Cura.
# reflect that and mark the printer not removed from the account
for device_id, cluster_data in all_clusters.items(): for device_id, cluster_data in all_clusters.items():
if device_id not in self._remote_clusters: if device_id not in self._remote_clusters:
new_clusters.append(cluster_data) new_clusters.append(cluster_data)
if device_id in self._um_cloud_printers and not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")): if device_id in self._um_cloud_printers:
self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True) # Existing cloud printers may not have the host_guid meta-data entry. If that's the case, add it.
if not self._um_cloud_printers[device_id].getMetaDataEntry(self.META_HOST_GUID, None):
self._um_cloud_printers[device_id].setMetaDataEntry(self.META_HOST_GUID, cluster_data.host_guid)
# If a printer was previously not linked to the account and is rediscovered, mark the printer as linked
# to the current account
if not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
self._onDevicesDiscovered(new_clusters) self._onDevicesDiscovered(new_clusters)
# Hide the current removed_printers_message, if there is any # Hide the current removed_printers_message, if there is any
@ -161,11 +167,22 @@ class CloudOutputDeviceManager:
""" """
new_devices = [] new_devices = []
remote_clusters_added = False remote_clusters_added = False
host_guid_map = {machine.getMetaDataEntry(self.META_HOST_GUID): device_cluster_id
for device_cluster_id, machine in self._um_cloud_printers.items()
if machine.getMetaDataEntry(self.META_HOST_GUID)}
machine_manager = CuraApplication.getInstance().getMachineManager()
for cluster_data in clusters: for cluster_data in clusters:
device = CloudOutputDevice(self._api, cluster_data) device = CloudOutputDevice(self._api, cluster_data)
# Create a machine if we don't already have it. Do not make it the active machine. # If the machine already existed before, it will be present in the host_guid_map
machine_manager = CuraApplication.getInstance().getMachineManager() if cluster_data.host_guid in host_guid_map:
machine = machine_manager.getMachine(device.printerType, {self.META_HOST_GUID: cluster_data.host_guid})
if machine and machine.getMetaDataEntry(self.META_CLUSTER_ID) != device.key:
# If the retrieved device has a different cluster_id than the existing machine, bring the existing
# machine up-to-date.
self._updateOutdatedMachine(outdated_machine = machine, new_cloud_output_device = device)
# Create a machine if we don't already have it. Do not make it the active machine.
# We only need to add it if it wasn't already added by "local" network or by cloud. # We only need to add it if it wasn't already added by "local" network or by cloud.
if machine_manager.getMachine(device.printerType, {self.META_CLUSTER_ID: device.key}) is None \ if machine_manager.getMachine(device.printerType, {self.META_CLUSTER_ID: device.key}) is None \
and machine_manager.getMachine(device.printerType, {self.META_NETWORK_KEY: cluster_data.host_name + "*"}) is None: # The host name is part of the network key. and machine_manager.getMachine(device.printerType, {self.META_NETWORK_KEY: cluster_data.host_name + "*"}) is None: # The host name is part of the network key.
@ -239,17 +256,42 @@ class CloudOutputDeviceManager:
num_hidden = len(new_devices) - max_disp_devices + 1 num_hidden = len(new_devices) - max_disp_devices + 1
device_name_list = ["<li>{} ({})</li>".format(device.name, device.printerTypeName) for device in new_devices[0:num_hidden]] device_name_list = ["<li>{} ({})</li>".format(device.name, device.printerTypeName) for device in new_devices[0:num_hidden]]
device_name_list.append(self.I18N_CATALOG.i18nc("info:hidden list items", "<li>... and {} others</li>", num_hidden)) device_name_list.append(self.I18N_CATALOG.i18nc("info:hidden list items", "<li>... and {} others</li>", num_hidden))
device_names = "\n".join(device_name_list) device_names = "".join(device_name_list)
else: else:
device_names = "\n".join(["<li>{} ({})</li>".format(device.name, device.printerTypeName) for device in new_devices]) device_names = "".join(["<li>{} ({})</li>".format(device.name, device.printerTypeName) for device in new_devices])
message_text = self.I18N_CATALOG.i18nc( message_text = self.I18N_CATALOG.i18nc(
"info:status", "info:status",
"Cloud printers added from your account:\n<ul>{}</ul>", "Cloud printers added from your account:<ul>{}</ul>",
device_names device_names
) )
message.setText(message_text) message.setText(message_text)
def _updateOutdatedMachine(self, outdated_machine: GlobalStack, new_cloud_output_device: CloudOutputDevice) -> None:
"""
Update the cloud metadata of a pre-existing machine that is rediscovered (e.g. if the printer was removed and
re-added to the account) and delete the old CloudOutputDevice related to this machine.
:param outdated_machine: The cloud machine that needs to be brought up-to-date with the new data received from
the account
:param new_cloud_output_device: The new CloudOutputDevice that should be linked to the pre-existing machine
:return: None
"""
old_cluster_id = outdated_machine.getMetaDataEntry(self.META_CLUSTER_ID)
outdated_machine.setMetaDataEntry(self.META_CLUSTER_ID, new_cloud_output_device.key)
outdated_machine.setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
# Cleanup the remainings of the old CloudOutputDevice(old_cluster_id)
self._um_cloud_printers[new_cloud_output_device.key] = self._um_cloud_printers.pop(old_cluster_id)
output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
if old_cluster_id in output_device_manager.getOutputDeviceIds():
output_device_manager.removeOutputDevice(old_cluster_id)
if old_cluster_id in self._remote_clusters:
# We need to close the device so that it stops checking for its status
self._remote_clusters[old_cluster_id].close()
del self._remote_clusters[old_cluster_id]
self._remote_clusters[new_cloud_output_device.key] = new_cloud_output_device
def _devicesRemovedFromAccount(self, removed_device_ids: Set[str]) -> None: def _devicesRemovedFromAccount(self, removed_device_ids: Set[str]) -> None:
""" """
Removes the CloudOutputDevice from the received device ids and marks the specific printers as "removed from Removes the CloudOutputDevice from the received device ids and marks the specific printers as "removed from
@ -378,6 +420,7 @@ class CloudOutputDeviceManager:
def _setOutputDeviceMetadata(self, device: CloudOutputDevice, machine: GlobalStack): def _setOutputDeviceMetadata(self, device: CloudOutputDevice, machine: GlobalStack):
machine.setName(device.name) machine.setName(device.name)
machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
machine.setMetaDataEntry(self.META_HOST_GUID, device.clusterData.host_guid)
machine.setMetaDataEntry("group_name", device.name) machine.setMetaDataEntry("group_name", device.name)
machine.setMetaDataEntry("group_size", device.clusterSize) machine.setMetaDataEntry("group_size", device.clusterSize)
machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc( machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc(

View File

@ -4474,6 +4474,19 @@
"enabled": "support_enable or support_meshes_present", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_bottom_stair_step_min_slope":
{
"label": "Support Stair Step Minimum Slope Angle",
"description": "The minimum slope of the area for stair-stepping to take effect. Low values should make support easier to remove on shallower slopes, but really low values may result in some very counter-intuitive results on other parts of the model.",
"unit": "°",
"type": "float",
"default_value": 10.0,
"limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr",
"minimum_value": "0.01",
"maximum_value": "89.99",
"enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true
},
"support_join_distance": "support_join_distance":
{ {
"label": "Support Join Distance", "label": "Support Join Distance",

View File

@ -153,6 +153,9 @@ class MockContainer(ContainerInterface, UM.PluginObject.PluginObject):
def isDirty(self): def isDirty(self):
return True return True
def setDirty(self, dirty):
pass
metaDataChanged = Signal() metaDataChanged = Signal()
propertyChanged = Signal() propertyChanged = Signal()
containersChanged = Signal() containersChanged = Signal()

View File

@ -12,7 +12,7 @@ from unittest.mock import patch, MagicMock
import UM.Settings.ContainerRegistry #To create empty instance containers. import UM.Settings.ContainerRegistry #To create empty instance containers.
import UM.Settings.ContainerStack #To set the container registry the container stacks use. import UM.Settings.ContainerStack #To set the container registry the container stacks use.
from UM.Settings.DefinitionContainer import DefinitionContainer #To check against the class of DefinitionContainer. from UM.Settings.DefinitionContainer import DefinitionContainer #To check against the class of DefinitionContainer.
from UM.VersionUpgradeManager import FilesDataUpdateResult
from UM.Resources import Resources from UM.Resources import Resources
Resources.addSearchPath(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources"))) Resources.addSearchPath(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources")))
@ -36,6 +36,7 @@ def definition_container():
assert result.getId() == uid assert result.getId() == uid
return result return result
@pytest.mark.parametrize("file_path", definition_filepaths) @pytest.mark.parametrize("file_path", definition_filepaths)
def test_definitionIds(file_path): def test_definitionIds(file_path):
""" """
@ -45,6 +46,7 @@ def test_definitionIds(file_path):
definition_id = os.path.basename(file_path).split(".")[0] definition_id = os.path.basename(file_path).split(".")[0]
assert " " not in definition_id # Definition IDs are not allowed to have spaces. assert " " not in definition_id # Definition IDs are not allowed to have spaces.
@pytest.mark.parametrize("file_path", definition_filepaths) @pytest.mark.parametrize("file_path", definition_filepaths)
def test_noCategory(file_path): def test_noCategory(file_path):
""" """
@ -57,6 +59,7 @@ def test_noCategory(file_path):
metadata = DefinitionContainer.deserializeMetadata(json, "test_container_id") metadata = DefinitionContainer.deserializeMetadata(json, "test_container_id")
assert "category" not in metadata[0] assert "category" not in metadata[0]
@pytest.mark.parametrize("file_path", machine_filepaths) @pytest.mark.parametrize("file_path", machine_filepaths)
def test_validateMachineDefinitionContainer(file_path, definition_container): def test_validateMachineDefinitionContainer(file_path, definition_container):
"""Tests all definition containers""" """Tests all definition containers"""
@ -65,13 +68,12 @@ def test_validateMachineDefinitionContainer(file_path, definition_container):
if file_name == "fdmprinter.def.json" or file_name == "fdmextruder.def.json": if file_name == "fdmprinter.def.json" or file_name == "fdmextruder.def.json":
return # Stop checking, these are root files. return # Stop checking, these are root files.
from UM.VersionUpgradeManager import FilesDataUpdateResult
mocked_vum = MagicMock() mocked_vum = MagicMock()
mocked_vum.updateFilesData = lambda ct, v, fdl, fnl: FilesDataUpdateResult(ct, v, fdl, fnl) mocked_vum.updateFilesData = lambda ct, v, fdl, fnl: FilesDataUpdateResult(ct, v, fdl, fnl)
with patch("UM.VersionUpgradeManager.VersionUpgradeManager.getInstance", MagicMock(return_value = mocked_vum)): with patch("UM.VersionUpgradeManager.VersionUpgradeManager.getInstance", MagicMock(return_value = mocked_vum)):
assertIsDefinitionValid(definition_container, file_path) assertIsDefinitionValid(definition_container, file_path)
def assertIsDefinitionValid(definition_container, file_path): def assertIsDefinitionValid(definition_container, file_path):
with open(file_path, encoding = "utf-8") as data: with open(file_path, encoding = "utf-8") as data:
json = data.read() json = data.read()
@ -86,6 +88,7 @@ def assertIsDefinitionValid(definition_container, file_path):
if "platform_texture" in metadata[0]: if "platform_texture" in metadata[0]:
assert metadata[0]["platform_texture"] in all_images assert metadata[0]["platform_texture"] in all_images
@pytest.mark.parametrize("file_path", definition_filepaths) @pytest.mark.parametrize("file_path", definition_filepaths)
def test_validateOverridingDefaultValue(file_path: str): def test_validateOverridingDefaultValue(file_path: str):
"""Tests whether setting values are not being hidden by parent containers. """Tests whether setting values are not being hidden by parent containers.
@ -189,7 +192,9 @@ def test_noId(file_path: str):
@pytest.mark.parametrize("file_path", extruder_filepaths) @pytest.mark.parametrize("file_path", extruder_filepaths)
def test_extruderMatch(file_path: str): def test_extruderMatch(file_path: str):
"""Verifies that extruders say that they work on the same extruder_nr as what is listed in their machine definition.""" """
Verifies that extruders say that they work on the same extruder_nr as what is listed in their machine definition.
"""
extruder_id = os.path.basename(file_path).split(".")[0] extruder_id = os.path.basename(file_path).split(".")[0]
with open(file_path, encoding = "utf-8") as f: with open(file_path, encoding = "utf-8") as f: