From 065464c7e6a5a1c0b44cc1f1a482443aeb15a1fe Mon Sep 17 00:00:00 2001 From: Tom Coleman <15375218+ColemanTom@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:54:14 +1100 Subject: [PATCH] Add a new entry_point for xtriggers This creates a clean way to add xtriggers from python packages. xtriggers no longer need to be directly in the PYTHONPATH, but instead can be added via a cylc.xtriggers entry point. Local cylc-flow xtriggers are defined via a new entry_point. --- cylc/flow/subprocpool.py | 28 +++++++++++++++++++--------- cylc/flow/xtriggers_entry_point.py | 30 ++++++++++++++++++++++++++++++ setup.cfg | 3 +++ 3 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 cylc/flow/xtriggers_entry_point.py diff --git a/cylc/flow/subprocpool.py b/cylc/flow/subprocpool.py index c380bdaa3e8..0e045503065 100644 --- a/cylc/flow/subprocpool.py +++ b/cylc/flow/subprocpool.py @@ -28,7 +28,7 @@ from subprocess import DEVNULL, run # nosec from typing import Any, Callable, List, Optional -from cylc.flow import LOG +from cylc.flow import LOG, iter_entry_points from cylc.flow.cfgspec.glbl_cfg import glbl_cfg from cylc.flow.cylc_subproc import procopen from cylc.flow.exceptions import PlatformLookupError @@ -69,29 +69,39 @@ def _killpg(proc, signal): def get_func(func_name, src_dir): """Find and return an xtrigger function from a module of the same name. - Can be in /lib/python, CYLC_MOD_LOC, or in Python path. + Can be in /lib/python, in Python path, or defined via an + entry_point. Loctions checked are in this order. + Workflow source directory passed in as this is executed in an independent process in the command pool and therefore doesn't know about the workflow. """ if func_name in _XTRIG_FUNCS: return _XTRIG_FUNCS[func_name] + # First look in /lib/python. sys.path.insert(0, os.path.join(src_dir, 'lib', 'python')) mod_name = func_name try: mod_by_name = __import__(mod_name, fromlist=[mod_name]) except ImportError: - # Then look in built-in xtriggers. - mod_name = "%s.%s" % ("cylc.flow.xtriggers", func_name) - try: - mod_by_name = __import__(mod_name, fromlist=[mod_name]) - except ImportError: - raise + # Look for xtriggers via entry_points for external sources. + # Do this after the lib/python and PYTHONPATH approaches to allow + # users to override entry_point definitions with local/custom + # implementations. + for entry_point in iter_entry_points('cylc.xtriggers'): + entries = entry_point.resolve()() + if func_name in entries: + _XTRIG_FUNCS[func_name] = entries[func_name] + return _XTRIG_FUNCS[func_name] + + # Still unable to find anything so abort + raise + try: _XTRIG_FUNCS[func_name] = getattr(mod_by_name, func_name) except AttributeError: - # Module func_name has no function func_name. + # Module func_name has no function func_name, nor an entry_point entry. raise return _XTRIG_FUNCS[func_name] diff --git a/cylc/flow/xtriggers_entry_point.py b/cylc/flow/xtriggers_entry_point.py new file mode 100644 index 00000000000..efa957116f9 --- /dev/null +++ b/cylc/flow/xtriggers_entry_point.py @@ -0,0 +1,30 @@ +# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. +# Copyright (C) NIWA & British Crown (Met Office) & Contributors. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +from cylc.flow.xtriggers import ( + echo, + wall_clock, + workflow_state, + xrandom, +) + +# Entry point: +def main(): + return { + 'echo': echo.echo, + 'wall_clock': wall_clock.wall_clock, + 'workflow_state': workflow_state.workflow_state, + 'xrandom': xrandom.xrandom, + } diff --git a/setup.cfg b/setup.cfg index e8e7f46b2d2..b825e5dec60 100644 --- a/setup.cfg +++ b/setup.cfg @@ -215,6 +215,9 @@ cylc.main_loop = cylc.pre_configure = cylc.post_install = log_vc_info = cylc.flow.install_plugins.log_vc_info:main +# NOTE: Built-in xtriggers +cylc.xtriggers = + cylc_flow = cylc.flow.xtrigger_entry_point:main [bdist_rpm] requires =