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__all__ = ("YamlFormatter", ) 

23 

24import builtins 

25import yaml 

26 

27from lsst.daf.butler.formatters.fileFormatter import FileFormatter 

28 

29 

30class YamlFormatter(FileFormatter): 

31 """Interface for reading and writing Python objects to and from YAML files. 

32 """ 

33 extension = ".yaml" 

34 

35 unsupportedParameters = None 

36 """This formatter does not support any parameters""" 

37 

38 def _readFile(self, path, pytype=None): 

39 """Read a file from the path in YAML format. 

40 

41 Parameters 

42 ---------- 

43 path : `str` 

44 Path to use to open YAML format file. 

45 pytype : `class`, optional 

46 Not used by this implementation. 

47 

48 Returns 

49 ------- 

50 data : `object` 

51 Either data as Python object read from YAML file, or None 

52 if the file could not be opened. 

53 

54 Notes 

55 ----- 

56 The `~yaml.UnsafeLoader` is used when parsing the YAML file. 

57 """ 

58 try: 

59 with open(path, "rb") as fd: 

60 data = self._fromBytes(fd.read(), pytype) 

61 except FileNotFoundError: 

62 data = None 

63 

64 return data 

65 

66 def _fromBytes(self, serializedDataset, pytype=None): 

67 """Read the bytes object as a python object. 

68 

69 Parameters 

70 ---------- 

71 serializedDataset : `bytes` 

72 Bytes object to unserialize. 

73 pytype : `class`, optional 

74 Not used by this implementation. 

75 

76 Returns 

77 ------- 

78 inMemoryDataset : `object` 

79 The requested data as an object, or None if the string could 

80 not be read. 

81 """ 

82 try: 

83 data = yaml.load(serializedDataset, Loader=yaml.UnsafeLoader) 

84 except yaml.YAMLError: 

85 data = None 

86 try: 

87 data = data.exportAsDict() 

88 except AttributeError: 

89 pass 

90 return data 

91 

92 def _writeFile(self, inMemoryDataset): 

93 """Write the in memory dataset to file on disk. 

94 

95 Will look for `_asdict()` method to aid YAML serialization, following 

96 the approach of the simplejson module. 

97 

98 Parameters 

99 ---------- 

100 inMemoryDataset : `object` 

101 Object to serialize. 

102 

103 Raises 

104 ------ 

105 Exception 

106 The file could not be written. 

107 """ 

108 with open(self.fileDescriptor.location.path, "wb") as fd: 

109 if hasattr(inMemoryDataset, "_asdict"): 

110 inMemoryDataset = inMemoryDataset._asdict() 

111 fd.write(self._toBytes(inMemoryDataset)) 

112 

113 def _toBytes(self, inMemoryDataset): 

114 """Write the in memory dataset to a bytestring. 

115 

116 Parameters 

117 ---------- 

118 inMemoryDataset : `object` 

119 Object to serialize 

120 

121 Returns 

122 ------- 

123 serializedDataset : `bytes` 

124 YAML string encoded to bytes. 

125 

126 Raises 

127 ------ 

128 Exception 

129 The object could not be serialized. 

130 """ 

131 return yaml.dump(inMemoryDataset).encode() 

132 

133 def _coerceType(self, inMemoryDataset, storageClass, pytype=None): 

134 """Coerce the supplied inMemoryDataset to type `pytype`. 

135 

136 Parameters 

137 ---------- 

138 inMemoryDataset : `object` 

139 Object to coerce to expected type. 

140 storageClass : `StorageClass` 

141 StorageClass associated with `inMemoryDataset`. 

142 pytype : `type`, optional 

143 Override type to use for conversion. 

144 

145 Returns 

146 ------- 

147 inMemoryDataset : `object` 

148 Object of expected type `pytype`. 

149 """ 

150 if not hasattr(builtins, pytype.__name__): 

151 if storageClass.isComposite(): 

152 inMemoryDataset = storageClass.assembler().assemble(inMemoryDataset, pytype=pytype) 

153 elif not isinstance(inMemoryDataset, pytype): 

154 # Hope that we can pass the arguments in directly 

155 inMemoryDataset = pytype(inMemoryDataset) 

156 return inMemoryDataset