def _onContainerLoadComplete(self, container_id): container = ContainerRegistry.getInstance().findContainers( id=container_id)[0] if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return material_settings_category = container.findDefinitions(key="material") klipper_settings_category = container.findDefinitions( key=self._category_key) if material_settings_category and not klipper_settings_category: # this machine doesn't have a GCODE Offset setting yet material_settings_category = material_settings_category[0] klipper_settings_category = SettingDefinition( self._category_key, container, None, self._i18n_catalog) category_dict = self._category_dict category_dict["children"] = OrderedDict() klipper_gcode_offset_definition = SettingDefinition( self._setting_k_g_offset_key, container, klipper_settings_category, self._i18n_catalog) klipper_gcode_offset_definition.deserialize( self._setting_k_g_offset_dict) klipper_pa_definition = SettingDefinition( self._setting_k_pa_key, container, klipper_settings_category, self._i18n_catalog) klipper_pa_definition.deserialize(self._setting_k_pa_dict) klipper_pa_l_definition = SettingDefinition( self._setting_k_pa_l_key, container, klipper_settings_category, self._i18n_catalog) klipper_pa_l_definition.deserialize(self._setting_k_pa_l_dict) category_dict["children"][ self._setting_k_g_offset_key] = self._setting_k_g_offset_dict category_dict["children"][ self._setting_k_pa_key] = self._setting_k_pa_dict category_dict["children"][ self._setting_k_pa_l_key] = self._setting_k_pa_l_dict klipper_settings_category.deserialize(category_dict) container.addDefinition(klipper_settings_category) container._updateRelations(klipper_settings_category)
def deserialize(self, serialized: str, file_name: Optional[str] = None) -> str: # update the serialized data first serialized = super().deserialize(serialized, file_name) parsed, is_valid = self.readAndValidateSerialized(serialized) # Update properties with the data from the JSON old_id = self.getId( ) #The ID must be set via the constructor. Retain it. self._metadata = parsed["metadata"] self._metadata["id"] = old_id self._metadata["name"] = parsed["name"] self._metadata[ "version"] = self.Version #Guaranteed to be equal to what's in the parsed data by the validation. self._metadata["container_type"] = DefinitionContainer for key, value in parsed["settings"].items(): definition = SettingDefinition(key, self, None, self._i18n_catalog) definition.deserialize(value) self._definitions.append(definition) for definition in self._definitions: self._updateRelations(definition) return serialized
def _onContainerLoadComplete(self, container_id): container = ContainerRegistry.getInstance().findContainers( id=container_id)[0] if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return material_category = container.findDefinitions(key="material") linear_advance_setting = container.findDefinitions( key=self._setting_key) if material_category and not linear_advance_setting: # this machine doesn't have a Linear Advance setting yet material_category = material_category[0] linear_advance_definition = SettingDefinition( self._setting_key, container, material_category, self._i18n_catalog) linear_advance_definition.deserialize(self._setting_dict) # add the setting to the already existing meterial settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff material_category._children.append(linear_advance_definition) container._definition_cache[ self._setting_key] = linear_advance_definition container._updateRelations(linear_advance_definition)
def _onContainerLoadComplete(self, container_id): if not ContainerRegistry.getInstance().isLoaded(container_id): # skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop return try: container = ContainerRegistry.getInstance().findContainers(id = container_id)[0] except IndexError: # the container no longer exists return if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return cooling_category = container.findDefinitions(key="cooling") cooling_chamber_setting = container.findDefinitions(key=list(self._settings_dict.keys())[0]) if cooling_category and not cooling_chamber_setting: # this machine doesn't have a cooling chamber setting yet cooling_category = cooling_category[0] for setting_key, setting_dict in self._settings_dict.items(): definition = SettingDefinition(setting_key, container, cooling_category, self._i18n_catalog) definition.deserialize(setting_dict) cooling_category._children.append(definition) container._definition_cache[setting_key] = definition container._updateRelations(definition)
def _processFunction(self, definition: SettingDefinition, property_name: str) -> None: try: function = getattr(definition, property_name) except AttributeError: return if not isinstance(function, SettingFunction): return for setting in function.getUsedSettingKeys(): # Prevent circular relations between the same setting and the same property # Note that the only property used by SettingFunction is the "value" property, which # is why this is hard coded here. if setting == definition.key and property_name == "value": Logger.log( "w", "Found circular relation for property 'value' between {0} and {1}", definition.key, setting) continue other = self._getDefinition(setting) if not other: other = SettingDefinition(setting) relation = SettingRelation(definition, other, RelationType.RequiresTarget, property_name) definition.relations.append(relation) relation = SettingRelation(other, definition, RelationType.RequiredByTarget, property_name) other.relations.append(relation)
def _onContainerLoadComplete(self, container_id): if not ContainerRegistry.getInstance().isLoaded(container_id): # skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop return try: container = ContainerRegistry.getInstance().findContainers(id = container_id)[0] except IndexError: # the container no longer exists return if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return platform_adhesion_category = container.findDefinitions(key="platform_adhesion") fh_setting = container.findDefinitions(key=list(self._settings_dict.keys())[0]) if platform_adhesion_category and not fh_setting: # this machine doesn't have a zoffset setting yet platform_adhesion_category = platform_adhesion_category[0] for setting_key, setting_dict in self._settings_dict.items(): setting_definition = SettingDefinition(setting_key, container, platform_adhesion_category, self._i18n_catalog) setting_definition.deserialize(setting_dict) # add the setting to the already existing platform adhesion settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff platform_adhesion_category._children.append(setting_definition) container._definition_cache[setting_key] = setting_definition container._updateRelations(setting_definition)
def benchmark_findDefinitions(benchmark, filter, match_count): definition = SettingDefinition("test", None) definition.deserialize({ "label": "Test", "type": "int", "default_value": 10, "description": "Test Setting", "children": { "test_child_1": { "label": "Test Child 1", "type": "int", "default_value": 20, "description": "Test Child Setting 1" }, "test_child_2": { "label": "Test Child 2", "type": "int", "default_value": 20, "description": "Test Child Setting 2" } } }) result = benchmark(definition.findDefinitions, **filter) assert len(result) == match_count
def _createSettingDefinition(properties): result = SettingDefinition(properties["key"]) # Key MUST be present. if "default_value" in properties: result._SettingDefinition__property_values["default_value"] = properties["default_value"] # Nota bene: Setting a private value depends on implementation, but changing a property is not currently exposed. result._SettingDefinition__property_values["description"] = "Test setting definition" result._SettingDefinition__property_values["type"] = "str" if "children" in properties: for child in properties["children"]: result.children.append(_createSettingDefinition(child)) return result
def _onContainerLoadComplete(self, container_id: str) -> None: if not ContainerRegistry.getInstance().isLoaded(container_id): # skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop return try: container = ContainerRegistry.getInstance().findContainers(id = container_id)[0] except IndexError: # the container no longer exists return if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return try: category = container.findDefinitions(key="blackmagic")[0] except IndexError: Logger.log("e", "Could not find parent category setting to add settings to") return for setting_key in self._settings_dict.keys(): setting_definition = SettingDefinition(setting_key, container, category, self._i18n_catalog) setting_definition.deserialize(self._settings_dict[setting_key]) # add the setting to the already existing blackmagic settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff category._children.append(setting_definition) container._definition_cache[setting_key] = setting_definition self._expanded_categories = self._application.expandedCategories.copy() self._updateAddedChildren(container, setting_definition) self._application.setExpandedCategories(self._expanded_categories) self._expanded_categories = [] # type: List[str] container._updateRelations(setting_definition) preferences = self._application.getPreferences() if not preferences.getValue("arcwelderplugin/settings_made_visible"): setting_keys = self._getAllSettingKeys(self._settings_dict) visible_settings = preferences.getValue("general/visible_settings") visible_settings_changed = False for key in setting_keys: if key not in visible_settings: visible_settings += ";%s" % key visible_settings_changed = True if visible_settings_changed: preferences.setValue("general/visible_settings", visible_settings) preferences.setValue("arcwelderplugin/settings_made_visible", True)
def create_and_attach_setting(self, container, setting_key, setting_dict, parent): parent_category = container.findDefinitions(key=parent) definition = container.findDefinitions(key=setting_key) if parent_category and not definition: # this machine doesn't have a scalable extra prime setting yet parent_category = parent_category[0] setting_definition = SettingDefinition(setting_key, container, parent_category, self._i18n_catalog) setting_definition.deserialize(setting_dict) parent_category._children.append(setting_definition) container._definition_cache[setting_key] = setting_definition container._updateRelations(setting_definition)
def deserialize(self, serialized): # update the serialized data first serialized = super().deserialize(serialized) parsed = self._readAndValidateSerialized(serialized) # Update properties with the data from the JSON self._name = parsed["name"] self._metadata = parsed["metadata"] for key, value in parsed["settings"].items(): definition = SettingDefinition(key, self, None, self._i18n_catalog) definition.deserialize(value) self._definitions.append(definition) for definition in self._definitions: self._updateRelations(definition)
def _onContainerLoadComplete(self, container_id): if not ContainerRegistry.getInstance().isLoaded(container_id): # skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop return try: container = ContainerRegistry.getInstance().findContainers(id = container_id)[0] except IndexError: # the container no longer exists return if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return machine_settings_category = container.findDefinitions(key="machine_settings") printer_settings_category = container.findDefinitions(key=self._category_key) if machine_settings_category and not printer_settings_category: # this machine doesn't have a printer_settings category yet machine_settings_category = machine_settings_category[0] printer_settings_category = SettingDefinition(self._category_key, container, None, self._i18n_catalog) category_dict = self._category_dict category_dict["children"] = OrderedDict() for setting in machine_settings_category.children: if setting.key not in self._hidden_settings: setting_dict = setting.serialize_to_dict() # Some settings values come out of serialize_to_dict with a = prepended, which does not deserialize nicely for key in ["value", "enabled", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning"]: if key in setting_dict and setting_dict[key][0] == "=": setting_dict[key] = setting_dict[key][1:] # Boolean values are deserialised as string for (key, value) in setting_dict.items(): if value == "True": setting_dict[key] = True if value == "False": setting_dict[key] = False category_dict["children"][setting.key] = setting_dict printer_settings_category.deserialize(category_dict) container.addDefinition(printer_settings_category) container._updateRelations(printer_settings_category)
def _onContainerLoadComplete(self, container_id: str) -> None: if not ContainerRegistry.getInstance().isLoaded(container_id): # skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop return try: container = ContainerRegistry.getInstance().findContainers( id=container_id)[0] except IndexError: # the container no longer exists return if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return try: material_category = container.findDefinitions(key="material")[0] except IndexError: Logger.log( "e", "Could not find parent category setting to add settings to") return for setting_key in self._settings_dict.keys(): setting_definition = SettingDefinition(setting_key, container, material_category, self._i18n_catalog) setting_definition.deserialize(self._settings_dict[setting_key]) # add the setting to the already existing material settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff material_category._children.append(setting_definition) container._definition_cache[setting_key] = setting_definition self._expanded_categories = self._application.expandedCategories.copy( ) self._updateAddedChildren(container, setting_definition) self._application.setExpandedCategories(self._expanded_categories) self._expanded_categories = [] # type: List[str] container._updateRelations(setting_definition)
def deserialize(self, serialized): parsed = json.loads(serialized, object_pairs_hook=collections.OrderedDict) self._verifyJson(parsed) # Pre-process the JSON data to include inherited data and overrides if "inherits" in parsed: inherited = self._resolveInheritance(parsed["inherits"]) parsed = self._mergeDicts(inherited, parsed) if "overrides" in parsed: for key, value in parsed["overrides"].items(): setting = self._findInDict(parsed["settings"], key) if setting is None: Logger.log("w", "Unable to override setting %s", key) else: setting.update(value) # If we do not have metadata or settings the file is invalid if not "metadata" in parsed: raise InvalidDefinitionError("Missing required metadata section") if not "settings" in parsed: raise InvalidDefinitionError("Missing required settings section") # Update properties with the data from the JSON self._name = parsed["name"] self._metadata = parsed["metadata"] for key, value in parsed["settings"].items(): definition = SettingDefinition(key, self, None, self._i18n_catalog) definition.deserialize(value) self._definitions.append(definition) for definition in self._definitions: self._updateRelations(definition)
def test_valueChanges(container_registry): setting_property_provider = SettingPropertyProvider() # First create the basics; A container stack that will hold 2 instance containers and a single definition container container_stack = ContainerStack("test!") instance_container = InstanceContainer("data") second_instance_container = InstanceContainer("data2") definition_container = DefinitionContainer("foo") # Create a setting definition for our one and only setting! setting_definition = SettingDefinition("test_setting") setting_definition._deserialize_dict({"value": 10, "label": "blorp", "type": "float", "description": "nah", "maximum_value": 23, "maximum_value_warning": 21, "enabled": "test_setting != 20"}) definition_container.addDefinition(setting_definition) # Make a single setting instance for our one and only setting. setting_instance = SettingInstance(setting_definition, instance_container) setting_instance.setProperty("value", 20) setting_instance.setProperty("enabled", False) instance_container.addInstance(setting_instance) # Make a setting instance that lives in our second instance_container setting_instance2 = SettingInstance(setting_definition, second_instance_container) second_instance_container.addInstance(setting_instance2) # Now that both containers are done, actually add them. container_stack.addContainer(definition_container) container_stack.addContainer(second_instance_container) container_stack.addContainer(instance_container) setting_property_provider.setContainerStack(container_stack) setting_property_provider.setKey("test_setting") assert setting_property_provider.key == "test_setting" assert setting_property_provider.getPropertyValue("value", 0) == 20 setting_property_provider.setWatchedProperties(["enabled", "value", "validationState"]) setting_property_provider._update() assert setting_property_provider.watchedProperties == ["enabled", "value", "validationState"] assert setting_property_provider.properties.value("enabled") == "False" assert setting_property_provider.properties.value("value") == "20" # Validator state is a special property that gets added based on the type and the value assert setting_property_provider.properties.value("validationState") == str(ValidatorState.Valid) # Set the property value to something that will trigger a warning setting_property_provider.setPropertyValue("value", 22) assert setting_property_provider.properties.value("validationState") == str(ValidatorState.MaximumWarning) assert setting_property_provider.getPropertyValue("value", 0) == 22 # The setting doesn't exist in our second instance container, so this should be None assert setting_property_provider.getPropertyValue("value", 1) is None # Set the property value to something that will trigger an error setting_property_provider.setPropertyValue("value", 25) # The Qtimer that we use to prevent flooding doesn't work in tests, so tickle the change manually. setting_property_provider._update() assert setting_property_provider.properties.value("validationState") == str(ValidatorState.MaximumError) # We now ask for the second instance container to be targeted setting_property_provider.setStoreIndex(1) assert setting_property_provider.storeIndex == 1 setting_property_provider.setPropertyValue("value", 2) setting_property_provider._update() # So now we should see a change in that instance container assert setting_property_provider.getPropertyValue("value", 1) == 2 # But not if we ask the provider, because the container above it still has a 25 as value! assert setting_property_provider.getPropertyValue("value", 0) == 25 assert setting_property_provider.stackLevels == [0, 1, 2] # We're asking for an index that doesn't exist. assert setting_property_provider.getPropertyValue("value", 2000) is None # The value is used, so the property must be true assert setting_property_provider.isValueUsed # Try to remove the setting from the container setting_property_provider.removeFromContainer(0) assert setting_property_provider.getPropertyValue("value", 0) is None # Ensure that a weird index doesn't break setting_property_provider.removeFromContainer(90001)
def _onContainerLoadComplete(self, container_id): container = ContainerRegistry.getInstance().findContainers( id=container_id)[0] if not isinstance(container, DefinitionContainer): # skip containers that are not definitions return if container.getMetaDataEntry("type") == "extruder": # skip extruder definitions return material_category1 = container.findDefinitions( key="material") # Pressure Advance material_category2 = container.findDefinitions( key="material") # Pressure Advance Lookahead speed_category1 = container.findDefinitions( key="speed") # square corner velocity speed_category4 = container.findDefinitions( key="speed") # acceleration speed_category2 = container.findDefinitions( key="speed") # acceleration to deceleration speed_category3 = container.findDefinitions( key="speed") # acceleration order pressure_advance_setting = container.findDefinitions( key=self._setting_key_klipper_pressure_advance) pressure_advance_lookahead_setting = container.findDefinitions( key=self._setting_key_klipper_pressure_advance_lookahead) square_corner_velocity_setting = container.findDefinitions( key=self._setting_key_square_corner_velocity) acceleration_setting = container.findDefinitions( key=self._setting_key_klipper_acceleration) acceleration_to_deceleration_setting = container.findDefinitions( key=self._setting_key_klipper_acceleration_to_deceleration) acceleration_order_setting = container.findDefinitions( key=self._setting_key_klipper_acceleration_order) # Pressure Advance Lookahead if material_category2 and not pressure_advance_lookahead_setting: # this machine doesn't have a Pressure Advance setting yet material_category2 = material_category2[0] pressure_advance_lookahead_definition = SettingDefinition( self._setting_key_klipper_pressure_advance_lookahead, container, material_category2, self._i18n_catalog) pressure_advance_lookahead_definition.deserialize( self._setting_dict_klipper_pressure_advance_lookahead) # add the setting to the already existing PA setting definition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff material_category2._children.append( pressure_advance_lookahead_definition) container._definition_cache[ self. _setting_key_klipper_pressure_advance_lookahead] = pressure_advance_lookahead_definition container._updateRelations(pressure_advance_lookahead_definition) # Pressure Advance if material_category1 and not pressure_advance_setting: # this machine doesn't have a Pressure Advance setting yet material_category1 = material_category1[0] pressure_advance_definition = SettingDefinition( self._setting_key_klipper_pressure_advance, container, material_category1, self._i18n_catalog) pressure_advance_definition.deserialize( self._setting_dict_klipper_pressure_advance) # add the setting to the already existing PA setting definition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff material_category1._children.append(pressure_advance_definition) container._definition_cache[ self. _setting_key_klipper_pressure_advance] = pressure_advance_definition container._updateRelations(pressure_advance_definition) # Square Corner Velocity if speed_category1 and not square_corner_velocity_setting: # this machine doesn't have a Square Corner Velocity setting yet speed_category1 = speed_category1[0] square_corner_velocity_definition = SettingDefinition( self._setting_key_square_corner_velocity, container, speed_category1, self._i18n_catalog) square_corner_velocity_definition.deserialize( self._setting_dict_square_corner_velocity) # add the setting to the already existing speed settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff speed_category1._children.append(square_corner_velocity_definition) container._definition_cache[ self. _setting_key_square_corner_velocity] = square_corner_velocity_definition container._updateRelations(square_corner_velocity_definition) # Acceleration if speed_category4 and not acceleration_setting: # this machine doesn't have a Acceleration setting yet speed_category4 = speed_category4[0] klipper_acceleration_definition = SettingDefinition( self._setting_key_klipper_acceleration, container, speed_category4, self._i18n_catalog) klipper_acceleration_definition.deserialize( self._setting_dict_klipper_acceleration) # add the setting to the already existing speed settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff speed_category4._children.append(klipper_acceleration_definition) container._definition_cache[ self. _setting_key_klipper_acceleration] = klipper_acceleration_definition container._updateRelations(klipper_acceleration_definition) # Acceleration to Deceleration if speed_category2 and not acceleration_to_deceleration_setting: # this machine doesn't have a Acceleration to deceleration setting yet speed_category2 = speed_category2[0] klipper_acceleration_to_deceleration_definition = SettingDefinition( self._setting_key_klipper_acceleration_to_deceleration, container, speed_category2, self._i18n_catalog) klipper_acceleration_to_deceleration_definition.deserialize( self._setting_dict_klipper_acceleration_to_deceleration) # add the setting to the already existing speed settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff speed_category2._children.append( klipper_acceleration_to_deceleration_definition) container._definition_cache[ self. _setting_key_klipper_acceleration_to_deceleration] = klipper_acceleration_to_deceleration_definition container._updateRelations( klipper_acceleration_to_deceleration_definition) # Acceleration Order if speed_category3 and not acceleration_order_setting: # this machine doesn't have a Acceleration to deceleration setting yet speed_category3 = speed_category3[0] klipper_acceleration_order_definition = SettingDefinition( self._setting_key_klipper_acceleration_order, container, speed_category3, self._i18n_catalog) klipper_acceleration_order_definition.deserialize( self._setting_dict_klipper_acceleration_order) # add the setting to the already existing speed settingdefinition # private member access is naughty, but the alternative is to serialise, nix and deserialise the whole thing, # which breaks stuff speed_category3._children.append( klipper_acceleration_order_definition) container._definition_cache[ self. _setting_key_klipper_acceleration_order] = klipper_acceleration_order_definition container._updateRelations(klipper_acceleration_order_definition)