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
@@ -60,12 +60,11 @@ class TextInterpreter(TextInspecter):
60
60
  if str_to_interpret is None:
61
61
  return None
62
62
 
63
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
64
-
65
- logger.trace("Interpreting '{}'...".format(str_to_interpret))
63
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
64
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), "Interpreting '{}'...".format(str_to_interpret)) # @UndefinedVariable
66
65
 
67
66
  # Interpret and get result as object
68
- res, _ = self.__interpret(str_to_interpret, eval_params=eval_params)
67
+ res, _ = self.__interpret(str_to_interpret, eval_params=eval_params, log_level=log_level)
69
68
 
70
69
  if Tools.do_log_if_objects_are_different(logger, log_level, str_to_interpret, res):
71
70
  logger.log(log_level, "Interpreting '{}' -> [{}] (type: {})".format(str_to_interpret, res, type(res)))
@@ -82,18 +81,17 @@ class TextInterpreter(TextInspecter):
82
81
  if str_to_interpret is None:
83
82
  return None
84
83
 
85
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
86
-
87
- logger.trace("Interpreting sections in '{}'...".format(str_to_interpret))
84
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
85
+ logger.log(Tools.do_log_level(logging.TRACE, log_level), "Interpreting sections in '{}'...".format(str_to_interpret)) # @UndefinedVariable
88
86
 
89
87
  # Interpret and get result as object
90
- res, locals_ = self.__interpret(str_to_interpret, replace_sections_by_variables=True, eval_params=eval_params)
88
+ res, locals_ = self.__interpret(str_to_interpret, replace_sections_by_variables=True, eval_params=eval_params, log_level=log_level)
91
89
 
92
90
  if Tools.do_log_if_objects_are_different(logger, log_level, str_to_interpret, res):
93
91
  logger.log(log_level, f"Interpreting sections in '{str_to_interpret}' -> [{res}] (type: {type(res)}, locals: {locals_})")
94
92
  return res, locals_
95
93
 
96
- def __interpret(self, str_to_interpret, replace_sections_by_variables=False, eval_params=EvaluateParameters.default_without_raise()):
94
+ def __interpret(self, str_to_interpret, replace_sections_by_variables=False, eval_params=EvaluateParameters.default_without_raise(), log_level=logging.DEBUG):
97
95
  res = None
98
96
  locals_ = {}
99
97
 
@@ -103,7 +101,7 @@ class TextInterpreter(TextInspecter):
103
101
  r_match = self.__regex_to_be_interpreted.match(str_to_interpret)
104
102
  if r_match:
105
103
  str_under_interpret = r_match.group(1).strip()
106
- res = self.__interpret_text(str_under_interpret, eval_params=eval_params)
104
+ res = self.__interpret_text(str_under_interpret, eval_params=eval_params, log_level=log_level)
107
105
  # Text is not interpretable ; expect it will be the case later
108
106
  if res == str_under_interpret:
109
107
  res = str_to_interpret
@@ -112,19 +110,20 @@ class TextInterpreter(TextInspecter):
112
110
  else:
113
111
  raise TechnicalException(f"Failed to find interpret section whereas its indexes were found")
114
112
  else:
115
- res, locals_ = self.__find_and_interpret_sections(str_to_interpret, replace_sections_by_variables=replace_sections_by_variables, eval_params=eval_params)
113
+ res, locals_ = self.__find_and_interpret_sections(str_to_interpret, replace_sections_by_variables=replace_sections_by_variables, eval_params=eval_params, log_level=log_level)
116
114
 
117
115
  return res, locals_
118
116
 
119
- def __interpret_text(self, text, eval_params=EvaluateParameters.default_without_raise()):
117
+ def __interpret_text(self, text, eval_params=EvaluateParameters.default_without_raise(), log_level=logging.DEBUG): # @UndefinedVariable
120
118
  # Manage functions
121
119
  if self._has_function(text, with_interpreted=False):
122
- return self.__evaluate_function(text, eval_params=eval_params)
120
+ return self.__evaluate_function(text, eval_params=eval_params, log_level=log_level)
123
121
 
124
122
  # Manage evaluation
125
- return self._expression_evaluator.evaluate_expression(text, eval_params=eval_params, log_level=logging.TRACE) # @UndefinedVariable
123
+ _, res = self._expression_evaluator.evaluate_expression(text, eval_params=eval_params, log_level=Tools.do_log_level(log_level, logging.TRACE)) # @UndefinedVariable
124
+ return res
126
125
 
127
- def __find_and_interpret_sections(self, str_to_interpret, replace_sections_by_variables=False, eval_params=EvaluateParameters.default_without_raise()):
126
+ def __find_and_interpret_sections(self, str_to_interpret, replace_sections_by_variables=False, eval_params=EvaluateParameters.default_without_raise(), log_level=logging.DEBUG):
128
127
  res = str_to_interpret
129
128
  locals_ = {}
130
129
 
@@ -145,7 +144,7 @@ class TextInterpreter(TextInspecter):
145
144
  sub_str = res[ind_beg:ind_end]
146
145
 
147
146
  # Interpret sub-section
148
- interpreted_value = self.interpret(sub_str, eval_params=eval_params)
147
+ interpreted_value = self.interpret(sub_str, eval_params=eval_params, log_level=log_level)
149
148
 
150
149
  # Manage sections that aren't interpretable
151
150
  interpreted_str = f"{interpreted_value}"
@@ -170,7 +169,7 @@ class TextInterpreter(TextInspecter):
170
169
 
171
170
  return res, locals_
172
171
 
173
- def __evaluate_function(self, fct_str, eval_params=EvaluateParameters.default_without_raise()):
172
+ def __evaluate_function(self, fct_str, eval_params=EvaluateParameters.default_without_raise(), log_level=logging.DEBUG):
174
173
  func_name, args_str = self._get_function_and_args_strings(fct_str, with_interpreted=False)
175
174
  func = self._get_function(func_name) if func_name is not None else None
176
175
  if func is None:
@@ -178,8 +177,8 @@ class TextInterpreter(TextInspecter):
178
177
 
179
178
  args = self._get_args(args_str)
180
179
 
181
- if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
182
- logger.trace(f"Evaluating function '{func_name}' with args {args}")
180
+ if Tools.do_log(logger, logging.TRACE, max_log_level=log_level): # @UndefinedVariable
181
+ logger.log(Tools.do_log_level(logging.TRACE, max_log_level=log_level), f"Evaluating function '{func_name}' with args {args}") # @UndefinedVariable
183
182
  # logger.trace(f"Evaluating function '{func_name}' with args {args} (eval_params: {eval_params})", stack_info=True)
184
183
  try:
185
184
  res = func.apply(args)
@@ -189,8 +188,8 @@ class TextInterpreter(TextInspecter):
189
188
  else:
190
189
  res = fct_str
191
190
 
192
- if Tools.do_log(logger, logging.DEBUG):
193
- logger.debug(f"Evaluate function [{fct_str}] => [{func_name}({', '.join(args)})] => [{res}] (type: {Typing.get_object_class_fullname(res)})")
191
+ if Tools.do_log(logger, log_level):
192
+ logger.log(log_level, f"Evaluate function [{fct_str}] => [{func_name}({', '.join(args)})] => [{res}] (type: {Typing.get_object_class_fullname(res)})")
194
193
  return res
195
194
 
196
195
  def __register_default_functions(self, dynamic_text_manager):
@@ -22,6 +22,8 @@ from holado_test.behave.scenario.behave_step_tools import BehaveStepTools
22
22
  from holado_test.scenario.step_tools import StepTools
23
23
  from holado_test.test_config import TestConfig
24
24
  import time
25
+ from behave.model_core import Status
26
+ from holado.common.handlers.undefined import undefined_value
25
27
 
26
28
 
27
29
  logger = logging.getLogger(__name__)
@@ -107,23 +109,40 @@ def after_step(context, step):
107
109
  # Session context
108
110
  SessionContext.instance().after_step(step)
109
111
 
110
- # Log failures
111
- if step.status == "failed":
112
- step_descr = __step_description(step)
113
- var_step_descr = StepTools.evaluate_variable_name(step_descr)
114
- interpreted_step_descr = StepTools.evaluate_string_parameter(step_descr)
115
- msg = "Step failed:\n step:\n{}{}{}\n error:\n{}\n step attributes:\n{}".format(
116
- Tools.indent_string(8, step_descr),
112
+ # Log step result
113
+ step_descr = __step_description(step)
114
+ try:
115
+ var_step_descr = StepTools.evaluate_variable_name(step_descr, log_level=logging.NOTSET)
116
+ except:
117
+ var_step_descr = "[ERROR during evaluation]"
118
+ try:
119
+ interpreted_step_descr = StepTools.evaluate_string_parameter(step_descr, log_level=logging.NOTSET)
120
+ except:
121
+ interpreted_step_descr = "[ERROR during interpretation]"
122
+ if step.status in [Status.failed, Status.error] or interpreted_step_descr != step_descr or var_step_descr != interpreted_step_descr:
123
+ msg = "Step {}:\n step:\n{}{}{}".format(
124
+ step.status.name, Tools.indent_string(8, step_descr),
117
125
  "" if interpreted_step_descr == step_descr else "\n interpreted step:\n{}".format(Tools.indent_string(8, interpreted_step_descr)),
118
- "" if var_step_descr == interpreted_step_descr else "\n partially interpreted step:\n{}".format(Tools.indent_string(8, var_step_descr)),
119
- Tools.indent_string(8, __step_error(step)),
120
- Tools.indent_string(8, __step_attributes(step)) )
121
- if step.hook_failed:
122
- msg += "\n Hook failed"
126
+ "" if var_step_descr == interpreted_step_descr else "\n partially interpreted step:\n{}".format(Tools.indent_string(8, var_step_descr)) )
127
+
128
+ if step.status in [Status.failed, Status.error]:
129
+ msg += "\n error:\n{}\n step attributes:\n{}".format(
130
+ Tools.indent_string(8, __step_error(step)),
131
+ Tools.indent_string(8, __step_attributes(step)) )
132
+ if step.hook_failed:
133
+ msg += "\n Hook failed"
134
+ elif '\n' in step_descr:
135
+ msg = "Step {}:\n{}".format(step.status.name, Tools.indent_string(4, step_descr))
136
+ else:
137
+ msg = "Step {}: {}".format(step.status.name, step_descr)
138
+
139
+ if step.status in [Status.failed, Status.error]:
123
140
  logger.error(msg)
124
141
 
125
142
  if TestConfig.wait_on_step_failure_s > 0:
126
143
  time.sleep(TestConfig.wait_on_step_failure_s)
144
+ else:
145
+ logger.debug(msg)
127
146
  except:
128
147
  logger.exception(f"Hook error (step: {step})")
129
148
  raise
@@ -78,7 +78,6 @@ class StepTools(object):
78
78
  res = text.encode('latin-1').decode('unicode-escape')
79
79
 
80
80
  if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
81
-
82
81
  logger.trace("unescaping string [{}] -> [{}]".format(text, res))
83
82
  return res
84
83
 
@@ -88,8 +87,8 @@ class StepTools(object):
88
87
 
89
88
  @staticmethod
90
89
  def evaluate_string_parameter(text_param, do_interpret=True, log_level=logging.DEBUG):
91
- eval_params = EvaluateParameters.default().with_interpret(do_interpret).with_eval(False)
92
- res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=logging.TRACE) # @UndefinedVariable
90
+ eval_params = EvaluateParameters.default().with_interpret(do_interpret).with_eval(False).with_result_type(str)
91
+ _, res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=Tools.do_log_level(log_level, logging.TRACE)) # @UndefinedVariable
93
92
  if Tools.do_log_if_objects_are_different(logger, log_level, text_param, res):
94
93
  logger.log(log_level, "evaluate_string_parameter: [{}] -> [{}]".format(text_param, res))
95
94
  return res
@@ -99,8 +98,8 @@ class StepTools(object):
99
98
  if text_param is None:
100
99
  return None
101
100
 
102
- eval_params = EvaluateParameters.default_without_eval(False)
103
- res = StepTools._get_text_interpreter().interpret(text_param, eval_params=eval_params, log_level=logging.TRACE) # @UndefinedVariable
101
+ eval_params = EvaluateParameters.default_without_eval(False).with_result_type(str)
102
+ res = StepTools._get_text_interpreter().interpret(text_param, eval_params=eval_params, log_level=Tools.do_log_level(log_level, logging.TRACE)) # @UndefinedVariable
104
103
  if Tools.do_log_if_objects_are_different(logger, log_level, text_param, res):
105
104
  logger.log(log_level, f"evaluate_variable_name: [{text_param}] -> [{res}] (type: {Typing.get_object_class_fullname(res)})")
106
105
  return res
@@ -111,7 +110,7 @@ class StepTools(object):
111
110
  return None
112
111
 
113
112
  eval_params = EvaluateParameters.default_without_eval(False)
114
- res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=logging.TRACE) # @UndefinedVariable
113
+ _, res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=Tools.do_log_level(log_level, logging.TRACE)) # @UndefinedVariable
115
114
  if Tools.do_log_if_objects_are_different(logger, log_level, text_param, res):
116
115
  logger.log(log_level, f"evaluate_variable_name: [{text_param}] -> [{res}] (type: {Typing.get_object_class_fullname(res)})")
117
116
  return res
@@ -122,14 +121,14 @@ class StepTools(object):
122
121
  return None
123
122
 
124
123
  eval_params = EvaluateParameters.default().with_raise_on_eval_error(False)
125
- res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=logging.TRACE) # @UndefinedVariable
124
+ _, res = StepTools._get_expression_evaluator().evaluate_expression(text_param, eval_params=eval_params, log_level=Tools.do_log_level(log_level, logging.TRACE)) # @UndefinedVariable
126
125
  if Tools.do_log_if_objects_are_different(logger, log_level, text_param, res):
127
126
  logger.log(log_level, f"evaluate_scenario_parameter: [{text_param}] -> [{res}] (type: {Typing.get_object_class_fullname(res)})")
128
127
  return res
129
128
 
130
129
  @staticmethod
131
130
  def evaluate_list_scenario_parameter(text_param, param_name, log_level=logging.DEBUG):
132
- res = StepTools.evaluate_scenario_parameter(text_param)
131
+ res = StepTools.evaluate_scenario_parameter(text_param, log_level=log_level)
133
132
  if isinstance(res, str):
134
133
  regex = re.compile(r"^\s*\[(.*)\]\s*$")
135
134
  m = regex.match(res)
@@ -294,8 +293,8 @@ class StepTools(object):
294
293
  @classmethod
295
294
  def has_table_header(cls, table):
296
295
  """
297
- Return True if scenario table has a header (for testing solution).
298
- For testing solution, table header names are all texts without quotes.
296
+ Return True if scenario table has a header (for HolAdo framework).
297
+ For HolAdo framework, table header names are all texts without quotes.
299
298
  """
300
299
  internal_header = cls._get_table_header(table)
301
300
  if internal_header is None:
@@ -303,7 +302,7 @@ class StepTools(object):
303
302
 
304
303
  for cell in internal_header:
305
304
  scell = ValueTableCell(cell)
306
- if scell.value_type not in [ValueTypes.Symbol]:
305
+ if not ( scell.content_type == ValueTypes.Symbol and scell.value_type == ValueTypes.String ):
307
306
  return False
308
307
 
309
308
  return True
@@ -402,7 +401,7 @@ class StepTools(object):
402
401
  def format_steps_with(cls, steps, format_with_list):
403
402
  res = steps
404
403
  for form in format_with_list:
405
- form_eval = cls._get_expression_evaluator().evaluate_expression(form)
404
+ _, form_eval = cls._get_expression_evaluator().evaluate_expression(form, log_level=logging.TRACE) # @UndefinedVariable
406
405
  if form_eval == form:
407
406
  raise FunctionalException(f"Not able to evaluation expression [{form}]. Is missing its initialization ?")
408
407
  res = res.replace(f"${{{form}}}", str(form_eval))
@@ -14,6 +14,7 @@
14
14
  from holado.common.context.session_context import SessionContext
15
15
  import logging
16
16
  from holado_core.common.tables.table import Table
17
+ from holado_core.common.tools.tools import Tools
17
18
 
18
19
  logger = logging.getLogger(__name__)
19
20
 
@@ -47,6 +48,7 @@ class TesterTools(object):
47
48
  if isinstance(obj, Table):
48
49
  res = obj.represent()
49
50
  else:
50
- res = str(obj)
51
+ # res = str(obj)
52
+ res = Tools.represent_object(obj)
51
53
  return res
52
54
 
@@ -107,7 +107,8 @@ class Table2ValueTable_CellComparator(TableCellComparator):
107
107
 
108
108
  cause = None
109
109
  try:
110
- value_type = cell_2.value_type
110
+ # value_type = cell_2.value_type
111
+ value_type = cell_2.content_type
111
112
  if value_type == ValueTypes.NotApplicable:
112
113
  res = True
113
114
  elif value_type == ValueTypes.Null:
@@ -121,7 +122,7 @@ class Table2ValueTable_CellComparator(TableCellComparator):
121
122
  res = comparator.equals(cell_1_value, cell_2_value, is_obtained_vs_expected=is_obtained_vs_expected, raise_exception=raise_exception)
122
123
  elif value_type == ValueTypes.Merged:
123
124
  return super().equals(cell_1, cell_2, is_obtained_vs_expected, raise_exception)
124
- elif value_type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]:
125
+ elif ValueTypes.is_string(value_type):
125
126
  res = self._equals_string(cell_1, cell_2, is_obtained_vs_expected, raise_exception)
126
127
  elif value_type == ValueTypes.Symbol:
127
128
  res = self._equals_symbol(cell_1, cell_2, is_obtained_vs_expected, raise_exception)
@@ -158,7 +158,7 @@ class ValueTableConverter(TableConverter):
158
158
 
159
159
  if row.get_cell(1).value_type in [ValueTypes.NotApplicable, ValueTypes.Merged]:
160
160
  pass
161
- elif row.get_cell(1).value_type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]:
161
+ elif ValueTypes.is_string(row.get_cell(1).value_type):
162
162
  name = row.get_cell(0).value
163
163
  value = row.get_cell(1).value
164
164
 
@@ -31,7 +31,7 @@ class ValueTableCell(TableCell):
31
31
  super().__init__(cell_content)
32
32
 
33
33
  self.__value = Value(original_value=cell_content, value=cell_value, do_eval_once=do_eval_once)
34
- self.content = self.__value.value_original
34
+ self.content = self.__value.original_value
35
35
 
36
36
  def __eq__(self, other):
37
37
  self._verify_valid_compared_object(other)
@@ -51,6 +51,10 @@ class ValueTableCell(TableCell):
51
51
  def string_content(self):
52
52
  return self.__value.string_value
53
53
 
54
+ @property
55
+ def content_type(self):
56
+ return self.__value.original_value_type
57
+
54
58
  @property
55
59
  def value_type(self):
56
60
  return self.__value.value_type
@@ -20,7 +20,7 @@ from holado_value.common.tools.value_types import ValueTypes
20
20
  from functools import total_ordering
21
21
  from holado_scripting.common.tools.evaluate_parameters import EvaluateParameters
22
22
  from holado.holado_config import Config
23
- from holado.common.handlers.undefined import undefined_value
23
+ from holado.common.handlers.undefined import undefined_value, undefined_argument, to_be_defined, not_applicable, is_undefined
24
24
  from holado_python.standard_library.typing import Typing
25
25
 
26
26
  logger = logging.getLogger(__name__)
@@ -29,26 +29,27 @@ logger = logging.getLogger(__name__)
29
29
  @total_ordering
30
30
  class Value(object):
31
31
 
32
- def __init__(self, original_value=undefined_value, value=undefined_value, do_eval_once=True, eval_params=undefined_value):
32
+ def __init__(self, original_value=undefined_argument, value=undefined_argument, do_eval_once=True, eval_params=undefined_argument):
33
33
  """
34
34
  @summary: Constructor
35
- @param original_value: Original value - can be a string or any object
35
+ @param original_value: Original value (before value expression evaluation) - can be a string or any object
36
36
  @param value: Value - can be a string or any object
37
37
  """
38
- self.__value_original = undefined_value
39
- self.__type = None
40
- self.__value = undefined_value
38
+ self.__original_value = to_be_defined
39
+ self.__value = to_be_defined
40
+ self.__value_type = None
41
41
 
42
42
  # Manage value evaluation
43
- self.__value_to_eval = undefined_value
44
- self.__value_evaluated = undefined_value
43
+ self.__value_to_eval = to_be_defined
44
+ self.__evaluated_value = to_be_defined
45
+ self.__evaluated_value_type = to_be_defined
45
46
  # By default, raise on interpret and variable evaluation error, but not on eval error
46
- self.__eval_params_default = eval_params if eval_params is not undefined_value else EvaluateParameters.default().with_raise_on_eval_error(False)
47
+ self.__eval_params_default = eval_params if eval_params is not undefined_argument else EvaluateParameters.default().with_raise_on_eval_error(False)
47
48
  self.__do_eval_once = do_eval_once
48
49
 
49
50
  self.__extract_value_information(original_value, value)
50
51
  if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
51
- logger.trace(f"New Value: value_original=[{self.__value_original}] ; type=[{self.value_type.name}] ; value=[{self.__value}] ; value_to_eval=[{self.__value_to_eval}]")
52
+ logger.trace(f"New Value: original_value=[{self.__original_value}] ; type=[{self.__value_type.name}] ; value=[{self.__value}] ; value_to_eval=[{self.__value_to_eval}]")
52
53
 
53
54
  def _verify_valid_compared_object(self, other, raise_exception=True):
54
55
  res = isinstance(other, Value)
@@ -73,7 +74,7 @@ class Value(object):
73
74
  def string_value(self):
74
75
  value = self.get_value()
75
76
 
76
- if value is undefined_value:
77
+ if value in [undefined_value, not_applicable]:
77
78
  return Config.NOT_APPLICABLE_SYMBOL
78
79
  if value is None:
79
80
  return Config.NONE_SYMBOL
@@ -81,15 +82,22 @@ class Value(object):
81
82
  return str(value)
82
83
 
83
84
  @property
84
- def value_original(self):
85
+ def original_value(self):
85
86
  """
86
87
  @summary: Return the original value
87
88
  """
88
- return self.__value_original
89
+ return self.__original_value
90
+
91
+ @property
92
+ def original_value_type(self):
93
+ """
94
+ @summary: Return the original value type
95
+ """
96
+ return self.__value_type
89
97
 
90
98
  @property
91
99
  def value_type(self):
92
- return self.__type
100
+ return self.get_value_type()
93
101
 
94
102
  @property
95
103
  def value_before_eval(self):
@@ -105,56 +113,71 @@ class Value(object):
105
113
  """
106
114
  return self.get_value(raise_if_undefined=True)
107
115
 
108
- def get_value(self, raise_if_undefined=False, eval_params=undefined_value):
116
+ def get_value(self, raise_if_undefined=False, eval_params=undefined_argument):
109
117
  if self.__value_to_eval is not undefined_value:
110
- if self.__value_evaluated is undefined_value or not self.__do_eval_once:
111
- eval_params = eval_params if eval_params is not undefined_value else self.__eval_params_default
112
- self.__value_evaluated = self.__get_expression_evaluator().evaluate_expression_of_information(self.__type, self.__value_to_eval, eval_params=eval_params)
113
- res = self.__value_evaluated
118
+ self.__evaluate_value_if_needed(eval_params=eval_params)
119
+ res = self.__evaluated_value
114
120
  else:
115
121
  res = self.__value
116
122
 
117
- if res is undefined_value and raise_if_undefined:
123
+ if is_undefined(res) and raise_if_undefined:
118
124
  msg = "Value is undefined"
119
125
  if self.value_type == ValueTypes.NotApplicable:
120
126
  msg += " (Not Applicable)"
121
- raise ValueError(f"Value is undefined (value type: {self.value_type.name} ; original value: [{self.value_original}] (type: {Typing.get_object_class_fullname(self.value_original)}))")
127
+ raise ValueError(f"Value is undefined (value type: {self.value_type.name} ; original value: [{self.original_value}] (type: {Typing.get_object_class_fullname(self.original_value)}))")
128
+ return res
129
+
130
+ def get_value_type(self, eval_params=undefined_argument):
131
+ if self.__value_to_eval is not undefined_value:
132
+ self.__evaluate_value_if_needed(eval_params=eval_params)
133
+ res = self.__evaluated_value_type
134
+ else:
135
+ res = self.__value_type
122
136
  return res
123
137
 
138
+ def __evaluate_value_if_needed(self, eval_params=undefined_argument):
139
+ if self.__evaluated_value is to_be_defined or not self.__do_eval_once:
140
+ eval_params = eval_params if eval_params is not undefined_argument else self.__eval_params_default
141
+ if ValueTypes.is_string(self.__value_type):
142
+ eval_params = eval_params.with_result_type(str)
143
+ self.__evaluated_value_type, self.__evaluated_value = self.__get_expression_evaluator().evaluate_expression_of_information(self.__value_type, self.__value_to_eval, eval_params=eval_params)
144
+
124
145
  def represent(self, indent = 0, do_evaluation = False):
125
146
  res_list = []
126
147
 
127
148
  res_list.append(Tools.get_indent_string(indent))
128
149
 
129
- if self.__type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]:
150
+ if ValueTypes.is_string(self.__value_type):
130
151
  if do_evaluation:
131
152
  res_list.append("'")
132
153
  res_list.append(self.string_value)
133
154
  res_list.append("'")
134
155
  else:
135
- res_list.append(str(self.value_original))
136
- elif self.__type in [ValueTypes.Boolean, ValueTypes.Integer, ValueTypes.Float, ValueTypes.Null, ValueTypes.NotApplicable, ValueTypes.Symbol, ValueTypes.Generic]:
156
+ res_list.append(str(self.original_value))
157
+ elif self.__value_type in [ValueTypes.Boolean, ValueTypes.Integer, ValueTypes.Float, ValueTypes.Null, ValueTypes.NotApplicable, ValueTypes.Symbol, ValueTypes.Generic]:
137
158
  if do_evaluation:
138
159
  res_list.append(self.string_value)
139
160
  else:
140
- res_list.append(str(self.value_original))
161
+ res_list.append(str(self.original_value))
141
162
  else:
142
- raise TechnicalException("Unmanaged value type '{}'".format(self.__type.name))
163
+ raise TechnicalException("Unmanaged value type '{}'".format(self.__value_type.name))
143
164
 
144
165
  return "".join(res_list)
145
166
 
146
- def __extract_value_information(self, value_original, value):
167
+ def __extract_value_information(self, original_value, value):
147
168
  # Define original value
148
- if value_original is not undefined_value and not (value_original is None and value not in [undefined_value, None]):
149
- self.__value_original = value_original
150
- elif value is not undefined_value:
169
+ if original_value is not undefined_argument and not (original_value in [undefined_value, None] and value not in [undefined_argument, undefined_value, None]):
170
+ self.__original_value = original_value
171
+ elif value is not undefined_argument:
151
172
  if value is not None and isinstance(value, str):
152
- self.__value_original = f"'{value}'"
173
+ self.__original_value = f"'{value}'"
153
174
  else:
154
- self.__value_original = value
175
+ self.__original_value = value
155
176
 
156
177
  # Define value information from original value
157
- self.__type, self.__value, self.__value_to_eval = self.__get_expression_evaluator().extract_expression_information(self.value_original)
178
+ self.__value_type, self.__value, self.__value_to_eval = self.__get_expression_evaluator().extract_expression_information(self.original_value)
179
+ if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
180
+ logger.trace(f"extracted value info: {self.__value_type=}, {self.__value=}, {self.__value_to_eval=}")
158
181
 
159
182
  def __get_expression_evaluator(self):
160
183
  if SessionContext.instance().has_scenario_context():
@@ -32,4 +32,10 @@ class ValueTypes(AutoNumber):
32
32
  Merged = ()
33
33
  Symbol = ()
34
34
  Generic = ()
35
+
36
+ @classmethod
37
+ def is_string(cls, value_type):
38
+ return value_type in [ValueTypes.String, ValueTypes.DynamicString, ValueTypes.ThreadDynamicString, ValueTypes.UniqueString]
39
+
40
+
35
41
 
@@ -3,6 +3,7 @@
3
3
  @go_nogo
4
4
  Feature: Test bit_series module
5
5
 
6
+ @to_hexadecimal_string
6
7
  Scenario: Create and convert bit-series to hexa
7
8
  Given BIT_SERIES = bit series
8
9
  | Name | Bit length | Type | Value |
@@ -24,6 +25,9 @@ Feature: Test bit_series module
24
25
  Given RAW_TM = convert bit series BIT_SERIES to hexadecimal string
25
26
  Then RAW_TM == '99FFFFAE1B'
26
27
 
28
+
29
+ @to_hexadecimal_string
30
+ @padding
27
31
  Scenario: Create and convert to hexa bit-series of bit length out of bytes array length
28
32
  Given BIT_SERIES = bit series
29
33
  | Name | Bit length | Type | Value |
@@ -56,6 +60,8 @@ Feature: Test bit_series module
56
60
  Given RAW_TM = convert bit series BIT_SERIES to hexadecimal string (right padded)
57
61
  Then RAW_TM == '92'
58
62
 
63
+
64
+ @from_hexadecimal_string
59
65
  Scenario: Create a bit-series from hexa
60
66
  Given BIT_SERIES = bit series
61
67
  | Name | Bit length | Type |
@@ -71,6 +77,9 @@ Feature: Test bit_series module
71
77
  | 'F3' | 2 | int | 0 |
72
78
  | 'F4' | 2 | int | 2 |
73
79
 
80
+
81
+ @from_hexadecimal_string
82
+ @padding
74
83
  Scenario: Create from hexa bit-series of bit length out of bytes array length
75
84
  Given BIT_SERIES = bit series
76
85
  | Name | Bit length | Type |
@@ -99,6 +108,8 @@ Feature: Test bit_series module
99
108
  | 'F2' | 1 | int | 1 |
100
109
  | 'F3' | 1 | int | 1 |
101
110
 
111
+
112
+ @is_bit_series
102
113
  Scenario: Verify hexa string is bit series
103
114
  Then hexadecimal string '92' is bit series
104
115
  | Name | Bit length | Type | Value |
@@ -107,6 +118,8 @@ Feature: Test bit_series module
107
118
  | 'F3' | 2 | int | 0 |
108
119
  | 'F4' | 2 | int | 2 |
109
120
 
121
+
122
+ @set_field
110
123
  Scenario: Set bit-series field by variable expression
111
124
  Given BIT_SERIES = bit series
112
125
  | Name | Bit length | Type | Value |
@@ -51,7 +51,7 @@ Feature: Steps in common_steps.py
51
51
  """
52
52
  Given TOTO = 'TITI'
53
53
  """
54
- When wait until wait 0.5 seconds (timeout: 0.7 s)
54
+ When wait until wait 0.5 seconds (timeout: 0.75 s)
55
55
  """
56
56
  Given TOTO = 'TITI'
57
57
  """
File without changes