Coverage for python/lsst/sphgeom/_yaml.py: 63%

42 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-02 03:12 -0700

1# This file is part of sphgeom. 

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 software is dual licensed under the GNU General Public License and also 

10# under a 3-clause BSD license. Recipients may choose which of these licenses 

11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, 

12# respectively. If you choose the GPL option then the following text applies 

13# (but note that there is still no warranty even if you opt for BSD instead): 

14# 

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

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

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

18# (at your option) any later version. 

19# 

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

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

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

23# GNU General Public License for more details. 

24# 

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

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

27 

28"""Add support for YAML serialization of regions.""" 

29 

30__all__ = () 

31 

32# YAML representers and constructors are only useful if yaml itself can 

33# be imported. If yaml can not be imported then there is no reason to 

34# break the entire module import of sphgeom. 

35try: 

36 import yaml 

37except ImportError: 

38 yaml = None 

39 

40from ._healpixPixelization import HealpixPixelization 

41from ._sphgeom import ( 

42 Box, 

43 Circle, 

44 ConvexPolygon, 

45 Ellipse, 

46 HtmPixelization, 

47 IntersectionRegion, 

48 Mq3cPixelization, 

49 Q3cPixelization, 

50 Region, 

51 UnionRegion, 

52) 

53 

54if yaml: 54 ↛ 69line 54 didn't jump to line 69, because the condition on line 54 was never false

55 try: 

56 # CLoader is not always available 

57 from yaml import CLoader 

58 except ImportError: 

59 CLoader = None 

60 

61 YamlLoaders = (yaml.Loader, yaml.FullLoader, yaml.SafeLoader, yaml.UnsafeLoader) 

62 if CLoader is not None: 62 ↛ 69line 62 didn't jump to line 69, because the condition on line 62 was never false

63 YamlLoaders += (CLoader,) 

64 

65 

66# Regions 

67 

68 

69def region_representer(dumper, data): 

70 """Represent a sphgeom region object in a form suitable for YAML. 

71 

72 Stores the region as a mapping with a single ``encoded`` key 

73 storing the hex encoded byte string. 

74 """ 

75 encoded = data.encode() 

76 return dumper.represent_mapping(f"lsst.sphgeom.{type(data).__name__}", {"encoded": encoded.hex()}) 

77 

78 

79def region_constructor(loader, node): 

80 """Construct a sphgeom region from YAML.""" 

81 mapping = loader.construct_mapping(node) 

82 encoded = bytes.fromhex(mapping["encoded"]) 

83 # The generic Region base class can instantiate a region of the 

84 # correct type. 

85 return Region.decode(encoded) 

86 

87 

88# Register all the region classes with the same constructor and representer 

89if yaml: 89 ↛ 100line 89 didn't jump to line 100, because the condition on line 89 was never false

90 for region_class in (ConvexPolygon, Ellipse, Circle, Box, UnionRegion, IntersectionRegion): 

91 yaml.add_representer(region_class, region_representer) 

92 

93 for loader in YamlLoaders: 

94 yaml.add_constructor(f"lsst.sphgeom.{region_class.__name__}", region_constructor, Loader=loader) 

95 

96 

97# Pixelization schemes 

98 

99 

100def pixel_representer(dumper, data): 

101 """Represent a pixelization in YAML. 

102 

103 Stored as the pixelization level in a mapping with a single key 

104 ``level``. 

105 """ 

106 return dumper.represent_mapping(f"lsst.sphgeom.{type(data).__name__}", {"level": data.getLevel()}) 

107 

108 

109def pixel_constructor(loader, node): 

110 """Construct a pixelization object from YAML.""" 

111 mapping = loader.construct_mapping(node) 

112 

113 className = node.tag 

114 pixelMap = { 

115 "lsst.sphgeom.Q3cPixelization": Q3cPixelization, 

116 "lsst.sphgeom.Mq3cPixelization": Mq3cPixelization, 

117 "lsst.sphgeom.HtmPixelization": HtmPixelization, 

118 "lsst.sphgeom.HealpixPixelization": HealpixPixelization, 

119 } 

120 

121 if className not in pixelMap: 

122 raise RuntimeError( 

123 f"Encountered unexpected class {className} associated with sphgeom pixelization YAML constructor" 

124 ) 

125 

126 return pixelMap[className](mapping["level"]) 

127 

128 

129# All the pixelization schemes use the same approach with getLevel 

130if yaml: 130 ↛ exitline 130 didn't jump to the function exit

131 for pixelSchemeCls in (HtmPixelization, Q3cPixelization, Mq3cPixelization, HealpixPixelization): 

132 yaml.add_representer(pixelSchemeCls, pixel_representer) 

133 for loader in YamlLoaders: 

134 yaml.add_constructor(f"lsst.sphgeom.{pixelSchemeCls.__name__}", pixel_constructor, Loader=loader)