From 39362ba278d80212977ab8c70d8b390a10f6a662 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Thu, 12 Oct 2023 21:09:10 +0200 Subject: [PATCH] Make sure default variables are available in start/end code The following properties are not settings-names, but could previously be used as template variables - material_id - time - date - day - initial_extruder_nr - material_id - material_name - material_type - material_brand - time - date - day - initial_extruder_nr These properties are _awkwardly_ propogated through the kwargs of the `get_value` method of `GcodeStartEndFormatter`. I don't quite like implementing it like this, but to avoid API breaks I couldn't change abusing the kwargs arg for this purpose. CURA-11155 --- UM/Settings/SettingFunction.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/UM/Settings/SettingFunction.py b/UM/Settings/SettingFunction.py index f2f50a53a..fb0d998f8 100644 --- a/UM/Settings/SettingFunction.py +++ b/UM/Settings/SettingFunction.py @@ -53,11 +53,12 @@ def __init__(self, expression: str) -> None: self._code = expression # Keys of all settings that are referenced to in this function. - self._used_keys = frozenset() # type: FrozenSet[str] - self._used_values = frozenset() # type: FrozenSet[str] + self._used_keys: FrozenSet[str] = frozenset() + self._used_values: FrozenSet[str] = frozenset() - self._compiled = None # type: Optional[CodeType] #Actually an Optional['code'] object, but Python doesn't properly expose this 'code' object via any library. - self._valid = False # type: bool + # Actually an Optional['code'] object, but Python doesn't properly expose this 'code' object via any library. + self._compiled: Optional[CodeType] = None + self._valid: bool = False self._safeCompile() @@ -78,7 +79,8 @@ def _safeCompile(self): except Exception as e: Logger.log("e", "Exception in function ({0}) for setting: {1}".format(str(e), self._code)) - def __call__(self, value_provider: ContainerInterface, context: Optional[PropertyEvaluationContext] = None) -> Any: + def __call__(self, value_provider: ContainerInterface, context: Optional[PropertyEvaluationContext] = None, *, + additional_variables: Optional[Dict[str, Any]] = None) -> Any: """Call the actual function to calculate the value. :param value_provider: The container from which to get setting values in the formula. @@ -91,7 +93,7 @@ def __call__(self, value_provider: ContainerInterface, context: Optional[Propert if not self._valid: return None - locals = {} # type: Dict[str, Any] + local_variables: Dict[str, Any] = {} # If there is a context, evaluate the values from the perspective of the original caller if context is not None: value_provider = context.rootStack() @@ -99,19 +101,22 @@ def __call__(self, value_provider: ContainerInterface, context: Optional[Propert value = value_provider.getProperty(name, "value", context) if value is None: continue + local_variables[name] = value - locals[name] = value + if additional_variables is not None: + for name, value in additional_variables.items(): + local_variables[name] = value - g = {} # type: Dict[str, Any] - g.update(globals()) - g.update(self.__operators) + globals_variables: Dict[str, Any] = {} + globals_variables.update(globals()) + globals_variables.update(self.__operators) # Override operators if there is any in the context if context is not None: - g.update(context.context.get("override_operators", {})) + globals_variables.update(context.context.get("override_operators", {})) try: if self._compiled: - return eval(self._compiled, g, locals) + return eval(self._compiled, globals_variables, local_variables) Logger.log("e", "An error occurred evaluating the function {0}.".format(self)) return 0 except Exception as e: