diff --git a/docs/python_api/Node.rst b/docs/python_api/Node.rst index b5064c647..753b691ad 100644 --- a/docs/python_api/Node.rst +++ b/docs/python_api/Node.rst @@ -1131,7 +1131,7 @@ Find the :term:`event` on the node only. Returns a object .. py:method:: Node.find_gen_variable( (Node)arg1, (str)arg2) -> Variable : :module: ecflow -Find generated variable on the node only. Returns a object +Find generated variable on the node only. Returns an object .. py:method:: Node.find_generic( (Node)arg1, (str)arg2) -> Generic : @@ -1155,7 +1155,7 @@ Find the :term:`limit` on the node only. returns a limit ptr .. py:method:: Node.find_meter( (Node)arg1, (str)arg2) -> Meter : :module: ecflow -Find the :term:`meter` on the node only. Returns a object +Find the :term:`meter` on the node only. Returns an object .. py:method:: Node.find_node_up_the_tree( (Node)arg1, (str)arg2) -> Node : @@ -1167,7 +1167,7 @@ Search immediate node, then up the node hierarchy .. py:method:: Node.find_parent_variable( (Node)arg1, (str)arg2) -> Variable : :module: ecflow -Find user variable variable up the parent hierarchy. Returns a object +Find user variable variable up the parent hierarchy. Returns an object .. py:method:: Node.find_parent_variable_sub_value( (Node)arg1, (str)arg2) -> str : @@ -1185,7 +1185,7 @@ Find the queue on the node only. Returns a queue object .. py:method:: Node.find_variable( (Node)arg1, (str)arg2) -> Variable : :module: ecflow -Find user variable on the node only. Returns a object +Find user variable on the node only. Returns an object .. py:property:: Node.generics @@ -1244,10 +1244,13 @@ Returns the state of node. This will include suspended state Return additional state associated with a node. -.. py:method:: Node.get_generated_variables( (Node)arg1, (VariableList)arg2) -> None : +.. py:method:: Node.get_generated_variables( (Node)arg1) -> list : :module: ecflow -returns a list of generated variables. Use ecflow.VariableList as return argument +Returns the list of generated variables. + +get_generated_variables( (Node)arg1, (VariableList)arg2) -> None : + Retrieves the list of generated variables. Pass in ecflow.VariableList as argument to hold variables. .. py:method:: Node.get_late( (Node)arg1) -> Late diff --git a/libs/pyext/CMakeLists.txt b/libs/pyext/CMakeLists.txt index 7961ea74d..7872e02f3 100644 --- a/libs/pyext/CMakeLists.txt +++ b/libs/pyext/CMakeLists.txt @@ -88,6 +88,7 @@ set(u_tests py_u_test_defs_constructor py_u_test_get_attr py_u_test_manual + py_u_test_node py_u_test_late py_u_test_replace_node py_u_test_tutorial diff --git a/libs/pyext/src/ecflow/python/ExportNode.cpp b/libs/pyext/src/ecflow/python/ExportNode.cpp index 315f19f38..315e44386 100644 --- a/libs/pyext/src/ecflow/python/ExportNode.cpp +++ b/libs/pyext/src/ecflow/python/ExportNode.cpp @@ -390,6 +390,20 @@ node_ptr add_defstatus1(node_ptr self, const Defstatus& ds) { return self; } +bp::list generated_variables_using_python_list(node_ptr self) { + bp::list list; + std::vector vec; + self->gen_variables(vec); + for (const auto& i : vec) { + list.append(i); + } + return list; +} + +void generated_variables_using_variablelist(node_ptr self, std::vector& vec) { + self->gen_variables(vec); +} + ///////////////////////////////////////////////////////////////////////////////////////// static object do_rshift(node_ptr self, const bp::object& arg) { @@ -677,28 +691,31 @@ void export_Node() { .def("has_time_dependencies", &Node::hasTimeDependencies) .def("update_generated_variables", &Node::update_generated_variables) .def("get_generated_variables", - &Node::gen_variables, - "returns a list of generated variables. Use ecflow.VariableList as return argument") + &generated_variables_using_python_list, + "Returns the list of generated variables.") + .def("get_generated_variables", + &generated_variables_using_variablelist, + "Retrieves the list of generated variables. Pass in ecflow.VariableList as argument to hold variables.") .def("is_suspended", &Node::isSuspended, "Returns true if the `node`_ is in a `suspended`_ state") .def("find_variable", &Node::findVariable, return_value_policy(), - "Find user variable on the node only. Returns a object") + "Find user variable on the node only. Returns an object") .def("find_gen_variable", &Node::findGenVariable, return_value_policy(), - "Find generated variable on the node only. Returns a object") + "Find generated variable on the node only. Returns an object") .def("find_parent_variable", &Node::find_parent_variable, return_value_policy(), - "Find user variable variable up the parent hierarchy. Returns a object") + "Find user variable variable up the parent hierarchy. Returns an object") .def("find_parent_variable_sub_value", &Node::find_parent_variable_sub_value, "Find user variable *up* node tree, then variable substitute the value, otherwise return empty string") .def("find_meter", &Node::findMeter, return_value_policy(), - "Find the `meter`_ on the node only. Returns a object") + "Find the `meter`_ on the node only. Returns an object") .def("find_event", &Node::findEventByNameOrNumber, return_value_policy(), diff --git a/libs/pyext/test/py_u_test_node.py b/libs/pyext/test/py_u_test_node.py new file mode 100644 index 000000000..33a6a06aa --- /dev/null +++ b/libs/pyext/test/py_u_test_node.py @@ -0,0 +1,129 @@ +# +# Copyright 2009- ECMWF. +# +# This software is licensed under the terms of the Apache Licence version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# In applying this licence, ECMWF does not waive the privileges and immunities +# granted to it by virtue of its status as an intergovernmental organisation +# nor does it submit to any jurisdiction. +# + +import ecflow_test_util as ect +import ecflow as ecf +import unittest +import sys +import os + + +class TestNode(unittest.TestCase): + + def setUp(self): + self.defs = ecf.Defs() + self.suite = self.defs.add_suite("suite"); + + self.suite.add_variable("VARIABLE", "value"); + + self.family = self.suite.add_family("family") + self.family.add_repeat(ecf.RepeatDate("REPEAT", 20010101, 20010102, 1)) + + self.task = self.family.add_task("task") + + def test_is_able_to_retrieve_suite_generated_variables_using_variable_list(self): + vars = ecf.VariableList() + self.suite.get_generated_variables(vars) + + names = [v.name() for v in vars] + self.assertIn("SUITE", names) + self.assertIn("ECF_DATE", names) + self.assertIn("ECF_CLOCK", names) + self.assertIn("ECF_TIME", names) + self.assertIn("ECF_JULIAN", names) + + self.assertIn("YYYY", names) + self.assertIn("DD", names) + self.assertIn("MM", names) + self.assertIn("DAY", names) + self.assertIn("MONTH", names) + self.assertIn("DATE", names) + self.assertIn("TIME", names) + self.assertIn("DOW", names) + self.assertIn("DOY", names) + + def test_is_able_to_retrieve_suite_generated_variables_using_python_list(self): + vars = self.suite.get_generated_variables() + + names = [v.name() for v in vars] + self.assertIn("SUITE", names) + self.assertIn("ECF_DATE", names) + self.assertIn("ECF_CLOCK", names) + self.assertIn("ECF_TIME", names) + self.assertIn("ECF_JULIAN", names) + + self.assertIn("YYYY", names) + self.assertIn("DD", names) + self.assertIn("MM", names) + self.assertIn("DAY", names) + self.assertIn("MONTH", names) + self.assertIn("DATE", names) + self.assertIn("TIME", names) + self.assertIn("DOW", names) + self.assertIn("DOY", names) + + def test_is_able_to_retrieve_family_generated_variables_using_variable_list(self): + vars = ecf.VariableList() + self.family.get_generated_variables(vars) + + names = [v.name() for v in vars] + self.assertIn("FAMILY", names) + self.assertIn("FAMILY1", names) + self.assertIn("REPEAT", names) + self.assertIn("REPEAT_YYYY", names) + self.assertIn("REPEAT_MM", names) + self.assertIn("REPEAT_DD", names) + self.assertIn("REPEAT_DOW", names) + self.assertIn("REPEAT_JULIAN", names) + + def test_is_able_to_retrieve_family_generated_variables_using_python_list(self): + vars = self.family.get_generated_variables() + + names = [v.name() for v in vars] + self.assertIn("FAMILY", names) + self.assertIn("FAMILY1", names) + self.assertIn("REPEAT", names) + self.assertIn("REPEAT_YYYY", names) + self.assertIn("REPEAT_MM", names) + self.assertIn("REPEAT_DD", names) + self.assertIn("REPEAT_DOW", names) + self.assertIn("REPEAT_JULIAN", names) + + def test_is_able_to_retrieve_task_generated_variables_using_variable_list(self): + vars = ecf.VariableList() + self.task.get_generated_variables(vars) + + names = [v.name() for v in vars] + self.assertIn("TASK", names) + self.assertIn("ECF_JOB", names) + self.assertIn("ECF_SCRIPT", names) + self.assertIn("ECF_JOBOUT", names) + self.assertIn("ECF_TRYNO", names) + self.assertIn("ECF_RID", names) + self.assertIn("ECF_PASS", names) + self.assertIn("ECF_NAME", names) + + def test_is_able_to_retrieve_task_generated_variables_using_python_list(self): + vars = self.task.get_generated_variables() + + names = [v.name() for v in vars] + self.assertIn("TASK", names) + self.assertIn("ECF_JOB", names) + self.assertIn("ECF_SCRIPT", names) + self.assertIn("ECF_JOBOUT", names) + self.assertIn("ECF_TRYNO", names) + self.assertIn("ECF_RID", names) + self.assertIn("ECF_PASS", names) + self.assertIn("ECF_NAME", names) + + +if __name__ == "__main__": + unittest.main() + print("All Tests pass")