holado 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of holado might be problematic. Click here for more details.

Files changed (32) hide show
  1. holado/__init__.py +9 -1
  2. holado/common/handlers/object.py +2 -1
  3. holado/common/handlers/undefined.py +16 -6
  4. {holado-0.2.5.dist-info → holado-0.2.7.dist-info}/METADATA +1 -1
  5. {holado-0.2.5.dist-info → holado-0.2.7.dist-info}/RECORD +32 -31
  6. holado_core/common/block/scope_steps.py +2 -2
  7. holado_core/common/resource/persisted_method_to_call_manager.py +18 -5
  8. holado_core/common/tools/tools.py +26 -9
  9. holado_core/tests/behave/steps/common/tables_steps.py +1 -1
  10. holado_helper/initialize_holado.py +72 -0
  11. holado_helper/script/action.py +21 -9
  12. holado_helper/script/initialize_script.py +3 -23
  13. holado_helper/script/script.py +2 -2
  14. holado_protobuf/ipc/protobuf/protobuf_messages.py +1 -1
  15. holado_scripting/common/tools/evaluate_parameters.py +23 -5
  16. holado_scripting/common/tools/expression_evaluator.py +115 -113
  17. holado_scripting/tests/behave/steps/scenario/if_steps.py +2 -2
  18. holado_scripting/text/interpreter/functions/function_hex_to_bytes.py +1 -1
  19. holado_scripting/text/interpreter/text_interpreter.py +20 -21
  20. holado_test/behave/behave_environment.py +31 -12
  21. holado_test/scenario/step_tools.py +11 -12
  22. holado_test/scenario/tester_tools.py +3 -1
  23. holado_value/common/tables/comparators/table_2_value_table_cell_comparator.py +3 -2
  24. holado_value/common/tables/converters/value_table_converter.py +1 -1
  25. holado_value/common/tables/value_table_cell.py +5 -1
  26. holado_value/common/tools/value.py +56 -33
  27. holado_value/common/tools/value_types.py +6 -0
  28. test_holado/features/NonReg/{ipc → holado_binary}/bit_series.feature +13 -0
  29. test_holado/features/NonReg/test_steps/common.feature +1 -1
  30. {holado-0.2.5.dist-info → holado-0.2.7.dist-info}/WHEEL +0 -0
  31. {holado-0.2.5.dist-info → holado-0.2.7.dist-info}/licenses/LICENSE +0 -0
  32. /test_holado/features/NonReg/{ipc → holado_binary}/bit_series.error.feature +0 -0
@@ -16,9 +16,9 @@
16
16
  # Usually, it is copied and adapted for specific usage.
17
17
 
18
18
  import os
19
- import sys
20
19
  import logging
21
20
  import argparse
21
+ from holado_helper.initialize_holado import insert_sys_path, insert_sys_paths
22
22
 
23
23
 
24
24
  def _chdir(path):
@@ -26,26 +26,6 @@ def _chdir(path):
26
26
  os.chdir(path)
27
27
  return res
28
28
 
29
- def __insert_sys_path(path):
30
- if path not in sys.path:
31
- sys.path.insert(0, path)
32
-
33
- def _insert_sys_paths(additional_sys_paths=None):
34
- # Insert additional paths
35
- if additional_sys_paths is not None:
36
- for sp in additional_sys_paths:
37
- __insert_sys_path(sp)
38
-
39
- # Insert Holado paths
40
- holado_path = os.getenv('HOLADO_PATH')
41
- if holado_path is None:
42
- # If HolAdo sources are not cloned on this environment, use path within this installation
43
- from holado import get_holado_path
44
- holado_path = get_holado_path()
45
- __insert_sys_path(os.path.join(holado_path) )
46
- __insert_sys_path(os.path.join(holado_path, "src") )
47
- __insert_sys_path(os.path.join(holado_path, "tests", "behave") )
48
-
49
29
  def _initialize_holado(TSessionContext=None, logging_config_file_path=None, log_level=logging.WARNING, log_in_file=False, with_session_path=False, **kwargs):
50
30
  import holado
51
31
  session_kwargs={'with_session_path':with_session_path or log_in_file}
@@ -67,7 +47,7 @@ def initialize(work_dir_path=None, change_work_dir=True,
67
47
 
68
48
  if additional_sys_paths:
69
49
  sys_paths.extend(additional_sys_paths)
70
- _insert_sys_paths(sys_paths)
50
+ insert_sys_paths(sys_paths)
71
51
 
72
52
  logging_config_file_path=None
73
53
  for dir_path in [res, work_dir_path, os.getcwd()]:
@@ -84,7 +64,7 @@ def initialize(work_dir_path=None, change_work_dir=True,
84
64
  def change_working_dir(work_dir_path=None):
85
65
  if work_dir_path:
86
66
  res = _chdir(work_dir_path)
87
- __insert_sys_path(work_dir_path)
67
+ insert_sys_path(work_dir_path)
88
68
  return res
89
69
  else:
90
70
  return None
@@ -76,7 +76,7 @@ class Script(object):
76
76
  return parser
77
77
 
78
78
  def change_working_dir(self, work_dir_path):
79
- from initialize_script import change_working_dir as init_cd # @UnresolvedImport
79
+ from holado_helper.script.initialize_script import change_working_dir as init_cd # @UnresolvedImport
80
80
 
81
81
  # If user working dir is not yet defined, save current working dir as user working dir
82
82
  if self.__user_work_dir is None:
@@ -90,7 +90,7 @@ class Script(object):
90
90
 
91
91
  def initialize(self):
92
92
  if self.args is not None and hasattr(self.args, 'log_level') and hasattr(self.args, 'log_in_file'):
93
- from initialize_script import change_logging_config # @UnresolvedImport
93
+ from holado_helper.script.initialize_script import change_logging_config # @UnresolvedImport
94
94
  change_logging_config(log_level=self.args.log_level, log_in_file=self.args.log_in_file)
95
95
 
96
96
  def run(self):
@@ -301,7 +301,7 @@ class ProtobufMessages(object):
301
301
  if ValueTableManager.verify_table_is_name_value_table(fields_table, raise_exception=False):
302
302
  self.__set_object_fields_with_name_value_table(res, fields_table)
303
303
  else:
304
- raise TechnicalException(f"When defining parameter fields_table, it must be a Name/Value table")
304
+ raise TechnicalException(f"When defining parameter fields_table, it must be a Name/Value table: [{Typing.get_object_class_fullname(fields_table)}]\n{fields_table.represent(4)}")
305
305
  elif fields_dict is not None:
306
306
  self.__set_object_fields_with_dict(res, fields_dict)
307
307
 
@@ -11,6 +11,7 @@
11
11
  #################################################
12
12
 
13
13
  import copy
14
+ from holado.common.handlers.undefined import undefined_value
14
15
 
15
16
 
16
17
  class EvaluateParameters(object):
@@ -23,7 +24,8 @@ class EvaluateParameters(object):
23
24
 
24
25
  def __init__(self, do_interpret=True, do_eval_variable=True, do_eval=True, \
25
26
  raise_on_interpret_error=True, raise_on_variable_eval_error=True, raise_on_eval_error=True,
26
- do_interpret_recursively=False, do_eval_variable_recursively=False):
27
+ do_interpret_recursively=False, do_eval_variable_recursively=False,
28
+ result_type=undefined_value):
27
29
  """
28
30
  Constructor
29
31
  @param
@@ -36,9 +38,11 @@ class EvaluateParameters(object):
36
38
  self.raise_on_interpret_error = raise_on_interpret_error
37
39
  self.raise_on_variable_eval_error = raise_on_variable_eval_error
38
40
  self.raise_on_eval_error = raise_on_eval_error
41
+ self.result_type = result_type
42
+ self.result_is_str = result_type is str
39
43
 
40
44
  def __str__(self)->str:
41
- return f"{{interpret:({self.do_interpret},recursive:{self.do_interpret_recursively},raise:{self.raise_on_interpret_error}) ; eval variable:({self.do_eval_variable},recursive:{self.do_eval_variable_recursively},raise:{self.raise_on_variable_eval_error}) ; eval:({self.do_eval},raise:{self.raise_on_eval_error})}}"
45
+ return f"{{interpret:({self.do_interpret},recursive:{self.do_interpret_recursively},raise:{self.raise_on_interpret_error}) ; eval variable:({self.do_eval_variable},recursive:{self.do_eval_variable_recursively},raise:{self.raise_on_variable_eval_error}) ; eval:({self.do_eval},raise:{self.raise_on_eval_error}) ; result type:{self.result_type}}}"
42
46
 
43
47
  def with_interpret(self, do_interpret):
44
48
  """
@@ -160,6 +164,20 @@ class EvaluateParameters(object):
160
164
  @return Same parameters but without raise
161
165
  """
162
166
  return self.with_raise(False)
167
+
168
+ def with_result_type(self, result_type=undefined_value):
169
+ """
170
+ Note: if result_type types are same, self instance is returned, else a new one is returned
171
+ @param result_type Evaluation result type
172
+ @return Same parameters but with result_type
173
+ """
174
+ if self.result_type == result_type:
175
+ return self
176
+ else:
177
+ res = copy.deepcopy(self)
178
+ res.result_type = result_type
179
+ res.result_is_str = result_type is str
180
+ return res
163
181
 
164
182
  @staticmethod
165
183
  def default(raise_exception=True):
@@ -178,7 +196,7 @@ class EvaluateParameters(object):
178
196
  @return Default evaluate parameters with raises
179
197
  """
180
198
  if EvaluateParameters.__instance_default is None:
181
- EvaluateParameters.__instance_default = EvaluateParameters(True, True, True, True, True, True)
199
+ EvaluateParameters.__instance_default = EvaluateParameters(True, True, True, True, True, True, undefined_value)
182
200
  return EvaluateParameters.__instance_default
183
201
 
184
202
  @staticmethod
@@ -187,7 +205,7 @@ class EvaluateParameters(object):
187
205
  @return Default evaluate parameters without any raise
188
206
  """
189
207
  if EvaluateParameters.__instance_default_without_raise is None:
190
- EvaluateParameters.__instance_default_without_raise = EvaluateParameters(True, True, True, False, False, False)
208
+ EvaluateParameters.__instance_default_without_raise = EvaluateParameters(True, True, True, False, False, False, undefined_value)
191
209
  return EvaluateParameters.__instance_default_without_raise
192
210
 
193
211
  @staticmethod
@@ -204,7 +222,7 @@ class EvaluateParameters(object):
204
222
  @return Default evaluate parameters without any raise
205
223
  """
206
224
  if EvaluateParameters.__instance_nothing is None:
207
- EvaluateParameters.__instance_nothing = EvaluateParameters(False, False, False, False, False, False)
225
+ EvaluateParameters.__instance_nothing = EvaluateParameters(False, False, False, False, False, False, undefined_value)
208
226
  return EvaluateParameters.__instance_nothing
209
227
 
210
228
 
@@ -25,7 +25,7 @@ from holado_scripting.common.tools.evaluate_parameters import EvaluateParameters
25
25
  from holado.holado_config import Config
26
26
  from holado_multitask.multitasking.multitask_manager import MultitaskManager
27
27
  from holado_python.standard_library.typing import Typing
28
- from holado.common.handlers.undefined import undefined_value
28
+ from holado.common.handlers.undefined import undefined_value, not_applicable
29
29
 
30
30
  logger = logging.getLogger(__name__)
31
31
 
@@ -47,52 +47,49 @@ class ExpressionEvaluator(object):
47
47
  self.__variable_manager = variable_manager
48
48
 
49
49
  def evaluate_expression(self, expression, unescape_string_method=None, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
50
- value_type, value, value_to_eval = self.extract_expression_information(expression, unescape_string_method)
50
+ value_type, value, value_to_eval = self.extract_expression_information(expression, unescape_string_method, eval_params=eval_params)
51
51
  if value_to_eval is not undefined_value:
52
- res = self.evaluate_expression_of_information(value_type, value_to_eval, eval_params=eval_params)
52
+ if ValueTypes.is_string(value_type):
53
+ eval_params = eval_params.with_result_type(str)
54
+ res_type, res = self.evaluate_expression_of_information(value_type, value_to_eval, eval_params=eval_params, log_level=log_level)
55
+ if Tools.do_log(logger, log_level):
56
+ logger.log(log_level, f"Evaluate expression [{expression}] => ({value_type.name}, {value}, '{value_to_eval}') => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
53
57
  else:
54
- res = value
55
- if Tools.do_log(logger, log_level):
56
- logger.log(log_level, f"Evaluate expression [{expression}] => ({value_type}, {value}, '{value_to_eval}') => [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
57
- return res
58
+ res_type, res = value_type, value
59
+ if Tools.do_log(logger, log_level):
60
+ logger.log(log_level, f"Evaluate expression [{expression}] => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
61
+ return res_type, res
58
62
 
59
63
  def evaluate_python_expression(self, expression, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
60
- res = self.evaluate_expression_of_information(ValueTypes.Symbol, expression, eval_params=eval_params)
64
+ res_type, res = self.evaluate_expression_of_information(ValueTypes.Symbol, expression, eval_params=eval_params, log_level=log_level)
61
65
  if Tools.do_log(logger, log_level):
62
- logger.log(log_level, f"Evaluate python expression [{expression}] => [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
63
- return res
66
+ logger.log(log_level, f"Evaluate python expression [{expression}] => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
67
+ return res_type, res
64
68
 
65
- def extract_expression_information(self, expression, unescape_string_method=None, log_level=logging.TRACE): # @UndefinedVariable
66
- res = self.__extract_expression_information(expression, unescape_string_method=unescape_string_method)
69
+ def extract_expression_information(self, expression, unescape_string_method=None, eval_params=EvaluateParameters.default(), log_level=logging.TRACE): # @UndefinedVariable
70
+ res = self.__extract_expression_information(expression, unescape_string_method=unescape_string_method, eval_params=eval_params)
67
71
  if Tools.do_log(logger, log_level):
68
72
  logger.log(log_level, f"Extract expression information [{expression}] => {res}")
69
73
  return res
70
74
 
71
- def __extract_expression_information(self, expression, unescape_string_method=None):
75
+ def __extract_expression_information(self, expression, unescape_string_method=None, eval_params=EvaluateParameters.default()):
72
76
  if isinstance(expression, str):
73
- return self.__extract_expression_information_str(expression, unescape_string_method = unescape_string_method)
77
+ return self.__extract_expression_information_str(expression, unescape_string_method=unescape_string_method, eval_params=eval_params)
74
78
  else:
75
- return self.__extract_value_information(expression)
79
+ return (*self.__extract_value_information(expression, from_symbol=False, from_str=False), undefined_value)
76
80
 
77
- def __extract_expression_information_str(self, expression, unescape_string_method=None):
81
+ def __extract_expression_information_str(self, expression, unescape_string_method=None, eval_params=EvaluateParameters.default()):
78
82
  if unescape_string_method is None:
79
83
  from holado_test.scenario.step_tools import StepTools
80
84
  unescape_string_method = StepTools.unescape_string
81
85
 
82
86
  try:
83
87
  expr_content = expression.strip()
84
-
85
- # Manage usual types
86
- if expr_content == Config.NONE_SYMBOL:
87
- return (ValueTypes.Null, None, undefined_value)
88
- elif expr_content == Config.NOT_APPLICABLE_SYMBOL:
89
- return (ValueTypes.NotApplicable, undefined_value, undefined_value)
90
- elif Converter.is_boolean(expr_content):
91
- return (ValueTypes.Boolean, Converter.to_boolean(expr_content), undefined_value)
92
- elif Converter.is_integer(expr_content):
93
- return (ValueTypes.Integer, int(expr_content), undefined_value)
94
- elif Converter.is_float(expr_content):
95
- return (ValueTypes.Float, float(expr_content), undefined_value)
88
+
89
+ # Manage usual types
90
+ value_type, value = self.__extract_value_information(expr_content, from_symbol=not eval_params.result_is_str, from_str=not eval_params.result_is_str)
91
+ if value_type != ValueTypes.String:
92
+ return (value_type, value, undefined_value)
96
93
 
97
94
  # Manage strings
98
95
  for end_sym, val_type in [(Config.DYNAMIC_SYMBOL, ValueTypes.DynamicString),
@@ -104,73 +101,73 @@ class ExpressionEvaluator(object):
104
101
  if unescape_string_method is not None:
105
102
  text = unescape_string_method(text)
106
103
  return (val_type, undefined_value, text)
107
-
108
- # # Manage evaluated values
109
- # try:
110
- # value_evaluated = eval(expr_content)
111
- # evaluated = True
112
- # except (SyntaxError, NameError, ValueError):
113
- # evaluated = False
114
- # if evaluated:
115
- # if isinstance(value_evaluated, bool):
116
- # value_type = ValueTypes.Boolean
117
- # elif isinstance(value_evaluated, int):
118
- # value_type = ValueTypes.Integer
119
- # elif isinstance(value_evaluated, float):
120
- # value_type = ValueTypes.Float
121
- # elif isinstance(value_evaluated, str):
122
- # value_type = ValueTypes.String
123
- # else:
124
- # value_type = ValueTypes.Generic
125
- # return (value_type, value_evaluated)
126
104
 
127
105
  # Else consider content as a symbol
128
106
  return (ValueTypes.Symbol, undefined_value, expr_content)
129
107
  except Exception as exc:
130
108
  raise TechnicalException(f"Error while extracting expression information in expression [{expression}] (type: {Typing.get_object_class_fullname(expression)})") from exc
131
109
 
132
- def extract_value_information(self, value):
133
- return self.__extract_value_information(value)
110
+ def extract_value_information(self, value, *, from_symbol=True, from_str=True):
111
+ return self.__extract_value_information(value, from_symbol=from_symbol, from_str=from_str)
134
112
 
135
- def __extract_value_information(self, value):
113
+ def __extract_value_information(self, value, *, from_symbol=False, from_str=False):
136
114
  if value is undefined_value:
137
- return (ValueTypes.Undefined, undefined_value, undefined_value)
115
+ return (ValueTypes.Undefined, undefined_value)
116
+ elif value is not_applicable:
117
+ return (ValueTypes.NotApplicable, not_applicable)
138
118
  elif value is None:
139
- return (ValueTypes.Null, None, undefined_value)
119
+ return (ValueTypes.Null, None)
140
120
  elif isinstance(value, bool):
141
- return (ValueTypes.Boolean, value, undefined_value)
121
+ return (ValueTypes.Boolean, value)
142
122
  elif isinstance(value, int):
143
- return (ValueTypes.Integer, value, undefined_value)
123
+ return (ValueTypes.Integer, value)
144
124
  elif isinstance(value, float):
145
- return (ValueTypes.Float, value, undefined_value)
125
+ return (ValueTypes.Float, value)
146
126
  elif isinstance(value, str):
147
- return (ValueTypes.String, value, undefined_value)
127
+ if from_symbol:
128
+ if value == Config.NONE_SYMBOL:
129
+ return (ValueTypes.Null, None)
130
+ elif value == Config.NOT_APPLICABLE_SYMBOL:
131
+ return (ValueTypes.NotApplicable, not_applicable)
132
+
133
+ if from_str:
134
+ if Converter.is_boolean(value):
135
+ return (ValueTypes.Boolean, Converter.to_boolean(value))
136
+ elif Converter.is_integer(value):
137
+ return (ValueTypes.Integer, int(value))
138
+ elif Converter.is_float(value):
139
+ return (ValueTypes.Float, float(value))
140
+
141
+ return (ValueTypes.String, value)
148
142
  else:
149
- return (ValueTypes.Generic, value, undefined_value)
143
+ return (ValueTypes.Generic, value)
150
144
 
151
- def evaluate_expression_of_information(self, value_type, value, eval_params=EvaluateParameters.default()):
152
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
153
- logger.trace(f"Evaluating expression of information ({value_type.name}, {value}, {eval_params})")
154
- res = self.__evaluate_expression_of_information(value_type, value, eval_params=eval_params)
155
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
156
- logger.trace(f"Evaluate expression of information ({value_type.name}, {value}) => [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
157
- return res
145
+ def evaluate_expression_of_information(self, value_type, value, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
146
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
147
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluating expression of information ({value_type.name}, {value}, {eval_params})") # @UndefinedVariable
148
+ res_type, res = self.__evaluate_expression_of_information(value_type, value, eval_params=eval_params, log_level=log_level)
149
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
150
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluate expression of information ({value_type.name}, {value}) => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})") # @UndefinedVariable
151
+ return res_type, res
158
152
 
159
- def __evaluate_expression_of_information(self, value_type, value, eval_params=EvaluateParameters.default()):
160
- if value_type in [ValueTypes.Null]:
161
- return None
153
+ def __evaluate_expression_of_information(self, value_type, value, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
154
+ if value_type in [ValueTypes.NotApplicable]:
155
+ return (value_type, not_applicable)
156
+ elif value_type in [ValueTypes.Null]:
157
+ return (value_type, None)
162
158
  elif value_type in [ValueTypes.Boolean, ValueTypes.Integer, ValueTypes.Float, ValueTypes.Generic]:
163
- return value
164
- elif value_type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]:
165
- return self.__evaluate_expression_of_information_string(value_type, value, eval_params=eval_params)
159
+ return (value_type, value)
160
+ elif ValueTypes.is_string(value_type):
161
+ eval_params = eval_params.with_result_type(str)
162
+ return self.__evaluate_expression_of_information_string(value_type, value, eval_params=eval_params, log_level=log_level)
166
163
  elif value_type in [ValueTypes.Symbol]:
167
- return self.__evaluate_expression_of_information_symbol(value, eval_params=eval_params)
164
+ return self.__evaluate_expression_of_information_symbol(value, eval_params=eval_params, log_level=log_level)
168
165
  else:
169
- return value
166
+ return self.__extract_value_information(value)
170
167
 
171
- def __evaluate_expression_of_information_string(self, value_type, value, eval_params=EvaluateParameters.default_without_raise()):
168
+ def __evaluate_expression_of_information_string(self, value_type, value, eval_params=EvaluateParameters.default_without_raise(), log_level=logging.DEBUG):
172
169
  if eval_params.do_interpret:
173
- res = self.__text_interpreter.interpret(value, eval_params=eval_params)
170
+ res = self.__text_interpreter.interpret(value, eval_params=eval_params, log_level=log_level)
174
171
  else:
175
172
  res = value
176
173
 
@@ -180,75 +177,80 @@ class ExpressionEvaluator(object):
180
177
  res = str(res)
181
178
 
182
179
  if value_type == ValueTypes.DynamicString:
183
- return self.__dynamic_text_manager.get(res)
180
+ res = self.__dynamic_text_manager.get(res)
184
181
  elif value_type == ValueTypes.ThreadDynamicString:
185
- return self.__dynamic_text_manager.get(res, scope=MultitaskManager.get_thread_id())
182
+ res = self.__dynamic_text_manager.get(res, scope=MultitaskManager.get_thread_id())
186
183
  elif value_type == ValueTypes.UniqueString:
187
- return res + self.__unique_value_manager.new_string(padding_length=Config.unique_string_padding_length)
188
- else:
189
- return res
184
+ res = res + self.__unique_value_manager.new_string(padding_length=Config.unique_string_padding_length)
185
+
186
+ return self.extract_value_information(res, from_symbol=not eval_params.result_is_str, from_str=not eval_params.result_is_str)
190
187
 
191
- def __evaluate_expression_of_information_symbol(self, value, eval_params=EvaluateParameters.default()):
192
- if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
193
- logger.trace(f"Evaluating symbol ([{value}], {eval_params})")
188
+ def __evaluate_expression_of_information_symbol(self, value, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
189
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
190
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluating symbol ([{value}], {eval_params})") # @UndefinedVariable
194
191
  res = value
195
192
 
196
193
  # Replace explicit interpret parts
197
194
  if eval_params.do_interpret and isinstance(res, str):
198
- res, _, is_evaluated = self.__evaluate_interpret_expression(res, eval_params=eval_params)
195
+ res, _, is_evaluated = self.__evaluate_interpret_expression(res, eval_params=eval_params, log_level=log_level)
199
196
  if is_evaluated:
200
197
  # If symbol is already evaluated, stop evaluation process
201
- if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
202
- logger.trace(f"Evaluate symbol [{value}] => [{res}] (type: {Typing.get_object_class_fullname(res)}) (after interpret, with evaluate parameters: {eval_params})")
203
- return res
198
+ # Note: evaluation of string was already done if asked, thus just evaluate symbols
199
+ res_type, res = self.__extract_value_information(res, from_symbol=not eval_params.result_is_str, from_str=not eval_params.result_is_str)
200
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
201
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluate symbol [{value}] => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (after interpret, with evaluate parameters: {eval_params})") # @UndefinedVariable
202
+ return res_type, res
204
203
  # if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
205
204
  # logger.trace(f"Evaluate symbol [{value}] - after interpret: [{res}] (type: {Typing.get_object_class_fullname(res)}) (with evaluate parameters: {eval_params})")
206
205
 
207
206
  # Evaluate variable expression
208
207
  # Note: if an eval must be done after interpret, variable shouldn't be evaluated unless it can makes failing eval
209
208
  if eval_params.do_eval_variable and isinstance(res, str) and len(res) > 0:
210
- result, is_evaluated = self.__evaluate_variable_expression(res, eval_params=eval_params)
209
+ result, is_evaluated = self.__evaluate_variable_expression(res, eval_params=eval_params, log_level=log_level)
211
210
  if is_evaluated:
212
211
  # If symbol is a variable expression, don't evaluate the result of the variable
213
- if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
214
- logger.trace(f"Evaluate symbol [{value}] => [{result}] (type: {Typing.get_object_class_fullname(result)}) (after variable evaluation, with evaluate parameters: {eval_params})")
215
- return result
212
+ res_type, res = self.__extract_value_information(result, from_symbol=False, from_str=False)
213
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
214
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluate symbol [{value}] => ({res_type.name}) [{res}] (type: {Typing.get_object_class_fullname(res)}) (after variable evaluation, with evaluate parameters: {eval_params})") # @UndefinedVariable
215
+ return res_type, res
216
216
 
217
217
  # Evaluate expression
218
218
  # if eval_params.do_eval and (isinstance(res, str) or isinstance(res, bytes)): # Commented as it doesn't work currently with bytes
219
219
  if eval_params.do_eval and isinstance(res, str):
220
- res = self.__evaluate_expression(res, locals_={}, eval_params=eval_params)
220
+ res = self.__evaluate_expression(res, locals_={}, eval_params=eval_params, log_level=log_level)
221
221
 
222
222
  # logger.debug(f"Evaluate symbol [{value}] => [{res}] (type: {Typing.get_object_class_fullname(res)})")
223
- if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
224
- logger.trace(f"Evaluate symbol [{value}] => [{res}] (type: {Typing.get_object_class_fullname(res)}) (after full evaluation, with evaluate parameters: {eval_params})")
225
- return res
223
+ # Note: evaluation of string was already done if asked, thus just evaluate symbols
224
+ res_type, res = self.__extract_value_information(res, from_symbol=not eval_params.result_is_str, from_str=not eval_params.result_is_str)
225
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
226
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Evaluate symbol [{value}] => [{res}] (type: {Typing.get_object_class_fullname(res)}) (after full evaluation, with evaluate parameters: {eval_params})") # @UndefinedVariable
227
+ return res_type, res
226
228
 
227
- def __evaluate_interpret_expression(self, value, eval_params=EvaluateParameters.default()):
229
+ def __evaluate_interpret_expression(self, value, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
228
230
  result, is_interpreted, is_evaluated = value, False, False
229
231
 
230
232
  nb_sections = self.__text_interpreter.get_number_of_sections(value)
231
233
  if nb_sections > 0:
232
234
  # If eval is authorized, and many sections exists, prefer interpret sections and eval result
233
235
  if eval_params.do_eval and nb_sections > 1:
234
- result, locals_ = self.__text_interpreter._interpret_sections(value, eval_params=eval_params)
236
+ result, locals_ = self.__text_interpreter._interpret_sections(value, eval_params=eval_params, log_level=log_level)
235
237
  if result != value:
236
- result = self.__evaluate_expression(result, locals_, eval_params=eval_params)
238
+ result = self.__evaluate_expression(result, locals_, eval_params=eval_params, log_level=log_level)
237
239
  is_evaluated = True
238
240
  else:
239
- result = self.__text_interpreter.interpret(value, eval_params=eval_params)
241
+ result = self.__text_interpreter.interpret(value, eval_params=eval_params, log_level=log_level)
240
242
  is_interpreted = result != value
241
243
 
242
244
  # Manage recursive interpret, only in case of first interpret and if it wasn't evaluated
243
245
  if eval_params.do_interpret_recursively and is_interpreted and not is_evaluated and isinstance(result, str):
244
- new_result, new_is_interpreted, new_is_evaluated = self.__evaluate_interpret_expression(result, eval_params.with_raise_on_interpret_error(False))
246
+ new_result, new_is_interpreted, new_is_evaluated = self.__evaluate_interpret_expression(result, eval_params.with_raise_on_interpret_error(False), log_level=log_level)
245
247
  if new_is_interpreted:
246
248
  result = new_result
247
249
  is_evaluated = new_is_evaluated
248
250
 
249
251
  return result, is_interpreted, is_evaluated
250
252
 
251
- def __evaluate_variable_expression(self, value, eval_params=EvaluateParameters.default()):
253
+ def __evaluate_variable_expression(self, value, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
252
254
  is_evaluated, result = False, None
253
255
 
254
256
  if self.__variable_manager.exists_variable(value):
@@ -261,20 +263,20 @@ class ExpressionEvaluator(object):
261
263
  if eval_params.raise_on_variable_eval_error:
262
264
  raise exc
263
265
  else:
264
- # logger.error(f"Error while evaluating variable expression [{value}]: {exc}")
265
- logger.error(f"Error while evaluating variable expression [{value}]: {Tools.represent_exception(exc)}\n -> traceback:\n{traceback.represent_stack(indent=4)}")
266
+ if Tools.do_log(logger, log_level):
267
+ logger.log(log_level, f"Error while evaluating variable expression [{value}]: {Tools.represent_exception(exc)}\n -> traceback:\n{traceback.represent_stack(indent=4)}")
266
268
  else:
267
269
  is_evaluated = True
268
270
 
269
271
  # Manage recursive evaluation, only in case of first variable evaluation
270
272
  if eval_params.do_eval_variable_recursively and is_evaluated and isinstance(result, str) and result != value:
271
- new_result, new_is_evaluated = self.__evaluate_variable_expression(result, eval_params.with_raise_on_variable_eval_error(False))
273
+ new_result, new_is_evaluated = self.__evaluate_variable_expression(result, eval_params.with_raise_on_variable_eval_error(False), log_level=log_level)
272
274
  if new_is_evaluated:
273
275
  result = new_result
274
276
 
275
277
  return result, is_evaluated
276
278
 
277
- def __evaluate_expression(self, value, locals_, eval_params=EvaluateParameters.default()):
279
+ def __evaluate_expression(self, value, locals_, eval_params=EvaluateParameters.default(), log_level=logging.DEBUG):
278
280
  res = value
279
281
  while True:
280
282
  try:
@@ -301,20 +303,20 @@ class ExpressionEvaluator(object):
301
303
 
302
304
  # If no import is done
303
305
  if not is_imported:
304
- if Tools.do_log(logger, logging.DEBUG):
305
- logger.debug(f"Error while evaluating expression [{value}]: {exc}")
306
+ if Tools.do_log(logger, logging.DEBUG, max_log_level=log_level):
307
+ logger.log(Tools.do_log_level(logging.DEBUG, log_level), f"Error while evaluating expression [{value}]: {exc}")
306
308
  break
307
309
  except Exception as exc:
308
310
  if eval_params.raise_on_eval_error:
309
311
  raise exc
310
312
  else:
311
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
312
- logger.trace(f"Error while evaluating expression [{value}]: {Tools.represent_exception(exc)}")
313
- elif Tools.do_log(logger, logging.DEBUG):
313
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
314
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), f"Error while evaluating expression [{value}]: {Tools.represent_exception(exc)}") # @UndefinedVariable
315
+ elif Tools.do_log(logger, logging.DEBUG, max_log_level=log_level):
314
316
  if isinstance(exc, SyntaxError):
315
- logger.debug(f"Error while evaluating expression [{value}]: {repr(exc)}")
317
+ logger.log(Tools.do_log_level(logging.DEBUG, log_level), f"Error while evaluating expression [{value}]: {repr(exc)}")
316
318
  else:
317
- logger.debug(f"Error while evaluating expression [{value}]: [{Typing.get_object_class_fullname(exc)}] {exc}")
319
+ logger.log(Tools.do_log_level(logging.DEBUG, log_level), f"Error while evaluating expression [{value}]: [{Typing.get_object_class_fullname(exc)}] {exc}")
318
320
  break
319
321
  else:
320
322
  if not isinstance(result, types.ModuleType):
@@ -374,7 +376,7 @@ class ExpressionEvaluator(object):
374
376
 
375
377
  def extract_string_value(self, expression, unescape_string_method=None, log_level=logging.DEBUG):
376
378
  value_type, value_str, value_to_eval = self.extract_expression_information(expression, unescape_string_method)
377
- if value_type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]:
379
+ if ValueTypes.is_string(value_type):
378
380
  if value_to_eval is not undefined_value:
379
381
  res = value_to_eval
380
382
  else:
@@ -382,6 +384,6 @@ class ExpressionEvaluator(object):
382
384
  else:
383
385
  res = expression
384
386
  if Tools.do_log(logger, log_level):
385
- logger.debug(f"Extract string value [{expression}] => ({value_type}, '{value_str}') => [{res}] (type: {Typing.get_object_class_fullname(res)})")
387
+ logger.log(log_level, f"Extract string value [{expression}] => ({value_type}, '{value_str}') => [{res}] (type: {Typing.get_object_class_fullname(res)})")
386
388
  return res
387
389
 
@@ -49,7 +49,7 @@ def __get_expression_evaluator():
49
49
  def step_impl(context, condition_expression):
50
50
  __get_scope_manager().log_conditions_info(f"Before evaluation of if condition expression [{condition_expression}]")
51
51
  __get_scope_manager().increase_condition_level()
52
- cond = __get_expression_evaluator().evaluate_python_expression(condition_expression)
52
+ _, cond = __get_expression_evaluator().evaluate_python_expression(condition_expression)
53
53
  if isinstance(cond, bool) or Converter.is_boolean(cond):
54
54
  if isinstance(cond, bool) and cond or Converter.is_boolean(cond) and Converter.to_boolean(cond):
55
55
  __get_scope_manager().enter_in_valid_condition()
@@ -61,7 +61,7 @@ def step_impl(context, condition_expression):
61
61
  def step_impl(context, condition_expression):
62
62
  __get_scope_manager().leave_condition()
63
63
  if not __get_scope_manager().had_valid_condition():
64
- cond = __get_expression_evaluator().evaluate_python_expression(condition_expression)
64
+ _, cond = __get_expression_evaluator().evaluate_python_expression(condition_expression)
65
65
  if isinstance(cond, bool) or Converter.is_boolean(cond):
66
66
  if isinstance(cond, bool) and cond or Converter.is_boolean(cond) and Converter.to_boolean(cond):
67
67
  __get_scope_manager().enter_in_valid_condition()
@@ -38,7 +38,7 @@ class FunctionHexToBytes(BaseFunction):
38
38
 
39
39
  # Evaluate parameter
40
40
  if isinstance(src, str):
41
- src_eval = self.__expression_evaluator.evaluate_expression(src)
41
+ _, src_eval = self.__expression_evaluator.evaluate_expression(src)
42
42
  if isinstance(src_eval, bytes) or isinstance(src_eval, str):
43
43
  src = src_eval
44
44
  else: