From dff9526bd8b414ee0a58fa662a4d4c529fa811ae Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Fri, 25 Oct 2024 16:47:41 +0100 Subject: [PATCH 1/3] Allow default parameters for Aviso attribute Re ECFLOW-1981 --- .../src/ecflow/python/ExportNodeAttr.cpp | 36 ++++++++- libs/pyext/test/py_u_TestAviso.py | 76 +++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp b/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp index 384f6ac7d..f59a7824f 100644 --- a/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp +++ b/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp @@ -285,14 +285,38 @@ static job_creation_ctrl_ptr makeJobCreationCtrl() { static std::shared_ptr aviso_init(const std::string& name, const std::string& listener, - const std::string& url, - const std::string& schema, - const std::string& polling, - const std::string& auth) { + const std::string& url = AvisoAttr::default_url, + const std::string& schema = AvisoAttr::default_schema, + const std::string& polling = AvisoAttr::default_polling, + const std::string& auth = AvisoAttr::default_auth) { auto attr = std::make_shared(nullptr, name, listener, url, schema, polling, 0, auth, ""); return attr; } +static std::shared_ptr aviso_init_defaults_0(const std::string& name, const std::string& listener) { + return aviso_init(name, listener); +} + +static std::shared_ptr +aviso_init_defaults_1(const std::string& name, const std::string& listener, const std::string& url) { + return aviso_init(name, listener, url); +} + +static std::shared_ptr aviso_init_defaults_2(const std::string& name, + const std::string& listener, + const std::string& url, + const std::string& schema) { + return aviso_init(name, listener, url, schema); +} + +static std::shared_ptr aviso_init_defaults_3(const std::string& name, + const std::string& listener, + const std::string& url, + const std::string& schema, + const std::string& polling) { + return aviso_init(name, listener, url, schema, polling); +} + static std::shared_ptr mirror_init(const std::string& name, const std::string& path, const std::string& host, @@ -1018,6 +1042,10 @@ void export_NodeAttr() { class_("AvisoAttr", NodeAttrDoc::aviso_doc()) .def("__init__", make_constructor(&aviso_init)) + .def("__init__", make_constructor(&aviso_init_defaults_0)) + .def("__init__", make_constructor(&aviso_init_defaults_1)) + .def("__init__", make_constructor(&aviso_init_defaults_2)) + .def("__init__", make_constructor(&aviso_init_defaults_3)) .def(self == self) // __eq__ .def("__str__", &ecf::to_python_string) // __str__ .def("__copy__", copyObject) // __copy__ uses copy constructor diff --git a/libs/pyext/test/py_u_TestAviso.py b/libs/pyext/test/py_u_TestAviso.py index c78a8acba..99d7a516e 100644 --- a/libs/pyext/test/py_u_TestAviso.py +++ b/libs/pyext/test/py_u_TestAviso.py @@ -25,6 +25,78 @@ def can_create_aviso_from_parameters(): assert aviso.auth() == "auth" +def can_create_aviso_from_default_parameters_0(): + suite = ecf.Suite("s1") + + family = ecf.Family("f1") + suite.add_family(family) + + task = ecf.Task("f1", ecf.AvisoAttr("name", "listener")) + assert len(list(task.avisos)) == 1 + + actual = list(task.avisos)[0] + assert actual.name() == "name" + assert actual.listener() == "listener" + assert actual.url() == "%ECF_AVISO_URL%" + assert actual.schema() == "%ECF_AVISO_SCHEMA%" + assert actual.polling() == "%ECF_AVISO_POLLING%" + assert actual.auth() == "%ECF_AVISO_AUTH%" + + +def can_create_aviso_from_default_parameters_1(): + suite = ecf.Suite("s1") + + family = ecf.Family("f1") + suite.add_family(family) + + task = ecf.Task("f1", ecf.AvisoAttr("name", "listener", "url")) + assert len(list(task.avisos)) == 1 + + actual = list(task.avisos)[0] + assert actual.name() == "name" + assert actual.listener() == "listener" + assert actual.url() == "url" + assert actual.schema() == "%ECF_AVISO_SCHEMA%" + assert actual.polling() == "%ECF_AVISO_POLLING%" + assert actual.auth() == "%ECF_AVISO_AUTH%" + + +def can_create_aviso_from_default_parameters_2(): + suite = ecf.Suite("s1") + + family = ecf.Family("f1") + suite.add_family(family) + + task = ecf.Task("f1", ecf.AvisoAttr("name", "listener", "url", "schema")) + assert len(list(task.avisos)) == 1 + + actual = list(task.avisos)[0] + assert actual.name() == "name" + assert actual.listener() == "listener" + assert actual.url() == "url" + assert actual.schema() == "schema" + assert actual.polling() == "%ECF_AVISO_POLLING%" + assert actual.auth() == "%ECF_AVISO_AUTH%" + + +def can_create_aviso_from_default_parameters_3(): + suite = ecf.Suite("s1") + + family = ecf.Family("f1") + suite.add_family(family) + + task = ecf.Task("f1", ecf.AvisoAttr("name", "listener", "url", "schema", "polling")) + assert len(list(task.avisos)) == 1 + + actual = list(task.avisos)[0] + assert actual.name() == "name" + assert actual.listener() == "listener" + assert actual.url() == "url" + assert actual.schema() == "schema" + assert actual.polling() == "polling" + assert actual.auth() == "%ECF_AVISO_AUTH%" + + def can_add_aviso_to_task(): suite = ecf.Suite("s1") @@ -101,6 +173,10 @@ def can_check_job_creation_with_aviso(): Test.print_test_start(os.path.basename(__file__)) can_create_aviso_from_parameters() + can_create_aviso_from_default_parameters_0() + can_create_aviso_from_default_parameters_1() + can_create_aviso_from_default_parameters_2() + can_create_aviso_from_default_parameters_3() can_add_aviso_to_task() can_embed_aviso_into_task() cannot_have_multiple_avisos_in_single_task() From b69a0bf64f4fe8264b607bb94ed9c2c841e44af4 Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Fri, 25 Oct 2024 16:47:52 +0100 Subject: [PATCH 2/3] Allow default parameters for Mirror attribute Re ECFLOW-1981 --- .../src/ecflow/python/ExportNodeAttr.cpp | 52 +++++++++++++--- libs/pyext/test/py_u_TestMirror.py | 59 +++++++++++++++++++ 2 files changed, 104 insertions(+), 7 deletions(-) diff --git a/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp b/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp index f59a7824f..627dd40a7 100644 --- a/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp +++ b/libs/pyext/src/ecflow/python/ExportNodeAttr.cpp @@ -319,15 +319,48 @@ static std::shared_ptr aviso_init_defaults_3(const std::string& name, static std::shared_ptr mirror_init(const std::string& name, const std::string& path, - const std::string& host, - const std::string& port, - const std::string& polling, - bool ssl, - const std::string& auth) { + const std::string& host = ecf::MirrorAttr::default_remote_host, + const std::string& port = ecf::MirrorAttr::default_remote_port, + const std::string& polling = ecf::MirrorAttr::default_polling, + bool ssl = false, + const std::string& auth = ecf::MirrorAttr::default_remote_auth) { auto attr = std::make_shared(nullptr, name, path, host, port, polling, ssl, auth, ""); return attr; } +static std::shared_ptr mirror_init_defaults_0(const std::string& name, const std::string& path) { + return mirror_init(name, path); +} + +static std::shared_ptr +mirror_init_defaults_1(const std::string& name, const std::string& path, const std::string& host) { + return mirror_init(name, path, host); +} + +static std::shared_ptr mirror_init_defaults_2(const std::string& name, + const std::string& path, + const std::string& host, + const std::string& port) { + return mirror_init(name, path, host, port); +} + +static std::shared_ptr mirror_init_defaults_3(const std::string& name, + const std::string& path, + const std::string& host, + const std::string& port, + const std::string& polling) { + return mirror_init(name, path, host, port, polling); +} + +static std::shared_ptr mirror_init_defaults_4(const std::string& name, + const std::string& path, + const std::string& host, + const std::string& port, + const std::string& polling, + bool ssl) { + return mirror_init(name, path, host, port, polling, ssl); +} + void export_NodeAttr() { // Trigger & Complete thin wrapper over Expression, allows us to call: Task("a").add(Trigger("a=1"),Complete("b=1")) class_>("Trigger", DefsDoc::trigger(), init()) @@ -969,8 +1002,8 @@ void export_NodeAttr() { .def("step", &Repeat::step, "The increment for the repeat, as an integer") .def("value", &Repeat::last_valid_value, "The current value of the repeat as an integer"); - void (CronAttr::*add_time_series)(const TimeSeries&) = &CronAttr::addTimeSeries; - void (CronAttr::*add_time_series_2)(const TimeSlot& s, const TimeSlot& f, const TimeSlot& i) = + void (CronAttr::* add_time_series)(const TimeSeries&) = &CronAttr::addTimeSeries; + void (CronAttr::* add_time_series_2)(const TimeSlot& s, const TimeSlot& f, const TimeSlot& i) = &CronAttr::addTimeSeries; class_>("Cron", NodeAttrDoc::cron_doc()) .def("__init__", raw_function(&cron_raw_constructor, 1)) // will call -> cron_init or cron_init1 @@ -1073,6 +1106,11 @@ void export_NodeAttr() { class_("MirrorAttr", NodeAttrDoc::mirror_doc()) .def("__init__", make_constructor(&mirror_init)) + .def("__init__", make_constructor(&mirror_init_defaults_0)) + .def("__init__", make_constructor(&mirror_init_defaults_1)) + .def("__init__", make_constructor(&mirror_init_defaults_2)) + .def("__init__", make_constructor(&mirror_init_defaults_3)) + .def("__init__", make_constructor(&mirror_init_defaults_4)) .def(self == self) // __eq__ .def("__str__", &ecf::to_python_string) // __str__ .def("__copy__", copyObject) // __copy__ uses copy constructor diff --git a/libs/pyext/test/py_u_TestMirror.py b/libs/pyext/test/py_u_TestMirror.py index 02bdc1535..c3822dabd 100644 --- a/libs/pyext/test/py_u_TestMirror.py +++ b/libs/pyext/test/py_u_TestMirror.py @@ -26,6 +26,61 @@ def can_create_mirror_from_parameters(): assert mirror.auth() == "auth" +def can_create_mirror_from_default_parameters_0(): + mirror = ecf.MirrorAttr("name", "r_path") + assert mirror.name() == "name" + assert mirror.remote_path() == "r_path" + assert mirror.remote_host() == "%ECF_MIRROR_REMOTE_HOST%" + assert mirror.remote_port() == "%ECF_MIRROR_REMOTE_PORT%" + assert mirror.polling() == "%ECF_MIRROR_REMOTE_POLLING%" + assert mirror.ssl() == False + assert mirror.auth() == "%ECF_MIRROR_REMOTE_AUTH%" + + +def can_create_mirror_from_default_parameters_1(): + mirror = ecf.MirrorAttr("name", "r_path", "r_host") + assert mirror.name() == "name" + assert mirror.remote_path() == "r_path" + assert mirror.remote_host() == "r_host" + assert mirror.remote_port() == "%ECF_MIRROR_REMOTE_PORT%" + assert mirror.polling() == "%ECF_MIRROR_REMOTE_POLLING%" + assert mirror.ssl() == False + assert mirror.auth() == "%ECF_MIRROR_REMOTE_AUTH%" + + +def can_create_mirror_from_default_parameters_2(): + mirror = ecf.MirrorAttr("name", "r_path", "r_host", "r_port") + assert mirror.name() == "name" + assert mirror.remote_path() == "r_path" + assert mirror.remote_host() == "r_host" + assert mirror.remote_port() == "r_port" + assert mirror.polling() == "%ECF_MIRROR_REMOTE_POLLING%" + assert mirror.ssl() == False + assert mirror.auth() == "%ECF_MIRROR_REMOTE_AUTH%" + + +def can_create_mirror_from_default_parameters_3(): + mirror = ecf.MirrorAttr("name", "r_path", "r_host", "r_port", "polling") + assert mirror.name() == "name" + assert mirror.remote_path() == "r_path" + assert mirror.remote_host() == "r_host" + assert mirror.remote_port() == "r_port" + assert mirror.polling() == "polling" + assert mirror.ssl() == False + assert mirror.auth() == "%ECF_MIRROR_REMOTE_AUTH%" + + +def can_create_mirror_from_default_parameters_4(): + mirror = ecf.MirrorAttr("name", "r_path", "r_host", "r_port", "polling", True) + assert mirror.name() == "name" + assert mirror.remote_path() == "r_path" + assert mirror.remote_host() == "r_host" + assert mirror.remote_port() == "r_port" + assert mirror.polling() == "polling" + assert mirror.ssl() == True + assert mirror.auth() == "%ECF_MIRROR_AUTH%" + + def can_add_mirror_to_task(): suite = ecf.Suite("s1") @@ -101,6 +156,10 @@ def can_check_job_creation_with_mirror(): Test.print_test_start(os.path.basename(__file__)) can_create_mirror_from_parameters() + can_create_mirror_from_default_parameters_0() + can_create_mirror_from_default_parameters_1() + can_create_mirror_from_default_parameters_2() + can_create_mirror_from_default_parameters_3() can_add_mirror_to_task() can_embed_mirror_into_task() cannot_have_multiple_mirrors_in_single_task() From 2c51e848d0eee576cbb5f6dcc290a1bbff2aff7d Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Fri, 25 Oct 2024 16:54:55 +0100 Subject: [PATCH 3/3] Update Aviso/Mirror Python documentation Re ECFLOW-1981 --- docs/python_api/AvisoAttr.rst | 2 ++ docs/python_api/MirrorAttr.rst | 2 ++ libs/pyext/src/ecflow/python/NodeAttrDoc.cpp | 8 ++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/python_api/AvisoAttr.rst b/docs/python_api/AvisoAttr.rst index 0aa7b6473..d106dff92 100644 --- a/docs/python_api/AvisoAttr.rst +++ b/docs/python_api/AvisoAttr.rst @@ -33,6 +33,8 @@ Usage: t2 = Task('t2') t2.add_aviso('name', '{...}', 'http://aviso.com', '60', '/path/to/auth') +The parameters `url`, `schema`, `polling`, and `auth` are optional + .. py:method:: AvisoAttr.auth( (AvisoAttr)arg1) -> str : :module: ecflow diff --git a/docs/python_api/MirrorAttr.rst b/docs/python_api/MirrorAttr.rst index 0e613d7b8..a69c0d434 100644 --- a/docs/python_api/MirrorAttr.rst +++ b/docs/python_api/MirrorAttr.rst @@ -34,6 +34,8 @@ Usage: t2 = Task('t2') t2.add_aviso('name', '/remote/task', 'remote-ecflow', '3141', '60', True, '/path/to/auth') +The parameters `remote_host`, `remote_port`, `polling`, `ssl`, and `auth` are optional + .. py:method:: MirrorAttr.auth( (MirrorAttr)arg1) -> str : :module: ecflow diff --git a/libs/pyext/src/ecflow/python/NodeAttrDoc.cpp b/libs/pyext/src/ecflow/python/NodeAttrDoc.cpp index 8388b7ee7..5954496c1 100644 --- a/libs/pyext/src/ecflow/python/NodeAttrDoc.cpp +++ b/libs/pyext/src/ecflow/python/NodeAttrDoc.cpp @@ -728,7 +728,9 @@ const char* NodeAttrDoc::aviso_doc() { " AvisoAttr('name', '{...}', 'http://aviso.com', '60', '/path/to/auth'))\n" "\n" " t2 = Task('t2')\n" - " t2.add_aviso('name', '{...}', 'http://aviso.com', '60', '/path/to/auth')\n"; + " t2.add_aviso('name', '{...}', 'http://aviso.com', '60', '/path/to/auth')\n" + "\n" + "The parameters `url`, `schema`, `polling`, and `auth` are optional\n"; } const char* NodeAttrDoc::mirror_doc() { @@ -754,5 +756,7 @@ const char* NodeAttrDoc::mirror_doc() { " MirrorAttr('name', '/remote/task', 'remote-ecflow', '3141', '60', True, '/path/to/auth'))\n" "\n" " t2 = Task('t2')\n" - " t2.add_aviso('name', '/remote/task', 'remote-ecflow', '3141', '60', True, '/path/to/auth')\n"; + " t2.add_aviso('name', '/remote/task', 'remote-ecflow', '3141', '60', True, '/path/to/auth')\n" + "\n" + "The parameters `remote_host`, `remote_port`, `polling`, `ssl`, and `auth` are optional\n"; }