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__ = ("JsonFormatter", ) 

23 

24import builtins 

25import json 

26 

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

28 

29 

30class JsonFormatter(FileFormatter): 

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

32 """ 

33 extension = ".json" 

34 

35 unsupportedParameters = None 

36 """This formatter does not support any parameters (`frozenset`)""" 

37 

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

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

40 

41 Parameters 

42 ---------- 

43 path : `str` 

44 Path to use to open JSON format file. 

45 

46 Returns 

47 ------- 

48 data : `object` 

49 Either data as Python object read from JSON file, or None 

50 if the file could not be opened. 

51 """ 

52 try: 

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

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

55 except FileNotFoundError: 

56 data = None 

57 

58 return data 

59 

60 def _writeFile(self, inMemoryDataset): 

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

62 

63 Will look for `_asdict()` method to aid JSON serialization, following 

64 the approach of the simplejson module. 

65 

66 Parameters 

67 ---------- 

68 inMemoryDataset : `object` 

69 Object to serialize. 

70 

71 Raises 

72 ------ 

73 Exception 

74 The file could not be written. 

75 """ 

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

77 if hasattr(inMemoryDataset, "_asdict"): 

78 inMemoryDataset = inMemoryDataset._asdict() 

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

80 

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

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

83 

84 Parameters 

85 ---------- 

86 serializedDataset : `bytes` 

87 Bytes object to unserialize. 

88 pytype : `class`, optional 

89 Not used by this implementation. 

90 

91 Returns 

92 ------- 

93 inMemoryDataset : `object` 

94 The requested data as a Python object or None if the string could 

95 not be read. 

96 """ 

97 try: 

98 data = json.loads(serializedDataset) 

99 except json.JSONDecodeError: 

100 data = None 

101 

102 return data 

103 

104 def _toBytes(self, inMemoryDataset): 

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

106 

107 Parameters 

108 ---------- 

109 inMemoryDataset : `object` 

110 Object to serialize 

111 

112 Returns 

113 ------- 

114 serializedDataset : `bytes` 

115 bytes representing the serialized dataset. 

116 

117 Raises 

118 ------ 

119 Exception 

120 The object could not be serialized. 

121 """ 

122 return json.dumps(inMemoryDataset, ensure_ascii=False).encode() 

123 

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

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

126 

127 Parameters 

128 ---------- 

129 inMemoryDataset : `object` 

130 Object to coerce to expected type. 

131 storageClass : `StorageClass` 

132 StorageClass associated with `inMemoryDataset`. 

133 pytype : `type`, optional 

134 Override type to use for conversion. 

135 

136 Returns 

137 ------- 

138 inMemoryDataset : `object` 

139 Object of expected type `pytype`. 

140 """ 

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

142 if storageClass.isComposite(): 142 ↛ 144line 142 didn't jump to line 144, because the condition on line 142 was never false

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

144 elif not isinstance(inMemoryDataset, pytype): 

145 # Hope that we can pass the arguments in directly 

146 inMemoryDataset = pytype(inMemoryDataset) 

147 return inMemoryDataset