lsst-pipe-base 29.2025.4200__tar.gz → 29.2025.4400__tar.gz
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.
- {lsst_pipe_base-29.2025.4200/python/lsst_pipe_base.egg-info → lsst_pipe_base-29.2025.4400}/PKG-INFO +3 -3
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/pyproject.toml +4 -3
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_status.py +1 -1
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/cmd/__init__.py +2 -2
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/cmd/commands.py +116 -1
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph_walker.py +8 -4
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_pipeline_graph.py +30 -5
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph/__init__.py +1 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph/_common.py +2 -1
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph/_multiblock.py +41 -7
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph/_predicted.py +62 -5
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/_provenance.py +1209 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/__init__.py +143 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_communicators.py +981 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_config.py +139 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_ingester.py +312 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_progress.py +208 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_scanner.py +371 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_structs.py +167 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_supervisor.py +225 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/quantum_graph/aggregator/_writer.py +593 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/resource_usage.py +183 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/util.py +31 -0
- lsst_pipe_base-29.2025.4400/python/lsst/pipe/base/version.py +2 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400/python/lsst_pipe_base.egg-info}/PKG-INFO +3 -3
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/SOURCES.txt +12 -0
- lsst_pipe_base-29.2025.4400/tests/test_aggregator.py +900 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_single_quantum_executor.py +17 -0
- lsst_pipe_base-29.2025.4200/python/lsst/pipe/base/version.py +0 -2
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/COPYRIGHT +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/LICENSE +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/MANIFEST.in +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/README.md +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/bsd_license.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/CHANGES.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/creating-a-pipeline.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/creating-a-pipelinetask.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/creating-a-task.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/index.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/task-framework-overview.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/task-retargeting-howto.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/testing-a-pipeline-task.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/testing-pipelines-with-mocks.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/doc/lsst.pipe.base/working-with-pipeline-graphs.rst +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/gpl-v3.0.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_datasetQueryConstraints.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_dataset_handle.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_instrument.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_observation_dimension_packer.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_quantumContext.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_task_metadata.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/all_dimensions_quantum_graph_builder.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/automatic_connection_constants.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/caching_limited_butler.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/_get_cli_subcommands.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/opt/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/opt/arguments.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/cli/opt/options.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/config.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/configOverrides.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/connectionTypes.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/connections.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/dot_tools.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/exec_fixup_data_id.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/execution_graph_fixup.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/execution_reports.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/formatters/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/formatters/pexConfig.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/_implDetails.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/_loadHelpers.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/_versionDeserializers.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/graphSummary.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph/quantumNode.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/log_capture.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/mermaid_tools.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/mp_graph_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipelineIR.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipelineTask.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/__main__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_dataset_types.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_edges.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_exceptions.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_mapping_views.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_nodes.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_task_subsets.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/_tasks.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/expressions.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/io.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_dot.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_formatting.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_layout.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_merge.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_mermaid.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_options.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_printer.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_show.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/prerequisite_helpers.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/py.typed +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph/visualization.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph_builder.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_graph_skeleton.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_provenance_graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/quantum_reports.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/register_instrument.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/retrieve_artifacts_for_quanta.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/transfer_from_graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/utils.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/script/zip_from_graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/separable_pipeline_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/simple_pipeline_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/single_quantum_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/struct.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/task.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/taskFactory.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/testUtils.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/in_memory_limited_butler.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/mocks/__init__.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/mocks/_data_id_match.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/mocks/_pipeline_task.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/mocks/_repo.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/mocks/_storage_class.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/no_dimensions.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/pipelineStepTester.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/tests/simpleQGraph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/utils.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/dependency_links.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/entry_points.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/requires.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/top_level.txt +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst_pipe_base.egg-info/zip-safe +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/setup.cfg +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_adjust_all_quanta.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_caching_limited_butler.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_cliCmdRegisterInstrument.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_configOverrides.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_config_formatter.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_connections.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_dataid_match.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_dataset_handle.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_dot_tools.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_dynamic_connections.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_execution_reports.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_execution_storage_class_conversion.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_graphBuilder.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_graph_walker.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_init_output_run.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_instrument.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_mermaid.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_mp_graph_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipeline.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipelineIR.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipelineLoadSubset.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipelineTask.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipeline_graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_pipeline_graph_expressions.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_predicted_qg.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_qg_builder_dimensions.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_quantumGraph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_quantum_provenance_graph.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_quantum_reports.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_quantum_success_caveats.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_script_utils.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_separable_pipeline_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_simple_pipeline_executor.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_struct.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_task.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_task_factory.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_taskmetadata.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_testUtils.py +0 -0
- {lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/tests/test_utils.py +0 -0
{lsst_pipe_base-29.2025.4200/python/lsst_pipe_base.egg-info → lsst_pipe_base-29.2025.4400}/PKG-INFO
RENAMED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lsst-pipe-base
|
|
3
|
-
Version: 29.2025.
|
|
3
|
+
Version: 29.2025.4400
|
|
4
4
|
Summary: Pipeline infrastructure for the Rubin Science Pipelines.
|
|
5
5
|
Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
|
|
6
|
-
License: BSD
|
|
6
|
+
License-Expression: BSD-3-Clause OR GPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://github.com/lsst/pipe_base
|
|
8
8
|
Keywords: lsst
|
|
9
9
|
Classifier: Intended Audience :: Science/Research
|
|
10
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
16
|
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
17
17
|
Requires-Python: >=3.11.0
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
@@ -6,19 +6,20 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
name = "lsst-pipe-base"
|
|
7
7
|
requires-python = ">=3.11.0"
|
|
8
8
|
description = "Pipeline infrastructure for the Rubin Science Pipelines."
|
|
9
|
-
license =
|
|
9
|
+
license = "BSD-3-Clause OR GPL-3.0-or-later"
|
|
10
|
+
license-files = ["COPYRIGHT", "LICENSE", "bsd_license.txt", "gpl-v3.0.txt"]
|
|
10
11
|
readme = "README.md"
|
|
11
12
|
authors = [
|
|
12
13
|
{name="Rubin Observatory Data Management", email="dm-admin@lists.lsst.org"},
|
|
13
14
|
]
|
|
14
15
|
classifiers = [
|
|
15
16
|
"Intended Audience :: Science/Research",
|
|
16
|
-
"License :: OSI Approved :: BSD License",
|
|
17
17
|
"Operating System :: OS Independent",
|
|
18
18
|
"Programming Language :: Python :: 3",
|
|
19
19
|
"Programming Language :: Python :: 3.11",
|
|
20
20
|
"Programming Language :: Python :: 3.12",
|
|
21
21
|
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
22
23
|
"Topic :: Scientific/Engineering :: Astronomy",
|
|
23
24
|
]
|
|
24
25
|
keywords=["lsst"]
|
|
@@ -54,7 +55,6 @@ where = ["python"]
|
|
|
54
55
|
|
|
55
56
|
[tool.setuptools]
|
|
56
57
|
zip-safe = true
|
|
57
|
-
license-files = ["COPYRIGHT", "LICENSE", "bsd_license.txt", "gpl-v3.0.txt"]
|
|
58
58
|
|
|
59
59
|
[tool.setuptools.package-data]
|
|
60
60
|
"lsst.pipe.base" = ["py.typed", "cli/resources.yaml"]
|
|
@@ -124,6 +124,7 @@ exclude_lines = [
|
|
|
124
124
|
"if __name__ == .__main__.:",
|
|
125
125
|
"if TYPE_CHECKING:",
|
|
126
126
|
'if "sphinx" in sys.modules:',
|
|
127
|
+
'if "sphinx" in sys.modules and not TYPE_CHECKING:'
|
|
127
128
|
]
|
|
128
129
|
|
|
129
130
|
[tool.pydocstyle]
|
{lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/_status.py
RENAMED
|
@@ -166,7 +166,7 @@ class QuantumSuccessCaveats(enum.Flag):
|
|
|
166
166
|
"""
|
|
167
167
|
return {
|
|
168
168
|
"+": "at least one predicted output was missing, but not all were",
|
|
169
|
-
"*": "all
|
|
169
|
+
"*": "all predicted outputs were missing (besides logs and metadata)",
|
|
170
170
|
"A": "adjustQuantum raised NoWorkFound; a regenerated QG would not include this quantum",
|
|
171
171
|
"D": "algorithm considers data too bad to be processable",
|
|
172
172
|
"U": "one or more input dataset was incomplete due to an upstream failure",
|
|
@@ -25,6 +25,6 @@
|
|
|
25
25
|
# You should have received a copy of the GNU General Public License
|
|
26
26
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
27
27
|
|
|
28
|
-
__all__ = ["register_instrument", "transfer_from_graph", "zip_from_graph", "retrieve_artifacts_for_quanta"]
|
|
28
|
+
__all__ = ["register_instrument", "transfer_from_graph", "zip_from_graph", "retrieve_artifacts_for_quanta", "aggregate_graph"]
|
|
29
29
|
|
|
30
|
-
from .commands import register_instrument, retrieve_artifacts_for_quanta, transfer_from_graph, zip_from_graph
|
|
30
|
+
from .commands import (register_instrument, retrieve_artifacts_for_quanta, transfer_from_graph, zip_from_graph, aggregate_graph)
|
|
@@ -40,6 +40,7 @@ from lsst.daf.butler.cli.opt import (
|
|
|
40
40
|
from lsst.daf.butler.cli.utils import ButlerCommand, split_commas, unwrap
|
|
41
41
|
|
|
42
42
|
from ... import script
|
|
43
|
+
from ...quantum_graph import aggregator
|
|
43
44
|
from ..opt import instrument_argument, update_output_chain_option
|
|
44
45
|
|
|
45
46
|
|
|
@@ -140,7 +141,7 @@ def zip_from_graph(**kwargs: Any) -> None:
|
|
|
140
141
|
"--include-outputs/--no-include-outputs",
|
|
141
142
|
is_flag=True,
|
|
142
143
|
default=True,
|
|
143
|
-
help="Whether to include
|
|
144
|
+
help="Whether to include output datasets in retrieval.",
|
|
144
145
|
)
|
|
145
146
|
@options_file_option()
|
|
146
147
|
def retrieve_artifacts_for_quanta(**kwargs: Any) -> None:
|
|
@@ -153,3 +154,117 @@ def retrieve_artifacts_for_quanta(**kwargs: Any) -> None:
|
|
|
153
154
|
"""
|
|
154
155
|
artifacts = script.retrieve_artifacts_for_quanta(**kwargs)
|
|
155
156
|
print(f"Written {len(artifacts)} artifacts to {kwargs['dest']}.")
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
_AGGREGATOR_DEFAULTS = aggregator.AggregatorConfig()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@click.command(short_help="Scan for the outputs of an active or completed quantum graph.", cls=ButlerCommand)
|
|
163
|
+
@click.argument("predicted_graph", required=True)
|
|
164
|
+
@repo_argument(required=True, help="Path to the central butler repository.")
|
|
165
|
+
@click.option(
|
|
166
|
+
"-o",
|
|
167
|
+
"--output",
|
|
168
|
+
"output_path",
|
|
169
|
+
default=_AGGREGATOR_DEFAULTS.output_path,
|
|
170
|
+
help=(
|
|
171
|
+
"Path to the output provenance quantum graph. THIS OPTION IS FOR "
|
|
172
|
+
"DEVELOPMENT AND DEBUGGING ONLY. IT MAY BE REMOVED IN THE FUTURE."
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
@click.option(
|
|
176
|
+
"--processes",
|
|
177
|
+
"-j",
|
|
178
|
+
"n_processes",
|
|
179
|
+
default=_AGGREGATOR_DEFAULTS.n_processes,
|
|
180
|
+
type=click.IntRange(min=1),
|
|
181
|
+
help="Number of processes to use.",
|
|
182
|
+
)
|
|
183
|
+
@click.option(
|
|
184
|
+
"--complete/--incomplete",
|
|
185
|
+
"assume_complete",
|
|
186
|
+
default=_AGGREGATOR_DEFAULTS.assume_complete,
|
|
187
|
+
help="Whether execution has completed (and failures cannot be retried).",
|
|
188
|
+
)
|
|
189
|
+
@click.option(
|
|
190
|
+
"--dry-run",
|
|
191
|
+
is_flag=True,
|
|
192
|
+
default=_AGGREGATOR_DEFAULTS.dry_run,
|
|
193
|
+
help="Do not actually perform any central database ingests.",
|
|
194
|
+
)
|
|
195
|
+
@click.option(
|
|
196
|
+
"--interactive-status/--no-interactive-status",
|
|
197
|
+
"interactive_status",
|
|
198
|
+
default=_AGGREGATOR_DEFAULTS.interactive_status,
|
|
199
|
+
help="Use progress bars for status reporting instead of periodic logging.",
|
|
200
|
+
)
|
|
201
|
+
@click.option(
|
|
202
|
+
"--log-status-interval",
|
|
203
|
+
type=int,
|
|
204
|
+
default=_AGGREGATOR_DEFAULTS.log_status_interval,
|
|
205
|
+
help="Interval (in seconds) between periodic logger status updates.",
|
|
206
|
+
)
|
|
207
|
+
@click.option(
|
|
208
|
+
"--register-dataset-types/--no-register-dataset-types",
|
|
209
|
+
default=_AGGREGATOR_DEFAULTS.register_dataset_types,
|
|
210
|
+
help="Register output dataset types.",
|
|
211
|
+
)
|
|
212
|
+
@click.option(
|
|
213
|
+
"--update-output-chain/--no-update-output-chain",
|
|
214
|
+
default=_AGGREGATOR_DEFAULTS.update_output_chain,
|
|
215
|
+
help="Prepend the output RUN collection to the output CHAINED collection.",
|
|
216
|
+
)
|
|
217
|
+
@click.option(
|
|
218
|
+
"--worker-log-dir",
|
|
219
|
+
type=str,
|
|
220
|
+
default=_AGGREGATOR_DEFAULTS.worker_log_dir,
|
|
221
|
+
help="Path to a directory (POSIX only) for parallel worker logs.",
|
|
222
|
+
)
|
|
223
|
+
@click.option(
|
|
224
|
+
"--worker-log-level",
|
|
225
|
+
type=str,
|
|
226
|
+
default=_AGGREGATOR_DEFAULTS.worker_log_level,
|
|
227
|
+
help="Log level for worker processes/threads (use DEBUG for per-quantum messages).",
|
|
228
|
+
)
|
|
229
|
+
@click.option(
|
|
230
|
+
"--zstd-level",
|
|
231
|
+
type=int,
|
|
232
|
+
default=_AGGREGATOR_DEFAULTS.zstd_level,
|
|
233
|
+
help="Compression level for the provenance quantum graph file.",
|
|
234
|
+
)
|
|
235
|
+
@click.option(
|
|
236
|
+
"--zstd-dict-size",
|
|
237
|
+
type=int,
|
|
238
|
+
default=_AGGREGATOR_DEFAULTS.zstd_dict_size,
|
|
239
|
+
help="Size (in bytes) of the ZStandard compression dictionary.",
|
|
240
|
+
)
|
|
241
|
+
@click.option(
|
|
242
|
+
"--zstd-dict-n-inputs",
|
|
243
|
+
type=int,
|
|
244
|
+
default=_AGGREGATOR_DEFAULTS.zstd_dict_n_inputs,
|
|
245
|
+
help=("Number of samples of each type to include in ZStandard compression dictionary training."),
|
|
246
|
+
)
|
|
247
|
+
@click.option(
|
|
248
|
+
"--mock-storage-classes/--no-mock-storage-classes",
|
|
249
|
+
default=_AGGREGATOR_DEFAULTS.mock_storage_classes,
|
|
250
|
+
help="Enable support for storage classes created by the lsst.pipe.base.tests.mocks package.",
|
|
251
|
+
)
|
|
252
|
+
def aggregate_graph(predicted_graph: str, repo: str, **kwargs: Any) -> None:
|
|
253
|
+
"""Scan for quantum graph's outputs to gather provenance, ingest datasets
|
|
254
|
+
into the central butler repository, and delete datasets that are no
|
|
255
|
+
longer needed.
|
|
256
|
+
"""
|
|
257
|
+
# It'd be nice to allow to the user to provide a path to an
|
|
258
|
+
# AggregatorConfig JSON file for options that weren't provided, but Click
|
|
259
|
+
# 8.1 fundamentally cannot handle flag options that default to None rather
|
|
260
|
+
# than True or False (i.e. so they fall back to the config value when not
|
|
261
|
+
# set). It's not clear whether Click 8.2.x has actually fixed this; Click
|
|
262
|
+
# 8.2.0 tried but caused new problems.
|
|
263
|
+
|
|
264
|
+
config = aggregator.AggregatorConfig(**kwargs)
|
|
265
|
+
try:
|
|
266
|
+
aggregator.aggregate_graph(predicted_graph, repo, config)
|
|
267
|
+
except aggregator.FatalWorkerError as err:
|
|
268
|
+
# When this exception is raised, we'll have already logged the relevant
|
|
269
|
+
# traceback from a separate worker.
|
|
270
|
+
raise click.ClickException(str(err)) from None
|
{lsst_pipe_base-29.2025.4200 → lsst_pipe_base-29.2025.4400}/python/lsst/pipe/base/graph_walker.py
RENAMED
|
@@ -81,10 +81,12 @@ class GraphWalker(Generic[_T]):
|
|
|
81
81
|
Parameters
|
|
82
82
|
----------
|
|
83
83
|
key : unspecified
|
|
84
|
-
NetworkX key of the node to mark finished.
|
|
84
|
+
NetworkX key of the node to mark finished. Does not need to have
|
|
85
|
+
been returned by the iterator yet.
|
|
85
86
|
"""
|
|
86
|
-
self._active.remove(key)
|
|
87
87
|
self._incomplete.remove(key)
|
|
88
|
+
self._active.discard(key)
|
|
89
|
+
self._ready.discard(key)
|
|
88
90
|
successors = list(self._xgraph.successors(key))
|
|
89
91
|
for successor in successors:
|
|
90
92
|
assert successor not in self._active, (
|
|
@@ -102,7 +104,8 @@ class GraphWalker(Generic[_T]):
|
|
|
102
104
|
Parameters
|
|
103
105
|
----------
|
|
104
106
|
key : unspecified
|
|
105
|
-
NetworkX key of the node to mark as a failure.
|
|
107
|
+
NetworkX key of the node to mark as a failure. Does not need to
|
|
108
|
+
have been returned by the iterator yet.
|
|
106
109
|
|
|
107
110
|
Returns
|
|
108
111
|
-------
|
|
@@ -110,8 +113,9 @@ class GraphWalker(Generic[_T]):
|
|
|
110
113
|
NetworkX keys of nodes that were recursive descendants of the
|
|
111
114
|
failed node, and will hence never be yielded by the iterator.
|
|
112
115
|
"""
|
|
113
|
-
self._active.remove(key)
|
|
114
116
|
self._incomplete.remove(key)
|
|
117
|
+
self._active.discard(key)
|
|
118
|
+
self._ready.discard(key)
|
|
115
119
|
descendants = list(networkx.dag.descendants(self._xgraph, key))
|
|
116
120
|
self._xgraph.remove_node(key)
|
|
117
121
|
self._xgraph.remove_nodes_from(descendants)
|
|
@@ -1697,7 +1697,15 @@ class PipelineGraph:
|
|
|
1697
1697
|
PACKAGES_INIT_OUTPUT_NAME, self._universe.empty, PACKAGES_INIT_OUTPUT_STORAGE_CLASS
|
|
1698
1698
|
)
|
|
1699
1699
|
|
|
1700
|
-
def register_dataset_types(
|
|
1700
|
+
def register_dataset_types(
|
|
1701
|
+
self,
|
|
1702
|
+
butler: Butler,
|
|
1703
|
+
include_packages: bool = True,
|
|
1704
|
+
*,
|
|
1705
|
+
include_inputs: bool = True,
|
|
1706
|
+
include_configs: bool = True,
|
|
1707
|
+
include_logs: bool = True,
|
|
1708
|
+
) -> None:
|
|
1701
1709
|
"""Register all dataset types in a data repository.
|
|
1702
1710
|
|
|
1703
1711
|
Parameters
|
|
@@ -1709,11 +1717,28 @@ class PipelineGraph:
|
|
|
1709
1717
|
software versions (this is not associated with a task and hence is
|
|
1710
1718
|
not considered part of the pipeline graph in other respects, but it
|
|
1711
1719
|
does get written with other provenance datasets).
|
|
1712
|
-
|
|
1713
|
-
|
|
1720
|
+
include_inputs : `bool`, optional
|
|
1721
|
+
Whether to register overall-input dataset types as well as outputs.
|
|
1722
|
+
include_configs : `bool`, optional
|
|
1723
|
+
Whether to register task config dataset types.
|
|
1724
|
+
include_logs : `bool`, optional
|
|
1725
|
+
Whether to register task log dataset types.
|
|
1726
|
+
"""
|
|
1727
|
+
dataset_types = {
|
|
1728
|
+
node.name: node.dataset_type
|
|
1729
|
+
for node in self.dataset_types.values()
|
|
1730
|
+
if include_inputs or self.producer_of(node.name) is not None
|
|
1731
|
+
}
|
|
1714
1732
|
if include_packages:
|
|
1715
|
-
dataset_types.
|
|
1716
|
-
|
|
1733
|
+
dataset_types[self.packages_dataset_type.name] = self.packages_dataset_type
|
|
1734
|
+
if not include_configs:
|
|
1735
|
+
for task_node in self.tasks.values():
|
|
1736
|
+
del dataset_types[task_node.init.config_output.dataset_type_name]
|
|
1737
|
+
if not include_logs:
|
|
1738
|
+
for task_node in self.tasks.values():
|
|
1739
|
+
if task_node.log_output is not None:
|
|
1740
|
+
del dataset_types[task_node.log_output.dataset_type_name]
|
|
1741
|
+
for dataset_type in dataset_types.values():
|
|
1717
1742
|
butler.registry.registerDatasetType(dataset_type)
|
|
1718
1743
|
|
|
1719
1744
|
def check_dataset_type_registrations(self, butler: Butler, include_packages: bool = True) -> None:
|
|
@@ -82,6 +82,7 @@ if TYPE_CHECKING:
|
|
|
82
82
|
TaskLabel: TypeAlias = str
|
|
83
83
|
DatasetTypeName: TypeAlias = str
|
|
84
84
|
ConnectionName: TypeAlias = str
|
|
85
|
+
DatasetIndex: TypeAlias = int
|
|
85
86
|
QuantumIndex: TypeAlias = int
|
|
86
87
|
DatastoreName: TypeAlias = str
|
|
87
88
|
DimensionElementName: TypeAlias = str
|
|
@@ -326,7 +327,7 @@ class BaseQuantumGraph(ABC):
|
|
|
326
327
|
----------
|
|
327
328
|
header : `HeaderModel`
|
|
328
329
|
Structured metadata for the graph.
|
|
329
|
-
pipeline_graph :
|
|
330
|
+
pipeline_graph : `.pipeline_graph.PipelineGraph`
|
|
330
331
|
Graph of tasks and dataset types. May contain a superset of the tasks
|
|
331
332
|
and dataset types that actually have quanta and datasets in the quantum
|
|
332
333
|
graph.
|
|
@@ -41,6 +41,7 @@ __all__ = (
|
|
|
41
41
|
|
|
42
42
|
import dataclasses
|
|
43
43
|
import logging
|
|
44
|
+
import tempfile
|
|
44
45
|
import uuid
|
|
45
46
|
from collections.abc import Iterator
|
|
46
47
|
from contextlib import contextmanager
|
|
@@ -501,13 +502,13 @@ class AddressReader:
|
|
|
501
502
|
self.pages.clear()
|
|
502
503
|
return self.rows
|
|
503
504
|
|
|
504
|
-
def find(self, key: uuid.UUID) -> AddressRow:
|
|
505
|
-
"""Read the row for the given UUID.
|
|
505
|
+
def find(self, key: uuid.UUID | int) -> AddressRow:
|
|
506
|
+
"""Read the row for the given UUID or integer index.
|
|
506
507
|
|
|
507
508
|
Parameters
|
|
508
509
|
----------
|
|
509
|
-
key : `uuid.UUID`
|
|
510
|
-
UUID to find.
|
|
510
|
+
key : `uuid.UUID` or `int`
|
|
511
|
+
UUID or integer index to find.
|
|
511
512
|
|
|
512
513
|
Returns
|
|
513
514
|
-------
|
|
@@ -517,6 +518,8 @@ class AddressReader:
|
|
|
517
518
|
match key:
|
|
518
519
|
case uuid.UUID():
|
|
519
520
|
return self._find_uuid(key)
|
|
521
|
+
case int():
|
|
522
|
+
return self._find_index(key)
|
|
520
523
|
case _:
|
|
521
524
|
raise TypeError(f"Invalid argument: {key}.")
|
|
522
525
|
|
|
@@ -546,6 +549,22 @@ class AddressReader:
|
|
|
546
549
|
# Ran out of pages to search.
|
|
547
550
|
raise LookupError(f"Address for {target} not found.")
|
|
548
551
|
|
|
552
|
+
def _find_index(self, target: int) -> AddressRow:
|
|
553
|
+
# First shortcut if we've already loaded this row.
|
|
554
|
+
if (row := self.rows_by_index.get(target)) is not None:
|
|
555
|
+
return row
|
|
556
|
+
if target < 0 or target >= self.n_rows:
|
|
557
|
+
raise LookupError(f"Address for index {target} not found.")
|
|
558
|
+
# Since all indexes should be present, we can predict the right page
|
|
559
|
+
# exactly.
|
|
560
|
+
page_index = target // self.rows_per_page
|
|
561
|
+
self._read_page(page_index)
|
|
562
|
+
try:
|
|
563
|
+
return self.rows_by_index[target]
|
|
564
|
+
except KeyError:
|
|
565
|
+
_LOG.debug("Index find failed: %s should have been in page %s.", target, page_index)
|
|
566
|
+
raise LookupError(f"Address for {target} not found.") from None
|
|
567
|
+
|
|
549
568
|
def _read_page(self, page_index: int, page_stream: BytesIO | None = None) -> bool:
|
|
550
569
|
page = self.pages[page_index]
|
|
551
570
|
if page.read:
|
|
@@ -594,7 +613,9 @@ class MultiblockWriter:
|
|
|
594
613
|
|
|
595
614
|
@classmethod
|
|
596
615
|
@contextmanager
|
|
597
|
-
def open_in_zip(
|
|
616
|
+
def open_in_zip(
|
|
617
|
+
cls, zf: zipfile.ZipFile, name: str, int_size: int, use_tempfile: bool = False
|
|
618
|
+
) -> Iterator[MultiblockWriter]:
|
|
598
619
|
"""Open a writer for a file in a zip archive.
|
|
599
620
|
|
|
600
621
|
Parameters
|
|
@@ -605,14 +626,26 @@ class MultiblockWriter:
|
|
|
605
626
|
Base name for the multi-block file; an extension will be added.
|
|
606
627
|
int_size : `int`
|
|
607
628
|
Number of bytes to use for all integers.
|
|
629
|
+
use_tempfile : `bool`, optional
|
|
630
|
+
If `True`, send writes to a temporary file and only add the file to
|
|
631
|
+
the zip archive when the context manager closes. This involves
|
|
632
|
+
more overall I/O, but it permits multiple multi-block files to be
|
|
633
|
+
open for writing in the same zip archive at once.
|
|
608
634
|
|
|
609
635
|
Returns
|
|
610
636
|
-------
|
|
611
637
|
writer : `contextlib.AbstractContextManager` [ `MultiblockWriter` ]
|
|
612
638
|
Context manager that returns a writer when entered.
|
|
613
639
|
"""
|
|
614
|
-
|
|
615
|
-
|
|
640
|
+
filename = f"{name}.mb"
|
|
641
|
+
if use_tempfile:
|
|
642
|
+
with tempfile.NamedTemporaryFile(suffix=filename) as tmp:
|
|
643
|
+
yield MultiblockWriter(tmp, int_size)
|
|
644
|
+
tmp.flush()
|
|
645
|
+
zf.write(tmp.name, filename)
|
|
646
|
+
else:
|
|
647
|
+
with zf.open(f"{name}.mb", mode="w", force_zip64=True) as stream:
|
|
648
|
+
yield MultiblockWriter(stream, int_size)
|
|
616
649
|
|
|
617
650
|
def write_bytes(self, id: uuid.UUID, data: bytes) -> Address:
|
|
618
651
|
"""Write raw bytes to the multi-block file.
|
|
@@ -629,6 +662,7 @@ class MultiblockWriter:
|
|
|
629
662
|
address : `Address`
|
|
630
663
|
Address of the bytes just written.
|
|
631
664
|
"""
|
|
665
|
+
assert id not in self.addresses, "Duplicate write to multi-block file detected."
|
|
632
666
|
self.stream.write(len(data).to_bytes(self.int_size))
|
|
633
667
|
self.stream.write(data)
|
|
634
668
|
block_size = len(data) + self.int_size
|
|
@@ -347,8 +347,21 @@ class PredictedQuantumDatasetsModel(pydantic.BaseModel):
|
|
|
347
347
|
the data repository.
|
|
348
348
|
"""
|
|
349
349
|
|
|
350
|
-
def
|
|
351
|
-
"""Return an iterator over the UUIDs of all datasets
|
|
350
|
+
def iter_input_dataset_ids(self) -> Iterator[uuid.UUID]:
|
|
351
|
+
"""Return an iterator over the UUIDs of all datasets consumed by this
|
|
352
|
+
quantum.
|
|
353
|
+
|
|
354
|
+
Returns
|
|
355
|
+
-------
|
|
356
|
+
iter : `~collections.abc.Iterator` [ `uuid.UUID` ]
|
|
357
|
+
Iterator over dataset IDs.
|
|
358
|
+
"""
|
|
359
|
+
for datasets in self.inputs.values():
|
|
360
|
+
for dataset in datasets:
|
|
361
|
+
yield dataset.dataset_id
|
|
362
|
+
|
|
363
|
+
def iter_output_dataset_ids(self) -> Iterator[uuid.UUID]:
|
|
364
|
+
"""Return an iterator over the UUIDs of all datasets produced by this
|
|
352
365
|
quantum.
|
|
353
366
|
|
|
354
367
|
Returns
|
|
@@ -356,10 +369,22 @@ class PredictedQuantumDatasetsModel(pydantic.BaseModel):
|
|
|
356
369
|
iter : `~collections.abc.Iterator` [ `uuid.UUID` ]
|
|
357
370
|
Iterator over dataset IDs.
|
|
358
371
|
"""
|
|
359
|
-
for datasets in
|
|
372
|
+
for datasets in self.outputs.values():
|
|
360
373
|
for dataset in datasets:
|
|
361
374
|
yield dataset.dataset_id
|
|
362
375
|
|
|
376
|
+
def iter_dataset_ids(self) -> Iterator[uuid.UUID]:
|
|
377
|
+
"""Return an iterator over the UUIDs of all datasets referenced by this
|
|
378
|
+
quantum.
|
|
379
|
+
|
|
380
|
+
Returns
|
|
381
|
+
-------
|
|
382
|
+
iter : `~collections.abc.Iterator` [ `uuid.UUID` ]
|
|
383
|
+
Iterator over dataset IDs.
|
|
384
|
+
"""
|
|
385
|
+
yield from self.iter_input_dataset_ids()
|
|
386
|
+
yield from self.iter_output_dataset_ids()
|
|
387
|
+
|
|
363
388
|
def deserialize_datastore_records(self) -> dict[DatastoreName, DatastoreRecordData]:
|
|
364
389
|
"""Deserialize the mapping of datastore records."""
|
|
365
390
|
return {
|
|
@@ -774,7 +799,7 @@ class PredictedQuantumGraph(BaseQuantumGraph):
|
|
|
774
799
|
Approximate number of bytes to read at once from address files.
|
|
775
800
|
Note that this does not set a page size for *all* reads, but it
|
|
776
801
|
does affect the smallest, most numerous reads.
|
|
777
|
-
import_mode :
|
|
802
|
+
import_mode : `.pipeline_graph.TaskImportMode`, optional
|
|
778
803
|
How to handle importing the task classes referenced in the pipeline
|
|
779
804
|
graph.
|
|
780
805
|
|
|
@@ -1498,6 +1523,38 @@ class PredictedQuantumGraphComponents:
|
|
|
1498
1523
|
This does include special "init" quanta.
|
|
1499
1524
|
"""
|
|
1500
1525
|
|
|
1526
|
+
def make_dataset_ref(self, predicted: PredictedDatasetModel) -> DatasetRef:
|
|
1527
|
+
"""Make a `lsst.daf.butler.DatasetRef` from information in the
|
|
1528
|
+
predicted quantum graph.
|
|
1529
|
+
|
|
1530
|
+
Parameters
|
|
1531
|
+
----------
|
|
1532
|
+
predicted : `PredictedDatasetModel`
|
|
1533
|
+
Model for the dataset in the predicted graph.
|
|
1534
|
+
|
|
1535
|
+
Returns
|
|
1536
|
+
-------
|
|
1537
|
+
ref : `lsst.daf.butler.DatasetRef`
|
|
1538
|
+
A dataset reference. Data ID will be expanded if and only if
|
|
1539
|
+
the dimension data has been loaded.
|
|
1540
|
+
"""
|
|
1541
|
+
try:
|
|
1542
|
+
dataset_type = self.pipeline_graph.dataset_types[predicted.dataset_type_name].dataset_type
|
|
1543
|
+
except KeyError:
|
|
1544
|
+
if predicted.dataset_type_name == acc.PACKAGES_INIT_OUTPUT_NAME:
|
|
1545
|
+
dataset_type = self.pipeline_graph.packages_dataset_type
|
|
1546
|
+
else:
|
|
1547
|
+
raise
|
|
1548
|
+
data_id = DataCoordinate.from_full_values(dataset_type.dimensions, tuple(predicted.data_coordinate))
|
|
1549
|
+
if self.dimension_data is not None:
|
|
1550
|
+
(data_id,) = self.dimension_data.attach(dataset_type.dimensions, [data_id])
|
|
1551
|
+
return DatasetRef(
|
|
1552
|
+
dataset_type,
|
|
1553
|
+
data_id,
|
|
1554
|
+
run=predicted.run,
|
|
1555
|
+
id=predicted.dataset_id,
|
|
1556
|
+
)
|
|
1557
|
+
|
|
1501
1558
|
def set_quantum_indices(self) -> None:
|
|
1502
1559
|
"""Populate the `quantum_indices` component by sorting the UUIDs in the
|
|
1503
1560
|
`init_quanta` and `quantum_datasets` components (which must both be
|
|
@@ -1813,7 +1870,7 @@ class PredictedQuantumGraphReader(BaseQuantumGraphReader):
|
|
|
1813
1870
|
Approximate number of bytes to read at once from address files.
|
|
1814
1871
|
Note that this does not set a page size for *all* reads, but it
|
|
1815
1872
|
does affect the smallest, most numerous reads.
|
|
1816
|
-
import_mode :
|
|
1873
|
+
import_mode : `.pipeline_graph.TaskImportMode`, optional
|
|
1817
1874
|
How to handle importing the task classes referenced in the pipeline
|
|
1818
1875
|
graph.
|
|
1819
1876
|
|