lsst-daf-butler 30.2026.100__tar.gz → 30.2026.300__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 (440) hide show
  1. {lsst_daf_butler-30.2026.100/python/lsst_daf_butler.egg-info → lsst_daf_butler-30.2026.300}/PKG-INFO +1 -1
  2. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler.py +8 -5
  3. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler_metrics.py +49 -2
  4. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_labeled_butler_factory.py +28 -8
  5. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/datastores/formatters.yaml +1 -0
  6. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/storageClasses.yaml +15 -0
  7. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_coordinate.py +5 -0
  8. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_butler/_direct_butler.py +45 -28
  9. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/logging.py +9 -3
  10. lsst_daf_butler-30.2026.300/python/lsst/daf/butler/registry/expand_data_ids.py +93 -0
  11. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/sql_registry.py +2 -24
  12. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_remote_butler.py +5 -1
  13. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/hybrid_butler.py +4 -1
  14. lsst_daf_butler-30.2026.300/python/lsst/daf/butler/tests/registry_data/lsstcam-subset.yaml +191 -0
  15. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/transfers/_context.py +7 -6
  16. lsst_daf_butler-30.2026.300/python/lsst/daf/butler/version.py +2 -0
  17. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300/python/lsst_daf_butler.egg-info}/PKG-INFO +1 -1
  18. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/SOURCES.txt +2 -0
  19. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_butler.py +98 -1
  20. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_butler_factory.py +11 -7
  21. lsst_daf_butler-30.2026.100/python/lsst/daf/butler/version.py +0 -2
  22. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/COPYRIGHT +0 -0
  23. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/LICENSE +0 -0
  24. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/MANIFEST.in +0 -0
  25. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/README.md +0 -0
  26. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/bsd_license.txt +0 -0
  27. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/CHANGES.rst +0 -0
  28. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/concreteStorageClasses.rst +0 -0
  29. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/configuring.rst +0 -0
  30. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/datastores.rst +0 -0
  31. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/dimensions.rst +0 -0
  32. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/formatters.rst +0 -0
  33. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/index.rst +0 -0
  34. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/organizing.rst +0 -0
  35. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/queries.rst +0 -0
  36. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/use-in-tests.rst +0 -0
  37. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/doc/lsst.daf.butler/writing-subcommands.rst +0 -0
  38. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/gpl-v3.0.txt +0 -0
  39. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/pyproject.toml +0 -0
  40. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/__init__.py +0 -0
  41. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/__init__.py +0 -0
  42. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/__init__.py +0 -0
  43. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler_collections.py +0 -0
  44. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler_config.py +0 -0
  45. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler_instance_options.py +0 -0
  46. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_butler_repo_index.py +0 -0
  47. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_collection_type.py +0 -0
  48. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_config.py +0 -0
  49. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_config_support.py +0 -0
  50. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_dataset_association.py +0 -0
  51. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_dataset_existence.py +0 -0
  52. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_dataset_provenance.py +0 -0
  53. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_dataset_ref.py +0 -0
  54. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_dataset_type.py +0 -0
  55. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_deferredDatasetHandle.py +0 -0
  56. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_exceptions.py +0 -0
  57. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_exceptions_legacy.py +0 -0
  58. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_file_dataset.py +0 -0
  59. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_file_descriptor.py +0 -0
  60. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_formatter.py +0 -0
  61. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_limited_butler.py +0 -0
  62. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_location.py +0 -0
  63. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_named.py +0 -0
  64. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_quantum.py +0 -0
  65. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_quantum_backed.py +0 -0
  66. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_query_all_datasets.py +0 -0
  67. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_registry_shim.py +0 -0
  68. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_rubin/__init__.py +0 -0
  69. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_rubin/file_datasets.py +0 -0
  70. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_rubin/temporary_for_ingest.py +0 -0
  71. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_standalone_datastore.py +0 -0
  72. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_storage_class.py +0 -0
  73. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_storage_class_delegate.py +0 -0
  74. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_timespan.py +0 -0
  75. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_topology.py +0 -0
  76. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_utilities/__init__.py +0 -0
  77. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_utilities/locked_object.py +0 -0
  78. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_utilities/named_locks.py +0 -0
  79. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_utilities/thread_safe_cache.py +0 -0
  80. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/_uuid.py +0 -0
  81. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/arrow_utils.py +0 -0
  82. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/__init__.py +0 -0
  83. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/butler.py +0 -0
  84. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/cliLog.py +0 -0
  85. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/cmd/__init__.py +0 -0
  86. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/cmd/_remove_collections.py +0 -0
  87. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/cmd/_remove_runs.py +0 -0
  88. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/cmd/commands.py +0 -0
  89. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/opt/__init__.py +0 -0
  90. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/opt/arguments.py +0 -0
  91. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/opt/optionGroups.py +0 -0
  92. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/opt/options.py +0 -0
  93. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/progress.py +0 -0
  94. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/cli/utils.py +0 -0
  95. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/column_spec.py +0 -0
  96. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/datastore.yaml +0 -0
  97. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/datastores/composites.yaml +0 -0
  98. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/datastores/fileDatastore.yaml +0 -0
  99. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/datastores/writeRecipes.yaml +0 -0
  100. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/dimensions.yaml +0 -0
  101. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe0.yaml +0 -0
  102. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe1.yaml +0 -0
  103. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe2.yaml +0 -0
  104. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe3.yaml +0 -0
  105. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe4.yaml +0 -0
  106. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe5.yaml +0 -0
  107. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe6.yaml +0 -0
  108. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe7.yaml +0 -0
  109. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/registry.yaml +0 -0
  110. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/configs/repo_transfer_formats.yaml +0 -0
  111. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/__init__.py +0 -0
  112. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/_datastore.py +0 -0
  113. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/_transfer.py +0 -0
  114. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/cache_manager.py +0 -0
  115. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/composites.py +0 -0
  116. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/constraints.py +0 -0
  117. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/file_templates.py +0 -0
  118. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/generic_base.py +0 -0
  119. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/record_data.py +0 -0
  120. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastore/stored_file_info.py +0 -0
  121. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/__init__.py +0 -0
  122. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/chainedDatastore.py +0 -0
  123. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/fileDatastore.py +0 -0
  124. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/file_datastore/__init__.py +0 -0
  125. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/file_datastore/get.py +0 -0
  126. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/file_datastore/retrieve_artifacts.py +0 -0
  127. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/file_datastore/transfer.py +0 -0
  128. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/datastores/inMemoryDatastore.py +0 -0
  129. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/ddl.py +0 -0
  130. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/delegates/__init__.py +0 -0
  131. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/delegates/arrowtable.py +0 -0
  132. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/__init__.py +0 -0
  133. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_config.py +0 -0
  134. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_data_coordinate_iterable.py +0 -0
  135. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_database.py +0 -0
  136. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_elements.py +0 -0
  137. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_governor.py +0 -0
  138. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_group.py +0 -0
  139. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_packer.py +0 -0
  140. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_record_set.py +0 -0
  141. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_record_table.py +0 -0
  142. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_records.py +0 -0
  143. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_schema.py +0 -0
  144. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_skypix.py +0 -0
  145. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/_universe.py +0 -0
  146. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/construction.py +0 -0
  147. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/dimensions/record_cache.py +0 -0
  148. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_butler/__init__.py +0 -0
  149. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_butler/_direct_butler_collections.py +0 -0
  150. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/__init__.py +0 -0
  151. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_driver.py +0 -0
  152. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_postprocessing.py +0 -0
  153. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_query_analysis.py +0 -0
  154. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_query_builder.py +0 -0
  155. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_result_page_converter.py +0 -0
  156. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_sql_builders.py +0 -0
  157. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/direct_query_driver/_sql_column_visitor.py +0 -0
  158. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/__init__.py +0 -0
  159. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/astropyTable.py +0 -0
  160. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/file.py +0 -0
  161. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/json.py +0 -0
  162. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/logs.py +0 -0
  163. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/matplotlib.py +0 -0
  164. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/packages.py +0 -0
  165. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/parquet.py +0 -0
  166. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/pickle.py +0 -0
  167. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/typeless.py +0 -0
  168. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/formatters/yaml.py +0 -0
  169. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/json.py +0 -0
  170. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/mapping_factory.py +0 -0
  171. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/name_shrinker.py +0 -0
  172. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/nonempty_mapping.py +0 -0
  173. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/persistence_context.py +0 -0
  174. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/progress.py +0 -0
  175. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/py.typed +0 -0
  176. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/pydantic_utils.py +0 -0
  177. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/__init__.py +0 -0
  178. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_base.py +0 -0
  179. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_data_coordinate_query_results.py +0 -0
  180. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_dataset_query_results.py +0 -0
  181. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_dimension_record_query_results.py +0 -0
  182. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_expression_strings.py +0 -0
  183. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_general_query_results.py +0 -0
  184. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_identifiers.py +0 -0
  185. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/_query.py +0 -0
  186. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/convert_args.py +0 -0
  187. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/driver.py +0 -0
  188. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expression_factory.py +0 -0
  189. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/__init__.py +0 -0
  190. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/categorize.py +0 -0
  191. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/__init__.py +0 -0
  192. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/exprTree.py +0 -0
  193. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/parser.py +0 -0
  194. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/parserLex.py +0 -0
  195. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/parserYacc.py +0 -0
  196. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/ply/__init__.py +0 -0
  197. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/ply/lex.py +0 -0
  198. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/ply/yacc.py +0 -0
  199. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/expressions/parser/treeVisitor.py +0 -0
  200. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/overlaps.py +0 -0
  201. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/predicate_constraints_summary.py +0 -0
  202. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/result_specs.py +0 -0
  203. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/__init__.py +0 -0
  204. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_base.py +0 -0
  205. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_column_expression.py +0 -0
  206. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_column_literal.py +0 -0
  207. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_column_reference.py +0 -0
  208. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_column_set.py +0 -0
  209. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_predicate.py +0 -0
  210. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/tree/_query_tree.py +0 -0
  211. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/queries/visitors.py +0 -0
  212. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/__init__.py +0 -0
  213. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_caching_context.py +0 -0
  214. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_collection_record_cache.py +0 -0
  215. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_collection_summary.py +0 -0
  216. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_collection_summary_cache.py +0 -0
  217. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_config.py +0 -0
  218. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_defaults.py +0 -0
  219. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_exceptions.py +0 -0
  220. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_registry.py +0 -0
  221. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_registry_base.py +0 -0
  222. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/_registry_factory.py +0 -0
  223. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/attributes.py +0 -0
  224. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/bridge/__init__.py +0 -0
  225. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/bridge/ephemeral.py +0 -0
  226. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/bridge/monolithic.py +0 -0
  227. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/collections/__init__.py +0 -0
  228. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/collections/_base.py +0 -0
  229. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/collections/nameKey.py +0 -0
  230. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/collections/synthIntKey.py +0 -0
  231. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/connectionString.py +0 -0
  232. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/databases/__init__.py +0 -0
  233. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/databases/postgresql.py +0 -0
  234. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/databases/sqlite.py +0 -0
  235. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/__init__.py +0 -0
  236. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/byDimensions/__init__.py +0 -0
  237. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/byDimensions/_dataset_type_cache.py +0 -0
  238. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/byDimensions/_manager.py +0 -0
  239. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/byDimensions/summaries.py +0 -0
  240. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/datasets/byDimensions/tables.py +0 -0
  241. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/dimensions/__init__.py +0 -0
  242. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/dimensions/static.py +0 -0
  243. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/__init__.py +0 -0
  244. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_attributes.py +0 -0
  245. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_bridge.py +0 -0
  246. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_collections.py +0 -0
  247. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_database.py +0 -0
  248. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_database_explain.py +0 -0
  249. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_datasets.py +0 -0
  250. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_dimensions.py +0 -0
  251. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_obscore.py +0 -0
  252. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_opaque.py +0 -0
  253. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/interfaces/_versioning.py +0 -0
  254. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/managers.py +0 -0
  255. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/nameShrinker.py +0 -0
  256. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/__init__.py +0 -0
  257. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/_config.py +0 -0
  258. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/_manager.py +0 -0
  259. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/_records.py +0 -0
  260. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/_schema.py +0 -0
  261. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/_spatial.py +0 -0
  262. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/default_spatial.py +0 -0
  263. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/obscore/pgsphere.py +0 -0
  264. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/opaque.py +0 -0
  265. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/__init__.py +0 -0
  266. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/_query_common.py +0 -0
  267. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/_query_data_coordinates.py +0 -0
  268. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/_query_datasets.py +0 -0
  269. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/_query_dimension_records.py +0 -0
  270. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/queries/_results.py +0 -0
  271. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/tests/__init__.py +0 -0
  272. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/tests/_database.py +0 -0
  273. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/tests/_registry.py +0 -0
  274. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/versions.py +0 -0
  275. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/registry/wildcards.py +0 -0
  276. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/__init__.py +0 -0
  277. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_collection_args.py +0 -0
  278. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_config.py +0 -0
  279. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_defaults.py +0 -0
  280. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_errors.py +0 -0
  281. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_factory.py +0 -0
  282. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_get.py +0 -0
  283. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_http_connection.py +0 -0
  284. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_query_driver.py +0 -0
  285. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_query_results.py +0 -0
  286. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_ref_utils.py +0 -0
  287. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_registry.py +0 -0
  288. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_remote_butler_collections.py +0 -0
  289. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/_remote_file_transfer_source.py +0 -0
  290. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/authentication/__init__.py +0 -0
  291. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/authentication/cadc.py +0 -0
  292. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/authentication/interface.py +0 -0
  293. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/authentication/rubin.py +0 -0
  294. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/registry/__init__.py +0 -0
  295. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/__init__.py +0 -0
  296. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_config.py +0 -0
  297. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_dependencies.py +0 -0
  298. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_factory.py +0 -0
  299. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_gafaelfawr.py +0 -0
  300. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_server.py +0 -0
  301. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/_telemetry.py +0 -0
  302. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_external.py +0 -0
  303. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_external_query.py +0 -0
  304. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_file_info.py +0 -0
  305. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_internal.py +0 -0
  306. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_query_limits.py +0 -0
  307. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_query_serialization.py +0 -0
  308. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_query_streaming.py +0 -0
  309. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server/handlers/_utils.py +0 -0
  310. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/remote_butler/server_models.py +0 -0
  311. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/repo_relocation.py +0 -0
  312. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/__init__.py +0 -0
  313. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/_associate.py +0 -0
  314. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/_pruneDatasets.py +0 -0
  315. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/butlerImport.py +0 -0
  316. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/certifyCalibrations.py +0 -0
  317. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/collectionChain.py +0 -0
  318. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/configDump.py +0 -0
  319. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/configValidate.py +0 -0
  320. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/createRepo.py +0 -0
  321. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/exportCalibs.py +0 -0
  322. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/ingest_files.py +0 -0
  323. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/ingest_zip.py +0 -0
  324. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/queryCollections.py +0 -0
  325. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/queryDataIds.py +0 -0
  326. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/queryDatasetTypes.py +0 -0
  327. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/queryDatasets.py +0 -0
  328. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/queryDimensionRecords.py +0 -0
  329. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/register_dataset_type.py +0 -0
  330. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/removeCollections.py +0 -0
  331. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/removeDatasetType.py +0 -0
  332. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/removeRuns.py +0 -0
  333. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/retrieveArtifacts.py +0 -0
  334. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/script/transferDatasets.py +0 -0
  335. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/__init__.py +0 -0
  336. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/_datasetsHelper.py +0 -0
  337. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/_dummyRegistry.py +0 -0
  338. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/_examplePythonTypes.py +0 -0
  339. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/_testRepo.py +0 -0
  340. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/butler_queries.py +0 -0
  341. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/cliCmdTestBase.py +0 -0
  342. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/cliLogTestBase.py +0 -0
  343. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/deferredFormatter.py +0 -0
  344. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/dict_convertible_model.py +0 -0
  345. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/hybrid_butler_collections.py +0 -0
  346. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/hybrid_butler_registry.py +0 -0
  347. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/postgresql.py +0 -0
  348. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/__init__.py +0 -0
  349. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/base.yaml +0 -0
  350. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset-skymap.yaml +0 -0
  351. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset.yaml +0 -0
  352. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/datasets.yaml +0 -0
  353. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/hsc-rc2-subset-v0.yaml +0 -0
  354. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/spatial.py +0 -0
  355. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/registry_data/spatial.yaml +0 -0
  356. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/server.py +0 -0
  357. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/server_available.py +0 -0
  358. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/server_utils.py +0 -0
  359. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/testFormatters.py +0 -0
  360. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/tests/utils.py +0 -0
  361. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/time_utils.py +0 -0
  362. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/timespan_database_representation.py +0 -0
  363. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/transfers/__init__.py +0 -0
  364. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/transfers/_interfaces.py +0 -0
  365. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/transfers/_yaml.py +0 -0
  366. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst/daf/butler/utils.py +0 -0
  367. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/dependency_links.txt +0 -0
  368. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/entry_points.txt +0 -0
  369. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/requires.txt +0 -0
  370. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/top_level.txt +0 -0
  371. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/python/lsst_daf_butler.egg-info/zip-safe +0 -0
  372. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/setup.cfg +0 -0
  373. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_astropyTableFormatter.py +0 -0
  374. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_authentication.py +0 -0
  375. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdAssociate.py +0 -0
  376. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdConfigDump.py +0 -0
  377. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdConfigValidate.py +0 -0
  378. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdCreate.py +0 -0
  379. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdImport.py +0 -0
  380. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdIngestFiles.py +0 -0
  381. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdPruneDatasets.py +0 -0
  382. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdQueryCollections.py +0 -0
  383. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdQueryDataIds.py +0 -0
  384. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdQueryDatasetTypes.py +0 -0
  385. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdQueryDatasets.py +0 -0
  386. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdQueryDimensionRecords.py +0 -0
  387. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdRemoveCollections.py +0 -0
  388. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdRemoveRuns.py +0 -0
  389. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliCmdRetrieveArtifacts.py +0 -0
  390. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliLog.py +0 -0
  391. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliPluginLoader.py +0 -0
  392. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliUtilSplitCommas.py +0 -0
  393. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliUtilSplitKv.py +0 -0
  394. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliUtilToUpper.py +0 -0
  395. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_cliUtils.py +0 -0
  396. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_column_spec.py +0 -0
  397. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_composites.py +0 -0
  398. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_config.py +0 -0
  399. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_connectionString.py +0 -0
  400. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_constraints.py +0 -0
  401. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_datasets.py +0 -0
  402. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_datastore.py +0 -0
  403. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_ddl.py +0 -0
  404. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_dimension_record_containers.py +0 -0
  405. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_dimensions.py +0 -0
  406. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_exprParserLex.py +0 -0
  407. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_exprParserYacc.py +0 -0
  408. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_formatter.py +0 -0
  409. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_gafaelfawr.py +0 -0
  410. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_location.py +0 -0
  411. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_logFormatter.py +0 -0
  412. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_logging.py +0 -0
  413. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_matplotlibFormatter.py +0 -0
  414. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_nonempty_mapping.py +0 -0
  415. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_obscore.py +0 -0
  416. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_packages.py +0 -0
  417. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_parquet.py +0 -0
  418. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_postgresql.py +0 -0
  419. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_progress.py +0 -0
  420. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_pydantic_utils.py +0 -0
  421. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_quantum.py +0 -0
  422. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_quantumBackedButler.py +0 -0
  423. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_query_direct_postgresql.py +0 -0
  424. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_query_direct_sqlite.py +0 -0
  425. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_query_interface.py +0 -0
  426. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_query_remote.py +0 -0
  427. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_query_utilities.py +0 -0
  428. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_remote_butler.py +0 -0
  429. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_server.py +0 -0
  430. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_simpleButler.py +0 -0
  431. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_sqlite.py +0 -0
  432. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_storageClass.py +0 -0
  433. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_templates.py +0 -0
  434. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_testRepo.py +0 -0
  435. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_thread_utils.py +0 -0
  436. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_time_utils.py +0 -0
  437. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_timespan.py +0 -0
  438. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_utils.py +0 -0
  439. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_uuid.py +0 -0
  440. {lsst_daf_butler-30.2026.100 → lsst_daf_butler-30.2026.300}/tests/test_versioning.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-daf-butler
3
- Version: 30.2026.100
3
+ Version: 30.2026.300
4
4
  Summary: An abstraction layer for reading and writing astronomical data to datastores.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License-Expression: BSD-3-Clause OR GPL-3.0-or-later
@@ -1566,7 +1566,7 @@ class Butler(LimitedButler): # numpydoc ignore=PR02
1566
1566
 
1567
1567
  @abstractmethod
1568
1568
  def transfer_dimension_records_from(
1569
- self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef]
1569
+ self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef | DataCoordinate]
1570
1570
  ) -> None:
1571
1571
  """Transfer dimension records to this Butler from another Butler.
1572
1572
 
@@ -1578,10 +1578,9 @@ class Butler(LimitedButler): # numpydoc ignore=PR02
1578
1578
  `Butler` whose registry will be used to expand data IDs. If the
1579
1579
  source refs contain coordinates that are used to populate other
1580
1580
  records then this will also need to be a full `Butler`.
1581
- source_refs : iterable of `DatasetRef`
1582
- Datasets defined in the source butler whose dimension records
1583
- should be transferred to this butler. In most circumstances.
1584
- transfer is faster if the dataset refs are expanded.
1581
+ source_refs : iterable of `DatasetRef` or `DataCoordinate`
1582
+ Datasets or data IDs defined in the source butler whose dimension
1583
+ records should be transferred to this butler.
1585
1584
  """
1586
1585
  raise NotImplementedError()
1587
1586
 
@@ -2227,3 +2226,7 @@ class Butler(LimitedButler): # numpydoc ignore=PR02
2227
2226
  @abstractmethod
2228
2227
  def close(self) -> None:
2229
2228
  raise NotImplementedError()
2229
+
2230
+ @abstractmethod
2231
+ def _expand_data_ids(self, data_ids: Iterable[DataCoordinate]) -> list[DataCoordinate]:
2232
+ raise NotImplementedError()
@@ -29,12 +29,15 @@ from __future__ import annotations
29
29
 
30
30
  from collections.abc import Callable, Iterator
31
31
  from contextlib import contextmanager
32
+ from typing import Concatenate, ParamSpec
32
33
 
33
34
  from pydantic import BaseModel
34
35
 
35
36
  from lsst.utils.logging import LsstLoggers
36
37
  from lsst.utils.timer import time_this
37
38
 
39
+ P = ParamSpec("P")
40
+
38
41
 
39
42
  class ButlerMetrics(BaseModel):
40
43
  """Metrics collected during Butler operations."""
@@ -45,18 +48,26 @@ class ButlerMetrics(BaseModel):
45
48
  time_in_get: float = 0.0
46
49
  """Wall-clock time, in seconds, spent in get()."""
47
50
 
51
+ time_in_ingest: float = 0.0
52
+ """Wall-clock time, in seconds, spent in ingest()."""
53
+
48
54
  n_get: int = 0
49
55
  """Number of datasets retrieved with get()."""
50
56
 
51
57
  n_put: int = 0
52
58
  """Number of datasets stored with put()."""
53
59
 
60
+ n_ingest: int = 0
61
+ """Number of datasets ingested."""
62
+
54
63
  def reset(self) -> None:
55
64
  """Reset all metrics."""
56
65
  self.time_in_put = 0.0
57
66
  self.time_in_get = 0.0
67
+ self.time_in_ingest = 0.0
58
68
  self.n_get = 0
59
69
  self.n_put = 0
70
+ self.n_ingest = 0
60
71
 
61
72
  def increment_get(self, duration: float) -> None:
62
73
  """Increment time for get().
@@ -80,13 +91,31 @@ class ButlerMetrics(BaseModel):
80
91
  self.time_in_put += duration
81
92
  self.n_put += 1
82
93
 
94
+ def increment_ingest(self, duration: float, n_datasets: int) -> None:
95
+ """Increment time and datasets for ingest().
96
+
97
+ Parameters
98
+ ----------
99
+ duration : `float`
100
+ Duration to add to the ingest() statistics.
101
+ n_datasets : `int`
102
+ Number of datasets to be ingested for this call.
103
+ """
104
+ self.time_in_ingest += duration
105
+ self.n_ingest += n_datasets
106
+
83
107
  @contextmanager
84
108
  def _timer(
85
- self, handler: Callable[[float], None], log: LsstLoggers | None = None, msg: str | None = None
109
+ self,
110
+ handler: Callable[Concatenate[float, P], None],
111
+ log: LsstLoggers | None = None,
112
+ msg: str | None = None,
113
+ *args: P.args,
114
+ **kwargs: P.kwargs,
86
115
  ) -> Iterator[None]:
87
116
  with time_this(log=log, msg=msg) as timer:
88
117
  yield
89
- handler(timer.duration)
118
+ handler(timer.duration, *args, **kwargs)
90
119
 
91
120
  @contextmanager
92
121
  def instrument_get(self, log: LsstLoggers | None = None, msg: str | None = None) -> Iterator[None]:
@@ -115,3 +144,21 @@ class ButlerMetrics(BaseModel):
115
144
  """
116
145
  with self._timer(self.increment_put, log=log, msg=msg):
117
146
  yield
147
+
148
+ @contextmanager
149
+ def instrument_ingest(
150
+ self, n_datasets: int, log: LsstLoggers | None = None, msg: str | None = None
151
+ ) -> Iterator[None]:
152
+ """Run code and increment ingest statistics.
153
+
154
+ Parameters
155
+ ----------
156
+ n_datasets : `int`
157
+ Number of datasets being ingested.
158
+ log : `logging.Logger` or `None`
159
+ Logger to use for any timing information.
160
+ msg : `str` or `None`
161
+ Any message to be included in log output.
162
+ """
163
+ with self._timer(self.increment_ingest, n_datasets=n_datasets, log=log, msg=msg):
164
+ yield
@@ -30,7 +30,9 @@ from __future__ import annotations
30
30
  __all__ = ("LabeledButlerFactory", "LabeledButlerFactoryProtocol")
31
31
 
32
32
  from collections.abc import Mapping
33
- from typing import Protocol
33
+ from contextlib import AbstractContextManager
34
+ from logging import getLogger
35
+ from typing import Any, Literal, Protocol, Self
34
36
 
35
37
  from lsst.resources import ResourcePathExpression
36
38
 
@@ -40,6 +42,8 @@ from ._butler_repo_index import ButlerRepoIndex
40
42
  from ._utilities.named_locks import NamedLocks
41
43
  from ._utilities.thread_safe_cache import ThreadSafeCache
42
44
 
45
+ _LOG = getLogger(__name__)
46
+
43
47
 
44
48
  class LabeledButlerFactoryProtocol(Protocol):
45
49
  """Callable to retrieve a butler from a label."""
@@ -47,7 +51,7 @@ class LabeledButlerFactoryProtocol(Protocol):
47
51
  def __call__(self, label: str) -> Butler: ...
48
52
 
49
53
 
50
- class LabeledButlerFactory:
54
+ class LabeledButlerFactory(AbstractContextManager):
51
55
  """Factory for efficiently instantiating Butler instances from the
52
56
  repository index file. This is intended for use from long-lived services
53
57
  that want to instantiate a separate Butler instance for each end user
@@ -60,6 +64,9 @@ class LabeledButlerFactory:
60
64
  files. If not provided, defaults to the global repository index
61
65
  configured by the ``DAF_BUTLER_REPOSITORY_INDEX`` environment variable
62
66
  -- see `ButlerRepoIndex`.
67
+ writeable : `bool`, optional
68
+ If `True`, Butler instances created by this factory will be writeable.
69
+ If `False` (the default), instances will be read-only.
63
70
 
64
71
  Notes
65
72
  -----
@@ -76,11 +83,12 @@ class LabeledButlerFactory:
76
83
  safely be used by separate threads.
77
84
  """
78
85
 
79
- def __init__(self, repositories: Mapping[str, str] | None = None) -> None:
86
+ def __init__(self, repositories: Mapping[str, str] | None = None, writeable: bool = False) -> None:
80
87
  if repositories is None:
81
88
  self._repositories = None
82
89
  else:
83
90
  self._repositories = dict(repositories)
91
+ self._writeable = writeable
84
92
 
85
93
  self._factories = ThreadSafeCache[str, _ButlerFactory]()
86
94
  self._initialization_locks = NamedLocks()
@@ -88,6 +96,16 @@ class LabeledButlerFactory:
88
96
  # This may be overridden by unit tests.
89
97
  self._preload_unsafe_direct_butler_caches = True
90
98
 
99
+ def __enter__(self) -> Self:
100
+ return self
101
+
102
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Literal[False]:
103
+ try:
104
+ self.close()
105
+ except Exception:
106
+ _LOG.exception("An exception occurred during LabeledButlerFactory.close()")
107
+ return False
108
+
91
109
  def bind(self, access_token: str | None) -> LabeledButlerFactoryProtocol:
92
110
  """Create a callable factory function for generating Butler instances
93
111
  with out needing to specify access tokans again.
@@ -109,7 +127,7 @@ class LabeledButlerFactory:
109
127
 
110
128
  return create
111
129
 
112
- def create_butler(self, *, label: str, access_token: str | None) -> Butler:
130
+ def create_butler(self, label: str, *, access_token: str | None = None) -> Butler:
113
131
  """Create a Butler instance.
114
132
 
115
133
  Parameters
@@ -118,7 +136,7 @@ class LabeledButlerFactory:
118
136
  Label of the repository to instantiate, from the ``repositories``
119
137
  parameter to the `LabeledButlerFactory` constructor or the global
120
138
  repository index file.
121
- access_token : `str` | `None`
139
+ access_token : `str` | `None`, optional
122
140
  Gafaelfawr access token used to authenticate to a Butler server.
123
141
  This is required for any repositories configured to use
124
142
  `RemoteButler`. If you only use `DirectButler`, this may be
@@ -167,7 +185,9 @@ class LabeledButlerFactory:
167
185
 
168
186
  match butler_type:
169
187
  case ButlerType.DIRECT:
170
- return _DirectButlerFactory(config, self._preload_unsafe_direct_butler_caches)
188
+ return _DirectButlerFactory(
189
+ config, self._preload_unsafe_direct_butler_caches, self._writeable
190
+ )
171
191
  case ButlerType.REMOTE:
172
192
  return _RemoteButlerFactory(config)
173
193
  case _:
@@ -189,12 +209,12 @@ class _ButlerFactory(Protocol):
189
209
 
190
210
 
191
211
  class _DirectButlerFactory(_ButlerFactory):
192
- def __init__(self, config: ButlerConfig, preload_unsafe_caches: bool) -> None:
212
+ def __init__(self, config: ButlerConfig, preload_unsafe_caches: bool, writeable: bool) -> None:
193
213
  import lsst.daf.butler.direct_butler
194
214
 
195
215
  # Create a 'template' Butler that will be cloned when callers request
196
216
  # an instance.
197
- self._butler = Butler.from_config(config)
217
+ self._butler = Butler.from_config(config, writeable=writeable)
198
218
  assert isinstance(self._butler, lsst.daf.butler.direct_butler.DirectButler)
199
219
 
200
220
  # Load caches so that data is available in cloned instances without
@@ -100,3 +100,4 @@ VisitBackgroundModel: lsst.daf.butler.formatters.json.JsonFormatter
100
100
  VignettingCorrection: lsst.ts.observatory.control.utils.extras.vignetting_storage.VignettingCorrectionFormatter
101
101
  SSPAuxiliaryFile: lsst.pipe.tasks.sspAuxiliaryFile.SSPAuxiliaryFileFormatter
102
102
  VisitGeometry: lsst.daf.butler.formatters.json.JsonFormatter
103
+ ProvenanceQuantumGraph: lsst.pipe.base.quantum_graph.formatter.ProvenanceFormatter
@@ -443,3 +443,18 @@ storageClasses:
443
443
  pytype: lsst.pipe.tasks.sspAuxiliaryFile.SSPAuxiliaryFile
444
444
  VisitGeometry:
445
445
  pytype: lsst.obs.base.visit_geometry.VisitGeometry
446
+ ProvenanceQuantumGraph:
447
+ pytype: lsst.pipe.base.quantum_graph.ProvenanceQuantumGraph
448
+ parameters:
449
+ - import_mode # lsst.pipe.base.pipeline_graph.TaskImportMode
450
+ - quanta # iterable of uuid.UUID; quanta to read
451
+ - datasets # iterable of uuid.UUID; datasets to read
452
+ - read_init_quanta # bool, defaults to True; whether to read pre-exec-init info
453
+ derivedComponents:
454
+ packages: Packages # ignores node parameters
455
+
456
+ # UUID keys can be quantum or data IDs (whichever is passed in via
457
+ # parameters). Nested lists are attempts to run the quantum (last is
458
+ # most recent).
459
+ logs: StructuredDataDict # dict[uuid.UUID, list[ButlerLogRecords]]
460
+ metadata: StructuredDataDict # dict[uuid.UUID, list[TaskMetadata]]
@@ -755,6 +755,11 @@ class DataCoordinate:
755
755
  to_json = to_json_pydantic
756
756
  from_json: ClassVar[Callable[..., Self]] = cast(Callable[..., Self], classmethod(from_json_pydantic))
757
757
 
758
+ @property
759
+ def dataId(self) -> Self:
760
+ """Return this `DataCoordinate` instance, unmodified."""
761
+ return self
762
+
758
763
 
759
764
  DataId = DataCoordinate | Mapping[str, Any]
760
765
  """A type-annotation alias for signatures that accept both informal data ID
@@ -1822,12 +1822,25 @@ class DirectButler(Butler): # numpydoc ignore=PR02
1822
1822
  f" Example: {existing_datasets[0]}"
1823
1823
  )
1824
1824
 
1825
+ # Calculate some statistics based on the given list of datasets.
1826
+ n_files = len(datasets)
1827
+ n_datasets = 0
1828
+ for d in datasets:
1829
+ n_datasets += len(d.refs)
1830
+ sfiles = "s" if n_files != 1 else ""
1831
+ srefs = "s" if n_datasets != 1 else ""
1832
+
1825
1833
  # We use `datasets` rather `new_datasets` for the Registry
1826
1834
  # portion of this, to let it confirm that everything matches the
1827
1835
  # existing datasets.
1828
1836
  import_info = self._prepare_ingest_file_datasets(datasets, progress)
1829
1837
 
1830
- with self.transaction():
1838
+ with (
1839
+ self._metrics.instrument_ingest(
1840
+ n_datasets, _LOG, msg=f"Ingesting {n_files} file{sfiles} with {n_datasets} dataset{srefs}"
1841
+ ),
1842
+ self.transaction(),
1843
+ ):
1831
1844
  self._ingest_file_datasets(datasets, import_info, progress)
1832
1845
 
1833
1846
  # Bulk-insert everything into Datastore.
@@ -1982,7 +1995,7 @@ class DirectButler(Butler): # numpydoc ignore=PR02
1982
1995
  doImport(filename) # type: ignore
1983
1996
 
1984
1997
  def transfer_dimension_records_from(
1985
- self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef]
1998
+ self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef | DataCoordinate]
1986
1999
  ) -> None:
1987
2000
  # Allowed dimensions in the target butler.
1988
2001
  elements = frozenset(element for element in self.dimensions.elements if element.has_own_table)
@@ -2012,16 +2025,13 @@ class DirectButler(Butler): # numpydoc ignore=PR02
2012
2025
  source_butler, data_ids, allowed_elements
2013
2026
  )
2014
2027
 
2015
- can_query = True if isinstance(source_butler, Butler) else False
2016
-
2017
2028
  additional_records: dict[DimensionElement, dict[DataCoordinate, DimensionRecord]] = defaultdict(dict)
2018
2029
  for original_element, record_mapping in primary_records.items():
2019
2030
  # Get dimensions that depend on this dimension.
2020
2031
  populated_by = self.dimensions.get_elements_populated_by(
2021
2032
  self.dimensions[original_element.name] # type: ignore
2022
2033
  )
2023
-
2024
- for data_id in record_mapping.keys():
2034
+ if populated_by:
2025
2035
  for element in populated_by:
2026
2036
  if element not in allowed_elements:
2027
2037
  continue
@@ -2040,28 +2050,32 @@ class DirectButler(Butler): # numpydoc ignore=PR02
2040
2050
  # have to be scanned.
2041
2051
  continue
2042
2052
 
2043
- if not can_query:
2044
- raise RuntimeError(
2045
- f"Transferring populated_by records like {element.name} requires a full Butler."
2046
- )
2053
+ if record_mapping:
2054
+ if not isinstance(source_butler, Butler):
2055
+ raise RuntimeError(
2056
+ f"Transferring populated_by records like {element.name}"
2057
+ " requires a full Butler."
2058
+ )
2047
2059
 
2048
- records = source_butler.query_dimension_records( # type: ignore
2049
- element.name,
2050
- explain=False,
2051
- **data_id.mapping, # type: ignore
2052
- )
2053
- for record in records:
2054
- additional_records[record.definition].setdefault(record.dataId, record)
2060
+ with source_butler.query() as query:
2061
+ records = query.join_data_coordinates(record_mapping.keys()).dimension_records(
2062
+ element.name
2063
+ )
2064
+ for record in records:
2065
+ additional_records[record.definition].setdefault(record.dataId, record)
2055
2066
 
2056
2067
  # The next step is to walk back through the additional records to
2057
2068
  # pick up any missing content (such as visit_definition needing to
2058
2069
  # know the exposure). Want to ensure we do not request records we
2059
2070
  # already have.
2060
2071
  missing_data_ids = set()
2061
- for name, record_mapping in additional_records.items():
2072
+ for record_mapping in additional_records.values():
2062
2073
  for data_id in record_mapping.keys():
2063
- if data_id not in primary_records[name]:
2064
- missing_data_ids.add(data_id)
2074
+ for dimension in data_id.dimensions.required:
2075
+ element = source_butler.dimensions[dimension]
2076
+ dimension_key = data_id.subset(dimension)
2077
+ if dimension_key not in primary_records[element]:
2078
+ missing_data_ids.add(dimension_key)
2065
2079
 
2066
2080
  # Fill out the new records. Assume that these new records do not
2067
2081
  # also need to carry over additional populated_by records.
@@ -2078,19 +2092,19 @@ class DirectButler(Butler): # numpydoc ignore=PR02
2078
2092
  def _extract_dimension_records_from_data_ids(
2079
2093
  self,
2080
2094
  source_butler: LimitedButler | Butler,
2081
- data_ids: set[DataCoordinate],
2095
+ data_ids: Iterable[DataCoordinate],
2082
2096
  allowed_elements: frozenset[DimensionElement],
2083
2097
  ) -> dict[DimensionElement, dict[DataCoordinate, DimensionRecord]]:
2084
2098
  dimension_records: dict[DimensionElement, dict[DataCoordinate, DimensionRecord]] = defaultdict(dict)
2085
2099
 
2100
+ data_ids = set(data_ids)
2101
+ if not all(data_id.hasRecords() for data_id in data_ids):
2102
+ if isinstance(source_butler, Butler):
2103
+ data_ids = source_butler._expand_data_ids(data_ids)
2104
+ else:
2105
+ raise TypeError("Input butler needs to be a full butler to expand DataId.")
2106
+
2086
2107
  for data_id in data_ids:
2087
- # Need an expanded record, if not expanded that we need a full
2088
- # butler with registry (allow mocks with registry too).
2089
- if not data_id.hasRecords():
2090
- if registry := getattr(source_butler, "registry", None):
2091
- data_id = registry.expandDataId(data_id)
2092
- else:
2093
- raise TypeError("Input butler needs to be a full butler to expand DataId.")
2094
2108
  # If this butler doesn't know about a dimension in the source
2095
2109
  # butler things will break later.
2096
2110
  for element_name in data_id.dimensions.elements:
@@ -2569,6 +2583,9 @@ class DirectButler(Butler): # numpydoc ignore=PR02
2569
2583
  """Immediately load caches that are used for common operations."""
2570
2584
  self._registry.preload_cache(load_dimension_record_cache=load_dimension_record_cache)
2571
2585
 
2586
+ def _expand_data_ids(self, data_ids: Iterable[DataCoordinate]) -> list[DataCoordinate]:
2587
+ return self._registry.expand_data_ids(data_ids)
2588
+
2572
2589
  _config: ButlerConfig
2573
2590
  """Configuration for this Butler instance."""
2574
2591
 
@@ -764,11 +764,17 @@ class ButlerLogRecords(MutableSequence[ButlerLogRecord]):
764
764
 
765
765
 
766
766
  class ButlerLogRecordHandler(StreamHandler):
767
- """Python log handler that accumulates records."""
767
+ """Python log handler that accumulates records.
768
768
 
769
- def __init__(self) -> None:
769
+ Parameters
770
+ ----------
771
+ records : `ButlerLogRecords`, optional
772
+ Container to store logs in.
773
+ """
774
+
775
+ def __init__(self, records: ButlerLogRecords | None = None) -> None:
770
776
  super().__init__()
771
- self.records = ButlerLogRecords([])
777
+ self.records = ButlerLogRecords([]) if records is None else records
772
778
 
773
779
  def emit(self, record: LogRecord) -> None:
774
780
  self.records.append(record)
@@ -0,0 +1,93 @@
1
+ # This file is part of daf_butler.
2
+ #
3
+ # Developed for the LSST Data Management System.
4
+ # This product includes software developed by the LSST Project
5
+ # (http://www.lsst.org).
6
+ # See the COPYRIGHT file at the top-level directory of this distribution
7
+ # for details of code ownership.
8
+ #
9
+ # This software is dual licensed under the GNU General Public License and also
10
+ # under a 3-clause BSD license. Recipients may choose which of these licenses
11
+ # to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12
+ # respectively. If you choose the GPL option then the following text applies
13
+ # (but note that there is still no warranty even if you opt for BSD instead):
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 3 of the License, or
18
+ # (at your option) any later version.
19
+ #
20
+ # This program is distributed in the hope that it will be useful,
21
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ # GNU General Public License for more details.
24
+ #
25
+ # You should have received a copy of the GNU General Public License
26
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
27
+
28
+ from __future__ import annotations
29
+
30
+ from collections import defaultdict
31
+ from collections.abc import Iterable
32
+
33
+ from ..dimensions import (
34
+ DataCoordinate,
35
+ DimensionDataAttacher,
36
+ DimensionGroup,
37
+ DimensionUniverse,
38
+ )
39
+ from ..dimensions.record_cache import DimensionRecordCache
40
+ from ..queries import QueryFactoryFunction
41
+
42
+
43
+ def expand_data_ids(
44
+ data_ids: Iterable[DataCoordinate],
45
+ universe: DimensionUniverse,
46
+ query_func: QueryFactoryFunction,
47
+ cache: DimensionRecordCache | None,
48
+ ) -> list[DataCoordinate]:
49
+ """Expand the given data IDs to look up implied dimension values and attach
50
+ dimension records.
51
+
52
+ Parameters
53
+ ----------
54
+ data_ids : `~collections.abc.Iterable` [ `DataCoordinate` ]
55
+ Data coordinates to be expanded.
56
+ universe : `DimensionUniverse`
57
+ Dimension universe associated with the given ``data_ids`` values.
58
+ query_func : QueryFactoryFunction
59
+ Function used to set up a Butler query context for looking up required
60
+ information from the database.
61
+ cache : `DimensionRecordCache` | None
62
+ Cache containing already-known dimension records. May be `None` if a
63
+ cache is not available.
64
+
65
+ Returns
66
+ -------
67
+ expanded : `list` [ `DataCoordinate` ]
68
+ List of `DataCoordinate` instances in the same order as the input
69
+ values. It is guaranteed that each `DataCoordinate` has
70
+ ``hasRecords()=True`` and ``hasFull()=True``.
71
+ """
72
+ output = list(data_ids)
73
+
74
+ grouped_by_dimensions: defaultdict[DimensionGroup, list[int]] = defaultdict(list)
75
+ for i, data_id in enumerate(data_ids):
76
+ if not data_id.hasRecords():
77
+ grouped_by_dimensions[data_id.dimensions].append(i)
78
+
79
+ if not grouped_by_dimensions:
80
+ # All given DataCoordinate values are already expanded.
81
+ return output
82
+
83
+ attacher = DimensionDataAttacher(
84
+ cache=cache,
85
+ dimensions=DimensionGroup.union(*grouped_by_dimensions.keys(), universe=universe),
86
+ )
87
+ for dimensions, indexes in grouped_by_dimensions.items():
88
+ with query_func() as query:
89
+ expanded = attacher.attach(dimensions, (output[index] for index in indexes), query)
90
+ for index, data_id in zip(indexes, expanded):
91
+ output[index] = data_id
92
+
93
+ return output
@@ -34,7 +34,6 @@ __all__ = ("SqlRegistry",)
34
34
  import contextlib
35
35
  import logging
36
36
  import warnings
37
- from collections import defaultdict
38
37
  from collections.abc import Iterable, Iterator, Mapping, Sequence
39
38
  from typing import TYPE_CHECKING, Any
40
39
 
@@ -54,7 +53,6 @@ from ..dimensions import (
54
53
  DataCoordinate,
55
54
  DataId,
56
55
  DimensionConfig,
57
- DimensionDataAttacher,
58
56
  DimensionElement,
59
57
  DimensionGroup,
60
58
  DimensionRecord,
@@ -78,6 +76,7 @@ from ..registry.interfaces import ChainedCollectionRecord, ReadOnlyDatabaseError
78
76
  from ..registry.managers import RegistryManagerInstances, RegistryManagerTypes
79
77
  from ..registry.wildcards import CollectionWildcard, DatasetTypeWildcard
80
78
  from ..utils import transactional
79
+ from .expand_data_ids import expand_data_ids
81
80
 
82
81
  if TYPE_CHECKING:
83
82
  from .._butler_config import ButlerConfig
@@ -1415,28 +1414,7 @@ class SqlRegistry:
1415
1414
  return DataCoordinate.standardize(keys, dimensions=standardized.dimensions).expanded(records=records)
1416
1415
 
1417
1416
  def expand_data_ids(self, data_ids: Iterable[DataCoordinate]) -> list[DataCoordinate]:
1418
- output = list(data_ids)
1419
-
1420
- grouped_by_dimensions: defaultdict[DimensionGroup, list[int]] = defaultdict(list)
1421
- for i, data_id in enumerate(data_ids):
1422
- if not data_id.hasRecords():
1423
- grouped_by_dimensions[data_id.dimensions].append(i)
1424
-
1425
- if not grouped_by_dimensions:
1426
- # All given DataCoordinate values are already expanded.
1427
- return output
1428
-
1429
- attacher = DimensionDataAttacher(
1430
- cache=self.dimension_record_cache,
1431
- dimensions=DimensionGroup.union(*grouped_by_dimensions.keys(), universe=self.dimensions),
1432
- )
1433
- with self._query() as query:
1434
- for dimensions, indexes in grouped_by_dimensions.items():
1435
- expanded = attacher.attach(dimensions, (output[index] for index in indexes), query)
1436
- for index, data_id in zip(indexes, expanded):
1437
- output[index] = data_id
1438
-
1439
- return output
1417
+ return expand_data_ids(data_ids, self.dimensions, self._query, self.dimension_record_cache)
1440
1418
 
1441
1419
  def expand_refs(self, dataset_refs: list[DatasetRef]) -> list[DatasetRef]:
1442
1420
  expanded_ids = self.expand_data_ids([ref.dataId for ref in dataset_refs])
@@ -65,6 +65,7 @@ from ..dimensions import DataCoordinate, DataIdValue, DimensionConfig, Dimension
65
65
  from ..queries import Query
66
66
  from ..queries.tree import make_column_literal
67
67
  from ..registry import CollectionArgType, NoDefaultCollectionError, Registry, RegistryDefaults
68
+ from ..registry.expand_data_ids import expand_data_ids
68
69
  from ._collection_args import convert_collection_arg_to_glob_string_list
69
70
  from ._defaults import DefaultsHolder
70
71
  from ._get import convert_http_url_to_resource_path, get_dataset_as_python_object
@@ -633,7 +634,7 @@ class RemoteButler(Butler): # numpydoc ignore=PR02
633
634
  raise NotImplementedError()
634
635
 
635
636
  def transfer_dimension_records_from(
636
- self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef]
637
+ self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef | DataCoordinate]
637
638
  ) -> None:
638
639
  # Docstring inherited.
639
640
  raise NotImplementedError()
@@ -738,6 +739,9 @@ class RemoteButler(Butler): # numpydoc ignore=PR02
738
739
  def close(self) -> None:
739
740
  pass
740
741
 
742
+ def _expand_data_ids(self, data_ids: Iterable[DataCoordinate]) -> list[DataCoordinate]:
743
+ return expand_data_ids(data_ids, self.dimensions, self.query, None)
744
+
741
745
  @property
742
746
  def _file_transfer_source(self) -> RemoteFileTransferSource:
743
747
  return RemoteFileTransferSource(self._connection)
@@ -338,7 +338,7 @@ class HybridButler(Butler):
338
338
  )
339
339
 
340
340
  def transfer_dimension_records_from(
341
- self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef]
341
+ self, source_butler: LimitedButler | Butler, source_refs: Iterable[DatasetRef | DataCoordinate]
342
342
  ) -> None:
343
343
  return self._direct_butler.transfer_dimension_records_from(source_butler, source_refs)
344
344
 
@@ -425,6 +425,9 @@ class HybridButler(Butler):
425
425
  source_butler, data_ids, allowed_elements
426
426
  )
427
427
 
428
+ def _expand_data_ids(self, data_ids: Iterable[DataCoordinate]) -> list[DataCoordinate]:
429
+ return self._remote_butler._expand_data_ids(data_ids)
430
+
428
431
  @property
429
432
  def collection_chains(self) -> ButlerCollections:
430
433
  return HybridButlerCollections(self)