Skip to content

Commit

Permalink
Merge pull request #914 from Ultimaker/CURA-11155-formulas-in-start-e…
Browse files Browse the repository at this point in the history
…nd-code

Formulas in start/end code
  • Loading branch information
saumyaj3 authored Oct 16, 2023
2 parents 66907d2 + eca460f commit 6745624
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions UM/Settings/SettingFunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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.
Expand All @@ -91,27 +93,30 @@ 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()
for name in self._used_values:
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:
Expand Down

0 comments on commit 6745624

Please sign in to comment.