Coverage for gws-app/gws/plugin/model_value/expression/__init__.py: 0%

31 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-05 13:35 +0200

1"""Expression value. 

2 

3Computes the value by evaluating a Python expression. The expression is 

4compiled at configuration time; a syntax error is a configuration error. 

5 

6The following variables are available in the expression: 

7 

8- ``app``: the Application object, 

9- ``user``: the current user, 

10- ``project``: the current project, 

11- ``feature``: the feature the value is computed for, 

12- ``mc``: the ``gws.ModelContext`` object, 

13- ``date``: the ``gws.lib.datetimex`` module. 

14 

15Additional modules can be made available with the ``imports`` option, a list 

16of module names, e.g. ``["math", "os"]``. Each module is available under its 

17name. If a module cannot be imported or the evaluation fails, the error is 

18logged and the value is None. 

19 

20Example:: 

21 

22 fields+ { 

23 name "area_ha" 

24 type "float" 

25 values+ { 

26 type "expression" 

27 expression "round(feature.get('area_m2', 0) / 10000, 2)" 

28 } 

29 } 

30""" 

31 

32from typing import Optional 

33import gws 

34import gws.base.model.value 

35import gws.lib.datetimex 

36 

37 

38@gws.ext.config.modelValue('expression') 

39class Config(gws.base.model.value.Config): 

40 """Value computed by a Python expression.""" 

41 

42 expression: str 

43 """Python expression to evaluate.""" 

44 

45 imports: Optional[list[str]] 

46 """Additional Python modules available to the expression.""" 

47 

48 

49@gws.ext.object.modelValue('expression') 

50class Object(gws.base.model.value.Object): 

51 """Expression value object.""" 

52 

53 expression: str 

54 """Python expression to evaluate.""" 

55 imports: list[str] 

56 """Names of modules imported for the expression.""" 

57 

58 def configure(self): 

59 self.expression = (self.cfg('expression') or '').strip() 

60 self.imports = self.cfg('imports') or [] 

61 try: 

62 compile(self.expression, 'expression', 'eval') 

63 except Exception as exc: 

64 raise gws.ConfigurationError(f'invalid expression: {exc!r}') from exc 

65 

66 def compute(self, field, feature, mc): 

67 context = { 

68 'app': self.root.app, 

69 'user': mc.user, 

70 'project': mc.project, 

71 'feature': feature, 

72 'mc': mc, 

73 'date': gws.lib.datetimex, 

74 } 

75 for mod in self.imports: 

76 try: 

77 context[mod] = __import__(mod) 

78 except ImportError as exc: 

79 gws.log.error(f'failed to import module {mod!r}: {exc!r}') 

80 return 

81 

82 try: 

83 return eval(self.expression, context) 

84 except Exception as exc: 

85 gws.log.error(f'failed to compute expression: {exc!r}')