def run_py_as_rtseq(toplevelfunc, rtseq_params={}): """ Runs a Python function as an RT sequence in the VeriStand Engine. Args: toplevelfunc: the Python function to run. rtseq_params (Dict[str, niveristand.clientapi._datatypes.rtprimitives.DoubleValue]): the parameters to be passed to the RT sequence. Returns: Union[float, None]: The numeric value returned by the real-time sequence execution. Raises: :any:`TranslateError`: if the function is not successfully translated. :any:`RunAbortedError`: if this function calls :any:`generate_error` with an action of Abort or Stop. :any:`RunFailedError`: if this function calls :any:`generate_error` with a Continue action. """ from niveristand.clientapi import RealTimeSequence seq = RealTimeSequence(toplevelfunc) result_state = seq.run(rtseq_params) result_state.wait_for_result() result_state.session.undeploy() if result_state.last_error: raise RunError.RunErrorFactory(result_state.last_error) return result_state.ret_val
def run_py_as_rtseq(toplevelfunc, timeout_within_each_step=100000): """ Runs a Python function as an RT sequence in the VeriStand Engine. Args: toplevelfunc: the Python function to run. timeout_within_each_step (Optional[int]): time, in milliseconds, each step can take before execution is aborted. Returns: The numeric value returned by the real-time sequence execution. Raises: :any:`TranslateError`: if the function is not successfully translated. :any:`RunAbortedError`: if this function calls :any:`generate_error` with an action of Abort or Stop. :any:`RunFailedError`: if this function calls :any:`generate_error` with a Continue action. """ from niveristand.clientapi import RealTimeSequence seq = RealTimeSequence(toplevelfunc) result_state = seq.run(timeout_within_each_step=timeout_within_each_step) result_state.wait_for_result() result_state.session.Undeploy() if result_state.last_error: raise RunError.RunErrorFactory(result_state.last_error) return result_state.ret_val
def test_realtimesequence_channel_reference_param(): desired_rpm = ChannelReference('Aliases/DesiredRPM') desired_rpm.value = 100.101 rtseq = RealTimeSequence(func1) actual = rtseq.run({"p": desired_rpm}) actual.wait_for_result() assert actual.ret_val == 100.101
def ret_func(*args, **kwargs): is_top_level = False this_task = get_scheduler().try_get_task_for_curr_thread() if this_task is None: is_top_level = True this_task = get_scheduler().create_and_register_task_for_top_level( ) get_scheduler().sched() this_task.wait_for_turn() try: if is_top_level: from niveristand.clientapi import RealTimeSequence RealTimeSequence(func) retval = func(*args, **kwargs) except errors.SequenceError: # generate error already saved this error in the task, so we can just pass. pass finally: if is_top_level: this_task.mark_stopped() this_task.iteration_counter.finished = True nivs_yield() if this_task.error and this_task.error.should_raise: raise errors.RunError.RunErrorFactory(this_task.error) return retval
def test_channel_ref_invalid_channel_transform(): # Transforming sequences with invalid channels should work, because they are not validated. This is, because users # need to be able to transform without a deployed system definition and therefore we are not checking through the # C# API the validity of a channel. This will be improved in the future to differentiate between the two cases. rtseq = RealTimeSequence( testfunctions.channel_ref_invalid_channel_transform) assert rtseq._rtseq.Code.Main.Body.Statements.Length == 0 assert rtseq._rtseq.Variables.ChannelReferences.Channels.Length == 1
def _try_resolve(self, item): seq = self._rtseqs.get(item) if inspect.isfunction(seq): for dep in self._dep_graph[item]: if not isinstance(self._rtseqs[dep], RealTimeSequence): self._try_resolve(item) seq = RealTimeSequence(seq, self) self._rtseqs[item] = seq return seq
def save_py_as_rtseq(toplevelfunc, dest_folder): """ Saves a Python function as an RT sequence that is compatible with the Stimulus Profile Editor. Args: toplevelfunc: the Python function you want to save. dest_folder[str]: the folder you want to save the sequence and all its dependencies in. Returns: The full path to the main sequence file. Raises: :class:`niveristand.errors.TranslateError`: if the function is not successfully translated. """ from niveristand.clientapi import RealTimeSequence seq = RealTimeSequence(toplevelfunc) filename = seq.save(dest_folder) return filename
def test_rtseq_with_deps_multiple_times_diff_folder(): seq = RealTimeSequence(calls_another) folder = tempfile.mkdtemp() seq.save(folder) _, _, files = next(os.walk(folder)) assert len(files) == 2 folder = tempfile.mkdtemp() seq.save(folder) _, _, files = next(os.walk(folder)) assert len(files) == 2
def test_rtseq_with_deps_multiple_times(): seq = RealTimeSequence(calls_another) folder = tempfile.mkdtemp() seq.save(folder) root, _, files = next(os.walk(folder)) assert len(files) == 2 for file in files: os.remove(os.path.join(root, file)) seq.save(folder) _, _, files = next(os.walk(folder)) assert len(files) == 2
def test_transform(func_name, params, expected_result): RealTimeSequence(func_name)
def test_return_untyped_symbol(): testfunc = testfuncs.return_untyped_symbol with pytest.raises(errors.TranslateError): RealTimeSequence(testfunc)
def test_return_named_type(): with pytest.raises(errors.TranslateError): RealTimeSequence(testfuncs.return_named_type)
def test_transform_invalid_function_fails(): with pytest.raises(errors.TranslateError): RealTimeSequence(testfuncs)
def test_transform_pi_assign_to_local(): testfunc = testfuncs.simple_assign_pi rtseq = RealTimeSequence(testfunc) assert (rtseq._rtseq.Variables.LocalVariables.Variables.Length is 1) assert (rtseq._rtseq.Code.Main.Body.Statements.Length is 3)
def test_channel_ref_array_setter(): rtseq = RealTimeSequence(testfunctions.channel_ref_array_setter) assert rtseq._rtseq.Code.Main.Body.Statements.Length == 1 expression = Expression('ch_a[0] = 5') assert rtseq._rtseq.Code.Main.Body.Statements[0].Equals(expression)
def test_transform_empty_with_two_decorators(): rtseq = RealTimeSequence(testfuncs.empty_func_with_double_decorator) assert rtseq._rtseq is not None assert rtseq._rtseq.Code.Main.Body.Statements.Length is 0 assert rtseq._rtseq.Variables.LocalVariables.Variables.Length is 0
def test_transform_simple_local_assignment(): testfunc = testfuncs.simple_local_assignment rtseq = RealTimeSequence(testfunc) assert (rtseq._rtseq.Variables.LocalVariables.Variables.Length is 1)
def test_channel_ref_type_string(): rtseq = RealTimeSequence(testfunctions.channel_ref_type_string) assert rtseq._rtseq.Variables.LocalVariables.Variables.Length == 0 assert rtseq._rtseq.Variables.ChannelReferences.Channels.Length == 1 assert rtseq._rtseq.Variables.ChannelReferences.Channels[0].Channel.Channel \ == "Aliases/DesiredRPM"
def test_untyped_declarations_fail(): testfunc = testfuncs.assign_untyped with pytest.raises(errors.TranslateError): RealTimeSequence(testfunc)
def test_channel_ref_array_return(): testfunc = testfunctions.channel_ref_array_return with pytest.raises(errors.TranslateError): RealTimeSequence(testfunc)
def test_undeclared_variable_fail(): testfunc = testfuncs.return_var_invalid_value with pytest.raises(errors.TranslateError): RealTimeSequence(testfunc)
def test_return_not_last(): with pytest.raises(errors.TranslateError): RealTimeSequence(testfuncs.return_not_last)
def test_return_var_pi(): testfunc = testfuncs.return_var_pi rtseq = RealTimeSequence(testfunc) assert (isinstance(rtseq._rtseq.Variables.ReturnType.DefaultValue.Value, float)) assert (rtseq._rtseq.Code.Main.Body.Statements.Length is 3)
def test_transform_func_without_decorator_fails(): with pytest.raises(errors.TranslateError): RealTimeSequence(testfuncs.func_without_decorator)
def test_multiple_returns(): with pytest.raises(errors.TranslateError): RealTimeSequence(testfuncs.multiple_returns)
def test_default_value_bool_false(): testfunc = testfuncs.return_false rtseq = RealTimeSequence(testfunc) assert rtseq._rtseq.Variables.LocalVariables.Variables[ 0].DefaultValue.Value is False
def test_not_wait_to_complete(): seq = RealTimeSequence(return_var) result_state = seq.run() assert result_state.ret_val is None result_state.wait_for_result() assert result_state.ret_val == 5
def test_a_value_value_assign_to(): testfunc = testfuncs.a_value_value_assign_to with pytest.raises(errors.TranslateError): RealTimeSequence(testfunc)
def test_failures(func_name, params, expected_result): with pytest.raises(expected_result): RealTimeSequence(func_name) with pytest.raises(expected_result): func_name(*params)
def test_transform_empty(): rtseq = RealTimeSequence(testfuncs.empty_func) assert rtseq._rtseq is not None assert rtseq._rtseq.Code.Main.Body.Statements.Length is 0 assert rtseq._rtseq.Variables.LocalVariables.Variables.Length is 0