Merge branch 'master' into CS-234_network_plugin_code_quality

This commit is contained in:
ChrisTerBeke 2019-08-02 15:30:04 +02:00
commit b2719af0e3
5 changed files with 54 additions and 23 deletions

View File

@ -54,13 +54,13 @@ class PlatformPhysics:
# same direction.
transformed_nodes = []
# We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
# By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
nodes = list(BreadthFirstIterator(root))
# Only check nodes inside build area.
nodes = [node for node in nodes if (hasattr(node, "_outside_buildarea") and not node._outside_buildarea)]
# We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
# By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
random.shuffle(nodes)
for node in nodes:
if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None:

View File

@ -4,7 +4,7 @@
import os
import urllib.parse
import uuid
from typing import Dict, Union, Any, TYPE_CHECKING, List
from typing import Dict, Union, Any, TYPE_CHECKING, List, cast
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtWidgets import QMessageBox
@ -438,7 +438,7 @@ class ContainerManager(QObject):
if not path:
return
container_list = [n.getContainer() for n in quality_changes_group.getAllNodes() if n.getContainer() is not None]
container_list = [cast(InstanceContainer, n.getContainer()) for n in quality_changes_group.getAllNodes() if n.getContainer() is not None]
self._container_registry.exportQualityProfile(container_list, path, file_type)
__instance = None # type: ContainerManager

View File

@ -5,10 +5,11 @@ import os
import re
import configparser
from typing import Any, cast, Dict, Optional
from typing import Any, cast, Dict, Optional, List, Union
from PyQt5.QtWidgets import QMessageBox
from UM.Decorators import override
from UM.PluginObject import PluginObject
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.Interfaces import ContainerInterface
from UM.Settings.ContainerRegistry import ContainerRegistry
@ -22,6 +23,7 @@ from UM.Platform import Platform
from UM.PluginRegistry import PluginRegistry # For getting the possible profile writers to write with.
from UM.Util import parseBool
from UM.Resources import Resources
from cura.ReaderWriters.ProfileWriter import ProfileWriter
from . import ExtruderStack
from . import GlobalStack
@ -50,10 +52,10 @@ class CuraContainerRegistry(ContainerRegistry):
# This will also try to convert a ContainerStack to either Extruder or
# Global stack based on metadata information.
@override(ContainerRegistry)
def addContainer(self, container):
def addContainer(self, container: ContainerInterface) -> None:
# Note: Intentional check with type() because we want to ignore subclasses
if type(container) == ContainerStack:
container = self._convertContainerStack(container)
container = self._convertContainerStack(cast(ContainerStack, container))
if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()):
# Check against setting version of the definition.
@ -61,7 +63,7 @@ class CuraContainerRegistry(ContainerRegistry):
actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0))
if required_setting_version != actual_setting_version:
Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version))
return #Don't add.
return # Don't add.
super().addContainer(container)
@ -71,7 +73,7 @@ class CuraContainerRegistry(ContainerRegistry):
# \param new_name \type{string} Base name, which may not be unique
# \param fallback_name \type{string} Name to use when (stripped) new_name is empty
# \return \type{string} Name that is unique for the specified type and name/id
def createUniqueName(self, container_type, current_name, new_name, fallback_name):
def createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str:
new_name = new_name.strip()
num_check = re.compile("(.*?)\s*#\d+$").match(new_name)
if num_check:
@ -92,7 +94,7 @@ class CuraContainerRegistry(ContainerRegistry):
# Both the id and the name are checked, because they may not be the same and it is better if they are both unique
# \param container_type \type{string} Type of the container (machine, quality, ...)
# \param container_name \type{string} Name to check
def _containerExists(self, container_type, container_name):
def _containerExists(self, container_type: str, container_name: str):
container_class = ContainerStack if container_type == "machine" else InstanceContainer
return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \
@ -100,11 +102,11 @@ class CuraContainerRegistry(ContainerRegistry):
## Exports an profile to a file
#
# \param instance_ids \type{list} the IDs of the profiles to export.
# \param container_list \type{list} the containers to export
# \param file_name \type{str} the full path and filename to export to.
# \param file_type \type{str} the file type with the format "<description> (*.<extension>)"
# \return True if the export succeeded, false otherwise.
def exportQualityProfile(self, container_list, file_name, file_type) -> bool:
def exportQualityProfile(self, container_list: List[InstanceContainer], file_name: str, file_type: str) -> bool:
# Parse the fileType to deduce what plugin can save the file format.
# fileType has the format "<description> (*.<extension>)"
split = file_type.rfind(" (*.") # Find where the description ends and the extension starts.
@ -126,6 +128,8 @@ class CuraContainerRegistry(ContainerRegistry):
profile_writer = self._findProfileWriter(extension, description)
try:
if profile_writer is None:
raise Exception("Unable to find a profile writer")
success = profile_writer.write(file_name, container_list)
except Exception as e:
Logger.log("e", "Failed to export profile to %s: %s", file_name, str(e))
@ -150,7 +154,7 @@ class CuraContainerRegistry(ContainerRegistry):
# \param extension
# \param description
# \return The plugin object matching the given extension and description.
def _findProfileWriter(self, extension, description):
def _findProfileWriter(self, extension: str, description: str) -> Optional[ProfileWriter]:
plugin_registry = PluginRegistry.getInstance()
for plugin_id, meta_data in self._getIOPlugins("profile_writer"):
for supported_type in meta_data["profile_writer"]: # All file types this plugin can supposedly write.
@ -158,7 +162,7 @@ class CuraContainerRegistry(ContainerRegistry):
if supported_extension == extension: # This plugin supports a file type with the same extension.
supported_description = supported_type.get("description", None)
if supported_description == description: # The description is also identical. Assume it's the same file type.
return plugin_registry.getPluginObject(plugin_id)
return cast(ProfileWriter, plugin_registry.getPluginObject(plugin_id))
return None
## Imports a profile from a file
@ -324,7 +328,7 @@ class CuraContainerRegistry(ContainerRegistry):
return {"status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type or is corrupted.", file_name)}
@override(ContainerRegistry)
def load(self):
def load(self) -> None:
super().load()
self._registerSingleExtrusionMachinesExtruderStacks()
self._connectUpgradedExtruderStacksToMachines()
@ -406,7 +410,7 @@ class CuraContainerRegistry(ContainerRegistry):
return result
## Convert an "old-style" pure ContainerStack to either an Extruder or Global stack.
def _convertContainerStack(self, container):
def _convertContainerStack(self, container: ContainerStack) -> Union[ExtruderStack.ExtruderStack, GlobalStack.GlobalStack]:
assert type(container) == ContainerStack
container_type = container.getMetaDataEntry("type")
@ -430,14 +434,14 @@ class CuraContainerRegistry(ContainerRegistry):
return new_stack
def _registerSingleExtrusionMachinesExtruderStacks(self):
def _registerSingleExtrusionMachinesExtruderStacks(self) -> None:
machines = self.findContainerStacks(type = "machine", machine_extruder_trains = {"0": "fdmextruder"})
for machine in machines:
extruder_stacks = self.findContainerStacks(type = "extruder_train", machine = machine.getId())
if not extruder_stacks:
self.addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder")
def _onContainerAdded(self, container):
def _onContainerAdded(self, container: ContainerInterface) -> None:
# We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack
# for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack
# is added, we check to see if an extruder stack needs to be added.
@ -671,7 +675,7 @@ class CuraContainerRegistry(ContainerRegistry):
return extruder_stack
def _findQualityChangesContainerInCuraFolder(self, name):
def _findQualityChangesContainerInCuraFolder(self, name: str) -> Optional[InstanceContainer]:
quality_changes_dir = Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.QualityChangesInstanceContainer)
instance_container = None
@ -684,7 +688,7 @@ class CuraContainerRegistry(ContainerRegistry):
parser = configparser.ConfigParser(interpolation = None)
try:
parser.read([file_path])
except:
except Exception:
# Skip, it is not a valid stack file
continue
@ -716,7 +720,7 @@ class CuraContainerRegistry(ContainerRegistry):
# due to problems with loading order, some stacks may not have the proper next stack
# set after upgrading, because the proper global stack was not yet loaded. This method
# makes sure those extruders also get the right stack set.
def _connectUpgradedExtruderStacksToMachines(self):
def _connectUpgradedExtruderStacksToMachines(self) -> None:
extruder_stacks = self.findContainers(container_type = ExtruderStack.ExtruderStack)
for extruder_stack in extruder_stacks:
if extruder_stack.getNextStack():

View File

@ -29,6 +29,17 @@ UM.TooltipArea
UM.ActiveTool.forceUpdate();
}
}
// When the user removes settings from the list addedSettingsModel, we need to recheck if the
// setting is visible or not to show a mark in the CheckBox.
Connections
{
target: addedSettingsModel
onVisibleCountChanged:
{
check.checked = addedSettingsModel.getVisible(model.key)
}
}
}

View File

@ -12,7 +12,7 @@ from cura.Settings.GlobalStack import GlobalStack #Testing for returning the cor
import UM.Settings.InstanceContainer #Creating instance containers to register.
import UM.Settings.ContainerRegistry #Making empty container stacks.
import UM.Settings.ContainerStack #Setting the container registry here properly.
import cura.CuraApplication
def teardown():
#If the temporary file for the legacy file rename test still exists, remove it.
@ -299,4 +299,20 @@ class TestImportProfile:
with unittest.mock.patch.object(container_registry, "createUniqueName", return_value="derp"):
with unittest.mock.patch.object(container_registry, "_configureProfile", return_value=None):
result = container_registry.importProfile("test.zomg")
assert result["status"] == "ok"
assert result["status"] == "ok"
@pytest.mark.parametrize("metadata,result", [(None, False),
({}, False),
({"setting_version": cura.CuraApplication.CuraApplication.SettingVersion}, True),
({"setting_version": 0}, False)])
def test_isMetaDataValid(container_registry, metadata, result):
assert container_registry._isMetadataValid(metadata) == result
def test_getIOPlugins(container_registry):
plugin_registry = unittest.mock.MagicMock()
plugin_registry.getActivePlugins = unittest.mock.MagicMock(return_value = ["lizard"])
plugin_registry.getMetaData = unittest.mock.MagicMock(return_value = {"zomg": {"test": "test"}})
with unittest.mock.patch("UM.PluginRegistry.PluginRegistry.getInstance", unittest.mock.MagicMock(return_value = plugin_registry)):
assert container_registry._getIOPlugins("zomg") == [("lizard", {"zomg": {"test": "test"}})]