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"""Tests related to the formatter infrastructure. 

23""" 

24 

25import inspect 

26import os.path 

27import unittest 

28 

29from lsst.daf.butler.tests import DatasetTestHelper 

30from lsst.daf.butler import (Formatter, FormatterFactory, StorageClass, DatasetType, Config, 

31 FileDescriptor, Location, DimensionUniverse, DimensionGraph) 

32 

33TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

34 

35 

36class FormatterFactoryTestCase(unittest.TestCase, DatasetTestHelper): 

37 """Tests of the formatter factory infrastructure. 

38 """ 

39 

40 def setUp(self): 

41 self.id = 0 

42 self.factory = FormatterFactory() 

43 

44 # Dummy FileDescriptor for testing getFormatter 

45 self.fileDescriptor = FileDescriptor(Location("/a/b/c", "d"), 

46 StorageClass("DummyStorageClass", dict, None)) 

47 

48 def assertIsFormatter(self, formatter): 

49 """Check that the supplied parameter is either a Formatter instance 

50 or Formatter class.""" 

51 

52 if inspect.isclass(formatter): 

53 self.assertTrue(issubclass(formatter, Formatter), f"Is {formatter} a Formatter") 

54 else: 

55 self.assertIsInstance(formatter, Formatter) 

56 

57 def testRegistry(self): 

58 """Check that formatters can be stored in the registry. 

59 """ 

60 formatterTypeName = "lsst.daf.butler.formatters.fitsCatalogFormatter.FitsCatalogFormatter" 

61 storageClassName = "Image" 

62 self.factory.registerFormatter(storageClassName, formatterTypeName) 

63 f = self.factory.getFormatter(storageClassName, self.fileDescriptor) 

64 self.assertIsFormatter(f) 

65 self.assertEqual(f.name(), formatterTypeName) 

66 self.assertIn(formatterTypeName, str(f)) 

67 self.assertIn(self.fileDescriptor.location.path, str(f)) 

68 

69 fcls = self.factory.getFormatterClass(storageClassName) 

70 self.assertIsFormatter(fcls) 

71 # Defer the import so that we ensure that the infrastructure loaded 

72 # it on demand previously 

73 from lsst.daf.butler.formatters.fitsCatalogFormatter import FitsCatalogFormatter 

74 self.assertEqual(type(f), FitsCatalogFormatter) 

75 

76 with self.assertRaises(TypeError): 

77 # Requires a constructor parameter 

78 self.factory.getFormatter(storageClassName) 

79 

80 with self.assertRaises(KeyError): 

81 self.factory.getFormatter("Missing", self.fileDescriptor) 

82 

83 def testRegistryWithStorageClass(self): 

84 """Test that the registry can be given a StorageClass object. 

85 """ 

86 formatterTypeName = "lsst.daf.butler.formatters.yamlFormatter.YamlFormatter" 

87 storageClassName = "TestClass" 

88 sc = StorageClass(storageClassName, dict, None) 

89 

90 universe = DimensionUniverse() 

91 datasetType = DatasetType("calexp", universe.empty, sc) 

92 

93 # Store using an instance 

94 self.factory.registerFormatter(sc, formatterTypeName) 

95 

96 # Retrieve using the class 

97 f = self.factory.getFormatter(sc, self.fileDescriptor) 

98 self.assertIsFormatter(f) 

99 self.assertEqual(f.fileDescriptor, self.fileDescriptor) 

100 

101 # Retrieve using the DatasetType 

102 f2 = self.factory.getFormatter(datasetType, self.fileDescriptor) 

103 self.assertIsFormatter(f2) 

104 self.assertEqual(f.name(), f2.name()) 

105 

106 # Class directly 

107 f2cls = self.factory.getFormatterClass(datasetType) 

108 self.assertIsFormatter(f2cls) 

109 

110 # This might defer the import, pytest may have already loaded it 

111 from lsst.daf.butler.formatters.yamlFormatter import YamlFormatter 

112 self.assertEqual(type(f), YamlFormatter) 

113 

114 with self.assertRaises(KeyError): 

115 # Attempt to overwrite using a different value 

116 self.factory.registerFormatter(storageClassName, 

117 "lsst.daf.butler.formatters.jsonFormatter.JsonFormatter") 

118 

119 def testRegistryConfig(self): 

120 configFile = os.path.join(TESTDIR, "config", "basic", "posixDatastore.yaml") 

121 config = Config(configFile) 

122 universe = DimensionUniverse() 

123 self.factory.registerFormatters(config["datastore", "formatters"], universe=universe) 

124 

125 # Create a DatasetRef with and without instrument matching the 

126 # one in the config file. 

127 dimensions = universe.extract(("visit", "physical_filter", "instrument")) 

128 sc = StorageClass("DummySC", dict, None) 

129 refPviHsc = self.makeDatasetRef("pvi", dimensions, sc, {"instrument": "DummyHSC", 

130 "physical_filter": "v"}, 

131 conform=False) 

132 refPviHscFmt = self.factory.getFormatterClass(refPviHsc) 

133 self.assertIsFormatter(refPviHscFmt) 

134 self.assertIn("JsonFormatter", refPviHscFmt.name()) 

135 

136 refPviNotHsc = self.makeDatasetRef("pvi", dimensions, sc, {"instrument": "DummyNotHSC", 

137 "physical_filter": "v"}, 

138 conform=False) 

139 refPviNotHscFmt = self.factory.getFormatterClass(refPviNotHsc) 

140 self.assertIsFormatter(refPviNotHscFmt) 

141 self.assertIn("PickleFormatter", refPviNotHscFmt.name()) 

142 

143 # Create a DatasetRef that should fall back to using Dimensions 

144 refPvixHsc = self.makeDatasetRef("pvix", dimensions, sc, {"instrument": "DummyHSC", 

145 "physical_filter": "v"}, 

146 conform=False) 

147 refPvixNotHscFmt = self.factory.getFormatterClass(refPvixHsc) 

148 self.assertIsFormatter(refPvixNotHscFmt) 

149 self.assertIn("PickleFormatter", refPvixNotHscFmt.name()) 

150 

151 # Create a DatasetRef that should fall back to using StorageClass 

152 dimensionsNoV = DimensionGraph(universe, names=("physical_filter", "instrument")) 

153 refPvixNotHscDims = self.makeDatasetRef("pvix", dimensionsNoV, sc, {"instrument": "DummyHSC", 

154 "physical_filter": "v"}, 

155 conform=False) 

156 refPvixNotHscDims_fmt = self.factory.getFormatterClass(refPvixNotHscDims) 

157 self.assertIsFormatter(refPvixNotHscDims_fmt) 

158 self.assertIn("YamlFormatter", refPvixNotHscDims_fmt.name()) 

159 

160 

161if __name__ == "__main__": 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true

162 unittest.main()