Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of daf_butler. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22"""Support for reading and writing composite objects.""" 

23 

24__all__ = ("CompositesConfig", "CompositesMap") 

25 

26import logging 

27 

28from .configSupport import processLookupConfigs 

29from .config import ConfigSubset 

30 

31log = logging.getLogger(__name__) 

32 

33# Key to access disassembly information 

34DISASSEMBLY_KEY = "disassembled" 

35 

36 

37class CompositesConfig(ConfigSubset): 

38 component = "composites" 

39 requiredKeys = ("default", DISASSEMBLY_KEY) 

40 defaultConfigFile = "composites.yaml" 

41 

42 def validate(self): 

43 """Validate entries have the correct type.""" 

44 super().validate() 

45 # For now assume flat config with keys mapping to booleans 

46 for k, v in self[DISASSEMBLY_KEY].items(): 

47 if not isinstance(v, bool): 

48 raise ValueError(f"CompositesConfig: Key {k} is not a Boolean") 

49 

50 

51class CompositesMap: 

52 """Determine whether a specific datasetType or StorageClass should be 

53 disassembled. 

54 

55 Parameters 

56 ---------- 

57 config : `str`, `ButlerConfig`, or `CompositesConfig` 

58 Configuration to control composites disassembly. 

59 universe : `DimensionUniverse` 

60 Set of all known dimensions, used to expand and validate any used 

61 in lookup keys. 

62 """ 

63 

64 def __init__(self, config, *, universe): 

65 if not isinstance(config, CompositesConfig): 

66 config = CompositesConfig(config) 

67 assert isinstance(config, CompositesConfig) 

68 self.config = config 

69 

70 # Calculate the disassembly lookup table -- no need to process 

71 # the values 

72 self._lut = processLookupConfigs(self.config[DISASSEMBLY_KEY], universe=universe) 

73 

74 def shouldBeDisassembled(self, entity): 

75 """Given some choices, indicate whether the entity should be 

76 disassembled. 

77 

78 Parameters 

79 ---------- 

80 entity : `StorageClass` or `DatasetType` or `DatasetRef` 

81 Thing to test against the configuration. The ``name`` property 

82 is used to determine a match. A `DatasetType` will first check 

83 its name, before checking its `StorageClass`. If there are no 

84 matches the default will be returned. If the associated 

85 `StorageClass` is not a composite, will always return `False`. 

86 

87 Returns 

88 ------- 

89 disassemble : `bool` 

90 Returns `True` if disassembly should occur; `False` otherwise. 

91 

92 Raises 

93 ------ 

94 ValueError 

95 The supplied argument is not understood. 

96 """ 

97 

98 if not hasattr(entity, "isComposite"): 

99 raise ValueError(f"Supplied entity ({entity}) is not understood.") 

100 

101 # If this is not a composite there is nothing to disassemble. 

102 if not entity.isComposite(): 

103 log.debug("%s will not be disassembled (not a composite)", entity) 

104 return False 

105 

106 matchName = "{} (via default)".format(entity) 

107 disassemble = self.config["default"] 

108 

109 for key in (entity._lookupNames()): 

110 if key is not None and key in self._lut: 

111 disassemble = self._lut[key] 

112 matchName = key 

113 break 

114 

115 log.debug("%s will%s be disassembled", matchName, "" if disassemble else " not") 

116 return disassemble