diff --git a/glotaran/parameter/parameter.py b/glotaran/parameter/parameter.py index 7027da627..f6e454be0 100644 --- a/glotaran/parameter/parameter.py +++ b/glotaran/parameter/parameter.py @@ -29,14 +29,15 @@ class Keys: VARY = "vary" +PARAMETER_EXPRESION_REGEX = re.compile(r"\$(?P[\w\d\.]+)((?![\w\d\.]+)|$)") +"""A regexpression to find and replace parameter names in expressions.""" +VALID_LABEL_REGEX = re.compile(r"\W", flags=re.ASCII) +"""A regexpression to validate labels.""" + + class Parameter(_SupportsArray): """A parameter for optimization.""" - _find_parameter = re.compile(r"(\$[\w\d\.]+)") - """A regexpression to find and replace parameter names in expressions.""" - _label_validator_regexp = re.compile(r"\W", flags=re.ASCII) - """A regexpression to validate labels.""" - def __init__( self, label: str = None, @@ -85,10 +86,10 @@ def __init__( self._transformed_expression: str | None = None - @classmethod - def valid_label(cls, label: str) -> bool: + @staticmethod + def valid_label(label: str) -> bool: """Returns true if the `label` is valid string.""" - return cls._label_validator_regexp.search(label) is None and label not in RESERVED_LABELS + return VALID_LABEL_REGEX.search(label) is None and label not in RESERVED_LABELS @classmethod def from_list_or_value( @@ -264,11 +265,9 @@ def expression(self, expression: str | None): def transformed_expression(self) -> str | None: """The expression of the parameter transformed for evaluation within a `ParameterGroup`.""" if self.expression is not None and self._transformed_expression is None: - self._transformed_expression = self.expression - for match in Parameter._find_parameter.findall(self._transformed_expression): - self._transformed_expression = self._transformed_expression.replace( - match, f"group.get('{match[1:]}').value" - ) + self._transformed_expression = PARAMETER_EXPRESION_REGEX.sub( + r"group.get('\g').value", self.expression + ) return self._transformed_expression @property diff --git a/glotaran/parameter/parameter_group.py b/glotaran/parameter/parameter_group.py index 4377294c7..52131187e 100644 --- a/glotaran/parameter/parameter_group.py +++ b/glotaran/parameter/parameter_group.py @@ -374,7 +374,7 @@ def update_parameter_expression(self): value = self._evaluator(parameter.transformed_expression) if not isinstance(value, (int, float)): raise ValueError( - f"Expression '{parameter.expression}' of parameter '{label}' evaluates to" + f"Expression '{parameter.expression}' of parameter '{label}' evaluates to " f"non numeric value '{value}'." ) parameter.value = value diff --git a/glotaran/parameter/test/test_parameter.py b/glotaran/parameter/test/test_parameter.py index ba871c151..b39111061 100644 --- a/glotaran/parameter/test/test_parameter.py +++ b/glotaran/parameter/test/test_parameter.py @@ -336,6 +336,11 @@ def test_update_parameter_group_from_array(): ("$1", "group.get('1').value"), ("$1-$2", "group.get('1').value-group.get('2').value"), ("$1-$5", "group.get('1').value-group.get('5').value"), + ( + "100 - $inputs1.s1 - $inputs1.s3 - $inputs1.s8 - $inputs1.s12", + "100 - group.get('inputs1.s1').value - group.get('inputs1.s3').value " + "- group.get('inputs1.s8').value - group.get('inputs1.s12').value", + ), ], ) def test_transform_expression(case):