holado 0.2.4__py3-none-any.whl → 0.2.6__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.
- holado/__init__.py +62 -26
- holado/common/context/service_manager.py +10 -2
- holado/common/context/session_context.py +43 -12
- holado/common/handlers/object.py +14 -5
- holado/common/handlers/undefined.py +16 -6
- holado/holado_config.py +1 -0
- {holado-0.2.4.dist-info → holado-0.2.6.dist-info}/METADATA +1 -1
- {holado-0.2.4.dist-info → holado-0.2.6.dist-info}/RECORD +49 -48
- holado_core/common/block/scope_steps.py +2 -2
- holado_core/common/resource/persisted_method_to_call_manager.py +2 -2
- holado_core/common/tools/path_manager.py +8 -4
- holado_core/common/tools/tools.py +24 -7
- holado_grpc/api/rpc/grpc_client.py +122 -118
- holado_helper/docker/logging.conf +3 -1
- holado_helper/docker/run_holado_test_nonreg_in_docker.sh +28 -28
- holado_helper/docker/run_terminal_in_docker-with_docker_control.sh +27 -27
- holado_helper/docker/run_terminal_in_docker.sh +26 -26
- holado_helper/initialize_holado.py +72 -0
- holado_helper/script/action.py +21 -9
- holado_helper/script/initialize_script.py +8 -28
- holado_helper/script/script.py +2 -2
- holado_logging/__init__.py +5 -8
- holado_logging/common/logging/holado_logger.py +2 -2
- holado_logging/common/logging/log_config.py +43 -18
- holado_logging/common/logging/log_manager.py +20 -19
- holado_multitask/multitasking/multitask_manager.py +1 -1
- holado_multitask/multithreading/thread.py +8 -4
- holado_protobuf/ipc/protobuf/protobuf_messages.py +1 -1
- holado_scripting/common/tools/evaluate_parameters.py +23 -5
- holado_scripting/common/tools/expression_evaluator.py +115 -113
- holado_scripting/tests/behave/steps/scenario/if_steps.py +2 -2
- holado_scripting/text/interpreter/functions/function_hex_to_bytes.py +1 -1
- holado_scripting/text/interpreter/text_interpreter.py +20 -21
- holado_test/behave/behave_environment.py +31 -12
- holado_test/behave/independant_runner.py +3 -5
- holado_test/scenario/step_tools.py +13 -12
- holado_test/scenario/tester_tools.py +3 -1
- holado_value/common/tables/comparators/table_2_value_table_cell_comparator.py +1 -1
- holado_value/common/tables/converters/value_table_converter.py +1 -1
- holado_value/common/tables/value_table_cell.py +5 -1
- holado_value/common/tools/value.py +56 -33
- holado_value/common/tools/value_types.py +6 -0
- test_holado/environment.py +1 -1
- test_holado/features/NonReg/{ipc → holado_binary}/bit_series.feature +13 -0
- test_holado/features/NonReg/test_steps/common.feature +1 -1
- test_holado/logging.conf +3 -1
- {holado-0.2.4.dist-info → holado-0.2.6.dist-info}/WHEEL +0 -0
- {holado-0.2.4.dist-info → holado-0.2.6.dist-info}/licenses/LICENSE +0 -0
- /test_holado/features/NonReg/{ipc → holado_binary}/bit_series.error.feature +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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 =
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
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
|
|
119
|
+
return (ValueTypes.Null, None)
|
|
140
120
|
elif isinstance(value, bool):
|
|
141
|
-
return (ValueTypes.Boolean, value
|
|
121
|
+
return (ValueTypes.Boolean, value)
|
|
142
122
|
elif isinstance(value, int):
|
|
143
|
-
return (ValueTypes.Integer, value
|
|
123
|
+
return (ValueTypes.Integer, value)
|
|
144
124
|
elif isinstance(value, float):
|
|
145
|
-
return (ValueTypes.Float, value
|
|
125
|
+
return (ValueTypes.Float, value)
|
|
146
126
|
elif isinstance(value, str):
|
|
147
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
161
|
-
return
|
|
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
|
|
165
|
-
|
|
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
|
-
|
|
180
|
+
res = self.__dynamic_text_manager.get(res)
|
|
184
181
|
elif value_type == ValueTypes.ThreadDynamicString:
|
|
185
|
-
|
|
182
|
+
res = self.__dynamic_text_manager.get(res, scope=MultitaskManager.get_thread_id())
|
|
186
183
|
elif value_type == ValueTypes.UniqueString:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
193
|
-
logger.
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
265
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
317
|
+
logger.log(Tools.do_log_level(logging.DEBUG, log_level), f"Error while evaluating expression [{value}]: {repr(exc)}")
|
|
316
318
|
else:
|
|
317
|
-
logger.
|
|
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
|
|
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.
|
|
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:
|
|
@@ -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
|
-
|
|
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.
|
|
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,
|
|
193
|
-
logger.
|
|
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
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
var_step_descr = StepTools.evaluate_variable_name(step_descr)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import logging
|
|
15
15
|
from behave.runner import Runner
|
|
16
16
|
from behave.parser import parse_feature
|
|
17
|
+
from holado.holado_config import Config
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
logger = logging.getLogger(__name__)
|
|
@@ -55,12 +56,9 @@ class IndependantRunner(Runner):
|
|
|
55
56
|
feature_text = \
|
|
56
57
|
"""
|
|
57
58
|
Feature: Fake
|
|
58
|
-
|
|
59
59
|
Scenario: Fake
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
When wait DELAY seconds
|
|
63
|
-
"""
|
|
60
|
+
When wait {runner_session_timeout} seconds
|
|
61
|
+
""".format(runner_session_timeout=Config.session_timeout_seconds)
|
|
64
62
|
feature = parse_feature(feature_text)
|
|
65
63
|
|
|
66
64
|
return super().run_model([feature])
|