lsst-pipe-base 29.2025.2100__tar.gz → 29.2025.2400__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.
Files changed (146) hide show
  1. {lsst_pipe_base-29.2025.2100/python/lsst_pipe_base.egg-info → lsst_pipe_base-29.2025.2400}/PKG-INFO +1 -1
  2. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_task_metadata.py +1 -1
  3. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/graphSummary.py +2 -2
  4. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_dataset_types.py +18 -11
  5. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_edges.py +13 -11
  6. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_pipeline_graph.py +1 -1
  7. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/transfer_from_graph.py +29 -10
  8. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/utils.py +33 -4
  9. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/mocks/_storage_class.py +3 -3
  10. lsst_pipe_base-29.2025.2400/python/lsst/pipe/base/version.py +2 -0
  11. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400/python/lsst_pipe_base.egg-info}/PKG-INFO +1 -1
  12. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/SOURCES.txt +1 -0
  13. lsst_pipe_base-29.2025.2400/tests/test_script_utils.py +62 -0
  14. lsst_pipe_base-29.2025.2100/python/lsst/pipe/base/version.py +0 -2
  15. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/COPYRIGHT +0 -0
  16. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/LICENSE +0 -0
  17. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/MANIFEST.in +0 -0
  18. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/README.md +0 -0
  19. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/bsd_license.txt +0 -0
  20. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/CHANGES.rst +0 -0
  21. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/creating-a-pipeline.rst +0 -0
  22. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/creating-a-pipelinetask.rst +0 -0
  23. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/creating-a-task.rst +0 -0
  24. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/index.rst +0 -0
  25. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/task-framework-overview.rst +0 -0
  26. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/task-retargeting-howto.rst +0 -0
  27. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/testing-a-pipeline-task.rst +0 -0
  28. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/testing-pipelines-with-mocks.rst +0 -0
  29. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/doc/lsst.pipe.base/working-with-pipeline-graphs.rst +0 -0
  30. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/gpl-v3.0.txt +0 -0
  31. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/pyproject.toml +0 -0
  32. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/__init__.py +0 -0
  33. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/__init__.py +0 -0
  34. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/__init__.py +0 -0
  35. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_datasetQueryConstraints.py +0 -0
  36. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_dataset_handle.py +0 -0
  37. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_instrument.py +0 -0
  38. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_observation_dimension_packer.py +0 -0
  39. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_quantumContext.py +0 -0
  40. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/_status.py +0 -0
  41. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/all_dimensions_quantum_graph_builder.py +0 -0
  42. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/automatic_connection_constants.py +0 -0
  43. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/caching_limited_butler.py +0 -0
  44. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/__init__.py +0 -0
  45. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/_get_cli_subcommands.py +0 -0
  46. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/cmd/__init__.py +0 -0
  47. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/cmd/commands.py +0 -0
  48. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/opt/__init__.py +0 -0
  49. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/opt/arguments.py +0 -0
  50. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/cli/opt/options.py +0 -0
  51. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/config.py +0 -0
  52. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/configOverrides.py +0 -0
  53. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/connectionTypes.py +0 -0
  54. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/connections.py +0 -0
  55. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/dot_tools.py +0 -0
  56. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/executionButlerBuilder.py +0 -0
  57. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/execution_reports.py +0 -0
  58. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/formatters/__init__.py +0 -0
  59. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/formatters/pexConfig.py +0 -0
  60. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/__init__.py +0 -0
  61. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/_implDetails.py +0 -0
  62. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/_loadHelpers.py +0 -0
  63. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/_versionDeserializers.py +0 -0
  64. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/graph.py +0 -0
  65. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/graph/quantumNode.py +0 -0
  66. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/mermaid_tools.py +0 -0
  67. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline.py +0 -0
  68. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipelineIR.py +0 -0
  69. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipelineTask.py +0 -0
  70. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/__init__.py +0 -0
  71. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/__main__.py +0 -0
  72. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_exceptions.py +0 -0
  73. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_mapping_views.py +0 -0
  74. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_nodes.py +0 -0
  75. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_task_subsets.py +0 -0
  76. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/_tasks.py +0 -0
  77. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/expressions.py +0 -0
  78. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/io.py +0 -0
  79. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/__init__.py +0 -0
  80. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_dot.py +0 -0
  81. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_formatting.py +0 -0
  82. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_layout.py +0 -0
  83. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_merge.py +0 -0
  84. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_mermaid.py +0 -0
  85. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_options.py +0 -0
  86. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_printer.py +0 -0
  87. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_show.py +0 -0
  88. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/pipeline_graph/visualization/_status_annotator.py +0 -0
  89. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/prerequisite_helpers.py +0 -0
  90. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/py.typed +0 -0
  91. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/quantum_graph_builder.py +0 -0
  92. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/quantum_graph_skeleton.py +0 -0
  93. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/quantum_provenance_graph.py +0 -0
  94. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/__init__.py +0 -0
  95. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/register_instrument.py +0 -0
  96. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/retrieve_artifacts_for_quanta.py +0 -0
  97. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/script/zip_from_graph.py +0 -0
  98. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/struct.py +0 -0
  99. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/task.py +0 -0
  100. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/taskFactory.py +0 -0
  101. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/testUtils.py +0 -0
  102. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/__init__.py +0 -0
  103. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/mocks/__init__.py +0 -0
  104. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/mocks/_data_id_match.py +0 -0
  105. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/mocks/_pipeline_task.py +0 -0
  106. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/no_dimensions.py +0 -0
  107. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/pipelineStepTester.py +0 -0
  108. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/simpleQGraph.py +0 -0
  109. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/tests/util.py +0 -0
  110. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst/pipe/base/utils.py +0 -0
  111. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/dependency_links.txt +0 -0
  112. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/entry_points.txt +0 -0
  113. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/requires.txt +0 -0
  114. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/top_level.txt +0 -0
  115. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/python/lsst_pipe_base.egg-info/zip-safe +0 -0
  116. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/setup.cfg +0 -0
  117. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_adjust_all_quanta.py +0 -0
  118. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_caching_limited_butler.py +0 -0
  119. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_cliCmdRegisterInstrument.py +0 -0
  120. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_configOverrides.py +0 -0
  121. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_config_formatter.py +0 -0
  122. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_connections.py +0 -0
  123. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_dataid_match.py +0 -0
  124. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_dataset_handle.py +0 -0
  125. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_dot_tools.py +0 -0
  126. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_dynamic_connections.py +0 -0
  127. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_executionButler.py +0 -0
  128. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_execution_reports.py +0 -0
  129. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_graphBuilder.py +0 -0
  130. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_init_output_run.py +0 -0
  131. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_instrument.py +0 -0
  132. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_mermaid.py +0 -0
  133. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipeline.py +0 -0
  134. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipelineIR.py +0 -0
  135. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipelineLoadSubset.py +0 -0
  136. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipelineTask.py +0 -0
  137. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipeline_graph.py +0 -0
  138. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_pipeline_graph_expressions.py +0 -0
  139. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_quantumGraph.py +0 -0
  140. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_quantum_provenance_graph.py +0 -0
  141. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_quantum_success_caveats.py +0 -0
  142. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_struct.py +0 -0
  143. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_task.py +0 -0
  144. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_taskmetadata.py +0 -0
  145. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_testUtils.py +0 -0
  146. {lsst_pipe_base-29.2025.2100 → lsst_pipe_base-29.2025.2400}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-pipe-base
3
- Version: 29.2025.2100
3
+ Version: 29.2025.2400
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
@@ -677,7 +677,7 @@ class TaskMetadata(BaseModel):
677
677
  return super().model_copy(*args, **kwargs)
678
678
 
679
679
  @classmethod
680
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc]
680
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc, override]
681
681
  """See `pydantic.BaseModel.model_construct`."""
682
682
  return super().model_construct(*args, **kwargs)
683
683
 
@@ -66,7 +66,7 @@ class QgraphTaskSummary(pydantic.BaseModel):
66
66
  return super().model_copy(*args, **kwargs)
67
67
 
68
68
  @classmethod
69
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any:
69
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[override]
70
70
  """See `pydantic.BaseModel.model_construct`."""
71
71
  return super().model_construct(*args, **kwargs)
72
72
 
@@ -121,7 +121,7 @@ class QgraphSummary(pydantic.BaseModel):
121
121
  return super().model_copy(*args, **kwargs)
122
122
 
123
123
  @classmethod
124
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any:
124
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[override]
125
125
  """See `pydantic.BaseModel.model_construct`."""
126
126
  return super().model_construct(*args, **kwargs)
127
127
 
@@ -60,12 +60,13 @@ class DatasetTypeNode:
60
60
  """
61
61
 
62
62
  dataset_type: DatasetType
63
- """Common definition of this dataset type for the graph.
63
+ """Common definition of this dataset type for the graph
64
+ (`~lsst.daf.butler.DatasetType`).
64
65
  """
65
66
 
66
67
  is_initial_query_constraint: bool
67
68
  """Whether this dataset should be included as a constraint in the initial
68
- query for data IDs in QuantumGraph generation.
69
+ query for data IDs in QuantumGraph generation (`bool`).
69
70
 
70
71
  This is only `True` for dataset types that are overall regular inputs, and
71
72
  only if none of those input connections had ``deferQueryConstraint=True``.
@@ -73,14 +74,16 @@ class DatasetTypeNode:
73
74
 
74
75
  is_prerequisite: bool
75
76
  """Whether this dataset type is a prerequisite input that must exist in
76
- the Registry before graph creation.
77
+ the Registry before graph creation (`bool`).
77
78
  """
78
79
 
79
80
  producing_edge: WriteEdge | None
80
- """The edge to the task that produces this dataset type."""
81
+ """The edge to the task that produces this dataset type
82
+ (`lsst.pipe.base.pipeline_graph.WriteEdge` or `None`)."""
81
83
 
82
84
  consuming_edges: Collection[ReadEdge]
83
- """The edges to tasks that consume this dataset type."""
85
+ """The edges to tasks that consume this dataset type
86
+ (collection [`lsst.pipe.base.pipeline_graph.ReadEdge`])."""
84
87
 
85
88
  @classmethod
86
89
  def _from_edges(
@@ -184,7 +187,7 @@ class DatasetTypeNode:
184
187
 
185
188
  @property
186
189
  def name(self) -> str:
187
- """Name of the dataset type.
190
+ """Name of the dataset type (`str`).
188
191
 
189
192
  This is always the parent dataset type, never that of a component.
190
193
  """
@@ -193,29 +196,33 @@ class DatasetTypeNode:
193
196
  @property
194
197
  def key(self) -> NodeKey:
195
198
  """Key that identifies this dataset type in internal and exported
196
- networkx graphs.
199
+ networkx graphs (`~lsst.pipe.base.pipeline_graph.NodeKey`).
197
200
  """
198
201
  return NodeKey(NodeType.DATASET_TYPE, self.dataset_type.name)
199
202
 
200
203
  @property
201
204
  def dimensions(self) -> DimensionGroup:
202
- """Dimensions of the dataset type."""
205
+ """Dimensions of the dataset type
206
+ (`~lsst.daf.butler.DimensionGroup`).
207
+ """
203
208
  return self.dataset_type.dimensions
204
209
 
205
210
  @property
206
211
  def storage_class_name(self) -> str:
207
- """String name of the storage class for this dataset type."""
212
+ """String name of the storage class for this dataset type (`str`)."""
208
213
  return self.dataset_type.storageClass_name
209
214
 
210
215
  @property
211
216
  def storage_class(self) -> StorageClass:
212
- """Storage class for this dataset type."""
217
+ """Storage class for this dataset type
218
+ (`~lsst.daf.butler.StorageClass`).
219
+ """
213
220
  return self.dataset_type.storageClass
214
221
 
215
222
  @property
216
223
  def is_calibration(self) -> bool:
217
224
  """Whether this dataset type can be included in
218
- `~lsst.daf.butler.CollectionType.CALIBRATION` collections.
225
+ `~lsst.daf.butler.CollectionType.CALIBRATION` collections (`bool`).
219
226
  """
220
227
  return self.dataset_type.isCalibration()
221
228
 
@@ -90,16 +90,16 @@ class Edge(ABC):
90
90
  """
91
91
 
92
92
  task_key: NodeKey
93
- """Task part of the key for this edge in networkx graphs."""
93
+ """Task part of the key for this edge in networkx graphs (`NodeKey`)."""
94
94
 
95
95
  dataset_type_key: NodeKey
96
- """Task part of the key for this edge in networkx graphs."""
96
+ """Task part of the key for this edge in networkx graphs (`NodeKey`)."""
97
97
 
98
98
  connection_name: str
99
- """Name used by the task to refer to this dataset type."""
99
+ """Name used by the task to refer to this dataset type (`str`)."""
100
100
 
101
101
  storage_class_name: str
102
- """Storage class expected by this task.
102
+ """Storage class expected by this task (`str`).
103
103
 
104
104
  If `ReadEdge.component` is not `None`, this is the component storage class,
105
105
  not the parent storage class.
@@ -111,7 +111,7 @@ class Edge(ABC):
111
111
  """
112
112
 
113
113
  raw_dimensions: frozenset[str]
114
- """Raw dimensions in the task declaration.
114
+ """Raw dimensions in the task declaration (`frozenset` [`str`]).
115
115
 
116
116
  This can only be used safely for partial comparisons: two edges with the
117
117
  same ``raw_dimensions`` (and the same parent dataset type name) always have
@@ -128,12 +128,12 @@ class Edge(ABC):
128
128
 
129
129
  @property
130
130
  def task_label(self) -> str:
131
- """Label of the task."""
131
+ """Label of the task (`str`)."""
132
132
  return str(self.task_key)
133
133
 
134
134
  @property
135
135
  def parent_dataset_type_name(self) -> str:
136
- """Name of the parent dataset type.
136
+ """Name of the parent dataset type (`str`).
137
137
 
138
138
  All dataset type nodes in a pipeline graph are for parent dataset
139
139
  types; components are represented by additional `ReadEdge` state.
@@ -154,7 +154,9 @@ class Edge(ABC):
154
154
  @property
155
155
  def key(self) -> tuple[NodeKey, NodeKey, str]:
156
156
  """Ordered tuple of node keys and connection name that uniquely
157
- identifies this edge in a pipeline graph.
157
+ identifies this edge in a pipeline graph (`NodeKey`, `NodeKey`, `str`).
158
+
159
+ The nodes are ordered in the same sense as for `nodes`.
158
160
  """
159
161
  return self.nodes + (self.connection_name,)
160
162
 
@@ -163,7 +165,7 @@ class Edge(ABC):
163
165
 
164
166
  @property
165
167
  def dataset_type_name(self) -> str:
166
- """Dataset type name seen by the task.
168
+ """Dataset type name seen by the task (`str`).
167
169
 
168
170
  This defaults to the parent dataset type name, which is appropriate
169
171
  for all writes and most reads.
@@ -355,7 +357,7 @@ class ReadEdge(Edge):
355
357
 
356
358
  component: str | None
357
359
  """Component to add to `parent_dataset_type_name` to form the dataset type
358
- name seen by this task.
360
+ name seen by this task (`str` or `None`).
359
361
  """
360
362
 
361
363
  is_prerequisite: bool
@@ -378,7 +380,7 @@ class ReadEdge(Edge):
378
380
 
379
381
  @property
380
382
  def dataset_type_name(self) -> str:
381
- """Complete dataset type name, as seen by the task."""
383
+ """Complete dataset type name, as seen by the task (`str`)."""
382
384
  if self.component is not None:
383
385
  return f"{self.parent_dataset_type_name}.{self.component}"
384
386
  return self.parent_dataset_type_name
@@ -1546,7 +1546,7 @@ class PipelineGraph:
1546
1546
 
1547
1547
  - the parent dataset type name;
1548
1548
  - the resolved `DatasetTypeNode`, or `None` if the dataset type has
1549
- - not been resolved.
1549
+ not been resolved.
1550
1550
  """
1551
1551
  for generation in networkx.algorithms.dag.topological_generations(self._xgraph):
1552
1552
  key: NodeKey
@@ -27,11 +27,17 @@
27
27
 
28
28
  __all__ = ["transfer_from_graph"]
29
29
 
30
+ import math
31
+
30
32
  from lsst.daf.butler import Butler, CollectionType, QuantumBackedButler, Registry
31
33
  from lsst.daf.butler.registry import MissingCollectionError
32
34
  from lsst.pipe.base import QuantumGraph
35
+ from lsst.utils.iteration import chunk_iterable
36
+ from lsst.utils.logging import getLogger
37
+
38
+ from .utils import filter_by_dataset_type_glob, filter_by_existence
33
39
 
34
- from .utils import filter_by_dataset_type_glob
40
+ _LOG = getLogger(__name__)
35
41
 
36
42
 
37
43
  def transfer_from_graph(
@@ -92,18 +98,31 @@ def transfer_from_graph(
92
98
 
93
99
  # Filter the refs based on requested dataset types.
94
100
  filtered_refs = filter_by_dataset_type_glob(output_refs, dataset_type)
101
+ _LOG.verbose("After filtering by dataset_type, number of datasets to transfer: %d", len(filtered_refs))
95
102
 
96
103
  dest_butler = Butler.from_config(dest, writeable=True)
97
104
 
98
- transferred = dest_butler.transfer_from(
99
- qbb,
100
- filtered_refs,
101
- transfer="auto",
102
- register_dataset_types=register_dataset_types,
103
- transfer_dimensions=transfer_dimensions,
104
- dry_run=dry_run,
105
- )
106
- count = len(transferred)
105
+ # For faster restarts, filter out those the destination already knows.
106
+ filtered_refs = filter_by_existence(dest_butler, filtered_refs)
107
+
108
+ # Transfer in chunks
109
+ chunk_size = 50_000
110
+ n_chunks = math.ceil(len(filtered_refs) / chunk_size)
111
+ chunk_num = 0
112
+ count = 0
113
+ for chunk in chunk_iterable(filtered_refs, chunk_size=chunk_size):
114
+ chunk_num += 1
115
+ if n_chunks > 1:
116
+ _LOG.verbose("Transferring %d datasets in chunk %d/%d", len(chunk), chunk_num, n_chunks)
117
+ transferred = dest_butler.transfer_from(
118
+ qbb,
119
+ chunk,
120
+ transfer="auto",
121
+ register_dataset_types=register_dataset_types,
122
+ transfer_dimensions=transfer_dimensions,
123
+ dry_run=dry_run,
124
+ )
125
+ count += len(transferred)
107
126
 
108
127
  # If anything was transferred then update output chain definition if asked.
109
128
  if count > 0 and update_output_chain and (metadata := qgraph.metadata) is not None:
@@ -27,15 +27,17 @@
27
27
 
28
28
  from __future__ import annotations
29
29
 
30
- __all__ = [
31
- "filter_by_dataset_type_glob",
32
- ]
30
+ __all__ = ["filter_by_dataset_type_glob", "filter_by_existence"]
33
31
 
34
32
  import re
35
33
  from collections.abc import Collection
36
34
 
37
- from lsst.daf.butler import DatasetRef
35
+ from lsst.daf.butler import Butler, DatasetRef
38
36
  from lsst.daf.butler.utils import globToRegex
37
+ from lsst.utils.logging import getLogger
38
+ from lsst.utils.timer import time_this
39
+
40
+ _LOG = getLogger(__name__)
39
41
 
40
42
 
41
43
  def _matches_dataset_type(dataset_type_name: str, regexes: list[str | re.Pattern]) -> bool:
@@ -72,3 +74,30 @@ def filter_by_dataset_type_glob(
72
74
  return refs
73
75
 
74
76
  return {ref for ref in refs if _matches_dataset_type(ref.datasetType.name, regexes)}
77
+
78
+
79
+ def filter_by_existence(butler: Butler, refs: Collection[DatasetRef]) -> Collection[DatasetRef]:
80
+ """Filter out the refs that the butler already knows exist.
81
+
82
+ Parameters
83
+ ----------
84
+ butler : `lsst.daf.butler.Butler`
85
+ Butler in which to check existence of given datarefs.
86
+ refs : `collections.abc.Collection` [ `lsst.daf.butler.DatasetRef` ]
87
+ Datasets to be filtered.
88
+
89
+ Returns
90
+ -------
91
+ filtered : `collections.abc.Collection` [ `lsst.daf.butler.DatasetRef` ]
92
+ Filter datasets.
93
+ """
94
+ _LOG.verbose("Filtering out datasets already known to the target butler...")
95
+ with time_this(log=_LOG, msg="Completed checking existence"):
96
+ existence = butler._datastore.knows_these(refs)
97
+ filtered = [ref for ref in existence if not existence[ref]]
98
+ _LOG.verbose(
99
+ "After filtering out those already in the target butler, number of datasets to transfer: %d",
100
+ len(filtered),
101
+ )
102
+
103
+ return filtered
@@ -227,7 +227,7 @@ class MockDataset(pydantic.BaseModel):
227
227
  return super().model_copy(*args, **kwargs)
228
228
 
229
229
  @classmethod
230
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any:
230
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[override]
231
231
  """See `pydantic.BaseModel.model_construct`."""
232
232
  return super().model_construct(*args, **kwargs)
233
233
 
@@ -266,7 +266,7 @@ class ConvertedUnmockedDataset(pydantic.BaseModel):
266
266
  return super().model_copy(*args, **kwargs)
267
267
 
268
268
  @classmethod
269
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc]
269
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc, override]
270
270
  """See `pydantic.BaseModel.model_construct`."""
271
271
  return super().model_construct(*args, **kwargs)
272
272
 
@@ -316,7 +316,7 @@ class MockDatasetQuantum(pydantic.BaseModel):
316
316
  return super().model_copy(*args, **kwargs)
317
317
 
318
318
  @classmethod
319
- def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc]
319
+ def model_construct(cls, *args: Any, **kwargs: Any) -> Any: # type: ignore[misc, override]
320
320
  """See `pydantic.BaseModel.model_construct`."""
321
321
  return super().model_construct(*args, **kwargs)
322
322
 
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "29.2025.2400"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-pipe-base
3
- Version: 29.2025.2100
3
+ Version: 29.2025.2400
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
@@ -136,6 +136,7 @@ tests/test_pipeline_graph_expressions.py
136
136
  tests/test_quantumGraph.py
137
137
  tests/test_quantum_provenance_graph.py
138
138
  tests/test_quantum_success_caveats.py
139
+ tests/test_script_utils.py
139
140
  tests/test_struct.py
140
141
  tests/test_task.py
141
142
  tests/test_taskmetadata.py
@@ -0,0 +1,62 @@
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
+ # (https://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 <https://www.gnu.org/licenses/>.
27
+
28
+ """Tests for scripts/utils.py functions."""
29
+
30
+ import logging
31
+ import unittest
32
+
33
+ from lsst.pipe.base.script.utils import filter_by_existence
34
+
35
+
36
+ class FilterByExistenceTestCase(unittest.TestCase):
37
+ """Test filter_by_existence function."""
38
+
39
+ def setUp(self):
40
+ # Currently function itself does not need real DatasetRefs.
41
+ # Only the butler calls requires DatasetRefs, but butler
42
+ # is being mocked in these tests. So using strings in place
43
+ # of DatasetRefs.
44
+ self.orig_refs = [f"{i:05}" for i in range(1, 11)]
45
+ self.mock_exists = {}
46
+ for i in range(1, 11):
47
+ self.mock_exists[f"{i:05}"] = True if i % 3 == 0 else False
48
+ self.filtered_refs = [f"{i:05}" for i in range(1, 11) if i % 3 != 0]
49
+
50
+ def test_success(self):
51
+ butler_mock = unittest.mock.Mock()
52
+ butler_mock._datastore.knows_these.return_value = self.mock_exists
53
+ with self.assertLogs(logging.getLogger("lsst.pipe.base"), level="VERBOSE") as cm:
54
+ filtered = filter_by_existence(butler_mock, self.orig_refs)
55
+ self.assertCountEqual(self.filtered_refs, filtered)
56
+ log_messages = " ".join(cm.output)
57
+ self.assertIn("Filtering out datasets already known to the target butler", log_messages)
58
+ self.assertIn("number of datasets to transfer", log_messages)
59
+
60
+
61
+ if __name__ == "__main__":
62
+ unittest.main()
@@ -1,2 +0,0 @@
1
- __all__ = ["__version__"]
2
- __version__ = "29.2025.2100"