lsst-daf-butler 29.2025.2300__tar.gz → 29.2025.2500__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 (445) hide show
  1. {lsst_daf_butler-29.2025.2300/python/lsst_daf_butler.egg-info → lsst_daf_butler-29.2025.2500}/PKG-INFO +1 -1
  2. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/CHANGES.rst +71 -0
  3. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/pyproject.toml +1 -1
  4. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_limited_butler.py +8 -1
  5. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/__init__.py +1 -0
  6. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/_datastore.py +18 -15
  7. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/datastore/_transfer.py +102 -0
  8. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/stored_file_info.py +65 -12
  9. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/chainedDatastore.py +53 -7
  10. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/fileDatastore.py +51 -180
  11. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/datastores/file_datastore/transfer.py +104 -0
  12. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_coordinate.py +3 -0
  13. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/_direct_butler.py +36 -34
  14. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_driver.py +1 -1
  15. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/parquet.py +7 -3
  16. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_config.py +21 -0
  17. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/postgresql.py +15 -1
  18. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/sqlite.py +16 -1
  19. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_database.py +21 -1
  20. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_config.py +10 -0
  21. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_records.py +7 -2
  22. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/sql_registry.py +5 -1
  23. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/_registry.py +59 -46
  24. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_http_connection.py +6 -2
  25. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_remote_butler.py +5 -0
  26. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/remote_butler/_remote_file_transfer_source.py +124 -0
  27. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_factory.py +4 -0
  28. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_external.py +90 -3
  29. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_external_query.py +24 -11
  30. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/remote_butler/server/handlers/_query_limits.py +105 -0
  31. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_query_streaming.py +11 -47
  32. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_utils.py +15 -1
  33. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server_models.py +17 -1
  34. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/butler_queries.py +50 -43
  35. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler.py +5 -1
  36. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/__init__.py +0 -0
  37. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/base.yaml +81 -0
  38. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset-skymap.yaml +45 -0
  39. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset.yaml +732 -0
  40. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/datasets.yaml +138 -0
  41. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/hsc-rc2-subset-v0.yaml +159 -0
  42. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/spatial.py +617 -0
  43. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/spatial.yaml +192 -0
  44. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/utils.py +12 -3
  45. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/version.py +2 -0
  46. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500/python/lsst_daf_butler.egg-info}/PKG-INFO +1 -1
  47. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/SOURCES.txt +12 -0
  48. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_butler.py +167 -142
  49. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryCollections.py +2 -5
  50. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDataIds.py +1 -1
  51. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_datastore.py +7 -1
  52. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_dimension_record_containers.py +2 -3
  53. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_postgresql.py +4 -3
  54. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_quantumBackedButler.py +1 -1
  55. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_remote_butler.py +2 -1
  56. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_server.py +87 -7
  57. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_simpleButler.py +26 -26
  58. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_sqlite.py +11 -7
  59. lsst_daf_butler-29.2025.2300/python/lsst/daf/butler/version.py +0 -2
  60. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/COPYRIGHT +0 -0
  61. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/LICENSE +0 -0
  62. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/MANIFEST.in +0 -0
  63. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/README.md +0 -0
  64. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/bsd_license.txt +0 -0
  65. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/concreteStorageClasses.rst +0 -0
  66. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/configuring.rst +0 -0
  67. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/datastores.rst +0 -0
  68. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/dimensions.rst +0 -0
  69. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/formatters.rst +0 -0
  70. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/index.rst +0 -0
  71. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/organizing.rst +0 -0
  72. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/queries.rst +0 -0
  73. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/use-in-tests.rst +0 -0
  74. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/writing-subcommands.rst +0 -0
  75. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/gpl-v3.0.txt +0 -0
  76. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/__init__.py +0 -0
  77. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/__init__.py +0 -0
  78. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/__init__.py +0 -0
  79. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler.py +0 -0
  80. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_collections.py +0 -0
  81. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_config.py +0 -0
  82. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_instance_options.py +0 -0
  83. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_metrics.py +0 -0
  84. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_repo_index.py +0 -0
  85. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_collection_type.py +0 -0
  86. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_categorization.py +0 -0
  87. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_tags.py +0 -0
  88. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_type_info.py +0 -0
  89. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_config.py +0 -0
  90. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_config_support.py +0 -0
  91. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_association.py +0 -0
  92. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_existence.py +0 -0
  93. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_provenance.py +0 -0
  94. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_ref.py +0 -0
  95. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_type.py +0 -0
  96. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_deferredDatasetHandle.py +0 -0
  97. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_exceptions.py +0 -0
  98. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_exceptions_legacy.py +0 -0
  99. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_file_dataset.py +0 -0
  100. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_file_descriptor.py +0 -0
  101. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_formatter.py +0 -0
  102. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_labeled_butler_factory.py +0 -0
  103. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_location.py +0 -0
  104. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_named.py +0 -0
  105. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_quantum.py +0 -0
  106. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_quantum_backed.py +0 -0
  107. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_query_all_datasets.py +0 -0
  108. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_registry_shim.py +0 -0
  109. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_storage_class.py +0 -0
  110. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_storage_class_delegate.py +0 -0
  111. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_timespan.py +0 -0
  112. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_topology.py +0 -0
  113. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/__init__.py +0 -0
  114. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/locked_object.py +0 -0
  115. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/named_locks.py +0 -0
  116. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/thread_safe_cache.py +0 -0
  117. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/arrow_utils.py +0 -0
  118. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/__init__.py +0 -0
  119. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/butler.py +0 -0
  120. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cliLog.py +0 -0
  121. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/__init__.py +0 -0
  122. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/_remove_collections.py +0 -0
  123. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/_remove_runs.py +0 -0
  124. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/commands.py +0 -0
  125. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/__init__.py +0 -0
  126. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/arguments.py +0 -0
  127. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/optionGroups.py +0 -0
  128. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/options.py +0 -0
  129. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/progress.py +0 -0
  130. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/utils.py +0 -0
  131. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/column_spec.py +0 -0
  132. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastore.yaml +0 -0
  133. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/composites.yaml +0 -0
  134. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/fileDatastore.yaml +0 -0
  135. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/formatters.yaml +0 -0
  136. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/writeRecipes.yaml +0 -0
  137. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/dimensions.yaml +0 -0
  138. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe0.yaml +0 -0
  139. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe1.yaml +0 -0
  140. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe2.yaml +0 -0
  141. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe3.yaml +0 -0
  142. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe4.yaml +0 -0
  143. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe5.yaml +0 -0
  144. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe6.yaml +0 -0
  145. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe7.yaml +0 -0
  146. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/registry.yaml +0 -0
  147. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/repo_transfer_formats.yaml +0 -0
  148. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/storageClasses.yaml +0 -0
  149. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/cache_manager.py +0 -0
  150. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/composites.py +0 -0
  151. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/constraints.py +0 -0
  152. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/file_templates.py +0 -0
  153. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/generic_base.py +0 -0
  154. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/record_data.py +0 -0
  155. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/__init__.py +0 -0
  156. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/fileDatastoreClient.py +0 -0
  157. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/__init__.py +0 -0
  158. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/get.py +0 -0
  159. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/retrieve_artifacts.py +0 -0
  160. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/inMemoryDatastore.py +0 -0
  161. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/ddl.py +0 -0
  162. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/delegates/__init__.py +0 -0
  163. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/delegates/arrowtable.py +0 -0
  164. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/__init__.py +0 -0
  165. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_config.py +0 -0
  166. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_data_coordinate_iterable.py +0 -0
  167. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_database.py +0 -0
  168. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_elements.py +0 -0
  169. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_governor.py +0 -0
  170. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_group.py +0 -0
  171. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_packer.py +0 -0
  172. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_record_set.py +0 -0
  173. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_record_table.py +0 -0
  174. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_records.py +0 -0
  175. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_schema.py +0 -0
  176. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_skypix.py +0 -0
  177. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_universe.py +0 -0
  178. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/construction.py +0 -0
  179. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/record_cache.py +0 -0
  180. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/__init__.py +0 -0
  181. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/_direct_butler_collections.py +0 -0
  182. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/__init__.py +0 -0
  183. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_postprocessing.py +0 -0
  184. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_query_analysis.py +0 -0
  185. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_query_builder.py +0 -0
  186. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_result_page_converter.py +0 -0
  187. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_sql_builders.py +0 -0
  188. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_sql_column_visitor.py +0 -0
  189. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/__init__.py +0 -0
  190. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/astropyTable.py +0 -0
  191. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/file.py +0 -0
  192. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/json.py +0 -0
  193. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/logs.py +0 -0
  194. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/matplotlib.py +0 -0
  195. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/packages.py +0 -0
  196. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/pickle.py +0 -0
  197. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/typeless.py +0 -0
  198. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/yaml.py +0 -0
  199. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/json.py +0 -0
  200. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/logging.py +0 -0
  201. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/mapping_factory.py +0 -0
  202. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/name_shrinker.py +0 -0
  203. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/nonempty_mapping.py +0 -0
  204. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/persistence_context.py +0 -0
  205. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/progress.py +0 -0
  206. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/py.typed +0 -0
  207. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/pydantic_utils.py +0 -0
  208. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/__init__.py +0 -0
  209. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_base.py +0 -0
  210. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_data_coordinate_query_results.py +0 -0
  211. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_dataset_query_results.py +0 -0
  212. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_dimension_record_query_results.py +0 -0
  213. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_expression_strings.py +0 -0
  214. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_general_query_results.py +0 -0
  215. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_identifiers.py +0 -0
  216. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_query.py +0 -0
  217. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/convert_args.py +0 -0
  218. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/driver.py +0 -0
  219. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/expression_factory.py +0 -0
  220. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/overlaps.py +0 -0
  221. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/predicate_constraints_summary.py +0 -0
  222. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/result_specs.py +0 -0
  223. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/__init__.py +0 -0
  224. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_base.py +0 -0
  225. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_expression.py +0 -0
  226. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_literal.py +0 -0
  227. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_reference.py +0 -0
  228. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_set.py +0 -0
  229. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_predicate.py +0 -0
  230. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_query_tree.py +0 -0
  231. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/visitors.py +0 -0
  232. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/__init__.py +0 -0
  233. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_caching_context.py +0 -0
  234. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_record_cache.py +0 -0
  235. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_summary.py +0 -0
  236. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_summary_cache.py +0 -0
  237. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_defaults.py +0 -0
  238. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_exceptions.py +0 -0
  239. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_registry.py +0 -0
  240. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_registry_factory.py +0 -0
  241. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/attributes.py +0 -0
  242. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/__init__.py +0 -0
  243. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/ephemeral.py +0 -0
  244. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/monolithic.py +0 -0
  245. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/__init__.py +0 -0
  246. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/_base.py +0 -0
  247. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/nameKey.py +0 -0
  248. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/synthIntKey.py +0 -0
  249. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/connectionString.py +0 -0
  250. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/__init__.py +0 -0
  251. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/__init__.py +0 -0
  252. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/__init__.py +0 -0
  253. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/_dataset_type_cache.py +0 -0
  254. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/_manager.py +0 -0
  255. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/summaries.py +0 -0
  256. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/tables.py +0 -0
  257. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/dimensions/__init__.py +0 -0
  258. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/dimensions/static.py +0 -0
  259. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/__init__.py +0 -0
  260. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_attributes.py +0 -0
  261. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_bridge.py +0 -0
  262. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_collections.py +0 -0
  263. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_database_explain.py +0 -0
  264. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_datasets.py +0 -0
  265. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_dimensions.py +0 -0
  266. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_obscore.py +0 -0
  267. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_opaque.py +0 -0
  268. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_versioning.py +0 -0
  269. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/managers.py +0 -0
  270. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/nameShrinker.py +0 -0
  271. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/__init__.py +0 -0
  272. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_manager.py +0 -0
  273. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_schema.py +0 -0
  274. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_spatial.py +0 -0
  275. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/default_spatial.py +0 -0
  276. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/pgsphere.py +0 -0
  277. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/opaque.py +0 -0
  278. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/__init__.py +0 -0
  279. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_builder.py +0 -0
  280. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query.py +0 -0
  281. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query_backend.py +0 -0
  282. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query_context.py +0 -0
  283. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_readers.py +0 -0
  284. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_results.py +0 -0
  285. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_sql_query_backend.py +0 -0
  286. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_sql_query_context.py +0 -0
  287. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_structs.py +0 -0
  288. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/butler_sql_engine.py +0 -0
  289. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/__init__.py +0 -0
  290. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/_predicate.py +0 -0
  291. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/categorize.py +0 -0
  292. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/check.py +0 -0
  293. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/normalForm.py +0 -0
  294. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/__init__.py +0 -0
  295. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/exprTree.py +0 -0
  296. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parser.py +0 -0
  297. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parserLex.py +0 -0
  298. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parserYacc.py +0 -0
  299. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/__init__.py +0 -0
  300. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/lex.py +0 -0
  301. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/yacc.py +0 -0
  302. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/treeVisitor.py +0 -0
  303. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/find_first_dataset.py +0 -0
  304. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/__init__.py +0 -0
  305. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/_database.py +0 -0
  306. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/versions.py +0 -0
  307. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/wildcards.py +0 -0
  308. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/__init__.py +0 -0
  309. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_authentication.py +0 -0
  310. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_collection_args.py +0 -0
  311. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_config.py +0 -0
  312. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_defaults.py +0 -0
  313. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_errors.py +0 -0
  314. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_factory.py +0 -0
  315. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_query_driver.py +0 -0
  316. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_query_results.py +0 -0
  317. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_ref_utils.py +0 -0
  318. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_registry.py +0 -0
  319. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_remote_butler_collections.py +0 -0
  320. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/__init__.py +0 -0
  321. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_common.py +0 -0
  322. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_data_coordinates.py +0 -0
  323. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_datasets.py +0 -0
  324. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_dimension_records.py +0 -0
  325. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/__init__.py +0 -0
  326. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_config.py +0 -0
  327. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_dependencies.py +0 -0
  328. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_gafaelfawr.py +0 -0
  329. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_server.py +0 -0
  330. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_telemetry.py +0 -0
  331. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_internal.py +0 -0
  332. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_query_serialization.py +0 -0
  333. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/repo_relocation.py +0 -0
  334. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/__init__.py +0 -0
  335. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/_associate.py +0 -0
  336. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/_pruneDatasets.py +0 -0
  337. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/butlerImport.py +0 -0
  338. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/certifyCalibrations.py +0 -0
  339. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/collectionChain.py +0 -0
  340. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/configDump.py +0 -0
  341. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/configValidate.py +0 -0
  342. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/createRepo.py +0 -0
  343. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/exportCalibs.py +0 -0
  344. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/ingest_files.py +0 -0
  345. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/ingest_zip.py +0 -0
  346. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryCollections.py +0 -0
  347. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDataIds.py +0 -0
  348. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDatasetTypes.py +0 -0
  349. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDatasets.py +0 -0
  350. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDimensionRecords.py +0 -0
  351. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/register_dataset_type.py +0 -0
  352. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeCollections.py +0 -0
  353. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeDatasetType.py +0 -0
  354. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeRuns.py +0 -0
  355. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/retrieveArtifacts.py +0 -0
  356. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/transferDatasets.py +0 -0
  357. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/__init__.py +0 -0
  358. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_datasetsHelper.py +0 -0
  359. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_dummyRegistry.py +0 -0
  360. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_examplePythonTypes.py +0 -0
  361. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_testRepo.py +0 -0
  362. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/cliCmdTestBase.py +0 -0
  363. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/cliLogTestBase.py +0 -0
  364. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/deferredFormatter.py +0 -0
  365. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/dict_convertible_model.py +0 -0
  366. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler_collections.py +0 -0
  367. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler_registry.py +0 -0
  368. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/postgresql.py +0 -0
  369. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/server.py +0 -0
  370. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/server_utils.py +0 -0
  371. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/testFormatters.py +0 -0
  372. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/time_utils.py +0 -0
  373. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/timespan_database_representation.py +0 -0
  374. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/__init__.py +0 -0
  375. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_context.py +0 -0
  376. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_interfaces.py +0 -0
  377. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_yaml.py +0 -0
  378. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/utils.py +0 -0
  379. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/dependency_links.txt +0 -0
  380. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/entry_points.txt +0 -0
  381. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/requires.txt +0 -0
  382. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/top_level.txt +0 -0
  383. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/zip-safe +0 -0
  384. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/setup.cfg +0 -0
  385. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_astropyTableFormatter.py +0 -0
  386. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_authentication.py +0 -0
  387. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_butler_factory.py +0 -0
  388. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdAssociate.py +0 -0
  389. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdConfigDump.py +0 -0
  390. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdConfigValidate.py +0 -0
  391. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdCreate.py +0 -0
  392. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdImport.py +0 -0
  393. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdIngestFiles.py +0 -0
  394. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdPruneDatasets.py +0 -0
  395. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDatasetTypes.py +0 -0
  396. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDatasets.py +0 -0
  397. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDimensionRecords.py +0 -0
  398. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRemoveCollections.py +0 -0
  399. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRemoveRuns.py +0 -0
  400. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRetrieveArtifacts.py +0 -0
  401. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliLog.py +0 -0
  402. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliPluginLoader.py +0 -0
  403. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilSplitCommas.py +0 -0
  404. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilSplitKv.py +0 -0
  405. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilToUpper.py +0 -0
  406. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtils.py +0 -0
  407. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_column_spec.py +0 -0
  408. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_composites.py +0 -0
  409. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_config.py +0 -0
  410. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_connectionString.py +0 -0
  411. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_constraints.py +0 -0
  412. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_datasets.py +0 -0
  413. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_ddl.py +0 -0
  414. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_dimensions.py +0 -0
  415. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_exprParserLex.py +0 -0
  416. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_exprParserYacc.py +0 -0
  417. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_expressions.py +0 -0
  418. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_formatter.py +0 -0
  419. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_gafaelfawr.py +0 -0
  420. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_location.py +0 -0
  421. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_logFormatter.py +0 -0
  422. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_logging.py +0 -0
  423. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_matplotlibFormatter.py +0 -0
  424. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_nonempty_mapping.py +0 -0
  425. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_normalFormExpression.py +0 -0
  426. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_obscore.py +0 -0
  427. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_packages.py +0 -0
  428. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_parquet.py +0 -0
  429. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_progress.py +0 -0
  430. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_pydantic_utils.py +0 -0
  431. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_quantum.py +0 -0
  432. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_direct_postgresql.py +0 -0
  433. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_direct_sqlite.py +0 -0
  434. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_interface.py +0 -0
  435. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_relations.py +0 -0
  436. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_remote.py +0 -0
  437. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_query_utilities.py +0 -0
  438. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_storageClass.py +0 -0
  439. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_templates.py +0 -0
  440. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_testRepo.py +0 -0
  441. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_thread_utils.py +0 -0
  442. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_time_utils.py +0 -0
  443. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_timespan.py +0 -0
  444. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_utils.py +0 -0
  445. {lsst_daf_butler-29.2025.2300 → lsst_daf_butler-29.2025.2500}/tests/test_versioning.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-daf-butler
3
- Version: 29.2025.2300
3
+ Version: 29.2025.2500
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: BSD 3-Clause License
@@ -1,3 +1,74 @@
1
+ Butler v29.1.0 (2025-06-13)
2
+ ===========================
3
+
4
+ New Features
5
+ ------------
6
+
7
+ - Added support in user expressions for explicit specification of bind identifiers with a preceding colon symbol.
8
+ Legacy format of bind identifiers without colon is still supported, but will be deprecated in the future. (`DM-38497 <https://rubinobs.atlassian.net/browse/DM-38497>`_)
9
+ - Added a new ``--show-dataset-types`` argument (``-t``) to ``butler query-collections`` to list the dataset types in each collection.
10
+ Also added a new ``--exclude-dataset-types`` which allows a comma-separated list of string globs to be passed in for exclusion when dataset types are shown. (`DM-48975 <https://rubinobs.atlassian.net/browse/DM-48975>`_)
11
+ - Added Pydantic serialization for ``DimensionRecordSet``. (`DM-49622 <https://rubinobs.atlassian.net/browse/DM-49622>`_)
12
+ - Added ``FileDataset.to_simple`` and ``FileDataset.from_simple`` for serializing ``FileDataset`` instances. (`DM-49670 <https://rubinobs.atlassian.net/browse/DM-49670>`_)
13
+ - Added a ``join_data_coordinate_table`` method to the ``Query`` class for uploading data IDs from Astropy tables.
14
+ This includes support for filling in required-dimension columns using constraints from a ``where`` string (for example now a table with just ``visit`` IDs along with ``instrument='LSSTCam'`` in the ``where`` string will work). (`DM-49949 <https://rubinobs.atlassian.net/browse/DM-49949>`_)
15
+ - Added support to the user expression language for a ``GLOB(expression, pattern)`` function.
16
+ The function performs case-sensitive match of the string expression against the pattern.
17
+ The pattern can include ``*`` and ``?`` meta-characters that match any number or a single character. (`DM-50191 <https://rubinobs.atlassian.net/browse/DM-50191>`_)
18
+ - Added the ability for Zip ingest to register any missing dimension records.
19
+ Note that if any datasets use ``visit`` that require registration then the records being registered will not fully define the visit and so can not be usable for graph building.
20
+ It is recommended that visits be defined first before ingest at this time. (`DM-50313 <https://rubinobs.atlassian.net/browse/DM-50313>`_)
21
+ - Added support to the user expression language for UUID literals that can be used to query dataset IDs.
22
+ UUID literals are specified using function call syntax: ``UUID('hex-string')``. (`DM-50451 <https://rubinobs.atlassian.net/browse/DM-50451>`_)
23
+ - Added ability for Butler to record timing metrics such as the amount of time spent in ``get()`` or ``put()`` and the number of times those are called.
24
+ A metrics object can be given to the ``Butler`` constructor to record everything, or alternatively a new context manager ``Butler.record_metrics`` can be used to record metrics for a specific usage. (`DM-50491 <https://rubinobs.atlassian.net/browse/DM-50491>`_)
25
+ - ``RemoteButler`` can now be used as a source Butler in ``transfer_from``. (`DM-51075 <https://rubinobs.atlassian.net/browse/DM-51075>`_)
26
+
27
+
28
+ API Changes
29
+ -----------
30
+
31
+ - * The ``unstore`` parameter for ``Butler.removeRuns()`` has been deprecated.
32
+ We now always remove the file artifacts when removing the collection.
33
+ * Added a ``unlink_from_chains`` parameter to ``Butler.removeRuns()`` to allow the RUN collections to be unlinked from their parent chains automatically. (`DM-50996 <https://rubinobs.atlassian.net/browse/DM-50996>`_)
34
+
35
+
36
+ Bug Fixes
37
+ ---------
38
+
39
+ - Fixed an issue where ``find_first=False`` dataset queries would sometimes return duplicate results if more than one collection was being searched. (`DM-47201 <https://rubinobs.atlassian.net/browse/DM-47201>`_)
40
+ - Query expressions now allow float columns to be compared with ``int`` literals.
41
+ Query expressions now allow ``OVERLAPS`` to be used to compare timespans with ``ingest_date.`` (`DM-47644 <https://rubinobs.atlassian.net/browse/DM-47644>`_)
42
+ - ``Butler.ingest()`` will now register missing run collections instead of raising a ``MissingCollectionError``. (`DM-49670 <https://rubinobs.atlassian.net/browse/DM-49670>`_)
43
+ - Fixed handling of expressions like ``"id=2"`` in contexts where ``"id"`` resolves unambigously to a dimension primary key column. (`DM-50465 <https://rubinobs.atlassian.net/browse/DM-50465>`_)
44
+ - ``butler remove-runs`` will no longer block if a parallel process calls ``butler remove-runs`` on a run contained in the same collection chain. (`DM-50855 <https://rubinobs.atlassian.net/browse/DM-50855>`_)
45
+
46
+
47
+ Performance Enhancement
48
+ -----------------------
49
+
50
+ - ``Butler.transfer_from()`` now uses fewer database queries when inserting datasets of multiple dataset types, when some of the dataset types have the same dimensions. (`DM-49513 <https://rubinobs.atlassian.net/browse/DM-49513>`_)
51
+ - Improve the performance of certain queries by moving ``WHERE`` clause terms down into subqueries. (`DM-50969 <https://rubinobs.atlassian.net/browse/DM-50969>`_)
52
+ - ``Butler.transfer_from`` now uses fewer database queries. (`DM-51302 <https://rubinobs.atlassian.net/browse/DM-51302>`_)
53
+
54
+
55
+ Other Changes and Additions
56
+ ---------------------------
57
+
58
+ - ``retrieveArtifacts`` and ``transfer_from`` now transfer their artifacts using multiple threads. (`DM-31824 <https://rubinobs.atlassian.net/browse/DM-31824>`_)
59
+ - * Reorganized the code for ``Butler.ingest`` and ``Butler.ingest_zip`` to share the code from ``Butler.transfer_from`` in order to provide consistent error messages for incompatible dataset types and to allow a future possibility of registering dataset types and dimension records as part of ``ingest_zip``.
60
+ * Removed the ``use_cache`` parameter from the ``DimensionUniverse`` constructor.
61
+ The universe is always cached and the remote butler now uses that cache and does not need to disable the cache. (`DM-50044 <https://rubinobs.atlassian.net/browse/DM-50044>`_)
62
+ - Significantly sped up ``Butler.pruneDatasets`` by using parallelized artifact deletions. (`DM-50724 <https://rubinobs.atlassian.net/browse/DM-50724>`_)
63
+ - Modified trash emptying in datastore such that only the datasets to be removed as part of the original butler request are the ones that are trashed immediately. (`DM-50727 <https://rubinobs.atlassian.net/browse/DM-50727>`_)
64
+ - Modified CLI tooling to work with both click 8.1 and click 8.2. (`DM-50823 <https://rubinobs.atlassian.net/browse/DM-50823>`_)
65
+ - Fixed handling of ``FileDatastore.transfer_from()`` such that it now works with chained datastores. (`DM-50935 <https://rubinobs.atlassian.net/browse/DM-50935>`_)
66
+ - Reorganized ``Butler.removeRuns()`` to remove datasets in chunks to provide more feedback to the user and allow for restarting if the command fails for some reason. (`DM-50996 <https://rubinobs.atlassian.net/browse/DM-50996>`_)
67
+ - Added a ``fallback_instrument`` to ObsCore configurations.
68
+ This instrument is used when an ObsCore record is constructed from a dataset type that has no instrument defined. (`DM-51269 <https://rubinobs.atlassian.net/browse/DM-51269>`_)
69
+ - ``Butler.transfer_from()`` will now raise a `FileNotFoundError` while transferring files if a file listed in the database is not actually available on the filesystem. Previously, it would silently skip the file. (`DM-51302 <https://rubinobs.atlassian.net/browse/DM-51302>`_)
70
+
71
+
1
72
  Butler v29.0.0 (2025-03-25)
2
73
  ===========================
3
74
 
@@ -77,7 +77,7 @@ zip-safe = true
77
77
  license-files = ["COPYRIGHT", "LICENSE", "bsd_license.txt", "gpl-v3.0.txt"]
78
78
 
79
79
  [tool.setuptools.package-data]
80
- "lsst.daf.butler" = ["py.typed", "configs/*.yaml", "configs/*/*.yaml"]
80
+ "lsst.daf.butler" = ["py.typed", "configs/*.yaml", "configs/*/*.yaml", "tests/registry_data/*.yaml"]
81
81
 
82
82
  [tool.setuptools.dynamic]
83
83
  version = { attr = "lsst_versions.get_lsst_version" }
@@ -42,7 +42,7 @@ from ._dataset_provenance import DatasetProvenance
42
42
  from ._dataset_ref import DatasetRef
43
43
  from ._deferredDatasetHandle import DeferredDatasetHandle
44
44
  from ._storage_class import StorageClass, StorageClassFactory
45
- from .datastore import DatasetRefURIs, Datastore
45
+ from .datastore import DatasetRefURIs, Datastore, FileTransferSource
46
46
  from .dimensions import DimensionUniverse
47
47
 
48
48
  log = logging.getLogger(__name__)
@@ -450,6 +450,13 @@ class LimitedButler(ABC):
450
450
  """
451
451
  raise NotImplementedError()
452
452
 
453
+ @property
454
+ def _file_transfer_source(self) -> FileTransferSource:
455
+ """Object that manages the transfer of files between Butler
456
+ repositories.
457
+ """
458
+ return self._datastore
459
+
453
460
  _datastore: Datastore
454
461
  """The object that manages actual dataset storage (`Datastore`)."""
455
462
 
@@ -26,3 +26,4 @@
26
26
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
27
27
 
28
28
  from ._datastore import *
29
+ from ._transfer import *
@@ -54,6 +54,7 @@ from .._config import Config, ConfigSubset
54
54
  from .._exceptions import DatasetTypeNotSupportedError, ValidationError
55
55
  from .._file_dataset import FileDataset
56
56
  from .._storage_class import StorageClassFactory
57
+ from ._transfer import FileTransferMap, FileTransferSource
57
58
  from .constraints import Constraints
58
59
 
59
60
  if TYPE_CHECKING:
@@ -62,10 +63,11 @@ if TYPE_CHECKING:
62
63
  from .. import ddl
63
64
  from .._config_support import LookupKey
64
65
  from .._dataset_provenance import DatasetProvenance
65
- from .._dataset_ref import DatasetRef
66
+ from .._dataset_ref import DatasetId, DatasetRef
66
67
  from .._dataset_type import DatasetType
67
68
  from .._storage_class import StorageClass
68
69
  from ..datastores.file_datastore.retrieve_artifacts import ArtifactIndexInfo
70
+ from ..datastores.fileDatastoreClient import FileDatastoreGetPayload
69
71
  from ..registry.interfaces import DatasetIdRef, DatastoreRegistryBridgeManager
70
72
  from .record_data import DatastoreRecordData
71
73
  from .stored_file_info import StoredDatastoreItemInfo
@@ -283,7 +285,7 @@ class DatasetRefURIs(abc.Sequence):
283
285
  return f"DatasetRefURIs({repr(self.primaryURI)}, {repr(self.componentURIs)})"
284
286
 
285
287
 
286
- class Datastore(metaclass=ABCMeta):
288
+ class Datastore(FileTransferSource, metaclass=ABCMeta):
287
289
  """Datastore interface.
288
290
 
289
291
  Parameters
@@ -612,7 +614,7 @@ class Datastore(metaclass=ABCMeta):
612
614
  """
613
615
  raise NotImplementedError("Must be implemented by subclass")
614
616
 
615
- def prepare_get_for_external_client(self, ref: DatasetRef) -> object | None:
617
+ def prepare_get_for_external_client(self, ref: DatasetRef) -> FileDatastoreGetPayload | None:
616
618
  """Retrieve serializable data that can be used to execute a ``get()``.
617
619
 
618
620
  Parameters
@@ -868,7 +870,7 @@ class Datastore(metaclass=ABCMeta):
868
870
 
869
871
  def transfer_from(
870
872
  self,
871
- source_datastore: Datastore,
873
+ source_records: FileTransferMap,
872
874
  refs: Collection[DatasetRef],
873
875
  transfer: str = "auto",
874
876
  artifact_existence: dict[ResourcePath, bool] | None = None,
@@ -878,9 +880,8 @@ class Datastore(metaclass=ABCMeta):
878
880
 
879
881
  Parameters
880
882
  ----------
881
- source_datastore : `Datastore`
882
- The datastore from which to transfer artifacts. That datastore
883
- must be compatible with this datastore receiving the artifacts.
883
+ source_records : `FileTransferMap`
884
+ The artifacts to be transferred into this datastore.
884
885
  refs : `~collections.abc.Collection` of `DatasetRef`
885
886
  The datasets to transfer from the source datastore.
886
887
  transfer : `str`, optional
@@ -915,13 +916,7 @@ class Datastore(metaclass=ABCMeta):
915
916
  TypeError
916
917
  Raised if the two datastores are not compatible.
917
918
  """
918
- if type(self) is not type(source_datastore):
919
- raise TypeError(
920
- f"Datastore mismatch between this datastore ({type(self)}) and the "
921
- f"source datastore ({type(source_datastore)})."
922
- )
923
-
924
- raise NotImplementedError(f"Datastore {type(self)} must implement a transfer_from method.")
919
+ raise NotImplementedError(f"Datastore {type(self)} does not implement a transfer_from method.")
925
920
 
926
921
  def getManyURIs(
927
922
  self,
@@ -1420,6 +1415,14 @@ class Datastore(metaclass=ABCMeta):
1420
1415
  """
1421
1416
  raise NotImplementedError()
1422
1417
 
1418
+ def get_file_info_for_transfer(self, dataset_ids: Iterable[DatasetId]) -> FileTransferMap:
1419
+ raise NotImplementedError(f"Transferring files is not supported by datastore {self}")
1420
+
1421
+ def locate_missing_files_for_transfer(
1422
+ self, refs: Iterable[DatasetRef], artifact_existence: dict[ResourcePath, bool]
1423
+ ) -> FileTransferMap:
1424
+ return {}
1425
+
1423
1426
 
1424
1427
  class NullDatastore(Datastore):
1425
1428
  """A datastore that implements the `Datastore` API but always fails when
@@ -1494,7 +1497,7 @@ class NullDatastore(Datastore):
1494
1497
 
1495
1498
  def transfer_from(
1496
1499
  self,
1497
- source_datastore: Datastore,
1500
+ source_records: FileTransferMap,
1498
1501
  refs: Iterable[DatasetRef],
1499
1502
  transfer: str = "auto",
1500
1503
  artifact_existence: dict[ResourcePath, bool] | None = None,
@@ -0,0 +1,102 @@
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.abc import Iterable
31
+ from typing import NamedTuple, Protocol, TypeAlias
32
+
33
+ from lsst.resources import ResourcePath
34
+
35
+ from .._dataset_ref import DatasetId, DatasetRef
36
+ from .stored_file_info import Location, StoredFileInfo
37
+
38
+ __all__ = ("FileTransferMap", "FileTransferRecord", "FileTransferSource")
39
+
40
+
41
+ class FileTransferSource(Protocol):
42
+ """Protocol for an object that can return information about files that need
43
+ to be transferred to copy datasets from one Butler repository to another.
44
+ """
45
+
46
+ name: str
47
+ """A human-readable, descriptive name for this file transfer source."""
48
+
49
+ def get_file_info_for_transfer(self, dataset_ids: Iterable[DatasetId]) -> FileTransferMap:
50
+ """Given a list of dataset IDs, return all file information associated
51
+ with the datasets that can be determined without searching the
52
+ filesystem.
53
+
54
+ Parameters
55
+ ----------
56
+ dataset_ids : `~collections.abc.Iterable` [ `DatasetId` ]
57
+ List of dataset IDs for which we will retrieve file information.
58
+
59
+ Return
60
+ ------
61
+ transfer_map : `FileTransferMap`
62
+ Dictionary from `DatasetId` to a list of files found for that
63
+ dataset. If information about any given dataset IDs could not
64
+ be found, the missing IDs are omitted from the dictionary.
65
+ """
66
+
67
+ def locate_missing_files_for_transfer(
68
+ self, refs: Iterable[DatasetRef], artifact_existence: dict[ResourcePath, bool]
69
+ ) -> FileTransferMap:
70
+ """Given a list of `DatasetRef`, search the filesystem to locate
71
+ artifacts associated with the dataset.
72
+
73
+ Parameters
74
+ ----------
75
+ refs : iterable of `DatasetRef`
76
+ The datasets to be checked.
77
+ artifact_existence : `dict` [`lsst.resources.ResourcePath`, `bool`]
78
+ Optional mapping of datastore artifact to existence. Updated by
79
+ this method with details of all artifacts tested.
80
+
81
+ Return
82
+ ------
83
+ transfer_map : `FileTransferMap`
84
+ Dictionary from `DatasetId` to a list of files found for that
85
+ dataset. If information about any given dataset IDs could not
86
+ be found, the missing IDs are omitted from the dictionary.
87
+ """
88
+
89
+
90
+ class FileTransferRecord(NamedTuple):
91
+ """Information needed to transfer a file from one Butler repository to
92
+ another.
93
+ """
94
+
95
+ location: Location
96
+ file_info: StoredFileInfo
97
+
98
+
99
+ FileTransferMap: TypeAlias = dict[DatasetId, list[FileTransferRecord]]
100
+ """A dictionary from `DatasetId` to a list of `FileTransferRecord`, containing
101
+ the datastore information about a set of files to be transferred.
102
+ """
@@ -32,7 +32,7 @@ __all__ = ("SerializedStoredFileInfo", "StoredDatastoreItemInfo", "StoredFileInf
32
32
  import inspect
33
33
  from collections.abc import Iterable, Mapping
34
34
  from dataclasses import dataclass
35
- from typing import TYPE_CHECKING, Any
35
+ from typing import TYPE_CHECKING, Any, ClassVar
36
36
 
37
37
  import pydantic
38
38
 
@@ -192,30 +192,44 @@ class StoredFileInfo(StoredDatastoreItemInfo):
192
192
  The formatter to use for this dataset.
193
193
  path : `str`
194
194
  Path to the artifact associated with this dataset.
195
- storageClass : `StorageClass`
196
- The storage class associated with this dataset.
195
+ storageClass : `StorageClass` or `None`
196
+ The storage class associated with this dataset. If `None`,
197
+ ``storage_class_name`` must be provided as a keyword argument.
197
198
  component : `str` or `None`, optional
198
199
  The component if disassembled.
199
200
  checksum : `str` or `None`, optional
200
201
  The checksum of the artifact.
201
202
  file_size : `int`
202
203
  The size of the file in bytes. -1 indicates the size is not known.
204
+ storage_class_name : `str`, optional
205
+ Name of the storage class. This may be passed instead of
206
+ ``storageClass`` to defer loading storage class definitions (e.g. if a
207
+ butler configuration may not have been loaded yet). Note that
208
+ ``storageClass=None`` must be passed explicitly (for backward
209
+ compatibility, it remains a positional argument with no default).
203
210
  """
204
211
 
205
- storageClassFactory = StorageClassFactory()
212
+ storageClassFactory: ClassVar[StorageClassFactory] = StorageClassFactory()
206
213
 
207
214
  def __init__(
208
215
  self,
209
216
  formatter: FormatterParameter,
210
217
  path: str,
211
- storageClass: StorageClass,
218
+ storageClass: StorageClass | None,
212
219
  component: str | None,
213
220
  checksum: str | None,
214
221
  file_size: int,
222
+ *,
223
+ storage_class_name: str | None = None,
215
224
  ):
216
225
  # Use these shenanigans to allow us to use a frozen dataclass
217
226
  object.__setattr__(self, "path", path)
218
- object.__setattr__(self, "storageClass", storageClass)
227
+ if storageClass is not None:
228
+ object.__setattr__(self, "storage_class_name", storageClass.name)
229
+ else:
230
+ if storage_class_name is None:
231
+ raise TypeError("At least one of 'storageClass' and 'storage_class_name' must be provided.")
232
+ object.__setattr__(self, "storage_class_name", storage_class_name)
219
233
  object.__setattr__(self, "component", component)
220
234
  object.__setattr__(self, "checksum", checksum)
221
235
  object.__setattr__(self, "file_size", file_size)
@@ -238,8 +252,8 @@ class StoredFileInfo(StoredDatastoreItemInfo):
238
252
  path: str
239
253
  """Path to dataset within Datastore."""
240
254
 
241
- storageClass: StorageClass
242
- """StorageClass associated with Dataset."""
255
+ storage_class_name: str
256
+ """Name of the storage class associated with this dataset."""
243
257
 
244
258
  component: str | None
245
259
  """Component associated with this file. Can be `None` if the file does
@@ -251,6 +265,11 @@ class StoredFileInfo(StoredDatastoreItemInfo):
251
265
  file_size: int
252
266
  """Size of the serialized dataset in bytes."""
253
267
 
268
+ @property
269
+ def storageClass(self) -> StorageClass:
270
+ """Storage class associated with this dataset."""
271
+ return self.storageClassFactory.getStorageClass(self.storage_class_name)
272
+
254
273
  def rebase(self, ref: DatasetRef) -> StoredFileInfo:
255
274
  """Return a copy of the record suitable for a specified reference.
256
275
 
@@ -287,7 +306,7 @@ class StoredFileInfo(StoredDatastoreItemInfo):
287
306
  return dict(
288
307
  formatter=self.formatter,
289
308
  path=self.path,
290
- storage_class=self.storageClass.name,
309
+ storage_class=self.storage_class_name,
291
310
  component=component,
292
311
  checksum=self.checksum,
293
312
  file_size=self.file_size,
@@ -336,12 +355,12 @@ class StoredFileInfo(StoredDatastoreItemInfo):
336
355
  The newly-constructed item corresponding to the record.
337
356
  """
338
357
  # Convert name of StorageClass to instance
339
- storageClass = cls.storageClassFactory.getStorageClass(record["storage_class"])
340
358
  component = record["component"] if (record["component"] and record["component"] != NULLSTR) else None
341
359
  info = cls(
342
360
  formatter=record["formatter"],
343
361
  path=record["path"],
344
- storageClass=storageClass,
362
+ storageClass=None,
363
+ storage_class_name=record["storage_class"],
345
364
  component=component,
346
365
  checksum=record["checksum"],
347
366
  file_size=record["file_size"],
@@ -353,7 +372,7 @@ class StoredFileInfo(StoredDatastoreItemInfo):
353
372
  return cls.from_record(dict(model))
354
373
 
355
374
  def update(self, **kwargs: Any) -> StoredFileInfo:
356
- new_args = {}
375
+ new_args: dict[str, Any] = {"storageClass": None} # so `storage_class_name` can be passed.
357
376
  for k in self.__slots__:
358
377
  if k in kwargs:
359
378
  new_args[k] = kwargs.pop(k)
@@ -395,3 +414,37 @@ class SerializedStoredFileInfo(pydantic.BaseModel):
395
414
 
396
415
  file_size: int
397
416
  """Size of the serialized dataset in bytes."""
417
+
418
+
419
+ def make_datastore_path_relative(path: str) -> str:
420
+ """Normalize a path from a `StoredFileInfo` object so
421
+ that it is always relative.
422
+
423
+ Parameters
424
+ ----------
425
+ path : `str`
426
+ The file path from a `StoredFileInfo`.
427
+
428
+ Return
429
+ ------
430
+ normalized_path : `str`
431
+ The original path, if it was relative. Otherwise, a version of it that
432
+ was converted to a relative path, stripping URI scheme and netloc from
433
+ it.
434
+ """
435
+ # Force the datastore file path sent to the client to be relative, since
436
+ # absolute URLs in the server will generally not be reachable by the
437
+ # client. If an absolute URL is sent, it (or a portion of it) can end up
438
+ # baked into the FileDatastore that is the target of the transfer in some
439
+ # cases.
440
+ rpath = ResourcePath(path, forceAbsolute=False, forceDirectory=False)
441
+ if rpath.isabs():
442
+ relative = rpath.relativeToPathRoot
443
+ if rpath.fragment:
444
+ # Preserve the fragment, since this used to indicate special
445
+ # processing like zip extraction.
446
+ return f"{relative}#{rpath.fragment}"
447
+ else:
448
+ return relative
449
+ else:
450
+ return path
@@ -50,13 +50,19 @@ from lsst.daf.butler.datastore.record_data import DatastoreRecordData
50
50
  from lsst.daf.butler.datastores.file_datastore.retrieve_artifacts import ArtifactIndexInfo, ZipIndex
51
51
  from lsst.resources import ResourcePath
52
52
  from lsst.utils import doImportType
53
+ from lsst.utils.introspection import get_full_type_name
53
54
  from lsst.utils.logging import getLogger
54
55
 
56
+ from .._dataset_ref import DatasetId
57
+ from ..datastore import FileTransferMap
58
+
55
59
  if TYPE_CHECKING:
56
60
  from lsst.daf.butler import Config, DatasetProvenance, DatasetType, LookupKey, StorageClass
57
61
  from lsst.daf.butler.registry.interfaces import DatasetIdRef, DatastoreRegistryBridgeManager
58
62
  from lsst.resources import ResourcePathExpression
59
63
 
64
+ from .fileDatastoreClient import FileDatastoreGetPayload
65
+
60
66
  log = getLogger(__name__)
61
67
 
62
68
 
@@ -405,7 +411,7 @@ class ChainedDatastore(Datastore):
405
411
 
406
412
  raise FileNotFoundError(f"Dataset {ref} could not be found in any of the datastores")
407
413
 
408
- def prepare_get_for_external_client(self, ref: DatasetRef) -> object | None:
414
+ def prepare_get_for_external_client(self, ref: DatasetRef) -> FileDatastoreGetPayload | None:
409
415
  datastore = self._get_matching_datastore(ref)
410
416
  if datastore is None:
411
417
  return None
@@ -1234,9 +1240,50 @@ class ChainedDatastore(Datastore):
1234
1240
  raise FileNotFoundError(f"Failed to export dataset {refs[i]}.")
1235
1241
  yield dataset
1236
1242
 
1243
+ def get_file_info_for_transfer(self, dataset_ids: Iterable[DatasetId]) -> FileTransferMap:
1244
+ unassigned_ids = set(dataset_ids)
1245
+ output: FileTransferMap = {}
1246
+ found_acceptable_datastore = False
1247
+ for datastore in self.datastores:
1248
+ try:
1249
+ found = datastore.get_file_info_for_transfer(unassigned_ids)
1250
+ found_acceptable_datastore = True
1251
+ output.update(found)
1252
+ unassigned_ids -= found.keys()
1253
+ except NotImplementedError:
1254
+ pass
1255
+
1256
+ if not found_acceptable_datastore:
1257
+ types = {get_full_type_name(d) for d in self.datastores}
1258
+ raise TypeError(
1259
+ "ChainedDatastore had no datastores able to provide file transfer information."
1260
+ f" Had {','.join(types)}"
1261
+ )
1262
+
1263
+ return output
1264
+
1265
+ def locate_missing_files_for_transfer(
1266
+ self, refs: Iterable[DatasetRef], artifact_existence: dict[ResourcePath, bool]
1267
+ ) -> FileTransferMap:
1268
+ missing_refs = {ref.id: ref for ref in refs}
1269
+ output: FileTransferMap = {}
1270
+ for datastore in self.datastores:
1271
+ # Have to check each datastore in turn. If we do not do
1272
+ # this warnings will be issued further down for datasets
1273
+ # that are in one and not the other. The existence cache
1274
+ # will prevent repeat checks.
1275
+
1276
+ found = datastore.locate_missing_files_for_transfer(missing_refs.values(), artifact_existence)
1277
+ output.update(found)
1278
+ for id in found.keys():
1279
+ missing_refs.pop(id)
1280
+ log.debug("Adding %d missing refs to list for transfer from %s", len(found), datastore.name)
1281
+
1282
+ return output
1283
+
1237
1284
  def transfer_from(
1238
1285
  self,
1239
- source_datastore: Datastore,
1286
+ source_records: FileTransferMap,
1240
1287
  refs: Collection[DatasetRef],
1241
1288
  transfer: str = "auto",
1242
1289
  artifact_existence: dict[ResourcePath, bool] | None = None,
@@ -1259,7 +1306,7 @@ class ChainedDatastore(Datastore):
1259
1306
  rejected: set[DatasetRef] = set()
1260
1307
  nsuccess = 0
1261
1308
 
1262
- log.debug("Initiating transfer to chained datastore %s from %s", self.name, source_datastore.name)
1309
+ log.debug("Initiating transfer to chained datastore %s", self.name)
1263
1310
  for datastore in self.datastores:
1264
1311
  # Rejections from this datastore might be acceptances in the next.
1265
1312
  # We add them all up but then recalculate at the end.
@@ -1269,7 +1316,7 @@ class ChainedDatastore(Datastore):
1269
1316
 
1270
1317
  try:
1271
1318
  current_accepted, current_rejected = datastore.transfer_from(
1272
- source_datastore,
1319
+ source_records,
1273
1320
  available_refs,
1274
1321
  transfer=transfer,
1275
1322
  artifact_existence=artifact_existence,
@@ -1288,13 +1335,12 @@ class ChainedDatastore(Datastore):
1288
1335
  rejected.update(current_rejected)
1289
1336
 
1290
1337
  if nsuccess == 0:
1291
- raise TypeError(f"None of the child datastores could accept transfers from {source_datastore!r}")
1338
+ raise TypeError("None of the child datastores could accept file transfers")
1292
1339
 
1293
1340
  # It's not rejected if some other datastore accepted it.
1294
1341
  rejected -= accepted
1295
1342
  log.verbose(
1296
- "Finished transfer_from %s to %s with %d accepted, %d rejected from %d requested.",
1297
- source_datastore.name,
1343
+ "Finished transfer_from to %s with %d accepted, %d rejected from %d requested.",
1298
1344
  self.name,
1299
1345
  len(accepted),
1300
1346
  len(rejected),