lsst-pipe-base 30.2026.300__py3-none-any.whl → 30.2026.500__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 (52) hide show
  1. lsst/pipe/base/_instrument.py +21 -12
  2. lsst/pipe/base/_quantumContext.py +3 -3
  3. lsst/pipe/base/_status.py +43 -10
  4. lsst/pipe/base/automatic_connection_constants.py +20 -1
  5. lsst/pipe/base/cli/cmd/__init__.py +18 -2
  6. lsst/pipe/base/cli/cmd/commands.py +149 -4
  7. lsst/pipe/base/connectionTypes.py +72 -160
  8. lsst/pipe/base/connections.py +3 -6
  9. lsst/pipe/base/execution_reports.py +0 -5
  10. lsst/pipe/base/graph/graph.py +9 -8
  11. lsst/pipe/base/log_capture.py +1 -1
  12. lsst/pipe/base/pipeline.py +5 -6
  13. lsst/pipe/base/pipelineIR.py +1 -7
  14. lsst/pipe/base/pipelineTask.py +5 -7
  15. lsst/pipe/base/pipeline_graph/_dataset_types.py +2 -2
  16. lsst/pipe/base/pipeline_graph/_edges.py +30 -18
  17. lsst/pipe/base/pipeline_graph/_pipeline_graph.py +10 -2
  18. lsst/pipe/base/pipeline_graph/visualization/_dot.py +13 -12
  19. lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py +7 -0
  20. lsst/pipe/base/prerequisite_helpers.py +2 -1
  21. lsst/pipe/base/quantum_graph/_common.py +3 -1
  22. lsst/pipe/base/quantum_graph/_multiblock.py +29 -13
  23. lsst/pipe/base/quantum_graph/_predicted.py +7 -0
  24. lsst/pipe/base/quantum_graph/_provenance.py +498 -56
  25. lsst/pipe/base/quantum_graph/aggregator/__init__.py +0 -1
  26. lsst/pipe/base/quantum_graph/aggregator/_communicators.py +9 -1
  27. lsst/pipe/base/quantum_graph/aggregator/_config.py +78 -9
  28. lsst/pipe/base/quantum_graph/aggregator/_ingester.py +12 -11
  29. lsst/pipe/base/quantum_graph/aggregator/_scanner.py +14 -6
  30. lsst/pipe/base/quantum_graph/aggregator/_structs.py +3 -3
  31. lsst/pipe/base/quantum_graph/aggregator/_supervisor.py +14 -13
  32. lsst/pipe/base/quantum_graph/aggregator/_writer.py +2 -2
  33. lsst/pipe/base/quantum_graph/formatter.py +74 -4
  34. lsst/pipe/base/quantum_graph/ingest_graph.py +413 -0
  35. lsst/pipe/base/quantum_graph_builder.py +1 -8
  36. lsst/pipe/base/quantum_graph_skeleton.py +29 -27
  37. lsst/pipe/base/quantum_provenance_graph.py +29 -12
  38. lsst/pipe/base/separable_pipeline_executor.py +6 -7
  39. lsst/pipe/base/single_quantum_executor.py +7 -7
  40. lsst/pipe/base/struct.py +4 -0
  41. lsst/pipe/base/tests/mocks/_storage_class.py +2 -1
  42. lsst/pipe/base/version.py +1 -1
  43. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/METADATA +2 -1
  44. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/RECORD +52 -51
  45. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/WHEEL +1 -1
  46. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/entry_points.txt +0 -0
  47. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/licenses/COPYRIGHT +0 -0
  48. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/licenses/LICENSE +0 -0
  49. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/licenses/bsd_license.txt +0 -0
  50. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/licenses/gpl-v3.0.txt +0 -0
  51. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/top_level.txt +0 -0
  52. {lsst_pipe_base-30.2026.300.dist-info → lsst_pipe_base-30.2026.500.dist-info}/zip-safe +0 -0
@@ -66,7 +66,7 @@ def show_dot(
66
66
  ----------
67
67
  pipeline_graph : `PipelineGraph`
68
68
  Pipeline graph to show.
69
- stream : `TextIO`, optional
69
+ stream : `io.TextIO`, optional
70
70
  Stream to write the DOT representation to.
71
71
  label_edge_connections : `bool`, optional
72
72
  If `True`, label edges with their connection names.
@@ -167,21 +167,22 @@ def _render_dataset_type_node(
167
167
 
168
168
  Parameters
169
169
  ----------
170
- node_key : NodeKey
171
- The key for the node
172
- node_data : Mapping[str, Any]
173
- The data associated with the node
174
- options : NodeAttributeOptions
175
- Options for rendering the node
176
- stream : TextIO
177
- The stream to write the node to
170
+ node_key : `NodeKey`
171
+ The key for the node.
172
+ node_data : `~collections.abc.Mapping` [`str`, `typing.Any`]
173
+ The data associated with the node.
174
+ options : `NodeAttributeOptions`
175
+ Options for rendering the node.
176
+ stream : `io.TextIO`
177
+ The stream to write the node to.
178
+ overflow_ref : `int`, optional
178
179
 
179
180
  Returns
180
181
  -------
181
182
  overflow_ref : int
182
- The reference number for the next overflow node
183
+ The reference number for the next overflow node.
183
184
  overflow_ids : str | None
184
- The ID of the overflow node, if any
185
+ The ID of the overflow node, if any.
185
186
  """
186
187
  labels, label_extras, common_prefix = _format_label(str(node_key), _LABEL_MAX_LINES_SOFT)
187
188
  if len(labels) + len(label_extras) <= _LABEL_MAX_LINES_HARD:
@@ -271,7 +272,7 @@ def _render_edge(from_node_id: str, to_node_id: str, stream: TextIO, **kwargs: A
271
272
  The unique ID of the node the edge is going to
272
273
  stream : TextIO
273
274
  The stream to write the edge to
274
- kwargs : Any
275
+ **kwargs : Any
275
276
  Additional keyword arguments to pass to the edge
276
277
  """
277
278
  if kwargs:
@@ -200,6 +200,13 @@ class QuantumGraphExecutionStatusAnnotator:
200
200
  """Annotates a networkx graph with task and dataset status information from
201
201
  a quantum graph execution summary, implementing the StatusAnnotator
202
202
  protocol to update the graph with status data.
203
+
204
+ Parameters
205
+ ----------
206
+ *args : `typing.Any`
207
+ Arbitrary arguments.
208
+ **kwargs : `typing.Any`
209
+ Arbitrary keyword arguments.
203
210
  """
204
211
 
205
212
  def __init__(self, *args: Any, **kwargs: Any) -> None:
@@ -252,7 +252,8 @@ class PrerequisiteFinder:
252
252
  Sequence of collections to search, in order.
253
253
  data_id : `lsst.daf.butler.DataCoordinate`
254
254
  Data ID for the quantum.
255
- skypix_bounds : `Mapping` [ `str`, `lsst.sphgeom.RangeSet` ]
255
+ skypix_bounds : `~collections.abc.Mapping` \
256
+ [ `str`, `lsst.sphgeom.RangeSet` ]
256
257
  The spatial bounds of this quantum in various skypix dimensions.
257
258
  Keys are skypix dimension names (a superset of those in
258
259
  `dataset_skypix`) and values are sets of integer pixel ID ranges.
@@ -453,8 +453,10 @@ class BaseQuantumGraphWriter:
453
453
  cdict_data: bytes | None = None,
454
454
  zstd_level: int = 10,
455
455
  ) -> Iterator[Self]:
456
- uri = ResourcePath(uri)
456
+ uri = ResourcePath(uri, forceDirectory=False)
457
457
  address_writer = AddressWriter()
458
+ if uri.isLocal:
459
+ os.makedirs(uri.dirname().ospath, exist_ok=True)
458
460
  cdict = zstandard.ZstdCompressionDict(cdict_data) if cdict_data is not None else None
459
461
  compressor = zstandard.ZstdCompressor(level=zstd_level, dict_data=cdict)
460
462
  with uri.open(mode="wb") as stream:
@@ -43,18 +43,15 @@ import dataclasses
43
43
  import logging
44
44
  import tempfile
45
45
  import uuid
46
- from collections.abc import Iterator
46
+ import zipfile
47
+ from collections.abc import Iterator, Set
47
48
  from contextlib import contextmanager
48
49
  from io import BufferedReader, BytesIO
49
50
  from operator import attrgetter
50
- from typing import IO, TYPE_CHECKING, Protocol, TypeAlias, TypeVar
51
+ from typing import IO, Protocol, TypeAlias, TypeVar
51
52
 
52
53
  import pydantic
53
54
 
54
- if TYPE_CHECKING:
55
- import zipfile
56
-
57
-
58
55
  _LOG = logging.getLogger(__name__)
59
56
 
60
57
 
@@ -212,7 +209,7 @@ class AddressWriter:
212
209
  The converse is not true.
213
210
  """
214
211
 
215
- def write(self, stream: IO[bytes], int_size: int) -> None:
212
+ def write(self, stream: IO[bytes], int_size: int, all_ids: Set[uuid.UUID] | None = None) -> None:
216
213
  """Write all addresses to a file-like object.
217
214
 
218
215
  Parameters
@@ -221,15 +218,17 @@ class AddressWriter:
221
218
  Binary file-like object.
222
219
  int_size : `int`
223
220
  Number of bytes to use for all integers.
221
+ all_ids : `~collections.abc.Set` [`uuid.UUID`], optional
222
+ Set of the union of all UUIDs in any dictionary from a call to
223
+ `get_all_ids`.
224
224
  """
225
- indices: set[uuid.UUID] = set()
226
- for address_map in self.addresses:
227
- indices.update(address_map.keys())
225
+ if all_ids is None:
226
+ all_ids = self.get_all_ids()
228
227
  stream.write(int_size.to_bytes(1))
229
- stream.write(len(indices).to_bytes(int_size))
228
+ stream.write(len(all_ids).to_bytes(int_size))
230
229
  stream.write(len(self.addresses).to_bytes(int_size))
231
230
  empty_address = Address()
232
- for n, key in enumerate(sorted(indices, key=attrgetter("int"))):
231
+ for n, key in enumerate(sorted(all_ids, key=attrgetter("int"))):
233
232
  row = AddressRow(key, n, [m.get(key, empty_address) for m in self.addresses])
234
233
  _LOG.debug("Wrote address %s.", row)
235
234
  row.write(stream, int_size)
@@ -246,9 +245,26 @@ class AddressWriter:
246
245
  int_size : `int`
247
246
  Number of bytes to use for all integers.
248
247
  """
249
- with zf.open(f"{name}.addr", mode="w") as stream:
248
+ all_ids = self.get_all_ids()
249
+ zip_info = zipfile.ZipInfo(f"{name}.addr")
250
+ row_size = AddressReader.compute_row_size(int_size, len(self.addresses))
251
+ zip_info.file_size = AddressReader.compute_header_size(int_size) + len(all_ids) * row_size
252
+ with zf.open(zip_info, mode="w") as stream:
250
253
  self.write(stream, int_size=int_size)
251
254
 
255
+ def get_all_ids(self) -> Set[uuid.UUID]:
256
+ """Return all IDs used by any address dictionary.
257
+
258
+ Returns
259
+ -------
260
+ all_ids : `~collections.abc.Set` [`uuid.UUID`]
261
+ Set of all IDs.
262
+ """
263
+ all_ids: set[uuid.UUID] = set()
264
+ for address_map in self.addresses:
265
+ all_ids.update(address_map.keys())
266
+ return all_ids
267
+
252
268
 
253
269
  @dataclasses.dataclass
254
270
  class AddressPage:
@@ -110,6 +110,13 @@ if TYPE_CHECKING:
110
110
  from ..config import PipelineTaskConfig
111
111
  from ..graph import QgraphSummary, QuantumGraph
112
112
 
113
+ # Sphinx needs imports for type annotations of base class members.
114
+ if "sphinx" in sys.modules:
115
+ import zipfile # noqa: F401
116
+
117
+ from ._multiblock import AddressReader, Decompressor # noqa: F401
118
+
119
+
113
120
  _LOG = logging.getLogger(__name__)
114
121
 
115
122