Coverage for python/lsst/pipe/base/pipeline_graph/_task_subsets.py: 60%
37 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 02:50 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 02:50 -0700
1# This file is part of pipe_base.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27from __future__ import annotations
29__all__ = ("TaskSubset",)
31from collections.abc import Iterator, MutableSet
33import networkx
34import networkx.algorithms.boundary
36from ._exceptions import PipelineGraphError
37from ._nodes import NodeKey, NodeType
40class TaskSubset(MutableSet[str]):
41 """A specialized set that represents a labeles subset of the tasks in a
42 pipeline graph.
44 Instances of this class should never be constructed directly; they should
45 only be accessed via the `PipelineGraph.task_subsets` attribute and created
46 by the `PipelineGraph.add_task_subset` method.
48 Parameters
49 ----------
50 parent_xgraph : `networkx.DiGraph`
51 Parent networkx graph that this subgraph is part of.
52 label : `str`
53 Label associated with this subset of the pipeline.
54 members : `set` [ `str` ]
55 Labels of the tasks that are members of this subset.
56 description : `str`, optional
57 Description string associated with this labeled subset.
59 Notes
60 -----
61 Iteration order is arbitrary, even when the parent pipeline graph is
62 ordered (there is no guarantee that an ordering of the tasks in the graph
63 implies a consistent ordering of subsets).
64 """
66 def __init__(
67 self,
68 parent_xgraph: networkx.DiGraph,
69 label: str,
70 members: set[str],
71 description: str,
72 ):
73 self._parent_xgraph = parent_xgraph
74 self._label = label
75 self._members = members
76 self._description = description
78 @property
79 def label(self) -> str:
80 """Label associated with this subset of the pipeline."""
81 return self._label
83 @property
84 def description(self) -> str:
85 """Description string associated with this labeled subset."""
86 return self._description
88 @description.setter
89 def description(self, value: str) -> None:
90 # Docstring in getter.
91 self._description = value
93 def __repr__(self) -> str:
94 return f"{self.label}: {self.description!r}, tasks={{{', '.join(iter(self))}}}"
96 def __contains__(self, key: object) -> bool:
97 return key in self._members
99 def __len__(self) -> int:
100 return len(self._members)
102 def __iter__(self) -> Iterator[str]:
103 return iter(self._members)
105 def add(self, task_label: str) -> None:
106 """Add a new task to this subset.
108 Parameters
109 ----------
110 task_label : `str`
111 Label for the task. Must already be present in the parent pipeline
112 graph.
113 """
114 key = NodeKey(NodeType.TASK, task_label)
115 if key not in self._parent_xgraph:
116 raise PipelineGraphError(f"{task_label!r} is not a task in the parent pipeline.")
117 self._members.add(key.name)
119 def discard(self, task_label: str) -> None:
120 """Remove a task from the subset if it is present.
122 Parameters
123 ----------
124 task_label : `str`
125 Label for the task. Must already be present in the parent pipeline
126 graph.
127 """
128 self._members.discard(task_label)