lsst-daf-butler 29.2025.3100__py3-none-any.whl → 29.2025.3200__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lsst/daf/butler/_limited_butler.py +1 -6
- lsst/daf/butler/_storage_class.py +66 -174
- lsst/daf/butler/datastore/record_data.py +22 -0
- lsst/daf/butler/datastore/stored_file_info.py +2 -4
- lsst/daf/butler/dimensions/_record_set.py +49 -2
- lsst/daf/butler/tests/_examplePythonTypes.py +1 -6
- lsst/daf/butler/version.py +1 -1
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/METADATA +1 -1
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/RECORD +17 -17
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/WHEEL +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/entry_points.txt +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/COPYRIGHT +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/LICENSE +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/bsd_license.txt +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/gpl-v3.0.txt +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/top_level.txt +0 -0
- {lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/zip-safe +0 -0
|
@@ -129,11 +129,6 @@ class LimitedButler(ABC):
|
|
|
129
129
|
obj : `object`
|
|
130
130
|
The dataset.
|
|
131
131
|
|
|
132
|
-
Raises
|
|
133
|
-
------
|
|
134
|
-
AmbiguousDatasetError
|
|
135
|
-
Raised if the supplied `DatasetRef` is unresolved.
|
|
136
|
-
|
|
137
132
|
Notes
|
|
138
133
|
-----
|
|
139
134
|
In a `LimitedButler` the only allowable way to specify a dataset is
|
|
@@ -326,7 +321,7 @@ class LimitedButler(ABC):
|
|
|
326
321
|
Whether the dataset artifact exists in the datastore and can be
|
|
327
322
|
retrieved.
|
|
328
323
|
"""
|
|
329
|
-
return self.
|
|
324
|
+
return self.stored_many([ref])[ref]
|
|
330
325
|
|
|
331
326
|
def stored_many(
|
|
332
327
|
self,
|
|
@@ -39,6 +39,8 @@ from collections.abc import Callable, Collection, Mapping, Sequence, Set
|
|
|
39
39
|
from threading import RLock
|
|
40
40
|
from typing import Any
|
|
41
41
|
|
|
42
|
+
import pydantic
|
|
43
|
+
|
|
42
44
|
from lsst.utils import doImportType
|
|
43
45
|
from lsst.utils.classes import Singleton
|
|
44
46
|
from lsst.utils.introspection import get_full_type_name
|
|
@@ -57,6 +59,18 @@ class StorageClassConfig(ConfigSubset):
|
|
|
57
59
|
defaultConfigFile = "storageClasses.yaml"
|
|
58
60
|
|
|
59
61
|
|
|
62
|
+
class _StorageClassModel(pydantic.BaseModel):
|
|
63
|
+
"""Model class used to validate storage class configuration."""
|
|
64
|
+
|
|
65
|
+
pytype: str | None = None
|
|
66
|
+
inheritsFrom: str | None = None
|
|
67
|
+
components: dict[str, str] = pydantic.Field(default_factory=dict)
|
|
68
|
+
derivedComponents: dict[str, str] = pydantic.Field(default_factory=dict)
|
|
69
|
+
parameters: list[str] = pydantic.Field(default_factory=list)
|
|
70
|
+
delegate: str | None = None
|
|
71
|
+
converters: dict[str, str] = pydantic.Field(default_factory=dict)
|
|
72
|
+
|
|
73
|
+
|
|
60
74
|
class StorageClass:
|
|
61
75
|
"""Class describing how a label maps to a particular Python type.
|
|
62
76
|
|
|
@@ -81,17 +95,9 @@ class StorageClass:
|
|
|
81
95
|
that python type to the valid type of this storage class.
|
|
82
96
|
"""
|
|
83
97
|
|
|
84
|
-
_cls_name: str = "BaseStorageClass"
|
|
85
|
-
_cls_components: dict[str, StorageClass] | None = None
|
|
86
|
-
_cls_derivedComponents: dict[str, StorageClass] | None = None
|
|
87
|
-
_cls_parameters: Set[str] | Sequence[str] | None = None
|
|
88
|
-
_cls_delegate: str | None = None
|
|
89
|
-
_cls_pytype: type | str | None = None
|
|
90
|
-
_cls_converters: dict[str, str] | None = None
|
|
91
|
-
|
|
92
98
|
def __init__(
|
|
93
99
|
self,
|
|
94
|
-
name: str
|
|
100
|
+
name: str = "",
|
|
95
101
|
pytype: type | str | None = None,
|
|
96
102
|
components: dict[str, StorageClass] | None = None,
|
|
97
103
|
derivedComponents: dict[str, StorageClass] | None = None,
|
|
@@ -99,23 +105,8 @@ class StorageClass:
|
|
|
99
105
|
delegate: str | None = None,
|
|
100
106
|
converters: dict[str, str] | None = None,
|
|
101
107
|
):
|
|
102
|
-
if name is None:
|
|
103
|
-
name = self._cls_name
|
|
104
|
-
if pytype is None:
|
|
105
|
-
pytype = self._cls_pytype
|
|
106
|
-
if components is None:
|
|
107
|
-
components = self._cls_components
|
|
108
|
-
if derivedComponents is None:
|
|
109
|
-
derivedComponents = self._cls_derivedComponents
|
|
110
|
-
if parameters is None:
|
|
111
|
-
parameters = self._cls_parameters
|
|
112
|
-
if delegate is None:
|
|
113
|
-
delegate = self._cls_delegate
|
|
114
|
-
|
|
115
108
|
# Merge converters with class defaults.
|
|
116
109
|
self._converters = {}
|
|
117
|
-
if self._cls_converters is not None:
|
|
118
|
-
self._converters.update(self._cls_converters)
|
|
119
110
|
if converters:
|
|
120
111
|
self._converters.update(converters)
|
|
121
112
|
|
|
@@ -634,7 +625,6 @@ class StorageClassFactory(metaclass=Singleton):
|
|
|
634
625
|
|
|
635
626
|
def __init__(self, config: StorageClassConfig | str | None = None):
|
|
636
627
|
self._storageClasses: dict[str, StorageClass] = {}
|
|
637
|
-
self._configs: list[StorageClassConfig] = []
|
|
638
628
|
self._lock = RLock()
|
|
639
629
|
|
|
640
630
|
# Always seed with the default config
|
|
@@ -657,40 +647,15 @@ class StorageClassFactory(metaclass=Singleton):
|
|
|
657
647
|
|
|
658
648
|
StorageClasses
|
|
659
649
|
--------------
|
|
660
|
-
{sep.join(f"{
|
|
650
|
+
{sep.join(f"{self._storageClasses[s]!r}" for s in sorted(self._storageClasses))}
|
|
661
651
|
"""
|
|
662
652
|
|
|
663
|
-
def __contains__(self, storageClassOrName:
|
|
664
|
-
"""Indicate whether the storage class exists in the factory.
|
|
665
|
-
|
|
666
|
-
Parameters
|
|
667
|
-
----------
|
|
668
|
-
storageClassOrName : `str` or `StorageClass`
|
|
669
|
-
If `str` is given existence of the named StorageClass
|
|
670
|
-
in the factory is checked. If `StorageClass` is given
|
|
671
|
-
existence and equality are checked.
|
|
672
|
-
|
|
673
|
-
Returns
|
|
674
|
-
-------
|
|
675
|
-
in : `bool`
|
|
676
|
-
True if the supplied string is present, or if the supplied
|
|
677
|
-
`StorageClass` is present and identical.
|
|
678
|
-
|
|
679
|
-
Notes
|
|
680
|
-
-----
|
|
681
|
-
The two different checks (one for "key" and one for "value") based on
|
|
682
|
-
the type of the given argument mean that it is possible for
|
|
683
|
-
StorageClass.name to be in the factory but StorageClass to not be
|
|
684
|
-
in the factory.
|
|
685
|
-
"""
|
|
653
|
+
def __contains__(self, storageClassOrName: object) -> bool:
|
|
686
654
|
with self._lock:
|
|
687
655
|
if isinstance(storageClassOrName, str):
|
|
688
656
|
return storageClassOrName in self._storageClasses
|
|
689
|
-
elif (
|
|
690
|
-
|
|
691
|
-
and storageClassOrName.name in self._storageClasses
|
|
692
|
-
):
|
|
693
|
-
return storageClassOrName == self._storageClasses[storageClassOrName.name]
|
|
657
|
+
elif isinstance(storageClassOrName, StorageClass):
|
|
658
|
+
return storageClassOrName.name in self._storageClasses
|
|
694
659
|
return False
|
|
695
660
|
|
|
696
661
|
def addFromConfig(self, config: StorageClassConfig | Config | str) -> None:
|
|
@@ -708,68 +673,54 @@ StorageClasses
|
|
|
708
673
|
# components or parents before their classes are defined
|
|
709
674
|
# we have a helper function that we can call recursively
|
|
710
675
|
# to extract definitions from the configuration.
|
|
711
|
-
def processStorageClass(name: str, _sconfig: StorageClassConfig, msg: str = "") ->
|
|
712
|
-
#
|
|
676
|
+
def processStorageClass(name: str, _sconfig: StorageClassConfig, msg: str = "") -> StorageClass:
|
|
677
|
+
# This might have already been processed through recursion, or
|
|
678
|
+
# already present in the factory.
|
|
713
679
|
if name not in _sconfig:
|
|
714
|
-
return
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
baseName,
|
|
759
|
-
)
|
|
760
|
-
processStorageClass(baseName, sconfig, msg)
|
|
761
|
-
else:
|
|
762
|
-
processStorageClass(baseName, sconfig, msg)
|
|
763
|
-
baseClass = type(self.getStorageClass(baseName))
|
|
764
|
-
if baseClass is StorageClass:
|
|
765
|
-
raise TypeError(
|
|
766
|
-
f"Configuration for storage class {name} requests to inherit from "
|
|
767
|
-
f" storage class {baseName} but that class is not defined correctly."
|
|
768
|
-
)
|
|
769
|
-
|
|
770
|
-
newStorageClassType = self.makeNewStorageClass(name, baseClass, **storageClassKwargs)
|
|
771
|
-
newStorageClass = newStorageClassType()
|
|
772
|
-
self.registerStorageClass(newStorageClass, msg=msg)
|
|
680
|
+
return self.getStorageClass(name)
|
|
681
|
+
try:
|
|
682
|
+
model = _StorageClassModel.model_validate(_sconfig.pop(name))
|
|
683
|
+
except Exception as err:
|
|
684
|
+
err.add_note(msg)
|
|
685
|
+
raise
|
|
686
|
+
components: dict[str, StorageClass] = {}
|
|
687
|
+
derivedComponents: dict[str, StorageClass] = {}
|
|
688
|
+
parameters: set[str] = set()
|
|
689
|
+
delegate: str | None = None
|
|
690
|
+
converters: dict[str, str] = {}
|
|
691
|
+
if model.inheritsFrom is not None:
|
|
692
|
+
base = processStorageClass(model.inheritsFrom, _sconfig, msg + f"; processing base of {name}")
|
|
693
|
+
pytype = base._pytypeName
|
|
694
|
+
components.update(base.components)
|
|
695
|
+
derivedComponents.update(base.derivedComponents)
|
|
696
|
+
parameters.update(base.parameters)
|
|
697
|
+
delegate = base._delegateClassName
|
|
698
|
+
converters.update(base.converters)
|
|
699
|
+
if model.pytype is not None:
|
|
700
|
+
pytype = model.pytype
|
|
701
|
+
for k, v in model.components.items():
|
|
702
|
+
components[k] = processStorageClass(
|
|
703
|
+
v, _sconfig, msg + f"; processing component {k} of {name}"
|
|
704
|
+
)
|
|
705
|
+
for k, v in model.derivedComponents.items():
|
|
706
|
+
derivedComponents[k] = processStorageClass(
|
|
707
|
+
v, _sconfig, msg + f"; processing derivedCmponent {k} of {name}"
|
|
708
|
+
)
|
|
709
|
+
parameters.update(model.parameters)
|
|
710
|
+
if model.delegate is not None:
|
|
711
|
+
delegate = model.delegate
|
|
712
|
+
converters.update(model.converters)
|
|
713
|
+
result = StorageClass(
|
|
714
|
+
name=name,
|
|
715
|
+
pytype=pytype,
|
|
716
|
+
components=components,
|
|
717
|
+
derivedComponents=derivedComponents,
|
|
718
|
+
parameters=parameters,
|
|
719
|
+
delegate=delegate,
|
|
720
|
+
converters=converters,
|
|
721
|
+
)
|
|
722
|
+
self.registerStorageClass(result, msg=msg)
|
|
723
|
+
return result
|
|
773
724
|
|
|
774
725
|
# In case there is a problem, construct a context message for any
|
|
775
726
|
# error reporting.
|
|
@@ -778,68 +729,9 @@ StorageClasses
|
|
|
778
729
|
log.debug("Adding definitions from config %s", ", ".join(files))
|
|
779
730
|
|
|
780
731
|
with self._lock:
|
|
781
|
-
self._configs.append(sconfig)
|
|
782
732
|
for name in list(sconfig.keys()):
|
|
783
733
|
processStorageClass(name, sconfig, context)
|
|
784
734
|
|
|
785
|
-
@staticmethod
|
|
786
|
-
def makeNewStorageClass(
|
|
787
|
-
name: str, baseClass: type[StorageClass] | None = StorageClass, **kwargs: Any
|
|
788
|
-
) -> type[StorageClass]:
|
|
789
|
-
"""Create a new Python class as a subclass of `StorageClass`.
|
|
790
|
-
|
|
791
|
-
Parameters
|
|
792
|
-
----------
|
|
793
|
-
name : `str`
|
|
794
|
-
Name to use for this class.
|
|
795
|
-
baseClass : `type`, optional
|
|
796
|
-
Base class for this `StorageClass`. Must be either `StorageClass`
|
|
797
|
-
or a subclass of `StorageClass`. If `None`, `StorageClass` will
|
|
798
|
-
be used.
|
|
799
|
-
**kwargs
|
|
800
|
-
Additional parameter values to use as defaults for this class.
|
|
801
|
-
This can include ``components``, ``parameters``,
|
|
802
|
-
``derivedComponents``, and ``converters``.
|
|
803
|
-
|
|
804
|
-
Returns
|
|
805
|
-
-------
|
|
806
|
-
newtype : `type` subclass of `StorageClass`
|
|
807
|
-
Newly created Python type.
|
|
808
|
-
"""
|
|
809
|
-
if baseClass is None:
|
|
810
|
-
baseClass = StorageClass
|
|
811
|
-
if not issubclass(baseClass, StorageClass):
|
|
812
|
-
raise ValueError(f"Base class must be a StorageClass not {baseClass}")
|
|
813
|
-
|
|
814
|
-
# convert the arguments to use different internal names
|
|
815
|
-
clsargs = {f"_cls_{k}": v for k, v in kwargs.items() if v is not None}
|
|
816
|
-
clsargs["_cls_name"] = name
|
|
817
|
-
|
|
818
|
-
# Some container items need to merge with the base class values
|
|
819
|
-
# so that a child can inherit but override one bit.
|
|
820
|
-
# lists (which you get from configs) are treated as sets for this to
|
|
821
|
-
# work consistently.
|
|
822
|
-
for k in ("components", "parameters", "derivedComponents", "converters"):
|
|
823
|
-
classKey = f"_cls_{k}"
|
|
824
|
-
if classKey in clsargs:
|
|
825
|
-
baseValue = getattr(baseClass, classKey, None)
|
|
826
|
-
if baseValue is not None:
|
|
827
|
-
currentValue = clsargs[classKey]
|
|
828
|
-
if isinstance(currentValue, dict):
|
|
829
|
-
newValue = baseValue.copy()
|
|
830
|
-
else:
|
|
831
|
-
newValue = set(baseValue)
|
|
832
|
-
newValue.update(currentValue)
|
|
833
|
-
clsargs[classKey] = newValue
|
|
834
|
-
|
|
835
|
-
# If we have parameters they should be a frozen set so that the
|
|
836
|
-
# parameters in the class can not be modified.
|
|
837
|
-
pk = "_cls_parameters"
|
|
838
|
-
if pk in clsargs:
|
|
839
|
-
clsargs[pk] = frozenset(clsargs[pk])
|
|
840
|
-
|
|
841
|
-
return type(f"StorageClass{name}", (baseClass,), clsargs)
|
|
842
|
-
|
|
843
735
|
def getStorageClass(self, storageClassName: str) -> StorageClass:
|
|
844
736
|
"""Get a StorageClass instance associated with the supplied name.
|
|
845
737
|
|
|
@@ -111,6 +111,28 @@ class DatastoreRecordData:
|
|
|
111
111
|
"""Opaque table data, indexed by dataset ID and grouped by opaque table
|
|
112
112
|
name."""
|
|
113
113
|
|
|
114
|
+
@staticmethod
|
|
115
|
+
def merge_mappings(*args: Mapping[str, DatastoreRecordData]) -> dict[str, DatastoreRecordData]:
|
|
116
|
+
"""Merge mappings of datastore record data.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
*args : `~collections.abc.Mapping` [ `str`, `DatastoreRecordData` ]
|
|
121
|
+
Mappings of record data, keyed by datastore name.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
merged : `~collections.abc.Mapping` [ `str`, `DatastoreRecordData` ]
|
|
126
|
+
Merged mapping of record data, keyed by datastore name.
|
|
127
|
+
"""
|
|
128
|
+
result: dict[str, DatastoreRecordData] = {}
|
|
129
|
+
for arg in args:
|
|
130
|
+
for datastore_name, record_data in arg.items():
|
|
131
|
+
if datastore_name not in result:
|
|
132
|
+
result[datastore_name] = DatastoreRecordData()
|
|
133
|
+
result[datastore_name].update(record_data)
|
|
134
|
+
return result
|
|
135
|
+
|
|
114
136
|
def update(self, other: DatastoreRecordData) -> None:
|
|
115
137
|
"""Update contents of this instance with data from another instance.
|
|
116
138
|
|
|
@@ -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
|
|
36
36
|
|
|
37
37
|
import pydantic
|
|
38
38
|
|
|
@@ -209,8 +209,6 @@ class StoredFileInfo(StoredDatastoreItemInfo):
|
|
|
209
209
|
compatibility, it remains a positional argument with no default).
|
|
210
210
|
"""
|
|
211
211
|
|
|
212
|
-
storageClassFactory: ClassVar[StorageClassFactory] = StorageClassFactory()
|
|
213
|
-
|
|
214
212
|
def __init__(
|
|
215
213
|
self,
|
|
216
214
|
formatter: FormatterParameter,
|
|
@@ -268,7 +266,7 @@ class StoredFileInfo(StoredDatastoreItemInfo):
|
|
|
268
266
|
@property
|
|
269
267
|
def storageClass(self) -> StorageClass:
|
|
270
268
|
"""Storage class associated with this dataset."""
|
|
271
|
-
return
|
|
269
|
+
return StorageClassFactory().getStorageClass(self.storage_class_name)
|
|
272
270
|
|
|
273
271
|
def rebase(self, ref: DatasetRef) -> StoredFileInfo:
|
|
274
272
|
"""Return a copy of the record suitable for a specified reference.
|
|
@@ -753,7 +753,6 @@ class SerializableDimensionData(pydantic.RootModel):
|
|
|
753
753
|
]
|
|
754
754
|
|
|
755
755
|
|
|
756
|
-
@dataclasses.dataclass
|
|
757
756
|
class DimensionDataAttacher:
|
|
758
757
|
"""A helper class for attaching dimension records to data IDs.
|
|
759
758
|
|
|
@@ -786,7 +785,7 @@ class DimensionDataAttacher:
|
|
|
786
785
|
dimensions: DimensionGroup | None = None,
|
|
787
786
|
):
|
|
788
787
|
self.records = {record_set.element.name: record_set for record_set in records}
|
|
789
|
-
self.deserializers = {}
|
|
788
|
+
self.deserializers: dict[str, DimensionRecordSetDeserializer] = {}
|
|
790
789
|
for deserializer in deserializers:
|
|
791
790
|
self.deserializers[deserializer.element.name] = deserializer
|
|
792
791
|
if deserializer.element.name not in self.records:
|
|
@@ -851,6 +850,54 @@ class DimensionDataAttacher:
|
|
|
851
850
|
|
|
852
851
|
return [r.data_id.expanded(r.done) for r in records]
|
|
853
852
|
|
|
853
|
+
def serialized(
|
|
854
|
+
self, *, ignore: Iterable[str] = (), ignore_cached: bool = False, include_skypix: bool = False
|
|
855
|
+
) -> SerializableDimensionData:
|
|
856
|
+
"""Serialize all dimension data in this attacher, with deduplication
|
|
857
|
+
across fully- and partially-deserialized records.
|
|
858
|
+
|
|
859
|
+
Parameters
|
|
860
|
+
----------
|
|
861
|
+
ignore : `~collections.abc.Iterable` [ `str` ], optional
|
|
862
|
+
Names of dimension elements that should not be serialized.
|
|
863
|
+
ignore_cached : `bool`, optional
|
|
864
|
+
If `True`, ignore all dimension elements for which
|
|
865
|
+
`DimensionElement.is_cached` is `True`.
|
|
866
|
+
include_skypix : `bool`, optional
|
|
867
|
+
If `True`, include skypix dimensions. These are ignored by default
|
|
868
|
+
because they can always be recomputed from their IDs on-the-fly.
|
|
869
|
+
|
|
870
|
+
Returns
|
|
871
|
+
-------
|
|
872
|
+
serialized : `SerializedDimensionData`
|
|
873
|
+
Serialized dimension records.
|
|
874
|
+
"""
|
|
875
|
+
from ._skypix import SkyPixDimension
|
|
876
|
+
|
|
877
|
+
ignore = set(ignore)
|
|
878
|
+
result = SerializableDimensionData()
|
|
879
|
+
for record_set in self.records.values():
|
|
880
|
+
if record_set.element.name in ignore:
|
|
881
|
+
continue
|
|
882
|
+
if not include_skypix and isinstance(record_set.element, SkyPixDimension):
|
|
883
|
+
continue
|
|
884
|
+
if ignore_cached and record_set.element.is_cached:
|
|
885
|
+
continue
|
|
886
|
+
serialized_records: dict[tuple[DataIdValue, ...], SerializedKeyValueDimensionRecord] = {}
|
|
887
|
+
if (deserializer := self.deserializers.get(record_set.element.name)) is not None:
|
|
888
|
+
for key, value in deserializer._mapping.items():
|
|
889
|
+
serialized_record = list(key)
|
|
890
|
+
serialized_record.extend(value)
|
|
891
|
+
serialized_records[key] = serialized_record
|
|
892
|
+
for key, record in record_set._by_required_values.items():
|
|
893
|
+
if key not in serialized_records:
|
|
894
|
+
serialized_records[key] = record.serialize_key_value()
|
|
895
|
+
result.root[record_set.element.name] = list(serialized_records.values())
|
|
896
|
+
if self.cache is not None and not ignore_cached:
|
|
897
|
+
for record_set in self.cache.values():
|
|
898
|
+
result.root[record_set.element.name] = record_set.serialize_records()
|
|
899
|
+
return result
|
|
900
|
+
|
|
854
901
|
|
|
855
902
|
@dataclasses.dataclass
|
|
856
903
|
class _InProgressRecordDicts:
|
|
@@ -147,12 +147,7 @@ def _addFullStorageClass(butler: Butler, name: str, formatter: str, **kwargs: An
|
|
|
147
147
|
previously found in the repository.
|
|
148
148
|
"""
|
|
149
149
|
storageRegistry = butler._datastore.storageClassFactory
|
|
150
|
-
|
|
151
|
-
# Use the special constructor to allow a subclass of storage class
|
|
152
|
-
# to be created. This allows other test storage classes to inherit from
|
|
153
|
-
# this one.
|
|
154
|
-
storage_type = storageRegistry.makeNewStorageClass(name, None, **kwargs)
|
|
155
|
-
storage = storage_type()
|
|
150
|
+
storage = StorageClass(name, **kwargs)
|
|
156
151
|
try:
|
|
157
152
|
storageRegistry.registerStorageClass(storage)
|
|
158
153
|
except ValueError:
|
lsst/daf/butler/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "29.2025.
|
|
2
|
+
__version__ = "29.2025.3200"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lsst-daf-butler
|
|
3
|
-
Version: 29.2025.
|
|
3
|
+
Version: 29.2025.3200
|
|
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
|
|
@@ -25,14 +25,14 @@ lsst/daf/butler/_file_dataset.py,sha256=KF_o5zi01L0gK4t_Ncb3BSbCTiyf9zmwwTpWoNga
|
|
|
25
25
|
lsst/daf/butler/_file_descriptor.py,sha256=PIYT9O2NRbNndtI2rMXfx7tP6nUcTnd9fxFVsq-Hu1s,3841
|
|
26
26
|
lsst/daf/butler/_formatter.py,sha256=BZTpbAwATykj6Omz4pl5f5SdI_Qa0rWxhSUk1G4_UIc,83156
|
|
27
27
|
lsst/daf/butler/_labeled_butler_factory.py,sha256=vsh5rcdX0ZeVfDeC9eLWxRNy5KYz8W-bFN5WrRICcEY,8593
|
|
28
|
-
lsst/daf/butler/_limited_butler.py,sha256=
|
|
28
|
+
lsst/daf/butler/_limited_butler.py,sha256=85na5IWR3nRRWEgMcuy-lY46FPrxBRqsvgEMEnZoOkQ,16696
|
|
29
29
|
lsst/daf/butler/_location.py,sha256=oX-AKZeSdToeKBxvB6y-pxLMiFwF-3nz3YleH5SiA3A,10451
|
|
30
30
|
lsst/daf/butler/_named.py,sha256=-AvkTP5JIsCwj5tAmZO8epoRoF1_dGuz2aC0ItLg7-M,19541
|
|
31
31
|
lsst/daf/butler/_quantum.py,sha256=xqWk2mHLydf4VWpRTCR74eBjApESuaTb46_iOdLKFDo,25575
|
|
32
32
|
lsst/daf/butler/_quantum_backed.py,sha256=tvOB2kY8QMZKV98fQPjd8e6_1iW9oJtbdJT3xTCihz4,36476
|
|
33
33
|
lsst/daf/butler/_query_all_datasets.py,sha256=Ev5LHI3Mq9a3XEB9bccX4n70EDQ6OVHhKqeHoThIkz8,7135
|
|
34
34
|
lsst/daf/butler/_registry_shim.py,sha256=M15HOHpQTUPFfA7oPCnDw-IlmG0BrjZWu3KBfpAnoL8,14420
|
|
35
|
-
lsst/daf/butler/_storage_class.py,sha256=
|
|
35
|
+
lsst/daf/butler/_storage_class.py,sha256=p74C-_QjYbcVFm6SdS0RYa_Gjmz9sJJ3JAA98llisdc,32997
|
|
36
36
|
lsst/daf/butler/_storage_class_delegate.py,sha256=0fpDwQILeP0TcXP1W147Va4rX3qZhAyFpFkq6vrf6fo,16324
|
|
37
37
|
lsst/daf/butler/_timespan.py,sha256=t0FTm5rAJQ1xEGNJ2UqsOSH_TYvKJk-70l7FSeAIdmY,23685
|
|
38
38
|
lsst/daf/butler/_topology.py,sha256=TkPCLE_Rr_wkK6iOJcWeUP-wIkJkeQzPEl5-P8rqvHw,6323
|
|
@@ -52,7 +52,7 @@ lsst/daf/butler/repo_relocation.py,sha256=Ivhx2xU4slc53Z6RExhNnquMr2Hx-S8h62emml
|
|
|
52
52
|
lsst/daf/butler/time_utils.py,sha256=MVTfOFI2xt3IeA46pa-fWY2kJRwSzaQyq1uzeUABcTM,11805
|
|
53
53
|
lsst/daf/butler/timespan_database_representation.py,sha256=MWDusjIQIL2RH1CDpWSW5sYvdHCJKzAfpg1rm1DfgEU,24302
|
|
54
54
|
lsst/daf/butler/utils.py,sha256=5u50COK5z4u31grOhmQF7mFz55biNLOvSMRdQjEdsjo,5140
|
|
55
|
-
lsst/daf/butler/version.py,sha256=
|
|
55
|
+
lsst/daf/butler/version.py,sha256=5kA_2hRyFYLCSuDYZQBSx1jsWCdezZbf05_1pktQdgw,55
|
|
56
56
|
lsst/daf/butler/_utilities/__init__.py,sha256=vLzPZYAJ-9r1cnqsP64MVpFgSw2166yOpq0iPMSdAvw,1298
|
|
57
57
|
lsst/daf/butler/_utilities/locked_object.py,sha256=3RQf0Ish55mfQAfBy3V4Tfnfq5Q7-cxrwTlQMUhrIno,1931
|
|
58
58
|
lsst/daf/butler/_utilities/named_locks.py,sha256=Zj_u1rZELaiWec3wJfkgmGD_YiZMLVxbMQmdbbVgk5E,2286
|
|
@@ -95,8 +95,8 @@ lsst/daf/butler/datastore/composites.py,sha256=NZ7rBK5yH-hrtpqZxC8d49UwwQqWZlEmm
|
|
|
95
95
|
lsst/daf/butler/datastore/constraints.py,sha256=OcUXuXZq1UBnuQqq8U7Hp3Ezqu0RBN8pIo93BEq7lyI,5921
|
|
96
96
|
lsst/daf/butler/datastore/file_templates.py,sha256=xnb4ZheW6NqeCE__vkIvLF91d57nhfcX3ynGWI0rX_0,35095
|
|
97
97
|
lsst/daf/butler/datastore/generic_base.py,sha256=C15FN1fDVxs-XjeDc1hw5un3MMMVIaZN4QdFbjqQ168,5176
|
|
98
|
-
lsst/daf/butler/datastore/record_data.py,sha256=
|
|
99
|
-
lsst/daf/butler/datastore/stored_file_info.py,sha256=
|
|
98
|
+
lsst/daf/butler/datastore/record_data.py,sha256=dhku1kCG0WCeYeWOq9m0Euq02pa96XDF5W9nD_ZEe8k,10428
|
|
99
|
+
lsst/daf/butler/datastore/stored_file_info.py,sha256=s_9LsLZgIF7TwjiXEXgNPz3OaaRiUyzmf5SOdJ1elhk,15838
|
|
100
100
|
lsst/daf/butler/datastores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
101
101
|
lsst/daf/butler/datastores/chainedDatastore.py,sha256=0KWzBzUyUpd9wy4e6zPcJdNIr53Fl1eut__38jRUm-E,55468
|
|
102
102
|
lsst/daf/butler/datastores/fileDatastore.py,sha256=QC1zRPbD4ID8KPSgar3ttvnAsOscDexT7lMvf15I9HE,135991
|
|
@@ -116,7 +116,7 @@ lsst/daf/butler/dimensions/_elements.py,sha256=3Hn884mHbxz6H2KkMm-SFitEG_eHVRivU
|
|
|
116
116
|
lsst/daf/butler/dimensions/_governor.py,sha256=En0Ar_uBuUnuKG1IACbyaZ7FRwf234zI5IEjwIQmMHw,5963
|
|
117
117
|
lsst/daf/butler/dimensions/_group.py,sha256=GNKRmWwH4eiakGtzJPcwinVH57GSW86WRPNZ92erRx8,22833
|
|
118
118
|
lsst/daf/butler/dimensions/_packer.py,sha256=yfgw7gXMSkPC59Kr51X6Isi8j6ihxqoR1OO2xPnd8FY,6461
|
|
119
|
-
lsst/daf/butler/dimensions/_record_set.py,sha256=
|
|
119
|
+
lsst/daf/butler/dimensions/_record_set.py,sha256=IEH2dBxPTn56eHjOsyaneNjqeVv4VgqM6Z4_NiGBfNY,40454
|
|
120
120
|
lsst/daf/butler/dimensions/_record_table.py,sha256=b1ijXQlnXH1N8rdiAV4C4GlDmOsBbWGuzob8Gv0mtII,9733
|
|
121
121
|
lsst/daf/butler/dimensions/_records.py,sha256=QX8XxiHRhRKFkUO3CvoDpe_8KGGyt3nyl08ifxUWwVs,24677
|
|
122
122
|
lsst/daf/butler/dimensions/_schema.py,sha256=DOuhmI98f3yuvasFFATJCFrx6cjQSx4o2kyLioMbHlU,18507
|
|
@@ -320,7 +320,7 @@ lsst/daf/butler/script/transferDatasets.py,sha256=VPTiooLgpMkHWelTHCCvOYccr6OCPk
|
|
|
320
320
|
lsst/daf/butler/tests/__init__.py,sha256=JPCjf2ppCcTqC8pDpo5O-RNKlDlMqzql_rdQ41NUses,1506
|
|
321
321
|
lsst/daf/butler/tests/_datasetsHelper.py,sha256=LH1ZPuzSpRijAPtAiwBoSZZPzI-aSaHN3FU93AtJ6JI,8288
|
|
322
322
|
lsst/daf/butler/tests/_dummyRegistry.py,sha256=CowulEeirnWwSJf-AnutvOLvGSr3ITgShlYj9f_IuYk,9509
|
|
323
|
-
lsst/daf/butler/tests/_examplePythonTypes.py,sha256=
|
|
323
|
+
lsst/daf/butler/tests/_examplePythonTypes.py,sha256=oKuKhFkyipD7XCojlQR7D9xPyq6YS9nkB-U4_l07BIM,13281
|
|
324
324
|
lsst/daf/butler/tests/_testRepo.py,sha256=MVkQwXJ5vI86--Npa7SDHRblpJC5pig6vpGxv-dgGvE,23755
|
|
325
325
|
lsst/daf/butler/tests/butler_queries.py,sha256=DYEOZUHkv2T58CWydlfKozEddwCfwLMD_txW3nEQZsI,121629
|
|
326
326
|
lsst/daf/butler/tests/cliCmdTestBase.py,sha256=6SsDIIttbvwi9TX7jkaPa8VuTvzO17hL6WGAm_T6uxM,6994
|
|
@@ -347,13 +347,13 @@ lsst/daf/butler/transfers/__init__.py,sha256=M1YcFszSkNB5hB2pZwwGXqbJE2dKt4YXDin
|
|
|
347
347
|
lsst/daf/butler/transfers/_context.py,sha256=1oOlKWj53bjcVioOIzRNPZSC_Q0dLDI_R4syI9gMOkg,16938
|
|
348
348
|
lsst/daf/butler/transfers/_interfaces.py,sha256=Ia1NqcFR5E-Ik4zsXEe2fuMtNCJj5Yfe_gVHLTBtJDw,7490
|
|
349
349
|
lsst/daf/butler/transfers/_yaml.py,sha256=w_0GmrueuHVLfOfAXGHFBbWAl18tX6eSElbTC-2jRoc,32632
|
|
350
|
-
lsst_daf_butler-29.2025.
|
|
351
|
-
lsst_daf_butler-29.2025.
|
|
352
|
-
lsst_daf_butler-29.2025.
|
|
353
|
-
lsst_daf_butler-29.2025.
|
|
354
|
-
lsst_daf_butler-29.2025.
|
|
355
|
-
lsst_daf_butler-29.2025.
|
|
356
|
-
lsst_daf_butler-29.2025.
|
|
357
|
-
lsst_daf_butler-29.2025.
|
|
358
|
-
lsst_daf_butler-29.2025.
|
|
359
|
-
lsst_daf_butler-29.2025.
|
|
350
|
+
lsst_daf_butler-29.2025.3200.dist-info/licenses/COPYRIGHT,sha256=k1Vq0-Be_K-puaeW4UZnckPjksEL-MJh4XKiWcjMxJE,312
|
|
351
|
+
lsst_daf_butler-29.2025.3200.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
|
|
352
|
+
lsst_daf_butler-29.2025.3200.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
|
|
353
|
+
lsst_daf_butler-29.2025.3200.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
354
|
+
lsst_daf_butler-29.2025.3200.dist-info/METADATA,sha256=EKxNPWN4-EBJsVSYYnLginCjq8YLfqjt2sRDy_SZoRI,3265
|
|
355
|
+
lsst_daf_butler-29.2025.3200.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
356
|
+
lsst_daf_butler-29.2025.3200.dist-info/entry_points.txt,sha256=XsRxyTK3c-jGlKVuVnbpch3gtaO0lAA_fS3i2NGS5rw,59
|
|
357
|
+
lsst_daf_butler-29.2025.3200.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
|
|
358
|
+
lsst_daf_butler-29.2025.3200.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
359
|
+
lsst_daf_butler-29.2025.3200.dist-info/RECORD,,
|
|
File without changes
|
{lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/COPYRIGHT
RENAMED
|
File without changes
|
{lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lsst_daf_butler-29.2025.3100.dist-info → lsst_daf_butler-29.2025.3200.dist-info}/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|