lsst-daf-butler 29.2025.2400__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.2400/python/lsst_daf_butler.egg-info → lsst_daf_butler-29.2025.2500}/PKG-INFO +1 -1
  2. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/CHANGES.rst +71 -0
  3. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/pyproject.toml +1 -1
  4. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/_datastore.py +2 -1
  5. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/stored_file_info.py +31 -12
  6. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/chainedDatastore.py +3 -1
  7. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/_direct_butler.py +5 -6
  8. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_driver.py +1 -1
  9. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_config.py +21 -0
  10. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/postgresql.py +15 -1
  11. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/sqlite.py +16 -1
  12. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_database.py +21 -1
  13. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_config.py +5 -0
  14. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_records.py +3 -0
  15. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/sql_registry.py +5 -1
  16. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/_registry.py +59 -46
  17. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_http_connection.py +6 -2
  18. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_remote_file_transfer_source.py +49 -7
  19. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_factory.py +4 -0
  20. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_external.py +67 -9
  21. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_external_query.py +24 -11
  22. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/remote_butler/server/handlers/_query_limits.py +105 -0
  23. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_query_streaming.py +11 -47
  24. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_utils.py +15 -1
  25. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server_models.py +1 -0
  26. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/butler_queries.py +50 -43
  27. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/__init__.py +0 -0
  28. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/base.yaml +81 -0
  29. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset-skymap.yaml +45 -0
  30. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/ci_hsc-subset.yaml +732 -0
  31. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/datasets.yaml +138 -0
  32. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/hsc-rc2-subset-v0.yaml +159 -0
  33. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/spatial.py +617 -0
  34. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/tests/registry_data/spatial.yaml +192 -0
  35. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/utils.py +12 -3
  36. lsst_daf_butler-29.2025.2500/python/lsst/daf/butler/version.py +2 -0
  37. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500/python/lsst_daf_butler.egg-info}/PKG-INFO +1 -1
  38. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/SOURCES.txt +9 -0
  39. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_butler.py +19 -6
  40. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryCollections.py +2 -5
  41. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDataIds.py +1 -1
  42. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_dimension_record_containers.py +2 -3
  43. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_postgresql.py +4 -3
  44. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_quantumBackedButler.py +1 -1
  45. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_remote_butler.py +2 -1
  46. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_server.py +87 -7
  47. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_simpleButler.py +26 -26
  48. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_sqlite.py +11 -7
  49. lsst_daf_butler-29.2025.2400/python/lsst/daf/butler/version.py +0 -2
  50. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/COPYRIGHT +0 -0
  51. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/LICENSE +0 -0
  52. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/MANIFEST.in +0 -0
  53. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/README.md +0 -0
  54. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/bsd_license.txt +0 -0
  55. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/concreteStorageClasses.rst +0 -0
  56. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/configuring.rst +0 -0
  57. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/datastores.rst +0 -0
  58. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/dimensions.rst +0 -0
  59. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/formatters.rst +0 -0
  60. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/index.rst +0 -0
  61. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/organizing.rst +0 -0
  62. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/queries.rst +0 -0
  63. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/use-in-tests.rst +0 -0
  64. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/doc/lsst.daf.butler/writing-subcommands.rst +0 -0
  65. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/gpl-v3.0.txt +0 -0
  66. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/__init__.py +0 -0
  67. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/__init__.py +0 -0
  68. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/__init__.py +0 -0
  69. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler.py +0 -0
  70. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_collections.py +0 -0
  71. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_config.py +0 -0
  72. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_instance_options.py +0 -0
  73. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_metrics.py +0 -0
  74. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_butler_repo_index.py +0 -0
  75. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_collection_type.py +0 -0
  76. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_categorization.py +0 -0
  77. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_tags.py +0 -0
  78. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_column_type_info.py +0 -0
  79. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_config.py +0 -0
  80. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_config_support.py +0 -0
  81. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_association.py +0 -0
  82. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_existence.py +0 -0
  83. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_provenance.py +0 -0
  84. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_ref.py +0 -0
  85. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_dataset_type.py +0 -0
  86. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_deferredDatasetHandle.py +0 -0
  87. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_exceptions.py +0 -0
  88. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_exceptions_legacy.py +0 -0
  89. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_file_dataset.py +0 -0
  90. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_file_descriptor.py +0 -0
  91. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_formatter.py +0 -0
  92. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_labeled_butler_factory.py +0 -0
  93. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_limited_butler.py +0 -0
  94. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_location.py +0 -0
  95. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_named.py +0 -0
  96. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_quantum.py +0 -0
  97. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_quantum_backed.py +0 -0
  98. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_query_all_datasets.py +0 -0
  99. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_registry_shim.py +0 -0
  100. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_storage_class.py +0 -0
  101. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_storage_class_delegate.py +0 -0
  102. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_timespan.py +0 -0
  103. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_topology.py +0 -0
  104. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/__init__.py +0 -0
  105. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/locked_object.py +0 -0
  106. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/named_locks.py +0 -0
  107. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/_utilities/thread_safe_cache.py +0 -0
  108. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/arrow_utils.py +0 -0
  109. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/__init__.py +0 -0
  110. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/butler.py +0 -0
  111. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cliLog.py +0 -0
  112. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/__init__.py +0 -0
  113. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/_remove_collections.py +0 -0
  114. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/_remove_runs.py +0 -0
  115. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/cmd/commands.py +0 -0
  116. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/__init__.py +0 -0
  117. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/arguments.py +0 -0
  118. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/optionGroups.py +0 -0
  119. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/opt/options.py +0 -0
  120. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/progress.py +0 -0
  121. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/cli/utils.py +0 -0
  122. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/column_spec.py +0 -0
  123. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastore.yaml +0 -0
  124. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/composites.yaml +0 -0
  125. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/fileDatastore.yaml +0 -0
  126. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/formatters.yaml +0 -0
  127. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/datastores/writeRecipes.yaml +0 -0
  128. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/dimensions.yaml +0 -0
  129. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe0.yaml +0 -0
  130. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe1.yaml +0 -0
  131. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe2.yaml +0 -0
  132. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe3.yaml +0 -0
  133. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe4.yaml +0 -0
  134. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe5.yaml +0 -0
  135. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe6.yaml +0 -0
  136. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/old_dimensions/daf_butler_universe7.yaml +0 -0
  137. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/registry.yaml +0 -0
  138. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/repo_transfer_formats.yaml +0 -0
  139. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/configs/storageClasses.yaml +0 -0
  140. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/__init__.py +0 -0
  141. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/_transfer.py +0 -0
  142. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/cache_manager.py +0 -0
  143. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/composites.py +0 -0
  144. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/constraints.py +0 -0
  145. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/file_templates.py +0 -0
  146. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/generic_base.py +0 -0
  147. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastore/record_data.py +0 -0
  148. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/__init__.py +0 -0
  149. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/fileDatastore.py +0 -0
  150. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/fileDatastoreClient.py +0 -0
  151. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/__init__.py +0 -0
  152. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/get.py +0 -0
  153. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/retrieve_artifacts.py +0 -0
  154. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/file_datastore/transfer.py +0 -0
  155. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/datastores/inMemoryDatastore.py +0 -0
  156. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/ddl.py +0 -0
  157. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/delegates/__init__.py +0 -0
  158. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/delegates/arrowtable.py +0 -0
  159. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/__init__.py +0 -0
  160. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_config.py +0 -0
  161. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_coordinate.py +0 -0
  162. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_data_coordinate_iterable.py +0 -0
  163. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_database.py +0 -0
  164. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_elements.py +0 -0
  165. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_governor.py +0 -0
  166. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_group.py +0 -0
  167. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_packer.py +0 -0
  168. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_record_set.py +0 -0
  169. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_record_table.py +0 -0
  170. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_records.py +0 -0
  171. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_schema.py +0 -0
  172. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_skypix.py +0 -0
  173. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/_universe.py +0 -0
  174. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/construction.py +0 -0
  175. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/dimensions/record_cache.py +0 -0
  176. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/__init__.py +0 -0
  177. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_butler/_direct_butler_collections.py +0 -0
  178. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/__init__.py +0 -0
  179. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_postprocessing.py +0 -0
  180. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_query_analysis.py +0 -0
  181. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_query_builder.py +0 -0
  182. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_result_page_converter.py +0 -0
  183. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_sql_builders.py +0 -0
  184. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/direct_query_driver/_sql_column_visitor.py +0 -0
  185. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/__init__.py +0 -0
  186. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/astropyTable.py +0 -0
  187. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/file.py +0 -0
  188. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/json.py +0 -0
  189. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/logs.py +0 -0
  190. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/matplotlib.py +0 -0
  191. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/packages.py +0 -0
  192. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/parquet.py +0 -0
  193. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/pickle.py +0 -0
  194. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/typeless.py +0 -0
  195. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/formatters/yaml.py +0 -0
  196. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/json.py +0 -0
  197. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/logging.py +0 -0
  198. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/mapping_factory.py +0 -0
  199. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/name_shrinker.py +0 -0
  200. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/nonempty_mapping.py +0 -0
  201. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/persistence_context.py +0 -0
  202. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/progress.py +0 -0
  203. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/py.typed +0 -0
  204. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/pydantic_utils.py +0 -0
  205. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/__init__.py +0 -0
  206. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_base.py +0 -0
  207. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_data_coordinate_query_results.py +0 -0
  208. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_dataset_query_results.py +0 -0
  209. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_dimension_record_query_results.py +0 -0
  210. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_expression_strings.py +0 -0
  211. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_general_query_results.py +0 -0
  212. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_identifiers.py +0 -0
  213. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/_query.py +0 -0
  214. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/convert_args.py +0 -0
  215. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/driver.py +0 -0
  216. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/expression_factory.py +0 -0
  217. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/overlaps.py +0 -0
  218. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/predicate_constraints_summary.py +0 -0
  219. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/result_specs.py +0 -0
  220. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/__init__.py +0 -0
  221. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_base.py +0 -0
  222. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_expression.py +0 -0
  223. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_literal.py +0 -0
  224. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_reference.py +0 -0
  225. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_column_set.py +0 -0
  226. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_predicate.py +0 -0
  227. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/tree/_query_tree.py +0 -0
  228. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/queries/visitors.py +0 -0
  229. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/__init__.py +0 -0
  230. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_caching_context.py +0 -0
  231. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_record_cache.py +0 -0
  232. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_summary.py +0 -0
  233. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_collection_summary_cache.py +0 -0
  234. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_defaults.py +0 -0
  235. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_exceptions.py +0 -0
  236. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_registry.py +0 -0
  237. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/_registry_factory.py +0 -0
  238. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/attributes.py +0 -0
  239. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/__init__.py +0 -0
  240. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/ephemeral.py +0 -0
  241. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/bridge/monolithic.py +0 -0
  242. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/__init__.py +0 -0
  243. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/_base.py +0 -0
  244. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/nameKey.py +0 -0
  245. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/collections/synthIntKey.py +0 -0
  246. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/connectionString.py +0 -0
  247. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/databases/__init__.py +0 -0
  248. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/__init__.py +0 -0
  249. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/__init__.py +0 -0
  250. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/_dataset_type_cache.py +0 -0
  251. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/_manager.py +0 -0
  252. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/summaries.py +0 -0
  253. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/datasets/byDimensions/tables.py +0 -0
  254. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/dimensions/__init__.py +0 -0
  255. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/dimensions/static.py +0 -0
  256. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/__init__.py +0 -0
  257. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_attributes.py +0 -0
  258. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_bridge.py +0 -0
  259. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_collections.py +0 -0
  260. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_database_explain.py +0 -0
  261. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_datasets.py +0 -0
  262. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_dimensions.py +0 -0
  263. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_obscore.py +0 -0
  264. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_opaque.py +0 -0
  265. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/interfaces/_versioning.py +0 -0
  266. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/managers.py +0 -0
  267. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/nameShrinker.py +0 -0
  268. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/__init__.py +0 -0
  269. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_manager.py +0 -0
  270. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_schema.py +0 -0
  271. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/_spatial.py +0 -0
  272. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/default_spatial.py +0 -0
  273. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/obscore/pgsphere.py +0 -0
  274. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/opaque.py +0 -0
  275. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/__init__.py +0 -0
  276. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_builder.py +0 -0
  277. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query.py +0 -0
  278. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query_backend.py +0 -0
  279. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_query_context.py +0 -0
  280. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_readers.py +0 -0
  281. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_results.py +0 -0
  282. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_sql_query_backend.py +0 -0
  283. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_sql_query_context.py +0 -0
  284. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/_structs.py +0 -0
  285. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/butler_sql_engine.py +0 -0
  286. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/__init__.py +0 -0
  287. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/_predicate.py +0 -0
  288. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/categorize.py +0 -0
  289. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/check.py +0 -0
  290. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/normalForm.py +0 -0
  291. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/__init__.py +0 -0
  292. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/exprTree.py +0 -0
  293. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parser.py +0 -0
  294. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parserLex.py +0 -0
  295. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/parserYacc.py +0 -0
  296. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/__init__.py +0 -0
  297. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/lex.py +0 -0
  298. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/ply/yacc.py +0 -0
  299. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/expressions/parser/treeVisitor.py +0 -0
  300. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/queries/find_first_dataset.py +0 -0
  301. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/__init__.py +0 -0
  302. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/tests/_database.py +0 -0
  303. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/versions.py +0 -0
  304. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/registry/wildcards.py +0 -0
  305. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/__init__.py +0 -0
  306. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_authentication.py +0 -0
  307. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_collection_args.py +0 -0
  308. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_config.py +0 -0
  309. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_defaults.py +0 -0
  310. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_errors.py +0 -0
  311. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_factory.py +0 -0
  312. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_query_driver.py +0 -0
  313. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_query_results.py +0 -0
  314. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_ref_utils.py +0 -0
  315. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_registry.py +0 -0
  316. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_remote_butler.py +0 -0
  317. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/_remote_butler_collections.py +0 -0
  318. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/__init__.py +0 -0
  319. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_common.py +0 -0
  320. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_data_coordinates.py +0 -0
  321. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_datasets.py +0 -0
  322. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/registry/_query_dimension_records.py +0 -0
  323. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/__init__.py +0 -0
  324. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_config.py +0 -0
  325. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_dependencies.py +0 -0
  326. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_gafaelfawr.py +0 -0
  327. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_server.py +0 -0
  328. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/_telemetry.py +0 -0
  329. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_internal.py +0 -0
  330. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/remote_butler/server/handlers/_query_serialization.py +0 -0
  331. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/repo_relocation.py +0 -0
  332. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/__init__.py +0 -0
  333. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/_associate.py +0 -0
  334. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/_pruneDatasets.py +0 -0
  335. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/butlerImport.py +0 -0
  336. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/certifyCalibrations.py +0 -0
  337. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/collectionChain.py +0 -0
  338. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/configDump.py +0 -0
  339. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/configValidate.py +0 -0
  340. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/createRepo.py +0 -0
  341. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/exportCalibs.py +0 -0
  342. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/ingest_files.py +0 -0
  343. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/ingest_zip.py +0 -0
  344. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryCollections.py +0 -0
  345. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDataIds.py +0 -0
  346. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDatasetTypes.py +0 -0
  347. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDatasets.py +0 -0
  348. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/queryDimensionRecords.py +0 -0
  349. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/register_dataset_type.py +0 -0
  350. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeCollections.py +0 -0
  351. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeDatasetType.py +0 -0
  352. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/removeRuns.py +0 -0
  353. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/retrieveArtifacts.py +0 -0
  354. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/script/transferDatasets.py +0 -0
  355. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/__init__.py +0 -0
  356. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_datasetsHelper.py +0 -0
  357. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_dummyRegistry.py +0 -0
  358. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_examplePythonTypes.py +0 -0
  359. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/_testRepo.py +0 -0
  360. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/cliCmdTestBase.py +0 -0
  361. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/cliLogTestBase.py +0 -0
  362. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/deferredFormatter.py +0 -0
  363. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/dict_convertible_model.py +0 -0
  364. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler.py +0 -0
  365. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler_collections.py +0 -0
  366. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/hybrid_butler_registry.py +0 -0
  367. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/postgresql.py +0 -0
  368. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/server.py +0 -0
  369. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/server_utils.py +0 -0
  370. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/tests/testFormatters.py +0 -0
  371. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/time_utils.py +0 -0
  372. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/timespan_database_representation.py +0 -0
  373. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/__init__.py +0 -0
  374. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_context.py +0 -0
  375. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_interfaces.py +0 -0
  376. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/transfers/_yaml.py +0 -0
  377. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst/daf/butler/utils.py +0 -0
  378. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/dependency_links.txt +0 -0
  379. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/entry_points.txt +0 -0
  380. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/requires.txt +0 -0
  381. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/top_level.txt +0 -0
  382. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/python/lsst_daf_butler.egg-info/zip-safe +0 -0
  383. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/setup.cfg +0 -0
  384. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_astropyTableFormatter.py +0 -0
  385. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_authentication.py +0 -0
  386. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_butler_factory.py +0 -0
  387. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdAssociate.py +0 -0
  388. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdConfigDump.py +0 -0
  389. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdConfigValidate.py +0 -0
  390. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdCreate.py +0 -0
  391. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdImport.py +0 -0
  392. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdIngestFiles.py +0 -0
  393. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdPruneDatasets.py +0 -0
  394. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDatasetTypes.py +0 -0
  395. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDatasets.py +0 -0
  396. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdQueryDimensionRecords.py +0 -0
  397. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRemoveCollections.py +0 -0
  398. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRemoveRuns.py +0 -0
  399. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliCmdRetrieveArtifacts.py +0 -0
  400. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliLog.py +0 -0
  401. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliPluginLoader.py +0 -0
  402. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilSplitCommas.py +0 -0
  403. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilSplitKv.py +0 -0
  404. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtilToUpper.py +0 -0
  405. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_cliUtils.py +0 -0
  406. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_column_spec.py +0 -0
  407. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_composites.py +0 -0
  408. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_config.py +0 -0
  409. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_connectionString.py +0 -0
  410. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_constraints.py +0 -0
  411. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_datasets.py +0 -0
  412. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_datastore.py +0 -0
  413. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_ddl.py +0 -0
  414. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_dimensions.py +0 -0
  415. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_exprParserLex.py +0 -0
  416. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_exprParserYacc.py +0 -0
  417. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_expressions.py +0 -0
  418. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_formatter.py +0 -0
  419. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_gafaelfawr.py +0 -0
  420. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_location.py +0 -0
  421. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_logFormatter.py +0 -0
  422. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_logging.py +0 -0
  423. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_matplotlibFormatter.py +0 -0
  424. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_nonempty_mapping.py +0 -0
  425. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_normalFormExpression.py +0 -0
  426. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_obscore.py +0 -0
  427. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_packages.py +0 -0
  428. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_parquet.py +0 -0
  429. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_progress.py +0 -0
  430. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_pydantic_utils.py +0 -0
  431. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_quantum.py +0 -0
  432. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_direct_postgresql.py +0 -0
  433. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_direct_sqlite.py +0 -0
  434. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_interface.py +0 -0
  435. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_relations.py +0 -0
  436. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_remote.py +0 -0
  437. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_query_utilities.py +0 -0
  438. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_storageClass.py +0 -0
  439. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_templates.py +0 -0
  440. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_testRepo.py +0 -0
  441. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_thread_utils.py +0 -0
  442. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_time_utils.py +0 -0
  443. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_timespan.py +0 -0
  444. {lsst_daf_butler-29.2025.2400 → lsst_daf_butler-29.2025.2500}/tests/test_utils.py +0 -0
  445. {lsst_daf_butler-29.2025.2400 → 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.2400
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" }
@@ -67,6 +67,7 @@ if TYPE_CHECKING:
67
67
  from .._dataset_type import DatasetType
68
68
  from .._storage_class import StorageClass
69
69
  from ..datastores.file_datastore.retrieve_artifacts import ArtifactIndexInfo
70
+ from ..datastores.fileDatastoreClient import FileDatastoreGetPayload
70
71
  from ..registry.interfaces import DatasetIdRef, DatastoreRegistryBridgeManager
71
72
  from .record_data import DatastoreRecordData
72
73
  from .stored_file_info import StoredDatastoreItemInfo
@@ -613,7 +614,7 @@ class Datastore(FileTransferSource, metaclass=ABCMeta):
613
614
  """
614
615
  raise NotImplementedError("Must be implemented by subclass")
615
616
 
616
- def prepare_get_for_external_client(self, ref: DatasetRef) -> object | None:
617
+ def prepare_get_for_external_client(self, ref: DatasetRef) -> FileDatastoreGetPayload | None:
617
618
  """Retrieve serializable data that can be used to execute a ``get()``.
618
619
 
619
620
  Parameters
@@ -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)
@@ -61,6 +61,8 @@ if TYPE_CHECKING:
61
61
  from lsst.daf.butler.registry.interfaces import DatasetIdRef, DatastoreRegistryBridgeManager
62
62
  from lsst.resources import ResourcePathExpression
63
63
 
64
+ from .fileDatastoreClient import FileDatastoreGetPayload
65
+
64
66
  log = getLogger(__name__)
65
67
 
66
68
 
@@ -409,7 +411,7 @@ class ChainedDatastore(Datastore):
409
411
 
410
412
  raise FileNotFoundError(f"Dataset {ref} could not be found in any of the datastores")
411
413
 
412
- def prepare_get_for_external_client(self, ref: DatasetRef) -> object | None:
414
+ def prepare_get_for_external_client(self, ref: DatasetRef) -> FileDatastoreGetPayload | None:
413
415
  datastore = self._get_matching_datastore(ref)
414
416
  if datastore is None:
415
417
  return None
@@ -1879,18 +1879,15 @@ class DirectButler(Butler): # numpydoc ignore=PR02
1879
1879
  # Docstring inherited.
1880
1880
  if not self.isWriteable():
1881
1881
  raise TypeError("Butler is read-only.")
1882
- if format is None:
1883
- if filename is None:
1884
- raise TypeError("At least one of 'filename' or 'format' must be provided.")
1885
- else:
1886
- _, format = os.path.splitext(filename) # type: ignore
1887
- elif filename is None:
1882
+ if filename is None and format is not None:
1888
1883
  filename = ResourcePath(f"export.{format}", forceAbsolute=False)
1889
1884
  if directory is not None:
1890
1885
  directory = ResourcePath(directory, forceDirectory=True)
1891
1886
  # mypy doesn't think this will work but it does in python >= 3.10.
1892
1887
  if isinstance(filename, ResourcePathExpression): # type: ignore
1893
1888
  filename = ResourcePath(filename, forceAbsolute=False) # type: ignore
1889
+ if format is None:
1890
+ format = filename.getExtension()
1894
1891
  if not filename.isabs() and directory is not None:
1895
1892
  potential = directory.join(filename)
1896
1893
  exists_in_cwd = filename.exists()
@@ -1914,6 +1911,8 @@ class DirectButler(Butler): # numpydoc ignore=PR02
1914
1911
  raise FileNotFoundError(
1915
1912
  f"Export file could not be found in {filename.abspath()} or {potential.abspath()}."
1916
1913
  )
1914
+ elif format is None:
1915
+ format = ".yaml"
1917
1916
  BackendClass: type[RepoImportBackend] = get_class_of(
1918
1917
  self._config["repo_transfer_formats"][format]["import"]
1919
1918
  )
@@ -353,7 +353,7 @@ class DirectQueryDriver(QueryDriver):
353
353
  else:
354
354
  dict_rows = [dict(zip(dimensions.required, values)) for values in rows]
355
355
  from_clause: sqlalchemy.FromClause
356
- if len(dict_rows) > self._constant_rows_limit:
356
+ if self.db.supports_temporary_tables and len(dict_rows) > self._constant_rows_limit:
357
357
  from_clause = self._exit_stack.enter_context(self.db.temporary_table(table_spec))
358
358
  self.db.insert(from_clause, *dict_rows)
359
359
  else:
@@ -119,3 +119,24 @@ class RegistryConfig(ConfigSubset):
119
119
  (`sqlalchemy.engine.url.URL`).
120
120
  """
121
121
  return ConnectionStringFactory.fromConfig(self)
122
+
123
+ @property
124
+ def areTemporaryTablesAllowed(self) -> bool:
125
+ """Return `True` if the database allows creating temporary tables for
126
+ read operations; `False` otherwise.
127
+
128
+ By default this is `True`, because there is a performance penalty
129
+ for some queries if temporary tables cannot be used.
130
+
131
+ This should be set to `False` when using a Postgres hot standby using
132
+ physical replication or an AlloyDB read pool, since these backends
133
+ do not support temporary tables.
134
+ """
135
+ key = "temporary_tables"
136
+ value = self.get(key)
137
+ if value is None:
138
+ return True
139
+ elif isinstance(value, bool):
140
+ return value
141
+
142
+ raise ValueError(f"Unexpected value '{value}' for '{key}' in registry configuration")
@@ -65,6 +65,10 @@ class PostgresqlDatabase(Database):
65
65
  writeable : `bool`, optional
66
66
  If `True`, allow write operations on the database, including
67
67
  ``CREATE TABLE``.
68
+ allow_temporary_tables : `bool`, optional
69
+ If `True`, database operations will be allowed to use temporary tables.
70
+ If `False`, other SQL constructs will be used instead of temporary
71
+ tables when possible.
68
72
 
69
73
  Notes
70
74
  -----
@@ -85,6 +89,7 @@ class PostgresqlDatabase(Database):
85
89
  origin: int,
86
90
  namespace: str | None = None,
87
91
  writeable: bool = True,
92
+ allow_temporary_tables: bool = True,
88
93
  ):
89
94
  with engine.connect() as connection:
90
95
  # `Any` to make mypy ignore the line below, can't use type: ignore
@@ -114,6 +119,7 @@ class PostgresqlDatabase(Database):
114
119
  dbname=dsn.get("dbname"),
115
120
  metadata=None,
116
121
  pg_version=pg_version,
122
+ allow_temporary_tables=allow_temporary_tables,
117
123
  )
118
124
 
119
125
  def _init(
@@ -126,9 +132,16 @@ class PostgresqlDatabase(Database):
126
132
  dbname: str,
127
133
  metadata: DatabaseMetadata | None,
128
134
  pg_version: tuple[int, int],
135
+ allow_temporary_tables: bool = True,
129
136
  ) -> None:
130
137
  # Initialization logic shared between ``__init__`` and ``clone``.
131
- super().__init__(origin=origin, engine=engine, namespace=namespace, metadata=metadata)
138
+ super().__init__(
139
+ origin=origin,
140
+ engine=engine,
141
+ namespace=namespace,
142
+ metadata=metadata,
143
+ allow_temporary_tables=allow_temporary_tables,
144
+ )
132
145
  self._writeable = writeable
133
146
  self.dbname = dbname
134
147
  self._pg_version = pg_version
@@ -143,6 +156,7 @@ class PostgresqlDatabase(Database):
143
156
  dbname=self.dbname,
144
157
  metadata=self._metadata,
145
158
  pg_version=self._pg_version,
159
+ allow_temporary_tables=self._allow_temporary_tables,
146
160
  )
147
161
  return clone
148
162
 
@@ -74,6 +74,11 @@ class SqliteDatabase(Database):
74
74
  writeable : `bool`, optional
75
75
  If `True`, allow write operations on the database, including
76
76
  ``CREATE TABLE``.
77
+ allow_temporary_tables : `bool`, optional
78
+ If `True`, database operations will be allowed to use temporary
79
+ tables.
80
+ If `False`, other SQL constructs will be used instead of temporary
81
+ tables when possible.
77
82
 
78
83
  Notes
79
84
  -----
@@ -90,6 +95,7 @@ class SqliteDatabase(Database):
90
95
  origin: int,
91
96
  namespace: str | None = None,
92
97
  writeable: bool = True,
98
+ allow_temporary_tables: bool = True,
93
99
  ):
94
100
  filename = _find_database_filename(engine, namespace)
95
101
  self._init(
@@ -99,6 +105,7 @@ class SqliteDatabase(Database):
99
105
  writeable=writeable,
100
106
  filename=filename,
101
107
  metadata=None,
108
+ allow_temporary_tables=allow_temporary_tables,
102
109
  )
103
110
 
104
111
  def _init(
@@ -110,9 +117,16 @@ class SqliteDatabase(Database):
110
117
  writeable: bool = True,
111
118
  filename: str | None,
112
119
  metadata: DatabaseMetadata | None,
120
+ allow_temporary_tables: bool,
113
121
  ) -> None:
114
122
  # Initialization logic shared between ``__init__`` and ``clone``.
115
- super().__init__(origin=origin, engine=engine, namespace=namespace, metadata=metadata)
123
+ super().__init__(
124
+ origin=origin,
125
+ engine=engine,
126
+ namespace=namespace,
127
+ metadata=metadata,
128
+ allow_temporary_tables=allow_temporary_tables,
129
+ )
116
130
  self._writeable = writeable
117
131
  self.filename = filename
118
132
 
@@ -125,6 +139,7 @@ class SqliteDatabase(Database):
125
139
  writeable=self._writeable,
126
140
  filename=self.filename,
127
141
  metadata=self._metadata,
142
+ allow_temporary_tables=self._allow_temporary_tables,
128
143
  )
129
144
  return clone
130
145
 
@@ -238,6 +238,10 @@ class Database(ABC):
238
238
  Object representing the tables and other schema entities. If not
239
239
  provided, will be generated during the next call to
240
240
  ``declareStaticTables``.
241
+ allow_temporary_tables : `bool`, optional
242
+ If `True`, database operations will be allowed to use temporary tables.
243
+ If `False`, other SQL constructs will be used instead of temporary
244
+ tables when possible.
241
245
 
242
246
  Notes
243
247
  -----
@@ -272,6 +276,7 @@ class Database(ABC):
272
276
  engine: sqlalchemy.engine.Engine,
273
277
  namespace: str | None = None,
274
278
  metadata: DatabaseMetadata | None = None,
279
+ allow_temporary_tables: bool = True,
275
280
  ):
276
281
  self.origin = origin
277
282
  self.name_shrinker = NameShrinker(engine.dialect.max_identifier_length)
@@ -280,6 +285,7 @@ class Database(ABC):
280
285
  self._session_connection: sqlalchemy.engine.Connection | None = None
281
286
  self._temp_tables: set[str] = set()
282
287
  self._metadata = metadata
288
+ self._allow_temporary_tables = allow_temporary_tables
283
289
 
284
290
  def __repr__(self) -> str:
285
291
  # Rather than try to reproduce all the parameters used to create
@@ -318,6 +324,7 @@ class Database(ABC):
318
324
  origin: int,
319
325
  namespace: str | None = None,
320
326
  writeable: bool = True,
327
+ allow_temporary_tables: bool = True,
321
328
  ) -> Database:
322
329
  """Construct a database from a SQLAlchemy URI.
323
330
 
@@ -336,15 +343,22 @@ class Database(ABC):
336
343
  writeable : `bool`, optional
337
344
  If `True`, allow write operations on the database, including
338
345
  ``CREATE TABLE``.
346
+ allow_temporary_tables : `bool`, optional
347
+ If `True`, database operations will be allowed to use temporary
348
+ tables.
349
+ If `False`, other SQL constructs will be used instead of temporary
350
+ tables when possible.
339
351
 
340
352
  Returns
341
353
  -------
342
354
  db : `Database`
343
355
  A new `Database` instance.
344
356
  """
345
- return cls.fromEngine(
357
+ db = cls.fromEngine(
346
358
  cls.makeEngine(uri, writeable=writeable), origin=origin, namespace=namespace, writeable=writeable
347
359
  )
360
+ db._allow_temporary_tables = allow_temporary_tables
361
+ return db
348
362
 
349
363
  @abstractmethod
350
364
  def clone(self) -> Database:
@@ -539,6 +553,8 @@ class Database(ABC):
539
553
  support the full range of expected read-only butler behavior.
540
554
  """
541
555
  assert self._metadata is not None, "Static tables must be created before temporary tables"
556
+ if not self.supports_temporary_tables:
557
+ raise ReadOnlyDatabaseError("Creation of temporary tables is not supported by this database.")
542
558
  with self._session() as connection:
543
559
  table = self._make_temporary_table(connection, spec=spec, name=name)
544
560
  self._temp_tables.add(table.key)
@@ -1954,6 +1970,10 @@ class Database(ABC):
1954
1970
  """
1955
1971
  raise NotImplementedError()
1956
1972
 
1973
+ @property
1974
+ def supports_temporary_tables(self) -> bool:
1975
+ return self._allow_temporary_tables
1976
+
1957
1977
  @abstractmethod
1958
1978
  def apply_any_aggregate(self, column: sqlalchemy.ColumnElement[Any]) -> sqlalchemy.ColumnElement[Any]:
1959
1979
  """Wrap the given SQLAlchemy column in the ``ANY_VALUE`` aggregate
@@ -183,6 +183,11 @@ class ObsCoreConfig(pydantic.BaseModel):
183
183
  dimension. Will be left unset if `None`. Can be dangerous to set this
184
184
  in a repository containing data from multiple instruments."""
185
185
 
186
+ obs_publisher_did_fmt: str | None = None
187
+ """Format string to generate an obs_publisher_did for a record. Assumes
188
+ that a single string is suitable for all results.
189
+ """
190
+
186
191
 
187
192
  class ConfigCollectionType(str, enum.Enum):
188
193
  """Enum class defining possible values for configuration attributes."""
@@ -197,6 +197,9 @@ class RecordFactory:
197
197
  if dataset_config.datalink_url_fmt:
198
198
  record["access_url"] = dataset_config.datalink_url_fmt.format(**fmt_kws)
199
199
 
200
+ if self.config.obs_publisher_did_fmt:
201
+ record["obs_publisher_did"] = self.config.obs_publisher_did_fmt.format(**fmt_kws)
202
+
200
203
  extra_columns = {}
201
204
  if self.config.extra_columns:
202
205
  extra_columns.update(self.config.extra_columns)
@@ -187,7 +187,10 @@ class SqlRegistry:
187
187
 
188
188
  DatabaseClass = config.getDatabaseClass()
189
189
  database = DatabaseClass.fromUri(
190
- config.connectionString, origin=config.get("origin", 0), namespace=config.get("namespace")
190
+ config.connectionString,
191
+ origin=config.get("origin", 0),
192
+ namespace=config.get("namespace"),
193
+ allow_temporary_tables=config.areTemporaryTablesAllowed,
191
194
  )
192
195
  managerTypes = RegistryManagerTypes.fromConfig(config)
193
196
  managers = managerTypes.makeRepo(database, dimensionConfig)
@@ -230,6 +233,7 @@ class SqlRegistry:
230
233
  origin=config.get("origin", 0),
231
234
  namespace=config.get("namespace"),
232
235
  writeable=writeable,
236
+ allow_temporary_tables=config.areTemporaryTablesAllowed,
233
237
  )
234
238
  managerTypes = RegistryManagerTypes.fromConfig(config)
235
239
  with database.session():