lsst-pipe-base 29.2025.1300__py3-none-any.whl → 29.2025.1500__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. lsst/pipe/base/all_dimensions_quantum_graph_builder.py +4 -0
  2. lsst/pipe/base/pipeline_graph/__main__.py +1 -0
  3. lsst/pipe/base/pipeline_graph/_exceptions.py +7 -0
  4. lsst/pipe/base/pipeline_graph/_pipeline_graph.py +360 -11
  5. lsst/pipe/base/pipeline_graph/expressions.py +271 -0
  6. lsst/pipe/base/pipeline_graph/visualization/__init__.py +1 -0
  7. lsst/pipe/base/pipeline_graph/visualization/_formatting.py +300 -5
  8. lsst/pipe/base/pipeline_graph/visualization/_options.py +11 -3
  9. lsst/pipe/base/pipeline_graph/visualization/_show.py +23 -3
  10. lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py +250 -0
  11. lsst/pipe/base/quantum_graph_skeleton.py +7 -0
  12. lsst/pipe/base/quantum_provenance_graph.py +28 -0
  13. lsst/pipe/base/version.py +1 -1
  14. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/METADATA +2 -1
  15. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/RECORD +23 -21
  16. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/WHEEL +0 -0
  17. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/entry_points.txt +0 -0
  18. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/licenses/COPYRIGHT +0 -0
  19. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/licenses/LICENSE +0 -0
  20. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/licenses/bsd_license.txt +0 -0
  21. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/licenses/gpl-v3.0.txt +0 -0
  22. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/top_level.txt +0 -0
  23. {lsst_pipe_base-29.2025.1300.dist-info → lsst_pipe_base-29.2025.1500.dist-info}/zip-safe +0 -0
@@ -48,6 +48,7 @@ from ._merge import (
48
48
  )
49
49
  from ._options import NodeAttributeOptions
50
50
  from ._printer import make_default_printer
51
+ from ._status_annotator import NodeStatusAnnotator, NodeStatusOptions
51
52
 
52
53
  DisplayNodeKey = NodeKey | MergedNodeKey
53
54
 
@@ -64,6 +65,8 @@ def parse_display_args(
64
65
  merge_output_trees: int = 4,
65
66
  merge_intermediates: bool = True,
66
67
  include_automatic_connections: bool = False,
68
+ status_annotator: NodeStatusAnnotator | None = None,
69
+ status_options: NodeStatusOptions | None = None,
67
70
  ) -> tuple[networkx.DiGraph | networkx.MultiDiGraph, NodeAttributeOptions]:
68
71
  """Print a text-based ~.PipelineGraph` visualization.
69
72
 
@@ -126,21 +129,34 @@ def parse_display_args(
126
129
  include_automatic_connections : `bool`, optional
127
130
  Whether to include automatically-added connections like the config,
128
131
  log, and metadata dataset types for each task. Default is `False`.
132
+ status_annotator : `NodeStatusAnnotator`, optional
133
+ Annotator to add status information to the graph. Default is `None`.
134
+ status_options : `NodeStatusOptions`, optional
135
+ Options for displaying execution status. Default is `None`.
129
136
  """
130
137
  if init is None:
131
138
  if not dataset_types:
132
139
  raise ValueError("Cannot show init and runtime graphs unless dataset types are shown.")
133
140
  xgraph = pipeline_graph.make_xgraph()
141
+ if status_annotator is not None:
142
+ raise ValueError("Cannot show status with both init and runtime graphs.")
134
143
  elif dataset_types:
135
144
  xgraph = pipeline_graph.make_bipartite_xgraph(init)
145
+ if status_annotator is not None:
146
+ status_annotator(xgraph, dataset_types=True)
136
147
  else:
137
148
  xgraph = pipeline_graph.make_task_xgraph(init)
138
149
  storage_classes = False
150
+ if status_annotator is not None:
151
+ status_annotator(xgraph, dataset_types=False)
139
152
 
140
153
  options = NodeAttributeOptions(
141
- dimensions=dimensions, storage_classes=storage_classes, task_classes=task_classes
154
+ dimensions=dimensions,
155
+ storage_classes=storage_classes,
156
+ task_classes=task_classes,
157
+ status=status_options,
142
158
  )
143
- options = options.checked(pipeline_graph.is_fully_resolved)
159
+ options = options.checked(pipeline_graph.is_fully_resolved, has_status=status_annotator is not None)
144
160
 
145
161
  if dataset_types and not include_automatic_connections:
146
162
  taskish_nodes: list[TaskNode | TaskInitNode] = []
@@ -219,10 +235,14 @@ def show(
219
235
  if width < 0:
220
236
  width, _ = get_terminal_size()
221
237
 
238
+ # Number of columns used for padding after a symbol.
239
+ # Must match the padding added by the `Printer` class.
240
+ symbol_padding = 2
241
+
222
242
  printer = make_default_printer(layout.width, color, stream)
223
243
  printer.get_symbol = get_node_symbol
224
244
 
225
- get_text = GetNodeText(xgraph, options, (width - printer.width) if width else 0)
245
+ get_text = GetNodeText(xgraph, options, (width - printer.width - symbol_padding) if width else 0)
226
246
  printer.get_text = get_text
227
247
 
228
248
  printer.print(stream, layout)
@@ -0,0 +1,250 @@
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/>.
27
+ from __future__ import annotations
28
+
29
+ __all__ = (
30
+ "QuantumGraphExecutionStatusAnnotator",
31
+ "QuantumGraphExecutionStatusOptions",
32
+ "QuantumProvenanceGraphStatusAnnotator",
33
+ "QuantumProvenanceGraphStatusOptions",
34
+ )
35
+
36
+ import dataclasses
37
+ from typing import TYPE_CHECKING, Any, Literal, Protocol, overload
38
+
39
+ import networkx
40
+
41
+ from .._nodes import NodeKey, NodeType
42
+
43
+ if TYPE_CHECKING:
44
+ from ... import quantum_provenance_graph as qpg
45
+
46
+ # ANSI color codes.
47
+ GREEN = "\033[32m"
48
+ RED = "\033[31m"
49
+ YELLOW = "\033[33m"
50
+ CYAN = "\033[36m"
51
+ WHITE = "\033[37m"
52
+ GRAY = "\033[90m"
53
+ MAGENTA = "\033[35m"
54
+ BROWN = "\u001b[38;5;130m"
55
+ RESET = "\033[0m"
56
+
57
+
58
+ @dataclasses.dataclass
59
+ class TaskStatusInfo:
60
+ """Holds status information for a task."""
61
+
62
+ expected: int
63
+ succeeded: int
64
+ failed: int
65
+ blocked: int
66
+ ready: int | None = None
67
+ running: int | None = None
68
+ wonky: int | None = None
69
+ unknown: int | None = None
70
+
71
+
72
+ @dataclasses.dataclass
73
+ class DatasetTypeStatusInfo:
74
+ """Holds status information for a dataset type."""
75
+
76
+ expected: int
77
+ produced: int
78
+
79
+
80
+ @dataclasses.dataclass
81
+ class StatusColors:
82
+ """Base class for holding ANSI color codes for different progress segments
83
+ or statuses.
84
+ """
85
+
86
+ # Base task status colors.
87
+ expected: str = WHITE
88
+ succeeded: str = GREEN
89
+ failed: str = RED
90
+
91
+ # Base dataset type status colors.
92
+ produced: str = GREEN
93
+
94
+ # Reset to default color.
95
+ reset: str = RESET
96
+
97
+
98
+ @dataclasses.dataclass
99
+ class QuantumGraphExecutionStatusColors(StatusColors):
100
+ """Holds ANSI color codes for different progress segments or statuses for
101
+ quantum graph execution reports.
102
+
103
+ Status colors for both task and dataset type nodes are included.
104
+ """
105
+
106
+ def __post_init__(self) -> None:
107
+ raise NotImplementedError("`QuantumGraphExecutionStatusColors` is not implemented yet.")
108
+
109
+
110
+ @dataclasses.dataclass
111
+ class QuantumProvenanceGraphStatusColors(StatusColors):
112
+ """Holds ANSI color codes for different progress segments or statuses for
113
+ quantum provenance graph reports.
114
+
115
+ Status colors for both task and dataset type nodes are included.
116
+ """
117
+
118
+ # Additional task status colors.
119
+ blocked: str = YELLOW
120
+ ready: str = GRAY
121
+ running: str = MAGENTA
122
+ wonky: str = CYAN
123
+ unknown: str = BROWN
124
+
125
+
126
+ @dataclasses.dataclass
127
+ class NodeStatusOptions:
128
+ """Base options for node status visualization.
129
+
130
+ Attributes
131
+ ----------
132
+ colors : `StatusColors`
133
+ A dataclass specifying ANSI color codes for distinct progress segments
134
+ or statuses.
135
+ display_percent : `bool`
136
+ Whether to show percentage of progress.
137
+ display_counts : `bool`
138
+ Whether to show numeric counts (e.g., succeeded/expected).
139
+ visualize : `bool`
140
+ If `True`, status information for task or dataset type nodes will be
141
+ visually indicated by segmented fills in text-based bars or flowchart
142
+ nodes.
143
+ min_bar_width : `int`
144
+ Minimum width of the visualized progress bar in characters. Only counts
145
+ the width of the bar itself, not any surrounding text. Only relevant if
146
+ `visualize` is `True` and it's a text-based visualization.
147
+ abbreviate : `bool`
148
+ If `True`, status labels will be abbreviated to save space. For
149
+ example, 'expected' will be abbreviated to 'exp' and 'blocked' to
150
+ 'blk'.
151
+ """
152
+
153
+ colors: QuantumGraphExecutionStatusColors | QuantumProvenanceGraphStatusColors
154
+ display_percent: bool = True
155
+ display_counts: bool = True
156
+ visualize: bool = True
157
+ min_bar_width: int = 15
158
+ abbreviate: bool = True
159
+
160
+ def __post_init__(self) -> None:
161
+ if not (self.display_percent or self.display_counts or self.visualize):
162
+ raise ValueError(
163
+ "At least one of 'display_percent', 'display_counts', or 'visualize' must be True."
164
+ )
165
+
166
+
167
+ @dataclasses.dataclass
168
+ class QuantumGraphExecutionStatusOptions(NodeStatusOptions):
169
+ """Specialized status options for quantum graph execution reports."""
170
+
171
+ colors: QuantumGraphExecutionStatusColors = dataclasses.field(
172
+ default_factory=QuantumGraphExecutionStatusColors
173
+ )
174
+
175
+
176
+ @dataclasses.dataclass
177
+ class QuantumProvenanceGraphStatusOptions(NodeStatusOptions):
178
+ """Specialized status options for quantum provenance graph reports."""
179
+
180
+ colors: QuantumProvenanceGraphStatusColors = dataclasses.field(
181
+ default_factory=QuantumProvenanceGraphStatusColors
182
+ )
183
+
184
+
185
+ class NodeStatusAnnotator(Protocol):
186
+ """Protocol for annotating a networkx graph with task and dataset type
187
+ status information.
188
+ """
189
+
190
+ @overload
191
+ def __call__(self, xgraph: networkx.DiGraph, dataset_types: Literal[False]) -> None: ...
192
+
193
+ @overload
194
+ def __call__(self, xgraph: networkx.MultiDiGraph, dataset_types: Literal[True]) -> None: ...
195
+
196
+ def __call__(self, xgraph: networkx.DiGraph | networkx.MultiDiGraph, dataset_types: bool) -> None: ...
197
+
198
+
199
+ class QuantumGraphExecutionStatusAnnotator:
200
+ """Annotates a networkx graph with task and dataset status information from
201
+ a quantum graph execution summary, implementing the StatusAnnotator
202
+ protocol to update the graph with status data.
203
+ """
204
+
205
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
206
+ raise NotImplementedError("`QuantumGraphExecutionStatusAnnotator` is not implemented yet.")
207
+
208
+
209
+ class QuantumProvenanceGraphStatusAnnotator:
210
+ """Annotates a networkx graph with task and dataset status information from
211
+ a quantum provenance summary, implementing the StatusAnnotator protocol to
212
+ update the graph with status data.
213
+
214
+ Parameters
215
+ ----------
216
+ qpg_summary : `~lsst.pipe.base.quantum_provenance_graph.Summary`
217
+ The quantum provenance summary to use for status information.
218
+ """
219
+
220
+ def __init__(self, qpg_summary: qpg.Summary) -> None:
221
+ self.qpg_summary = qpg_summary
222
+
223
+ @overload
224
+ def __call__(self, xgraph: networkx.DiGraph, dataset_types: Literal[False]) -> None: ...
225
+
226
+ @overload
227
+ def __call__(self, xgraph: networkx.MultiDiGraph, dataset_types: Literal[True]) -> None: ...
228
+
229
+ def __call__(self, xgraph: networkx.DiGraph | networkx.MultiDiGraph, dataset_types: bool) -> None:
230
+ for task_label, task_summary in self.qpg_summary.tasks.items():
231
+ fields = {
232
+ name.replace("n_", "").replace("successful", "succeeded"): getattr(task_summary, name)
233
+ for name in dir(task_summary)
234
+ if name.startswith("n_")
235
+ }
236
+ assert sum(fields.values()) == 2 * task_summary.n_expected, f"Incosistent status counts: {fields}"
237
+ task_status_info = TaskStatusInfo(**fields)
238
+
239
+ key = NodeKey(NodeType.TASK, task_label)
240
+ xgraph.nodes[key]["status"] = task_status_info
241
+
242
+ if dataset_types:
243
+ for dataset_type_name, dataset_type_summary in self.qpg_summary.datasets.items():
244
+ expected = dataset_type_summary.n_expected
245
+ produced = dataset_type_summary.n_visible + dataset_type_summary.n_shadowed
246
+ assert produced <= expected, f"Dataset types produced ({produced}) > expected ({expected})"
247
+ dataset_type_status_info = DatasetTypeStatusInfo(expected=expected, produced=produced)
248
+
249
+ key = NodeKey(NodeType.DATASET_TYPE, dataset_type_name)
250
+ xgraph.nodes[key]["status"] = dataset_type_status_info
@@ -194,6 +194,13 @@ class QuantumGraphSkeleton:
194
194
  """The total number of edges."""
195
195
  return len(self._xgraph.edges)
196
196
 
197
+ @property
198
+ def has_any_quanta(self) -> bool:
199
+ """Test whether this graph has any quanta."""
200
+ for _ in self.iter_all_quanta():
201
+ return True
202
+ return False
203
+
197
204
  def has_task(self, task_label: str) -> bool:
198
205
  """Test whether the given task is in this skeleton.
199
206
 
@@ -2106,6 +2106,12 @@ class _QuantumBackedButlerFactory:
2106
2106
  def _cli() -> None:
2107
2107
  import argparse
2108
2108
 
2109
+ from .pipeline_graph.visualization import (
2110
+ QuantumProvenanceGraphStatusAnnotator,
2111
+ QuantumProvenanceGraphStatusOptions,
2112
+ show,
2113
+ )
2114
+
2109
2115
  parser = argparse.ArgumentParser(
2110
2116
  "QuantumProvenanceGraph command-line utilities.",
2111
2117
  description=(
@@ -2114,6 +2120,7 @@ def _cli() -> None:
2114
2120
  ),
2115
2121
  )
2116
2122
  subparsers = parser.add_subparsers(dest="cmd")
2123
+
2117
2124
  pprint_parser = subparsers.add_parser("pprint", help="Print a saved summary as a series of tables.")
2118
2125
  pprint_parser.add_argument("file", type=argparse.FileType("r"), help="Saved summary JSON file.")
2119
2126
  pprint_parser.add_argument(
@@ -2127,12 +2134,33 @@ def _cli() -> None:
2127
2134
  action=argparse.BooleanOptionalAction,
2128
2135
  default=True,
2129
2136
  )
2137
+
2138
+ xgraph_parser = subparsers.add_parser("xgraph", help="Print a visual representation of a saved xgraph.")
2139
+ xgraph_parser.add_argument("file", type=argparse.FileType("r"), help="Saved summary JSON file.")
2140
+ xgraph_parser.add_argument("qgraph", type=str, help="Saved quantum graph file.")
2141
+
2130
2142
  args = parser.parse_args()
2143
+
2131
2144
  match args.cmd:
2132
2145
  case "pprint":
2133
2146
  summary = Summary.model_validate_json(args.file.read())
2134
2147
  args.file.close()
2135
2148
  summary.pprint(brief=args.brief, datasets=args.datasets)
2149
+ case "xgraph":
2150
+ summary = Summary.model_validate_json(args.file.read())
2151
+ args.file.close()
2152
+ status_annotator = QuantumProvenanceGraphStatusAnnotator(summary)
2153
+ status_options = QuantumProvenanceGraphStatusOptions(
2154
+ display_percent=True, display_counts=True, abbreviate=True, visualize=True
2155
+ )
2156
+ qgraph = QuantumGraph.loadUri(args.qgraph)
2157
+ pipeline_graph = qgraph.pipeline_graph
2158
+ show(
2159
+ pipeline_graph,
2160
+ dataset_types=True,
2161
+ status_annotator=status_annotator,
2162
+ status_options=status_options,
2163
+ )
2136
2164
  case _:
2137
2165
  raise AssertionError(f"Unhandled subcommand {args.dest}.")
2138
2166
 
lsst/pipe/base/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "29.2025.1300"
2
+ __version__ = "29.2025.1500"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-pipe-base
3
- Version: 29.2025.1300
3
+ Version: 29.2025.1500
4
4
  Summary: Pipeline infrastructure for the Rubin Science Pipelines.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -27,6 +27,7 @@ Requires-Dist: lsst-pex-config
27
27
  Requires-Dist: astropy
28
28
  Requires-Dist: pydantic<3.0,>=2
29
29
  Requires-Dist: networkx
30
+ Requires-Dist: wcwidth
30
31
  Requires-Dist: pyyaml>=5.1
31
32
  Requires-Dist: numpy>=1.17
32
33
  Requires-Dist: frozendict
@@ -8,7 +8,7 @@ lsst/pipe/base/_observation_dimension_packer.py,sha256=78Jg2OVFOdXIK62TS2Y3X4095
8
8
  lsst/pipe/base/_quantumContext.py,sha256=gb60mTHbgOIEptYvJ64SaChvViXyeKJlG6kEHq4nYVw,19345
9
9
  lsst/pipe/base/_status.py,sha256=t9jiM0YkL4cAJ1hokRJ4FFntijW86fRWbb_5bKaCDYk,15222
10
10
  lsst/pipe/base/_task_metadata.py,sha256=SfM4L07Pe5itBDCsNh-XjdQvlKLY5LBcG6lpdtpMxHA,24968
11
- lsst/pipe/base/all_dimensions_quantum_graph_builder.py,sha256=xG4WbpgHo_4w5xzLeii95IuNbOCJ0kkv6lQi3tm6Gyg,53057
11
+ lsst/pipe/base/all_dimensions_quantum_graph_builder.py,sha256=Z9MN7y8eltF7VcvQsprbiaf13HRJ-U21jwuXIaqhSfQ,53283
12
12
  lsst/pipe/base/automatic_connection_constants.py,sha256=H5uuh1rYRpjndgPdb0dh1L_-OyLKdT6VWOZTAb__xCU,3298
13
13
  lsst/pipe/base/caching_limited_butler.py,sha256=ZlvjznhHMuKi_0JkVa6WlCwhDXRSOozCcxpOHHSRMIQ,7311
14
14
  lsst/pipe/base/config.py,sha256=yNipVEc6awwhU_O9I01g20OnvQrs28dAwkXuI1hrlYE,11982
@@ -25,14 +25,14 @@ lsst/pipe/base/pipelineTask.py,sha256=K3GdjJLvy8A7I-jzQiERQZaYF7mC1LM3iB5TmUtbOC
25
25
  lsst/pipe/base/prerequisite_helpers.py,sha256=WxfIGkF0Wlucp9mE3Wp3E6K2M6d66O0oZrWecRqn5CI,28312
26
26
  lsst/pipe/base/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  lsst/pipe/base/quantum_graph_builder.py,sha256=zn--NtuypWss_-FgyLm-i2a98d_-c1g5hWJnv-q4VSU,54695
28
- lsst/pipe/base/quantum_graph_skeleton.py,sha256=QML_p5wLcfwOpegfQR0H7yJJXuV_UqHkksFjkHQII6s,24183
29
- lsst/pipe/base/quantum_provenance_graph.py,sha256=YkYP8-ooKunZ2IHIkOlchmTu0-fM-evUa7zzaJ_5524,91900
28
+ lsst/pipe/base/quantum_graph_skeleton.py,sha256=FyKrgDPO1UsvwyAYo1uBm-65FynEFLPbAocQAMMUx0A,24376
29
+ lsst/pipe/base/quantum_provenance_graph.py,sha256=llXcqu-50dtjkt_sVqAhBU10htfkxMiiArNN0_GqL1g,93034
30
30
  lsst/pipe/base/struct.py,sha256=Fa-UkpuXOxdzKWbHrMUkJYOszZuBXCm2NesXNR0IOPQ,5048
31
31
  lsst/pipe/base/task.py,sha256=XHBd-7m1a4-6LgobBYA1DgY4H7EV-_RWKfxbhZbMmD4,15145
32
32
  lsst/pipe/base/taskFactory.py,sha256=4GhN2DozPM8suBYIvoKN4E6VP0I3mYZHBjCUO5JcCGk,2901
33
33
  lsst/pipe/base/testUtils.py,sha256=lSBKMhoKflbi8JkMNYfEqqHNl-rtFI8UYT3QneDYpLo,18477
34
34
  lsst/pipe/base/utils.py,sha256=JmEt3l0xrh9uayKrSXuQEq12aXOhDr2YXmbYduaxCko,1940
35
- lsst/pipe/base/version.py,sha256=tryL-NT2fHNIinBXQOOXxLFsVaDOMR53wZgDt_5tYb0,55
35
+ lsst/pipe/base/version.py,sha256=altncYankWkwG1F2OVHhPl0np72lUhdVRAOSqBtd-kc,55
36
36
  lsst/pipe/base/cli/__init__.py,sha256=861tXIAW7SqtqNUYkjbeEdfg8lDswXsjJQca0gVCFz4,54
37
37
  lsst/pipe/base/cli/_get_cli_subcommands.py,sha256=g_af64klRybBGKAg7fmBSZBdw2LYBAsFON_yQIMZON0,1289
38
38
  lsst/pipe/base/cli/cmd/__init__.py,sha256=BGicstnryQ48rYcNRh4fa6Vy63ZIlZ_pPAEa17jhkwY,1519
@@ -50,25 +50,27 @@ lsst/pipe/base/graph/graph.py,sha256=34P22Ljc46P2oG5xHckIBocRBlEKlmDBBUQBNPoW9vE
50
50
  lsst/pipe/base/graph/graphSummary.py,sha256=aYYZ_fGQWpp2UB4bG99Okeh_7yRGdYTva_wXk_rlwWA,4872
51
51
  lsst/pipe/base/graph/quantumNode.py,sha256=l4mslxBgyUzBAqwjpx6XRP-UPxe-oRMxHJWt-_y3Dm0,7196
52
52
  lsst/pipe/base/pipeline_graph/__init__.py,sha256=yTEuvlzbeKIHIm7GeRmGSsma1wpZFNv8j12WfSH-deY,1516
53
- lsst/pipe/base/pipeline_graph/__main__.py,sha256=23z3Q0Er4SjpfPwaOMPYxXUNHl6hYM-_WPkcia56FnA,20740
53
+ lsst/pipe/base/pipeline_graph/__main__.py,sha256=E6ugEwJbds22wjgcfcgzeyO04JofQwVhn_Y8kZYY1lQ,20769
54
54
  lsst/pipe/base/pipeline_graph/_dataset_types.py,sha256=ksJe1eR1DUZBf18mQGeNYEA_LJGCbxZa3J9EUdp69Lc,10988
55
55
  lsst/pipe/base/pipeline_graph/_edges.py,sha256=tS9n_Z5iJlCGwApS9rsb4J67f5Ug2Dx9lf_BR-R7mhI,34449
56
- lsst/pipe/base/pipeline_graph/_exceptions.py,sha256=v6febIDykigYe4SsRigq5jzzTYSr-zrsbq6Nz70ApPs,3759
56
+ lsst/pipe/base/pipeline_graph/_exceptions.py,sha256=3jvCXms0_5ThLGtsOlKxsI1vWiq3gY4hba8fRBW0tgI,3943
57
57
  lsst/pipe/base/pipeline_graph/_mapping_views.py,sha256=9nLKPA8j7sS09haShbJnEtGXbb4vy_cWpbLeMLBmVvs,9194
58
58
  lsst/pipe/base/pipeline_graph/_nodes.py,sha256=WcP31yIRCNvFh9lhEtKJ_8bsgX2u_B_qwyV7DaHJ8JI,3376
59
- lsst/pipe/base/pipeline_graph/_pipeline_graph.py,sha256=tpN1fJ4LB1o7nqELy-t_ZfrVWhxVP6bmK9pFIkvOVL4,104856
59
+ lsst/pipe/base/pipeline_graph/_pipeline_graph.py,sha256=pb7SJFb--mLD5jWZgmzpudTOIA9GQR164zfRxTn-gng,120358
60
60
  lsst/pipe/base/pipeline_graph/_task_subsets.py,sha256=lLvcndSGcZigteWd4eeAM8LxQ1lHPBoysY8PjJTxx1c,13244
61
61
  lsst/pipe/base/pipeline_graph/_tasks.py,sha256=7rGxhc-qj-Ja56MZ5xD_WV01Kt7d1EPYwEz2_qggC5w,39914
62
+ lsst/pipe/base/pipeline_graph/expressions.py,sha256=MZ0qxGA4ctu_WqVjdjjezZF8Jd5174PWbio7EF2wdl0,7717
62
63
  lsst/pipe/base/pipeline_graph/io.py,sha256=GkelrZwpHFw0gUxwTNdyZmKCX_eYOnvhCMavH3YMwl8,30923
63
- lsst/pipe/base/pipeline_graph/visualization/__init__.py,sha256=7-00g9O7hH_rLibrkyV0jg9aFeJIPEKf6IEBK7fFGkE,1518
64
+ lsst/pipe/base/pipeline_graph/visualization/__init__.py,sha256=qQctfWuFpcmgRdgu8Y6OsJ_pXpLKrCK-alqfVtIecls,1551
64
65
  lsst/pipe/base/pipeline_graph/visualization/_dot.py,sha256=quja94wafmbCPJvC7HrHRE0Dsvhgz1Odx2MvVEpZup0,12936
65
- lsst/pipe/base/pipeline_graph/visualization/_formatting.py,sha256=_AWjp73iv-KQIFZ7fSvyyv-a5TYJSVtAenpT8pc3T5M,8319
66
+ lsst/pipe/base/pipeline_graph/visualization/_formatting.py,sha256=NsBxXwdmISitr8_4wPc-T8CqVB-Mq4pv7DmUefFm3JU,17845
66
67
  lsst/pipe/base/pipeline_graph/visualization/_layout.py,sha256=aMFl2Sgw_2-AfCBr_JBIWSs7VbSfSP7Nuol0mP9lkUo,17157
67
68
  lsst/pipe/base/pipeline_graph/visualization/_merge.py,sha256=cBKhNjgymDkzYtVutrXd9IGa-eE4Q9jnHO9F18e64dY,15435
68
69
  lsst/pipe/base/pipeline_graph/visualization/_mermaid.py,sha256=YC86ImEha6SIbHU-ZwTwHsCM-LqU64YZoMfLuxy0x_M,20576
69
- lsst/pipe/base/pipeline_graph/visualization/_options.py,sha256=UNzPiTKU9x0PRiHr6cOiKTHk2s0R_LbKipZPezxsGGc,4862
70
+ lsst/pipe/base/pipeline_graph/visualization/_options.py,sha256=vOIp2T7DLA48lTm5mTyCakIByb_wM21U_Crz_83MjoM,5237
70
71
  lsst/pipe/base/pipeline_graph/visualization/_printer.py,sha256=yJMRJ-aXd3nYDgs1FqS2l_hzNbQ50HUVm55VVaNi71s,16537
71
- lsst/pipe/base/pipeline_graph/visualization/_show.py,sha256=l0Ybq-bcdxBhgrf84rxiDGpLAHCOIX2uow418gTKbxA,9507
72
+ lsst/pipe/base/pipeline_graph/visualization/_show.py,sha256=lPRjO1To2n5r3f_Wgcwy-7TmyJ7UszGGFXAlOtN1wDs,10510
73
+ lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py,sha256=dp7PXl9Cu7GfWjBi5g8KjXZgnF1KGg_idKKxtICL53Q,8679
72
74
  lsst/pipe/base/script/__init__.py,sha256=cLEXE7aq5UZ0juL_ScmRw0weFgp4tDgwEX_ts-NEYic,1522
73
75
  lsst/pipe/base/script/register_instrument.py,sha256=TRC2r2tSoYBNWNVQya01ELxAtGH8WVk9Ya-uNgCIL5U,2426
74
76
  lsst/pipe/base/script/retrieve_artifacts_for_quanta.py,sha256=pYI0wNl5PU8ImgzWfGEDrRz3PSKSg2szWLEIVKdm7Og,3939
@@ -83,13 +85,13 @@ lsst/pipe/base/tests/mocks/__init__.py,sha256=NrIJYDeYgR3HsOJXBEXi8EXDhhV7iw7dgw
83
85
  lsst/pipe/base/tests/mocks/_data_id_match.py,sha256=MRGZUSD6ES0EiVG7kOIGZaJbZsaSIXB2M6tI9RpdUAc,6491
84
86
  lsst/pipe/base/tests/mocks/_pipeline_task.py,sha256=fqaJ-tB7K3jxlfCvCSnVd_GNrz-JhX7FB914h7nHLXc,29366
85
87
  lsst/pipe/base/tests/mocks/_storage_class.py,sha256=JvUmyXQC5DwOkFoLHkJk6u0ldn1VgZVVjh9GjpXRGg0,25211
86
- lsst_pipe_base-29.2025.1300.dist-info/licenses/COPYRIGHT,sha256=kB3Z9_f6a6uFLGpEmNJT_n186CE65H6wHu4F6BNt_zA,368
87
- lsst_pipe_base-29.2025.1300.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
88
- lsst_pipe_base-29.2025.1300.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
89
- lsst_pipe_base-29.2025.1300.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
90
- lsst_pipe_base-29.2025.1300.dist-info/METADATA,sha256=6eZQ1cjAQ31Xkpa2ttGa72CDDqd8Zqf9sZyTeT14-LA,2172
91
- lsst_pipe_base-29.2025.1300.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
92
- lsst_pipe_base-29.2025.1300.dist-info/entry_points.txt,sha256=bnmUhJBsChxMdqST9VmFBYYKxLQoToOfqW1wjW7khjk,64
93
- lsst_pipe_base-29.2025.1300.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
94
- lsst_pipe_base-29.2025.1300.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
95
- lsst_pipe_base-29.2025.1300.dist-info/RECORD,,
88
+ lsst_pipe_base-29.2025.1500.dist-info/licenses/COPYRIGHT,sha256=kB3Z9_f6a6uFLGpEmNJT_n186CE65H6wHu4F6BNt_zA,368
89
+ lsst_pipe_base-29.2025.1500.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
90
+ lsst_pipe_base-29.2025.1500.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
91
+ lsst_pipe_base-29.2025.1500.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
92
+ lsst_pipe_base-29.2025.1500.dist-info/METADATA,sha256=atznQZNRN24fuGmUKBmOSg24OPkl3R-WyEtE6PBcWnE,2195
93
+ lsst_pipe_base-29.2025.1500.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
94
+ lsst_pipe_base-29.2025.1500.dist-info/entry_points.txt,sha256=bnmUhJBsChxMdqST9VmFBYYKxLQoToOfqW1wjW7khjk,64
95
+ lsst_pipe_base-29.2025.1500.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
96
+ lsst_pipe_base-29.2025.1500.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
97
+ lsst_pipe_base-29.2025.1500.dist-info/RECORD,,