Skip to content

Commit cdeaf3f

Browse files
b-butlercsadorfbdice
authoredDec 5, 2022
Deprecate FlowGroupEntry.with_directives (#696)
* refactor: Add directives keyword argument to FlowGroupEntry.__call__ Also deprecates FlowGroupEntry.with_directives. * test: Update tests to not raise warnings * doc: Update changelog for #696. * doc: Make FlowGroupEntry directives change documentation user friendly * refactor: Use more clear spacing Co-authored-by: Carl Simon Adorf <carl.simon.adorf@gmail.com> * Require func to be positional-only. * Fix filterwarnings. * Update changelog.txt * Update changelog.txt * Require func to be positional-only. Co-authored-by: Carl Simon Adorf <carl.simon.adorf@gmail.com> Co-authored-by: Bradley Dice <bdice@bradleydice.com>
1 parent 38a7b8b commit cdeaf3f

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-14
lines changed
 

‎changelog.txt

+6
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ Version 0.23
1111
[0.23.0] -- 20xx-xx-xx
1212
----------------------
1313

14+
Added
15+
+++++
16+
17+
- The ``FlowGroupEntry`` class can be called with a ``directives`` keyword argument: ``FlowGroupEntry(directives={...})`` (#696).
18+
1419
Changed
1520
+++++++
1621

1722
- Deprecated placing ``@FlowProject.pre`` and ``@FlowProject.post`` before the ``FlowProject.operation`` decorator (#690).
1823
- Require ``signac`` version 1.8.0 (#693).
1924
- Deprecated ``alias`` CLI argument to ``flow init`` (#693).
2025
- Algorithm for computing cluster job ids (#695).
26+
- Deprecated ``FlowGroupEntry.with_directives`` in favor of a directives keyword argument in ``FlowGroupEntry()``(#696).
2127

2228
Fixed
2329
+++++

‎flow/project.py

+36-10
Original file line numberDiff line numberDiff line change
@@ -634,12 +634,10 @@ class FlowGroupEntry:
634634
635635
Operation functions can be marked for inclusion into a :class:`FlowGroup`
636636
by decorating the functions with a corresponding :class:`FlowGroupEntry`.
637-
If the operation requires specific directives, :meth:`~.with_directives`
638-
accepts keyword arguments that are mapped to directives and returns a
639-
decorator that can be applied to the operation to mark it for inclusion in
640-
the group and indicate that it should be executed using the specified
641-
directives. This overrides the default directives specified by
642-
:meth:`flow.directives`.
637+
If the operation requires group specific directives, calling the
638+
:class:`FlowGroupEntry` with the keyword argument ``directives`` allows the
639+
setting of directives for the exclusively for the group. Doing this overrides
640+
the default directives specified by :meth:`FlowProject.operation`.
643641
644642
Parameters
645643
----------
@@ -673,7 +671,7 @@ def __init__(
673671
# `@operation`.
674672
self.group_aggregator = group_aggregator
675673

676-
def __call__(self, func):
674+
def __call__(self, func=None, /, *, directives=None):
677675
"""Add the function into the group's operations.
678676
679677
This call operator allows the class to be used as a decorator.
@@ -683,12 +681,23 @@ def __call__(self, func):
683681
func : callable
684682
The function to decorate.
685683
684+
directives : dict
685+
Directives to use for resource requests and execution.
686+
The directives specified in this decorator are only applied when
687+
executing the operation through the :class:`FlowGroup`.
688+
To apply directives to an individual operation executed outside of the
689+
group, see :meth:`.FlowProject.operation`.
690+
686691
Returns
687692
-------
688-
callable
693+
func
689694
The decorated function.
690-
691695
"""
696+
if func is None:
697+
return functools.partial(self._internal_call, directives=directives)
698+
return self._internal_call(func, directives=directives)
699+
700+
def _internal_call(self, func, /, *, directives):
692701
if not any(
693702
func == op_func for _, op_func in self._project._OPERATION_FUNCTIONS
694703
):
@@ -702,6 +711,13 @@ def __call__(self, func):
702711
f"Cannot reregister operation '{func}' with the group '{self.name}'."
703712
)
704713
func._flow_groups[self._project].add(self.name)
714+
if directives is None:
715+
return func
716+
717+
if hasattr(func, "_flow_group_operation_directives"):
718+
func._flow_group_operation_directives[self.name] = directives
719+
else:
720+
func._flow_group_operation_directives = {self.name: directives}
705721
return func
706722

707723
def _set_directives(self, func, directives):
@@ -729,6 +745,9 @@ def with_directives(self, directives):
729745
To apply directives to an individual operation executed outside of the
730746
group, see :meth:`.FlowProject.operation`.
731747
748+
Note:
749+
This method has been deprecated and will be removed in 0.24.0.
750+
732751
Parameters
733752
----------
734753
directives : dict
@@ -740,6 +759,13 @@ def with_directives(self, directives):
740759
A decorator which registers the operation with the group using the
741760
specified directives.
742761
"""
762+
_deprecated_warning(
763+
deprecation="@FlowGroupEntry.with_directives",
764+
alternative="Use the directives keyword argument in base decorator e.g. "
765+
"@FlowGroupEntry(directives={...}).",
766+
deprecated_in="0.23.0",
767+
removed_in="0.24.0",
768+
)
743769

744770
def decorator(func):
745771
self._set_directives(func, directives)
@@ -763,7 +789,7 @@ class FlowGroup:
763789
764790
group = FlowProject.make_group(name='example_group')
765791
766-
@group.with_directives({"nranks": 4})
792+
@group(directives={"nranks": 4})
767793
@FlowProject.operation({"nranks": 2, "executable": "python3"})
768794
def op1(job):
769795
pass

‎tests/define_test_project.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def op2(job):
6262
job.document.test = os.getpid()
6363

6464

65-
@group2.with_directives(dict(omp_num_threads=4))
65+
@group2(directives={"omp_num_threads": 4})
6666
@_TestProject.post.true("test3_true")
6767
@_TestProject.post.false("test3_false")
6868
@_TestProject.post.not_(lambda job: job.doc.test3_false)

‎tests/test_project.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,9 @@ class A(FlowProject):
17111711
def foo_operation(job):
17121712
pass
17131713

1714+
@pytest.mark.filterwarnings(
1715+
"ignore:.*with_directives has been deprecated.*:FutureWarning"
1716+
)
17141717
def test_repeat_operation_group_directives_definition(self):
17151718
"""Test that operations cannot be registered with group directives multiple times."""
17161719

@@ -1733,12 +1736,12 @@ class A(flow.FlowProject):
17331736

17341737
group = A.make_group("group")
17351738

1736-
@group.with_directives(dict(ngpu=2, nranks=4))
1739+
@group(directives={"ngpu": 2, "nranks": 4})
17371740
@A.operation
17381741
def op1(job):
17391742
pass
17401743

1741-
@group.with_directives(dict(ngpu=2, nranks=4))
1744+
@group(directives={"ngpu": 2, "nranks": 4})
17421745
@A.operation
17431746
def op2(job):
17441747
pass
@@ -1764,7 +1767,7 @@ class A(flow.FlowProject):
17641767

17651768
group = A.make_group("group")
17661769

1767-
@group.with_directives(dict(ngpu=2, nranks=4))
1770+
@group(directives={"ngpu": 2, "nranks": 4})
17681771
@A.operation
17691772
def op1(job):
17701773
pass

0 commit comments

Comments
 (0)