Coverage for gws-app/gws/plugin/ows_client/wms/flatlayer.py: 0%
81 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
1"""WMS flat layer."""
3from typing import Optional
5import gws
6import gws.base.layer
7import gws.base.legend
8import gws.base.model
9import gws.base.search
10import gws.base.template
11import gws.config.util
12import gws.base.metadata
13import gws.lib.crs
14import gws.gis.source
15import gws.gis.zoom
17from . import grabber, provider
20@gws.ext.config.layer('wmsflat')
21class Config(gws.base.layer.Config):
22 """Layer that renders selected WMS layers as a single image."""
24 provider: Optional[provider.Config]
25 """WMS service the layer is loaded from."""
26 sourceLayers: Optional[gws.gis.source.LayerFilter]
27 """Source layers to render."""
30@gws.ext.object.layer('wmsflat')
31class Object(gws.base.layer.image.Object):
32 """Image layer that renders selected WMS source layers as a single image.
34 Map images are fetched with GetMap through a WMS grabber. Queryable source
35 layers can be searched with a ``wms`` finder.
36 """
38 provider: provider.Object
39 """WMS service provider."""
40 sourceLayers: list[gws.SourceLayer]
41 """Source layers selected for this layer."""
42 sourceCrs: gws.Crs
43 """CRS of GetMap requests: the forced CRS of the provider, or the source CRS that best matches the map CRS."""
45 imageLayers: list[gws.SourceLayer]
46 """Source layers that are rendered as images."""
47 searchLayers: list[gws.SourceLayer]
48 """Source layers that are queryable."""
50 def configure(self):
51 self.configure_layer()
53 def create_cache_name(self, cache):
54 return gws.u.sha256([
55 self.provider.cache_hash(),
56 [sl.name for sl in self.imageLayers],
57 vars(self.imageFormat),
58 list(self.wgsExtent),
59 cache.requestBuffer,
60 cache.requestTiles,
61 ])[: gws.base.layer.image.CACHE_NAME_LENGTH]
63 def create_grabber(self, opts):
64 return grabber.Object(opts, provider=self.provider, sourceLayers=self.imageLayers, sourceCrs=self.sourceCrs)
66 def configure_provider(self):
67 return gws.config.util.configure_provider_for(self, provider.Object)
69 def configure_sources(self):
70 if super().configure_sources():
71 return True
73 gws.u.require(self.provider, 'failed to configure service provider')
75 self.configure_source_layers()
76 if not self.sourceLayers:
77 raise gws.Error(f'layer {self!r}: no source layers found for {self.provider.url!r}')
79 self.imageLayers = gws.gis.source.filter_layers(self.sourceLayers, is_image=True)
80 self.searchLayers = gws.gis.source.filter_layers(self.sourceLayers, is_queryable=True)
82 self.sourceCrs = self.provider.forceCrs or gws.lib.crs.best_match(
83 self.mapCrs,
84 gws.gis.source.combined_crs_list(self.sourceLayers))
86 def configure_source_layers(self):
87 """Select the source layers from the layers of the provider.
89 Returns:
90 Always ``True``.
91 """
92 return gws.config.util.configure_source_layers_for(self, self.provider.sourceLayers)
94 def configure_models(self):
95 return gws.config.util.configure_models_for(self, with_default=True)
97 def create_model(self, cfg):
98 """Create a ``wms`` model bound to the provider and the source layers of the layer.
100 Args:
101 cfg: Model configuration, or ``None`` for the default model.
103 Returns:
104 The model object.
105 """
106 return self.create_child(
107 gws.ext.object.model,
108 cfg,
109 type='wms',
110 _defaultProvider=self.provider,
111 _defaultSourceLayers=self.sourceLayers
112 )
114 def configure_extent(self):
115 if super().configure_extent():
116 return True
117 self.wgsExtent = gws.gis.source.combined_wgs_extent(self.imageLayers) or self.mapCrs.wgsExtent
118 return True
120 def configure_resolutions(self):
121 if super().configure_resolutions():
122 return True
123 self.resolutions = gws.gis.zoom.resolutions_from_source_layers(
124 self.sourceLayers, self.cfg('_parentResolutions'), self.mapCrs)
125 if self.resolutions:
126 return True
127 raise gws.Error(f'layer {self!r}: no matching resolutions')
129 def configure_legend(self):
130 if super().configure_legend():
131 return True
132 urls = gws.u.compact(sl.legendUrl for sl in self.imageLayers)
133 if urls:
134 self.legend = self.create_child(gws.ext.object.legend, type='remote', urls=urls)
135 return True
137 def configure_metadata(self):
138 if super().configure_metadata():
139 return True
140 if len(self.sourceLayers) == 1:
141 self.metadata = self.sourceLayers[0].metadata
142 return True
144 def configure_search(self):
145 if super().configure_search():
146 return True
147 if self.searchLayers:
148 self.finders.append(self.create_finder(None))
149 return True
151 def create_finder(self, cfg):
152 """Create a ``wms`` finder bound to the provider and the queryable source layers of the layer.
154 Args:
155 cfg: Finder configuration, or ``None`` for the default finder.
157 Returns:
158 The finder object.
159 """
160 return self.create_child(
161 gws.ext.object.finder,
162 cfg,
163 type='wms',
164 _defaultProvider=self.provider,
165 _defaultSourceLayers=self.searchLayers
166 )