Skip to content

Commit b8a55d8

Browse files
Add a new entry_point for xtriggers (#5831)
* 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. * Built-in cylc-flow xtriggers are defined via new entry_points. --------- Co-authored-by: Ronnie Dutta <[email protected]>
1 parent 8a583b3 commit b8a55d8

File tree

6 files changed

+96
-9
lines changed

6 files changed

+96
-9
lines changed

changes.d/5831.feat.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add capability to install xtriggers via a new cylc.xtriggers entry point

cylc/flow/subprocpool.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from subprocess import DEVNULL, run # nosec
2929
from typing import Any, Callable, List, Optional
3030

31-
from cylc.flow import LOG
31+
from cylc.flow import LOG, iter_entry_points
3232
from cylc.flow.cfgspec.glbl_cfg import glbl_cfg
3333
from cylc.flow.cylc_subproc import procopen
3434
from cylc.flow.exceptions import PlatformLookupError
@@ -69,29 +69,41 @@ def _killpg(proc, signal):
6969
def get_func(func_name, src_dir):
7070
"""Find and return an xtrigger function from a module of the same name.
7171
72-
Can be in <src_dir>/lib/python, CYLC_MOD_LOC, or in Python path.
72+
These locations are checked in this order:
73+
- <src_dir>/lib/python/
74+
- `$CYLC_PYTHONPATH`
75+
- defined via a `cylc.xtriggers` entry point for an
76+
installed Python package.
77+
7378
Workflow source directory passed in as this is executed in an independent
7479
process in the command pool and therefore doesn't know about the workflow.
7580
7681
"""
7782
if func_name in _XTRIG_FUNCS:
7883
return _XTRIG_FUNCS[func_name]
84+
7985
# First look in <src-dir>/lib/python.
8086
sys.path.insert(0, os.path.join(src_dir, 'lib', 'python'))
8187
mod_name = func_name
8288
try:
8389
mod_by_name = __import__(mod_name, fromlist=[mod_name])
8490
except ImportError:
85-
# Then look in built-in xtriggers.
86-
mod_name = "%s.%s" % ("cylc.flow.xtriggers", func_name)
87-
try:
88-
mod_by_name = __import__(mod_name, fromlist=[mod_name])
89-
except ImportError:
90-
raise
91+
# Look for xtriggers via entry_points for external sources.
92+
# Do this after the lib/python and PYTHONPATH approaches to allow
93+
# users to override entry_point definitions with local/custom
94+
# implementations.
95+
for entry_point in iter_entry_points('cylc.xtriggers'):
96+
if func_name == entry_point.name:
97+
_XTRIG_FUNCS[func_name] = entry_point.load()
98+
return _XTRIG_FUNCS[func_name]
99+
100+
# Still unable to find anything so abort
101+
raise
102+
91103
try:
92104
_XTRIG_FUNCS[func_name] = getattr(mod_by_name, func_name)
93105
except AttributeError:
94-
# Module func_name has no function func_name.
106+
# Module func_name has no function func_name, nor an entry_point entry.
95107
raise
96108
return _XTRIG_FUNCS[func_name]
97109

setup.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ cylc.main_loop =
214214
cylc.pre_configure =
215215
cylc.post_install =
216216
log_vc_info = cylc.flow.install_plugins.log_vc_info:main
217+
# NOTE: Built-in xtriggers
218+
cylc.xtriggers =
219+
echo = cylc.flow.xtriggers.echo:echo
220+
wall_clock = cylc.flow.xtriggers.wall_clock:wall_clock
221+
workflow_state = cylc.flow.xtriggers.workflow_state:workflow_state
222+
xrandom = cylc.flow.xtriggers.xrandom:xrandom
217223

218224
[bdist_rpm]
219225
requires =
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
3+
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
#------------------------------------------------------------------------------
18+
19+
# An xtrigger added to $CYLC_PYTHONPATH should take precedence
20+
# over a `cylc.xtriggers` entry point of the same name
21+
22+
. "$(dirname "$0")/test_header"
23+
set_test_number 3
24+
25+
install_workflow "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
26+
27+
# Install the succeeding xtrigger function.
28+
export CYLC_PYTHONPATH=${WORKFLOW_RUN_DIR}/dir:${CYLC_PYTHONPATH:-}
29+
30+
# Validate the test workflow.
31+
run_ok "${TEST_NAME_BASE}-val" cylc validate --debug "${WORKFLOW_NAME}"
32+
33+
TEST_NAME="${TEST_NAME_BASE}-run"
34+
workflow_run_ok "${TEST_NAME}" cylc play --no-detach --debug "${WORKFLOW_NAME}"
35+
36+
# Check the result of xtrigger.
37+
grep_workflow_log_ok "${TEST_NAME_BASE}-grep" "echo overridden, args=('the_args',)"
38+
39+
purge
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python3
2+
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
3+
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
19+
def echo(*args, **kwargs):
20+
print(f"echo overridden, args={args}")
21+
return (True, {})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[scheduling]
2+
[[xtriggers]]
3+
x1 = echo("the_args")
4+
[[graph]]
5+
R1 = @x1 => foo
6+
[runtime]
7+
[[foo]]
8+
script = true

0 commit comments

Comments
 (0)