lsst-pipe-base 29.0.0rc1__py3-none-any.whl → 29.2025.1100__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.
@@ -29,9 +29,11 @@ from __future__ import annotations
29
29
  __all__ = ("show_mermaid",)
30
30
 
31
31
  import html
32
+ import importlib.util
32
33
  import os
33
34
  import sys
34
35
  from collections.abc import Mapping
36
+ from io import BufferedIOBase, BytesIO, StringIO, TextIOBase
35
37
  from typing import Any, TextIO
36
38
 
37
39
  from .._nodes import NodeType
@@ -40,6 +42,12 @@ from ._formatting import NodeKey, format_dimensions, format_task_class
40
42
  from ._options import NodeAttributeOptions
41
43
  from ._show import parse_display_args
42
44
 
45
+ MERMAID_AVAILABLE = importlib.util.find_spec("mermaid") is not None
46
+
47
+ if MERMAID_AVAILABLE:
48
+ from mermaid import Mermaid # type: ignore
49
+ from mermaid.graph import Graph # type: ignore
50
+
43
51
  # Configuration constants for label formatting and overflow handling.
44
52
  _LABEL_PX_SIZE = 18
45
53
  _LABEL_MAX_LINES_SOFT = 10
@@ -49,7 +57,11 @@ _OVERFLOW_MAX_LINES = 20
49
57
 
50
58
  def show_mermaid(
51
59
  pipeline_graph: PipelineGraph,
52
- stream: TextIO = sys.stdout,
60
+ stream: TextIO | BytesIO = sys.stdout,
61
+ output_format: str = "mmd",
62
+ width: int | None = None,
63
+ height: int | None = None,
64
+ scale: float | None = None,
53
65
  **kwargs: Any,
54
66
  ) -> None:
55
67
  """Write a Mermaid flowchart representation of the pipeline graph to a
@@ -65,9 +77,20 @@ def show_mermaid(
65
77
  ----------
66
78
  pipeline_graph : `PipelineGraph`
67
79
  The pipeline graph to visualize.
68
- stream : `TextIO`, optional
80
+ stream : `TextIO` or `BytesIO`, optional
69
81
  The output stream where Mermaid code is written. Defaults to
70
82
  `sys.stdout`.
83
+ output_format : str, optional
84
+ Defines the output format. 'mmd' (default) generates a Mermaid
85
+ definition text file, while 'svg' and 'png' produce rendered images as
86
+ binary streams.
87
+ width : int, optional
88
+ The width of the rendered image in pixels.
89
+ height : int, optional
90
+ The height of the rendered image in pixels.
91
+ scale : float, optional
92
+ The scale factor for the rendered image. Must be an float between 1
93
+ and 3, and one of height or width must be provided.
71
94
  **kwargs : Any
72
95
  Additional arguments passed to `parse_display_args` to control aspects
73
96
  such as displaying dimensions, storage classes, or full task class
@@ -85,27 +108,61 @@ def show_mermaid(
85
108
  - If a node's label is too long, overflow nodes are created to hold extra
86
109
  lines.
87
110
  """
111
+ # Generate Mermaid source code in-memory.
112
+ mermaid_source = _generate_mermaid_source(pipeline_graph, **kwargs)
113
+
114
+ if output_format == "mmd":
115
+ if isinstance(stream, TextIOBase):
116
+ # Write Mermaid source as a string.
117
+ stream.write(mermaid_source)
118
+ else:
119
+ raise TypeError(f"Expected a text stream, but got {type(stream)}.")
120
+ else:
121
+ if isinstance(stream, BufferedIOBase):
122
+ # Render Mermaid source as an image and write to binary stream.
123
+ _render_mermaid_image(
124
+ mermaid_source, stream, output_format, width=width, height=height, scale=scale
125
+ )
126
+ else:
127
+ raise ValueError(f"Expected a binary stream, but got {type(stream)}.")
128
+
129
+
130
+ def _generate_mermaid_source(pipeline_graph: PipelineGraph, **kwargs: Any) -> str:
131
+ """Generate the Mermaid source code from the pipeline graph.
132
+
133
+ Parameters
134
+ ----------
135
+ pipeline_graph : `PipelineGraph`
136
+ The pipeline graph to visualize.
137
+ **kwargs : Any
138
+ Additional arguments passed to `parse_display_args` for rendering.
139
+
140
+ Returns
141
+ -------
142
+ str
143
+ The Mermaid source code as a string.
144
+ """
145
+ # A buffer to collect Mermaid source code.
146
+ buffer = StringIO()
147
+
88
148
  # Parse display arguments to determine what to show.
89
149
  xgraph, options = parse_display_args(pipeline_graph, **kwargs)
90
150
 
91
151
  # Begin the Mermaid code block.
92
- print("flowchart TD", file=stream)
152
+ buffer.write("flowchart TD\n")
93
153
 
94
154
  # Define Mermaid classes for node styling.
95
- print(
155
+ buffer.write(
96
156
  f"classDef task fill:#B1F2EF,color:#000,stroke:#000,stroke-width:3px,"
97
- f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left;",
98
- file=stream,
157
+ f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left;\n"
99
158
  )
100
- print(
159
+ buffer.write(
101
160
  f"classDef dsType fill:#F5F5F5,color:#000,stroke:#00BABC,stroke-width:3px,"
102
- f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left,rx:8,ry:8;",
103
- file=stream,
161
+ f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left,rx:8,ry:8;\n"
104
162
  )
105
- print(
163
+ buffer.write(
106
164
  f"classDef taskInit fill:#F4DEFA,color:#000,stroke:#000,stroke-width:3px,"
107
- f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left;",
108
- file=stream,
165
+ f"font-family:Monospace,font-size:{_LABEL_PX_SIZE}px,text-align:left;\n"
109
166
  )
110
167
 
111
168
  # `overflow_ref` tracks the reference numbers for overflow nodes.
@@ -116,30 +173,27 @@ def show_mermaid(
116
173
  for node_key, node_data in xgraph.nodes.items():
117
174
  match node_key.node_type:
118
175
  case NodeType.TASK | NodeType.TASK_INIT:
119
- # Render a task or task-init node.
120
- _render_task_node(node_key, node_data, options, stream)
176
+ _render_task_node(node_key, node_data, options, buffer)
121
177
  case NodeType.DATASET_TYPE:
122
- # Render a dataset-type node with possible overflow handling.
123
178
  overflow_ref, node_overflow_ids = _render_dataset_type_node(
124
- node_key, node_data, options, stream, overflow_ref
179
+ node_key, node_data, options, buffer, overflow_ref
125
180
  )
126
- if node_overflow_ids:
127
- overflow_ids += node_overflow_ids
181
+ overflow_ids += node_overflow_ids if node_overflow_ids else []
128
182
  case _:
129
183
  raise AssertionError(f"Unexpected node type: {node_key.node_type}")
130
184
 
131
- # Collect edges for printing and track which ones are prerequisite
132
- # so we can apply dashed styling after printing them.
185
+ # Collect edges for adding to the Mermaid code and track which ones are
186
+ # prerequisite so we can apply dashed styling to them later.
133
187
  edges = []
134
188
  for _, (from_node, to_node, *_rest) in enumerate(xgraph.edges):
135
189
  is_prereq = xgraph.nodes[from_node].get("is_prerequisite", False)
136
190
  edges.append((from_node.node_id, to_node.node_id, is_prereq))
137
191
 
138
- # Print all edges
192
+ # Render all edges.
139
193
  for _, (f, t, p) in enumerate(edges):
140
- _render_edge(f, t, p, stream)
194
+ _render_edge(f, t, p, buffer)
141
195
 
142
- # After printing all edges, apply linkStyle to prerequisite edges to make
196
+ # After rendering all edges, apply linkStyle to prerequisite edges to make
143
197
  # them dashed:
144
198
 
145
199
  # First, gather indices of prerequisite edges.
@@ -147,7 +201,80 @@ def show_mermaid(
147
201
 
148
202
  # Then apply dashed styling to all prerequisite edges in one line.
149
203
  if prereq_indices:
150
- print(f"linkStyle {','.join(prereq_indices)} stroke-dasharray:5;", file=stream)
204
+ buffer.write(f"linkStyle {','.join(prereq_indices)} stroke-dasharray:5;\n")
205
+
206
+ # Return Mermaid source as string.
207
+ return buffer.getvalue()
208
+
209
+
210
+ def _render_mermaid_image(
211
+ mermaid_source: str,
212
+ binary_stream: BytesIO,
213
+ output_format: str,
214
+ width: int | None = None,
215
+ height: int | None = None,
216
+ scale: float | None = None,
217
+ ) -> None:
218
+ """Render a Mermaid diagram as an image and write the output to a binary
219
+ stream.
220
+
221
+ Parameters
222
+ ----------
223
+ mermaid_source : str
224
+ The Mermaid diagram source code.
225
+ binary_stream : `BytesIO`
226
+ The binary stream where the output content will be written.
227
+ output_format : str
228
+ The desired output format for the image. Supported image formats are
229
+ 'svg' and 'png'.
230
+ width : int, optional
231
+ The width of the rendered image in pixels.
232
+ height : int, optional
233
+ The height of the rendered image in pixels.
234
+ scale : float, optional
235
+ The scale factor for the rendered image. Must be a float between 1 and
236
+ 3, and one of height or width must be provided.
237
+
238
+ Raises
239
+ ------
240
+ ValueError
241
+ If the requested ``output_format`` is not supported.
242
+ RuntimeError
243
+ If the rendering process fails.
244
+ """
245
+ if output_format.lower() not in {"svg", "png"}:
246
+ raise ValueError(f"Unsupported format: {output_format}. Use 'svg' or 'png'.")
247
+
248
+ # Generate Mermaid graph object.
249
+ graph = Graph(title="Mermaid Diagram", script=mermaid_source)
250
+ diagram = Mermaid(graph, width=width, height=height, scale=scale)
251
+
252
+ # Determine the response type based on the output format.
253
+ if output_format.lower() == "svg":
254
+ response_type = "svg_response"
255
+ else:
256
+ response_type = "img_response"
257
+
258
+ # Select the appropriate output format and write the content to the stream.
259
+ try:
260
+ content = getattr(diagram, response_type).content
261
+
262
+ # Check if the response is actually an image.
263
+ if content.startswith(b"<!DOCTYPE html>") or b"<title>" in content[:200]:
264
+ error_msg = content.decode(errors="ignore")[:1000]
265
+ if "524" in error_msg or "timeout" in error_msg.lower():
266
+ raise RuntimeError(
267
+ f"Mermaid rendering service (mermaid.ink) timed out while generating {response_type}. "
268
+ "This may be due to server overload. Try again later or use a local rendering option."
269
+ )
270
+ raise RuntimeError(
271
+ f"Unexpected error from Mermaid API while generating {response_type}. Response:\n{error_msg}"
272
+ )
273
+
274
+ # Write the content to the binary stream if it's a valid image.
275
+ binary_stream.write(content)
276
+ except AttributeError as exc:
277
+ raise RuntimeError(f"Failed to generate {response_type} content") from exc
151
278
 
152
279
 
153
280
  def _render_task_node(
@@ -340,7 +340,7 @@ class PrerequisiteFinder:
340
340
  where_terms: list[str] = []
341
341
  bind: dict[str, list[int]] = {}
342
342
  for name in self.dataset_skypix:
343
- where_terms.append(f"{name} IN ({name}_pixels)")
343
+ where_terms.append(f"{name} IN (:{name}_pixels)")
344
344
  pixels: list[int] = []
345
345
  for begin, end in skypix_bounds[name]:
346
346
  pixels.extend(range(begin, end))
@@ -615,6 +615,9 @@ class QuantumGraphBuilder(ABC):
615
615
  # the metadata dataset doesn't guarantee that all of the other
616
616
  # outputs we predicted are present; we have to check.
617
617
  for output_dataset_key in list(skeleton.iter_outputs_of(quantum_key)):
618
+ # If this dataset was "in the way" (i.e. already in the
619
+ # output run), it isn't anymore.
620
+ skeleton.discard_output_in_the_way(output_dataset_key)
618
621
  if (output_ref := skeleton.get_output_for_skip(output_dataset_key)) is not None:
619
622
  # Populate the skeleton graph's node attributes
620
623
  # with the existing DatasetRef, just like a
@@ -625,9 +628,6 @@ class QuantumGraphBuilder(ABC):
625
628
  # because the quantum that would have produced it
626
629
  # is being skipped and it doesn't already exist.
627
630
  skeleton.remove_dataset_nodes([output_dataset_key])
628
- # If this dataset was "in the way" (i.e. already in the
629
- # output run), it isn't anymore.
630
- skeleton.discard_output_in_the_way(output_dataset_key)
631
631
  # Removing the quantum node from the graph will happen outside this
632
632
  # function.
633
633
  return True
@@ -73,6 +73,10 @@ class _DataIdMatchTreeVisitor(TreeVisitor):
73
73
  # docstring is inherited from base class
74
74
  return self.dataId[name]
75
75
 
76
+ def visitBind(self, name: str, node: Node) -> Any:
77
+ # docstring is inherited from base class
78
+ raise NotImplementedError()
79
+
76
80
  def visitUnaryOp(self, operator_name: str, operand: Any, node: Node) -> Any:
77
81
  # docstring is inherited from base class
78
82
  operators: dict[str, Callable[[Any], Any]] = {
lsst/pipe/base/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "29.0.0rc1"
2
+ __version__ = "29.2025.1100"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: lsst-pipe-base
3
- Version: 29.0.0rc1
3
+ Version: 29.2025.1100
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
@@ -32,6 +32,8 @@ Requires-Dist: numpy>=1.17
32
32
  Requires-Dist: frozendict
33
33
  Provides-Extra: test
34
34
  Requires-Dist: pytest>=3.2; extra == "test"
35
+ Provides-Extra: mermaid
36
+ Requires-Dist: mermaid; extra == "mermaid"
35
37
 
36
38
  # lsst-pipe-base
37
39
 
@@ -1,14 +1,14 @@
1
1
  lsst/__init__.py,sha256=_2bZAHuDVAx7MM7KA7pt3DYp641NY4RzSoRAwesWKfU,67
2
2
  lsst/pipe/__init__.py,sha256=_2bZAHuDVAx7MM7KA7pt3DYp641NY4RzSoRAwesWKfU,67
3
3
  lsst/pipe/base/__init__.py,sha256=qFDZrrmu4MHbzwiPPm74AUtUgLkPYtz5d1tvVEGxbPg,1008
4
- lsst/pipe/base/_datasetQueryConstraints.py,sha256=uxN1qTGDXHqlE7EJSv6GkiST1ZE46Y7ZZ11nboCtCcM,6358
4
+ lsst/pipe/base/_datasetQueryConstraints.py,sha256=eWKLxZcGEmOcYR8goxk5YeBfhG6UqqpOidyxhH5V0jY,6372
5
5
  lsst/pipe/base/_dataset_handle.py,sha256=ft_ke1LbhLLndDPARsHSQJUA05LgUFnfWOq2vbwH3wI,11353
6
6
  lsst/pipe/base/_instrument.py,sha256=I9UTaj81krR1zkTZ1owfOPBzHN29PY3Egg7fIE5obxQ,30057
7
7
  lsst/pipe/base/_observation_dimension_packer.py,sha256=78Jg2OVFOdXIK62TS2Y3X4095xqCzmiIx9o4TXyADYA,8027
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=b6_fi7vswOu93ikF0dhMHaBM6Cm_HylvqCQ0M2sESVs,40051
11
+ lsst/pipe/base/all_dimensions_quantum_graph_builder.py,sha256=gXjzXwn6wQBy6OBAgGVGlxVTzxagWS7D5A4PfvIHNxQ,52814
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
@@ -22,9 +22,9 @@ lsst/pipe/base/mermaid_tools.py,sha256=b_15oqCcxSom4ecMTDX8tfEtxe8W-juPVL65HOMyw
22
22
  lsst/pipe/base/pipeline.py,sha256=bFbgjyJHI4JsuMUPLAW-kg_xZFvWPBEdEb6hCUENpcU,37559
23
23
  lsst/pipe/base/pipelineIR.py,sha256=-tHyvnc3B9fTEqMh3wXYiTfYI4O5jOk_G0_G9YhPN6U,43660
24
24
  lsst/pipe/base/pipelineTask.py,sha256=K3GdjJLvy8A7I-jzQiERQZaYF7mC1LM3iB5TmUtbOCI,8394
25
- lsst/pipe/base/prerequisite_helpers.py,sha256=2R7tor-oOJduLJw4onNSP_EfRU69ohMys92Lg4dYSEQ,28311
25
+ lsst/pipe/base/prerequisite_helpers.py,sha256=WxfIGkF0Wlucp9mE3Wp3E6K2M6d66O0oZrWecRqn5CI,28312
26
26
  lsst/pipe/base/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- lsst/pipe/base/quantum_graph_builder.py,sha256=sbhm9DXyea6BphOpnosZHb8i-FO-H_MjxRyX1Szu0CE,53110
27
+ lsst/pipe/base/quantum_graph_builder.py,sha256=mUmIMQF6D3YfOvx_89IgDTUuAAruJUIYu7sHpJnrZJw,53110
28
28
  lsst/pipe/base/quantum_graph_skeleton.py,sha256=tO4TTIsJVHzlC_dvR9s3tBO_-X0uyjqNFuBz3mHUmFY,23641
29
29
  lsst/pipe/base/quantum_provenance_graph.py,sha256=z0_q1OZNOTULmejJHncKEYXpdhJm6M3jU20EieCsQk8,77537
30
30
  lsst/pipe/base/struct.py,sha256=Fa-UkpuXOxdzKWbHrMUkJYOszZuBXCm2NesXNR0IOPQ,5048
@@ -32,7 +32,7 @@ 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=7RDErOq5RGNAoQY53vvlgNSl38poXunVsozwg-tQkrU,52
35
+ lsst/pipe/base/version.py,sha256=sHiUhHRfi72yQHyY-cFkHWLqVyELO1VeQ3Uo0NmIBCc,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
@@ -65,7 +65,7 @@ lsst/pipe/base/pipeline_graph/visualization/_dot.py,sha256=quja94wafmbCPJvC7HrHR
65
65
  lsst/pipe/base/pipeline_graph/visualization/_formatting.py,sha256=_AWjp73iv-KQIFZ7fSvyyv-a5TYJSVtAenpT8pc3T5M,8319
66
66
  lsst/pipe/base/pipeline_graph/visualization/_layout.py,sha256=aMFl2Sgw_2-AfCBr_JBIWSs7VbSfSP7Nuol0mP9lkUo,17157
67
67
  lsst/pipe/base/pipeline_graph/visualization/_merge.py,sha256=cBKhNjgymDkzYtVutrXd9IGa-eE4Q9jnHO9F18e64dY,15435
68
- lsst/pipe/base/pipeline_graph/visualization/_mermaid.py,sha256=IhvsQdFwwUCLQLjuZdA40k5TdgqMaqzaLlNtNa1iRVI,15625
68
+ lsst/pipe/base/pipeline_graph/visualization/_mermaid.py,sha256=EnKcJkA-x2YJtMGN_pKTM4_nVt_ifi6gjOrEMViD_8w,20406
69
69
  lsst/pipe/base/pipeline_graph/visualization/_options.py,sha256=UNzPiTKU9x0PRiHr6cOiKTHk2s0R_LbKipZPezxsGGc,4862
70
70
  lsst/pipe/base/pipeline_graph/visualization/_printer.py,sha256=yJMRJ-aXd3nYDgs1FqS2l_hzNbQ50HUVm55VVaNi71s,16537
71
71
  lsst/pipe/base/pipeline_graph/visualization/_show.py,sha256=l0Ybq-bcdxBhgrf84rxiDGpLAHCOIX2uow418gTKbxA,9507
@@ -80,16 +80,16 @@ lsst/pipe/base/tests/pipelineStepTester.py,sha256=KGxdB8gdVpSey2RUGURDIzIfPL-4qv
80
80
  lsst/pipe/base/tests/simpleQGraph.py,sha256=G9C69caX8479JR9h48ERhOFvLTPJCoj5gKf_eRoaALQ,19660
81
81
  lsst/pipe/base/tests/util.py,sha256=eWuIRz55HYgNmMkexinN9HjUFmPC3uapO8jMjcQY-ao,4010
82
82
  lsst/pipe/base/tests/mocks/__init__.py,sha256=NrIJYDeYgR3HsOJXBEXi8EXDhhV7iw7dgwK9qlQ59PA,1551
83
- lsst/pipe/base/tests/mocks/_data_id_match.py,sha256=K0GZwouLxApEEC-3HzIf_BLwAimGAE6Xfbro8eQed0A,6350
83
+ lsst/pipe/base/tests/mocks/_data_id_match.py,sha256=MRGZUSD6ES0EiVG7kOIGZaJbZsaSIXB2M6tI9RpdUAc,6491
84
84
  lsst/pipe/base/tests/mocks/_pipeline_task.py,sha256=fqaJ-tB7K3jxlfCvCSnVd_GNrz-JhX7FB914h7nHLXc,29366
85
85
  lsst/pipe/base/tests/mocks/_storage_class.py,sha256=JvUmyXQC5DwOkFoLHkJk6u0ldn1VgZVVjh9GjpXRGg0,25211
86
- lsst_pipe_base-29.0.0rc1.dist-info/COPYRIGHT,sha256=kB3Z9_f6a6uFLGpEmNJT_n186CE65H6wHu4F6BNt_zA,368
87
- lsst_pipe_base-29.0.0rc1.dist-info/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
88
- lsst_pipe_base-29.0.0rc1.dist-info/METADATA,sha256=1_-ZaCnslnxaAWiCt2aUDRF5P1Zl4QQAPwGx7yQJjF8,2070
89
- lsst_pipe_base-29.0.0rc1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
90
- lsst_pipe_base-29.0.0rc1.dist-info/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
91
- lsst_pipe_base-29.0.0rc1.dist-info/entry_points.txt,sha256=bnmUhJBsChxMdqST9VmFBYYKxLQoToOfqW1wjW7khjk,64
92
- lsst_pipe_base-29.0.0rc1.dist-info/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
93
- lsst_pipe_base-29.0.0rc1.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
94
- lsst_pipe_base-29.0.0rc1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
95
- lsst_pipe_base-29.0.0rc1.dist-info/RECORD,,
86
+ lsst_pipe_base-29.2025.1100.dist-info/COPYRIGHT,sha256=kB3Z9_f6a6uFLGpEmNJT_n186CE65H6wHu4F6BNt_zA,368
87
+ lsst_pipe_base-29.2025.1100.dist-info/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
88
+ lsst_pipe_base-29.2025.1100.dist-info/METADATA,sha256=hJucauvX_isC8xPWQBVLglR_rmNO8CHukFO46BnGtQk,2140
89
+ lsst_pipe_base-29.2025.1100.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
90
+ lsst_pipe_base-29.2025.1100.dist-info/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
91
+ lsst_pipe_base-29.2025.1100.dist-info/entry_points.txt,sha256=bnmUhJBsChxMdqST9VmFBYYKxLQoToOfqW1wjW7khjk,64
92
+ lsst_pipe_base-29.2025.1100.dist-info/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
93
+ lsst_pipe_base-29.2025.1100.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
94
+ lsst_pipe_base-29.2025.1100.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
95
+ lsst_pipe_base-29.2025.1100.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5