Coverage for gws-app/gws/plugin/ows_client/wms/flatlayer.py: 0%

96 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-17 01:37 +0200

1from typing import Optional 

2 

3import gws 

4import gws.base.layer 

5import gws.base.legend 

6import gws.base.model 

7import gws.base.search 

8import gws.base.template 

9import gws.config.util 

10import gws.lib.metadata 

11import gws.gis.crs 

12import gws.gis.source 

13import gws.gis.zoom 

14import gws.gis.bounds 

15import gws.gis.extent 

16 

17from . import provider 

18 

19gws.ext.new.layer('wmsflat') 

20 

21 

22class Config(gws.base.layer.Config): 

23 """Flat WMS layer.""" 

24 

25 provider: Optional[provider.Config] 

26 """WMS provider""" 

27 sourceLayers: Optional[gws.gis.source.LayerFilter] 

28 """source layers to use""" 

29 

30 

31class Object(gws.base.layer.image.Object): 

32 serviceProvider: provider.Object 

33 sourceLayers: list[gws.SourceLayer] 

34 sourceCrs: gws.Crs 

35 

36 imageLayers: list[gws.SourceLayer] 

37 searchLayers: list[gws.SourceLayer] 

38 

39 def configure(self): 

40 self.configure_layer() 

41 

42 def configure_provider(self): 

43 return gws.config.util.configure_service_provider_for(self, provider.Object) 

44 

45 def configure_sources(self): 

46 if super().configure_sources(): 

47 return True 

48 

49 self.configure_source_layers() 

50 if not self.sourceLayers: 

51 raise gws.Error(f'layer {self!r}: no source layers found for {self.serviceProvider.url!r}') 

52 

53 self.imageLayers = gws.gis.source.filter_layers(self.sourceLayers, is_image=True) 

54 self.searchLayers = gws.gis.source.filter_layers(self.sourceLayers, is_queryable=True) 

55 

56 self.sourceCrs = self.serviceProvider.forceCrs or gws.gis.crs.best_match( 

57 self.mapCrs, 

58 gws.gis.source.combined_crs_list(self.sourceLayers)) 

59 

60 def configure_source_layers(self): 

61 return gws.config.util.configure_source_layers_for(self, self.serviceProvider.sourceLayers) 

62 

63 def configure_models(self): 

64 return gws.config.util.configure_models_for(self, with_default=True) 

65 

66 def create_model(self, cfg): 

67 return self.create_child( 

68 gws.ext.object.model, 

69 cfg, 

70 type='wms', 

71 _defaultProvider=self.serviceProvider, 

72 _defaultSourceLayers=self.sourceLayers 

73 ) 

74 

75 def configure_bounds(self): 

76 if super().configure_bounds(): 

77 return True 

78 self.bounds = gws.gis.source.combined_bounds(self.imageLayers, self.mapCrs) or self.mapCrs.bounds 

79 return True 

80 

81 def configure_resolutions(self): 

82 if super().configure_resolutions(): 

83 return True 

84 self.resolutions = gws.gis.zoom.resolutions_from_source_layers( 

85 self.sourceLayers, self.cfg('_parentResolutions')) 

86 if self.resolutions: 

87 return True 

88 raise gws.Error(f'layer {self!r}: no matching resolutions') 

89 

90 def configure_grid(self): 

91 if super().configure_grid(): 

92 return True 

93 self.grid = gws.TileGrid( 

94 origin=gws.Origin.nw, 

95 tileSize=256, 

96 bounds=self.bounds, 

97 resolutions=self.resolutions) 

98 return True 

99 

100 def configure_legend(self): 

101 if super().configure_legend(): 

102 return True 

103 urls = gws.u.compact(sl.legendUrl for sl in self.imageLayers) 

104 if urls: 

105 self.legend = self.create_child(gws.ext.object.legend, type='remote', urls=urls) 

106 return True 

107 

108 def configure_metadata(self): 

109 if super().configure_metadata(): 

110 return True 

111 if len(self.sourceLayers) == 1: 

112 self.metadata = self.sourceLayers[0].metadata 

113 return True 

114 

115 def configure_search(self): 

116 if super().configure_search(): 

117 return True 

118 if self.searchLayers: 

119 self.finders.append(self.create_finder(None)) 

120 return True 

121 

122 def create_finder(self, cfg): 

123 return self.create_child( 

124 gws.ext.object.finder, 

125 cfg, 

126 type='wms', 

127 _defaultProvider=self.serviceProvider, 

128 _defaultSourceLayers=self.searchLayers 

129 ) 

130 

131 ## 

132 

133 def render(self, lri): 

134 return gws.base.layer.util.mpx_raster_render(self, lri) 

135 

136 def mapproxy_config(self, mc, options=None): 

137 # NB reversed: see the note in plugin/ows_client/wms/provider.py 

138 layers = reversed([sl.name for sl in self.imageLayers]) 

139 op = self.serviceProvider.get_operation(gws.OwsVerb.GetMap) 

140 args = self.serviceProvider.prepare_operation(op) 

141 

142 req = gws.u.merge( 

143 args.params, 

144 transparent=True, 

145 layers=','.join(layers), 

146 url=args.url, 

147 ) 

148 

149 src = gws.u.compact({ 

150 'type': 'wms', 

151 'supported_srs': [self.sourceCrs.epsg], 

152 'concurrent_requests': self.serviceProvider.maxRequests, 

153 'req': req, 

154 'wms_opts': { 

155 'version': self.serviceProvider.version, 

156 } 

157 }) 

158 

159 if args.headers: 

160 src['http'] = {'headers': args.headers} 

161 

162 source_uid = mc.source(src) 

163 

164 gws.base.layer.util.mapproxy_layer_config(self, mc, source_uid)