mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-28 23:04:34 +08:00
Merge branch 'master' into CS-234_network_plugin_code_quality
This commit is contained in:
commit
b2719af0e3
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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():
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"}})]
|
Loading…
x
Reference in New Issue
Block a user