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

97 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 12:46 +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.base.metadata 

11import gws.lib.crs 

12import gws.gis.source 

13import gws.gis.zoom 

14import gws.lib.bounds 

15import gws.lib.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 gws.u.require(self.serviceProvider, 'failed to configure service provider') 

50 

51 self.configure_source_layers() 

52 if not self.sourceLayers: 

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

54 

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

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

57 

58 self.sourceCrs = self.serviceProvider.forceCrs or gws.lib.crs.best_match( 

59 self.mapCrs, 

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

61 

62 def configure_source_layers(self): 

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

64 

65 def configure_models(self): 

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

67 

68 def create_model(self, cfg): 

69 return self.create_child( 

70 gws.ext.object.model, 

71 cfg, 

72 type='wms', 

73 _defaultProvider=self.serviceProvider, 

74 _defaultSourceLayers=self.sourceLayers 

75 ) 

76 

77 def configure_bounds(self): 

78 if super().configure_bounds(): 

79 return True 

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

81 return True 

82 

83 def configure_resolutions(self): 

84 if super().configure_resolutions(): 

85 return True 

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

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

88 if self.resolutions: 

89 return True 

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

91 

92 def configure_grid(self): 

93 if super().configure_grid(): 

94 return True 

95 self.grid = gws.TileGrid( 

96 origin=gws.Origin.nw, 

97 tileSize=256, 

98 bounds=self.bounds, 

99 resolutions=self.resolutions) 

100 return True 

101 

102 def configure_legend(self): 

103 if super().configure_legend(): 

104 return True 

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

106 if urls: 

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

108 return True 

109 

110 def configure_metadata(self): 

111 if super().configure_metadata(): 

112 return True 

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

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

115 return True 

116 

117 def configure_search(self): 

118 if super().configure_search(): 

119 return True 

120 if self.searchLayers: 

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

122 return True 

123 

124 def create_finder(self, cfg): 

125 return self.create_child( 

126 gws.ext.object.finder, 

127 cfg, 

128 type='wms', 

129 _defaultProvider=self.serviceProvider, 

130 _defaultSourceLayers=self.searchLayers 

131 ) 

132 

133 ## 

134 

135 def render(self, lri): 

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

137 

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

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

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

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

142 args = self.serviceProvider.prepare_operation(op) 

143 

144 req = gws.u.merge( 

145 args.params, 

146 transparent=True, 

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

148 url=args.url, 

149 ) 

150 

151 src = gws.u.compact({ 

152 'type': 'wms', 

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

154 'concurrent_requests': self.serviceProvider.maxRequests, 

155 'req': req, 

156 'wms_opts': { 

157 'version': self.serviceProvider.version, 

158 } 

159 }) 

160 

161 if args.headers: 

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

163 

164 source_uid = mc.source(src) 

165 

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