From 00c074a9584af66680d2dbbcd99f73e56c16ed41 Mon Sep 17 00:00:00 2001 From: marcosbento Date: Mon, 25 Mar 2024 14:01:57 +0000 Subject: [PATCH 1/8] Link to CMake Python3::Module target (#98) Since ecflow is built as a `module` (i.e. a shared library, dynamically loaded by the Python interpreter), the linkage in macOs requires passing flags `-undefined` and `-dynamic_lookup`. This is handled directly by CMake which, since CMake 3.15, defines a specific target `Python3::Module` to be used when building Python modules. Re ECFLOW-1950 --- CMakeLists.txt | 2 -- Pyext/python3/CMakeLists.txt | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2d39e5d6..178cb2b58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,6 @@ option( ENABLE_UI_BACKTRACE "Print a UI debug backtrace" OFF ) option( ENABLE_UI_USAGE_LOG "Enable UI usage logging" OFF ) option( ENABLE_SSL "Enable SSL encrypted communication" ON ) option( ENABLE_PYTHON_PTR_REGISTER "Some compilers/boost versions do not register shared ptr automatically" OFF ) -option( ENABLE_PYTHON_UNDEF_LOOKUP "Some boost/python versions are too closely linked" OFF ) option( ENABLE_HTTP "Enable HTTP server (experimental)" ON ) option( ENABLE_HTTP_COMPRESSION "Enable compression support by HTTP server" ON ) option( ENABLE_UDP "Enable UDP server (experimental)" ON ) @@ -192,7 +191,6 @@ endif() ecbuild_info( "ENABLE_SERVER : ${ENABLE_SERVER}" ) ecbuild_info( "ENABLE_PYTHON : ${ENABLE_PYTHON}" ) ecbuild_info( "ENABLE_PYTHON_PTR_REGISTER : ${ENABLE_PYTHON_PTR_REGISTER}" ) -ecbuild_info( "ENABLE_PYTHON_UNDEF_LOOKUP : ${ENABLE_PYTHON_UNDEF_LOOKUP}" ) ecbuild_info( "ENABLE_UI : ${ENABLE_UI}" ) ecbuild_info( "ENABLE_TESTS : ${ENABLE_TESTS} *if* disabled no need for boost test libs" ) ecbuild_info( "ENABLE_ALL_TESTS : ${ENABLE_ALL_TESTS}" ) diff --git a/Pyext/python3/CMakeLists.txt b/Pyext/python3/CMakeLists.txt index 078288bd2..ef8e820db 100644 --- a/Pyext/python3/CMakeLists.txt +++ b/Pyext/python3/CMakeLists.txt @@ -8,16 +8,16 @@ # nor does it submit to any jurisdiction. # -# ENABLE_PYTHON_UNDEF_LOOKUP -# on some systems (e.g. conda on macOS) the boost Python libraries seem to be too -# closely linked with the exact version of the Python development libraries, -# meaning that we get segfaults when we try to run a Python example. By removing -# the Python libraries from the link line and adding -undefined dynamic_lookup -# we can make our ecflow shared library more movable bewteen systems - -if (ENABLE_PYTHON_UNDEF_LOOKUP) - add_link_options(-undefined dynamic_lookup) -endif() +# +# Important! +# +# Notice that ecflow Python module is linked with `Python3::Module` CMake imported target, +# to enable a loose linkage with Python development libraries -- this is necessary in some +# platforms, such as conda-forge+macOS. +# +# In practice, this implies that `-undefined` and `-dynamic_lookup` linkage flags are used +# and the Python development libraries are not linked directly into the ecflow Python module. +# ecbuild_add_library( TARGET @@ -35,7 +35,7 @@ ecbuild_add_library( node attributes core - Python3::Python + Python3::Module Boost::${ECFLOW_BOOST_PYTHON_COMPONENT} $<$:OpenSSL::SSL> CXXFLAGS From 8ba721b4d0b1e005f575ee2ff95b0a2371b87b74 Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Wed, 27 Mar 2024 12:01:29 +0000 Subject: [PATCH 2/8] Prepare ecFlow 5.12.4 release --- CMakeLists.txt | 2 +- Pyext/ecflow/__init__.py | 2 +- docs/conf.py | 2 +- docs/release_notes/version_5.12.rst | 10 ++++++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 178cb2b58..7b5c8a498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ endif() find_package( ecbuild 3.4 REQUIRED HINTS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild ) # Before project() # this will generate variables, see ACore/ecflow_version.h.in -project( ecflow LANGUAGES CXX VERSION 5.12.3 ) +project( ecflow LANGUAGES CXX VERSION 5.12.4 ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) diff --git a/Pyext/ecflow/__init__.py b/Pyext/ecflow/__init__.py index 3dc8188de..78e826bd7 100644 --- a/Pyext/ecflow/__init__.py +++ b/Pyext/ecflow/__init__.py @@ -15,6 +15,6 @@ The ecFlow python module """ -__version__ = '5.12.3' +__version__ = '5.12.4' # http://stackoverflow.com/questions/13040646/how-do-i-create-documentation-with-pydoc diff --git a/docs/conf.py b/docs/conf.py index f72047e87..ccfe41248 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -93,7 +93,7 @@ def get_ecflow_version(): - version = "5.12.3" + version = "5.12.4" ecflow_version = version.split(".") print("Extracted ecflow version '" + str(ecflow_version)) return ecflow_version diff --git a/docs/release_notes/version_5.12.rst b/docs/release_notes/version_5.12.rst index 1224c2210..bbd98d156 100644 --- a/docs/release_notes/version_5.12.rst +++ b/docs/release_notes/version_5.12.rst @@ -6,6 +6,16 @@ Version 5.12 updates .. role:: jiraissue :class: hidden +Version 5.12.4 +============== + +* `Released `__\ on 2024-03-XX + +ecFlow Client +------------- + +- **Bug** corrected ecFlow Python3 module linkage (specific for conda-forge) :jiraissue:`ECFLOW-1950` + Version 5.12.3 ============== From 6d75f2af71e9c69e8b26930557b3f590e02b9c56 Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Tue, 16 Apr 2024 13:58:17 +0100 Subject: [PATCH 3/8] Add "path" field to each Node on full tree content Re ECFLOW-1952 --- Http/src/ecflow/http/TreeGeneration.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Http/src/ecflow/http/TreeGeneration.hpp b/Http/src/ecflow/http/TreeGeneration.hpp index f13c0e4c6..6de40a55a 100644 --- a/Http/src/ecflow/http/TreeGeneration.hpp +++ b/Http/src/ecflow/http/TreeGeneration.hpp @@ -70,6 +70,7 @@ struct FullTree ojson& current = parent_[suite.name()] = ojson::object({}); current["type"] = "suite"; + current["path"] = suite.absNodePath(); publish_state(suite, current); publish_attributes(suite, current); @@ -84,6 +85,7 @@ struct FullTree ojson& current = parent_[family.name()] = ojson::object({}); current["type"] = "family"; + current["path"] = family.absNodePath(); publish_state(family, current); publish_attributes(family, current); @@ -98,6 +100,7 @@ struct FullTree ojson& current = parent_[task.name()] = ojson::object({}); current["type"] = "task"; + current["path"] = task.absNodePath(); publish_state(task, current); publish_attributes(task, current); @@ -113,6 +116,7 @@ struct FullTree stack_.push_back(¤t); current["type"] = "alias"; + current["path"] = alias.absNodePath(); publish_state(alias, current); publish_attributes(alias, current); } From 792e97dea0d229ce6f4b3d82f1df542d3f8d945e Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Tue, 16 Apr 2024 13:58:45 +0100 Subject: [PATCH 4/8] Avoid incorrectly cascading Alias nodes Re ECFLOW-1953 --- Http/src/ecflow/http/TreeGeneration.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Http/src/ecflow/http/TreeGeneration.hpp b/Http/src/ecflow/http/TreeGeneration.hpp index 6de40a55a..0945a6bb9 100644 --- a/Http/src/ecflow/http/TreeGeneration.hpp +++ b/Http/src/ecflow/http/TreeGeneration.hpp @@ -121,9 +121,7 @@ struct FullTree publish_attributes(alias, current); } - void end_visit(const Alias& alias [[maybe_unused]]) { - // Nothing to do... - } + void end_visit(const Alias& alias [[maybe_unused]]) { stack_.pop_back(); } const ojson& content() const { return root_; } From 2836ad50e1f2d1f45fbb2c35ad912306b0a49634 Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Tue, 16 Apr 2024 13:59:22 +0100 Subject: [PATCH 5/8] Add "flag" attribute to Node on full tree content Re ECFLOW-1954 --- Http/src/ecflow/http/TreeGeneration.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Http/src/ecflow/http/TreeGeneration.hpp b/Http/src/ecflow/http/TreeGeneration.hpp index 0945a6bb9..7b6fb79a6 100644 --- a/Http/src/ecflow/http/TreeGeneration.hpp +++ b/Http/src/ecflow/http/TreeGeneration.hpp @@ -227,6 +227,10 @@ struct FullTree for (const auto& attr : node.generics()) { array.emplace_back(publish_atribute(attr, "generic")); } + + if (auto flag = node.get_flag(); flag.flag()) { + array.emplace_back(publish_atribute(flag, "flag")); + } } private: From c96a0b43009f7ae7fafd36249bbce4fe487d895a Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Mon, 22 Apr 2024 11:43:33 +0100 Subject: [PATCH 6/8] Add URL 'with_id' option to enable "id" field - Rename "path" field to more generic name "id" Re ECFLOW-1952 --- Http/src/ecflow/http/ApiV1.cpp | 8 +++++++- Http/src/ecflow/http/ApiV1Impl.cpp | 4 ++-- Http/src/ecflow/http/ApiV1Impl.hpp | 2 +- Http/src/ecflow/http/TreeGeneration.hpp | 19 ++++++++++++++----- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Http/src/ecflow/http/ApiV1.cpp b/Http/src/ecflow/http/ApiV1.cpp index 49eb4e7aa..245b2f953 100644 --- a/Http/src/ecflow/http/ApiV1.cpp +++ b/Http/src/ecflow/http/ApiV1.cpp @@ -212,6 +212,11 @@ static std::string get_tree_content_kind(const httplib::Request& request) { return request.has_param(content) ? request.get_param_value(content) : "basic"; } +static bool get_tree_content_id_flag(const httplib::Request& request) { + constexpr const char* content = "with_id"; + return request.has_param(content) ? (request.get_param_value(content) == "true" ? true : false) : false; +} + } // namespace namespace v1 { @@ -262,7 +267,8 @@ void node_tree_read(const httplib::Request& request, httplib::Response& response num_cached_requests++; const std::string path = request.matches[1]; std::string tree_kind = get_tree_content_kind(request); - ojson tree_content = (tree_kind == "full") ? get_full_node_tree(path) : get_basic_node_tree(path); + bool with_id = get_tree_content_id_flag(request); + ojson tree_content = (tree_kind == "full") ? get_full_node_tree(path, with_id) : get_basic_node_tree(path); ojson j = filter_json(tree_content, request); response.status = HttpStatusCode::success_ok; response.set_content(j.dump(), "application/json"); diff --git a/Http/src/ecflow/http/ApiV1Impl.cpp b/Http/src/ecflow/http/ApiV1Impl.cpp index 0888a90f5..e39e7f721 100644 --- a/Http/src/ecflow/http/ApiV1Impl.cpp +++ b/Http/src/ecflow/http/ApiV1Impl.cpp @@ -129,8 +129,8 @@ ojson get_basic_node_tree(const std::string& path) { return tree.content(); } -ojson get_full_node_tree(const std::string& path) { - FullTree tree; +ojson get_full_node_tree(const std::string& path, bool with_id) { + FullTree tree{with_id}; DefsTreeVisitor(get_defs(), tree).visit_at(path); return tree.content(); } diff --git a/Http/src/ecflow/http/ApiV1Impl.hpp b/Http/src/ecflow/http/ApiV1Impl.hpp index b5514c750..97c5d1885 100644 --- a/Http/src/ecflow/http/ApiV1Impl.hpp +++ b/Http/src/ecflow/http/ApiV1Impl.hpp @@ -18,7 +18,7 @@ namespace ecf::http { ojson get_basic_node_tree(const std::string& path); -ojson get_full_node_tree(const std::string& path); +ojson get_full_node_tree(const std::string& path, bool with_id); ojson get_sparser_node_tree(const std::string& path); void add_suite(const httplib::Request& request, httplib::Response& response); diff --git a/Http/src/ecflow/http/TreeGeneration.hpp b/Http/src/ecflow/http/TreeGeneration.hpp index 7b6fb79a6..d1c8cb086 100644 --- a/Http/src/ecflow/http/TreeGeneration.hpp +++ b/Http/src/ecflow/http/TreeGeneration.hpp @@ -63,14 +63,16 @@ struct BasicTree struct FullTree { - FullTree() : root_(ojson::object({})), stack_{&root_} {} + FullTree(bool with_id) : root_(ojson::object({})), stack_{&root_}, with_id_{with_id} {} void begin_visit(const Suite& suite) { ojson& parent_ = *stack_.back(); ojson& current = parent_[suite.name()] = ojson::object({}); current["type"] = "suite"; - current["path"] = suite.absNodePath(); + if (with_id_) { + current["id"] = suite.absNodePath(); + } publish_state(suite, current); publish_attributes(suite, current); @@ -85,7 +87,9 @@ struct FullTree ojson& current = parent_[family.name()] = ojson::object({}); current["type"] = "family"; - current["path"] = family.absNodePath(); + if (with_id_) { + current["id"] = family.absNodePath(); + } publish_state(family, current); publish_attributes(family, current); @@ -100,7 +104,9 @@ struct FullTree ojson& current = parent_[task.name()] = ojson::object({}); current["type"] = "task"; - current["path"] = task.absNodePath(); + if (with_id_) { + current["id"] = task.absNodePath(); + } publish_state(task, current); publish_attributes(task, current); @@ -116,7 +122,9 @@ struct FullTree stack_.push_back(¤t); current["type"] = "alias"; - current["path"] = alias.absNodePath(); + if (with_id_) { + current["id"] = alias.absNodePath(); + } publish_state(alias, current); publish_attributes(alias, current); } @@ -236,6 +244,7 @@ struct FullTree private: ojson root_; std::vector stack_; + bool with_id_; }; } // namespace ecf::http From 17ec79f63e99186422f79b0b666de8a2c898cb4f Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Mon, 22 Apr 2024 15:29:18 +0100 Subject: [PATCH 7/8] Update documentation with new 'with_id' option Re ECFLOW-1952 --- docs/rest_api.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/rest_api.rst b/docs/rest_api.rst index 2538d3e9d..385c23199 100644 --- a/docs/rest_api.rst +++ b/docs/rest_api.rst @@ -492,7 +492,7 @@ Obtain the tree of all Suites * - Description - **Read** a tree with all suites * - Parameters - - :code:`content`, (optional), possible values: :code:`basic`, :code:`full` + - :code:`content`, (optional), possible values: :code:`basic`, :code:`full`; :code:`with_id`, (optional), possible values: :code:`true`, :code:`false` * - Payload - *empty* * - Response @@ -513,13 +513,14 @@ When query parameter :code:`content` is not provided, or query parameter is :cod } } -When query parameter :code:`content=full`, the full Suite tree is provided: +When query parameters :code:`content=full&with_id=true`, the full Suite tree is provided: .. code:: json { "some_suite": { "type": "suite", + "id": "/some_suite", "state": { "node": "active", "default": "complete" @@ -535,6 +536,7 @@ When query parameter :code:`content=full`, the full Suite tree is provided: "children": { "some_family": { "type": "family", + "id": "/some_suite/some_family", "state": { "node": "active", "default": "unknown" @@ -543,6 +545,7 @@ When query parameter :code:`content=full`, the full Suite tree is provided: "children": { "some_task": { "type": "task", + "id": "/some_suite/some_family/some_task", "state": { "node": "active", "default": "unknown" From 7e1cc73aa303f0b84179a487032ead029b03e986 Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Mon, 22 Apr 2024 15:55:42 +0100 Subject: [PATCH 8/8] Update the release notes for ecFlow 5.12.4 release --- docs/release_notes/version_5.12.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/release_notes/version_5.12.rst b/docs/release_notes/version_5.12.rst index bbd98d156..ffb96a2e4 100644 --- a/docs/release_notes/version_5.12.rst +++ b/docs/release_notes/version_5.12.rst @@ -9,13 +9,19 @@ Version 5.12 updates Version 5.12.4 ============== -* `Released `__\ on 2024-03-XX +* `Released `__\ on 2024-03-23 ecFlow Client ------------- - **Bug** corrected ecFlow Python3 module linkage (specific for conda-forge) :jiraissue:`ECFLOW-1950` +ecFlow HTTP +----------- + +- **Feature** added :code:`id` field to each Node in the :code:`//tree` endpoint response :jiraissue:`ECFLOW-1952` +- **Improvement** added *flag* attribute to Nodes in the :code:`//tree` endpoint response :jiraissue:`ECFLOW-1954` +- **Bug** corrected Alias node structure in the :code:`//tree` endpoint response :jiraissue:`ECFLOW-1953` Version 5.12.3 ==============