def transform_bbox(): source = SRS(request.json.get('source')) dest = SRS(request.json.get('dest')) bbox = source.align_bbox(request.json.get('bbox')) if grid.is_valid_transformation(bbox, source, dest): transformed_bbox = source.transform_bbox_to(dest, bbox) return {'bbox': transformed_bbox} else: response.status = 400 return {'error': 'Could not transform bbox'}
class TestTransform(object): def setup(self): self.src_img = ImageSource(create_debug_img((200, 200), transparent=False)) self.src_srs = SRS(31467) self.dst_size = (100, 150) self.dst_srs = SRS(4326) self.dst_bbox = (0.2, 45.1, 8.3, 53.2) self.src_bbox = self.dst_srs.transform_bbox_to(self.src_srs, self.dst_bbox) def test_transform(self, mesh_div=4): transformer = ImageTransformer(self.src_srs, self.dst_srs, mesh_div=mesh_div) result = transformer.transform(self.src_img, self.src_bbox, self.dst_size, self.dst_bbox, image_opts=ImageOptions(resampling='nearest')) assert isinstance(result, ImageSource) assert result.as_image() != self.src_img assert result.size == (100, 150) def _test_compare_mesh_div(self): """ Create transformations with different div values. """ for div in [1, 2, 4, 6, 8, 12, 16]: transformer = ImageTransformer(self.src_srs, self.dst_srs, mesh_div=div) result = transformer.transform(self.src_img, self.src_bbox, self.dst_size, self.dst_bbox) result.as_image().save('/tmp/transform-%d.png' % (div,))
def setup(self): self.src_img = ImageSource(create_debug_img((200, 200), transparent=False)) self.src_srs = SRS(31467) self.dst_size = (100, 150) self.dst_srs = SRS(4326) self.dst_bbox = (0.2, 45.1, 8.3, 53.2) self.src_bbox = self.dst_srs.transform_bbox_to(self.src_srs, self.dst_bbox)
def __init__(self, request_bbox=[], grid_bbox=[], level=None, grid_srs=None, grid_bbox_srs=None, map_srs=None, res=[], scales=[], origin='ll', units='m', dpi=None): self.grid_srs = SRS(grid_srs) if grid_srs else None self.grid_bbox_srs = SRS(grid_bbox_srs) if grid_bbox_srs else None self.map_srs = SRS(map_srs) if map_srs else None self.request_bbox = map(float, request_bbox) if request_bbox else None self.origin = origin self._res = list(map(float, res)) if res else None self._scales = list(map(float, scales)) if scales else None self._units = 1 if units == 'm' else constants.UNIT_FACTOR self._dpi = float(dpi) if dpi else constants.OGC_DPI _grid_bbox = list(map(float, grid_bbox)) if grid_bbox else None self.grid_bbox = self.transform_grid_bbox(_grid_bbox) if self._res: self._num_levels = len(self._res) elif self._scales: self._num_levels = len(self._scales) else: self._num_levels = None try: self.level = int(level) except TypeError: self.level = None if self.grid_srs: self.tilegrid = tile_grid(srs=self.grid_srs, bbox=_grid_bbox, bbox_srs=self.grid_bbox_srs, origin=self.origin, res=self.res, num_levels=self._num_levels) self.validate_tile_bbox_for_level_0() else: self.tilegrid = None
def test_geotiff_tags( self, tmpdir, srs, bbox, size, expected_pixel_res, expected_origin, projected, compression, ): img = ImageSource(create_debug_img(size), georef=GeoReference(bbox=bbox, srs=SRS(srs))) fname = os.path.join(str(tmpdir), 'geo.tiff') img_opts = ImageOptions( format='tiff', encoding_options={'tiff_compression': compression}) img2 = ImageSource(img.as_buffer(img_opts)).as_image() assert_geotiff_tags(img2, expected_origin, expected_pixel_res, srs, projected)
def test_get_map_non_image_content_type(self): with tmp_image((512, 512)) as img: expected_req = ({ 'path': r'/service?LAYERS=foo&SERVICE=WMS&FORMAT=image%2Fpng' '&REQUEST=GetMap&HEIGHT=512&SRS=EPSG%3A4326&styles=' '&VERSION=1.1.1&BBOX=0.0,10.0,10.0,20.0&WIDTH=512' }, { 'body': img.read(), 'headers': { 'content-type': 'text/plain' } }) with mock_httpd(TEST_SERVER_ADDRESS, [expected_req]): q = MapQuery((0.0, 10.0, 10.0, 20.0), (512, 512), SRS(4326)) try: self.source.get_map(q) except SourceError, e: assert 'no image returned' in e.args[0] else: assert False, 'no SourceError raised'
def test_meter(self): res_range = ResolutionRange(1000, 10) assert not res_range.contains([0, 0, 100000, 100000], (10, 10), SRS(900913)) assert not res_range.contains([0, 0, 100000, 100000], (99, 99), SRS(900913)) # min is exclusive but there is a delta assert res_range.contains([0, 0, 100000, 100000], (100, 100), SRS(900913)) assert res_range.contains([0, 0, 100000, 100000], (1000, 1000), SRS(900913)) # max is inclusive assert res_range.contains([0, 0, 100000, 100000], (10000, 10000), SRS(900913)) assert not res_range.contains([0, 0, 100000, 100000], (10001, 10001), SRS(900913))
class TestTransform(object): def setup(self): self.src_img = ImageSource( create_debug_img((200, 200), transparent=False)) self.src_srs = SRS(31467) self.dst_size = (100, 150) self.dst_srs = SRS(4326) self.dst_bbox = (0.2, 45.1, 8.3, 53.2) self.src_bbox = self.dst_srs.transform_bbox_to(self.src_srs, self.dst_bbox) def test_transform(self): transformer = ImageTransformer(self.src_srs, self.dst_srs) result = transformer.transform( self.src_img, self.src_bbox, self.dst_size, self.dst_bbox, image_opts=ImageOptions(resampling="nearest"), ) assert isinstance(result, ImageSource) assert result.as_image() != self.src_img.as_image() assert result.size == (100, 150) def _test_compare_max_px_err(self): """ Create transformations with different div values. """ for err in [0.2, 0.5, 1, 2, 4, 6, 8, 12, 16]: transformer = ImageTransformer(self.src_srs, self.dst_srs, max_px_err=err) result = transformer.transform( self.src_img, self.src_bbox, self.dst_size, self.dst_bbox, image_opts=ImageOptions(resampling="nearest"), ) result.as_image().save("/tmp/transform-%03d.png" % (err * 10, ))
def test_http_error_handler(self, client): error_handler = HTTPSourceErrorHandler() error_handler.add_handler(500, (255, 0, 0), cacheable=True) error_handler.add_handler(400, (0, 0, 0), cacheable=False) source = WMSSource(client, error_handler=error_handler) expected_req = [ ( { 'path': r'/service?LAYERS=foo&SERVICE=WMS&FORMAT=image%2Fpng' '&REQUEST=GetMap&HEIGHT=512&SRS=EPSG%3A4326' '&VERSION=1.1.1&BBOX=0.0,10.0,10.0,20.0&WIDTH=512&STYLES=' }, { 'body': b'error', 'status': 500, 'headers': {'content-type': 'text/plain'}, }, ), ( { 'path': r'/service?LAYERS=foo&SERVICE=WMS&FORMAT=image%2Fpng' '&REQUEST=GetMap&HEIGHT=512&SRS=EPSG%3A4326' '&VERSION=1.1.1&BBOX=0.0,10.0,10.0,20.0&WIDTH=512&STYLES=' }, { 'body': b'error', 'status': 400, 'headers': {'content-type': 'text/plain'}, }, ), ] with mock_httpd(TEST_SERVER_ADDRESS, expected_req): query = MapQuery((0.0, 10.0, 10.0, 20.0), (512, 512), SRS(4326)) resp = source.get_map(query) assert resp.cacheable assert resp.as_image().getcolors() == [((512 * 512), (255, 0, 0))] resp = source.get_map(query) assert not resp.cacheable assert resp.as_image().getcolors() == [((512 * 512), (0, 0, 0))]
def test_image_response(self): error_handler = HTTPSourceErrorHandler() error_handler.add_handler(500, (255, 0, 0), cacheable=False) self.source = TiledSource(self.grid, self.client, error_handler=error_handler) with mock_httpd(TEST_SERVER_ADDRESS, [({ 'path': '/1/0/0.png' }, { 'body': b'error', 'status': 500, 'headers': { 'content-type': 'text/plain' } })]): resp = self.source.get_map( MapQuery([-180, -90, 0, 90], (256, 256), SRS(4326), format='png')) assert not resp.cacheable eq_(resp.as_image().getcolors(), [((256 * 256), (255, 0, 0))])
class TestTransform(object): def setup(self): self.src_img = ImageSource( create_debug_img((200, 200), transparent=False)) self.src_srs = SRS(31467) self.dst_size = (100, 150) self.dst_srs = SRS(4326) self.dst_bbox = (0.2, 45.1, 8.3, 53.2) self.src_bbox = self.dst_srs.transform_bbox_to(self.src_srs, self.dst_bbox) def test_transform(self, mesh_div=4): transformer = ImageTransformer(self.src_srs, self.dst_srs, mesh_div=mesh_div) result = transformer.transform( self.src_img, self.src_bbox, self.dst_size, self.dst_bbox, image_opts=ImageOptions(resampling='nearest')) assert isinstance(result, ImageSource) assert result.as_image() != self.src_img.as_image() assert result.size == (100, 150) def _test_compare_mesh_div(self): """ Create transformations with different div values. """ for div in [1, 2, 4, 6, 8, 12, 16]: transformer = ImageTransformer(self.src_srs, self.dst_srs, mesh_div=div) result = transformer.transform(self.src_img, self.src_bbox, self.dst_size, self.dst_bbox) result.as_image().save('/tmp/transform-%d.png' % (div, ))
def doc(self, tile, grid): doc = {} x, y, z = tile.coord for key, value in iteritems(self.attributes): if not isinstance(value, string_type) or not value.startswith('{{'): doc[key] = value continue if value == '{{timestamp}}': doc[key] = time.time() elif value == '{{x}}': doc[key] = x elif value == '{{y}}': doc[key] = y elif value in ('{{z}}', '{{level}}'): doc[key] = z elif value == '{{utc_iso}}': doc[key] = utc_now_isoformat() elif value == '{{wgs_tile_centroid}}': tile_bbox = grid.tile_bbox(tile.coord) centroid = ( tile_bbox[0] + (tile_bbox[2]-tile_bbox[0])/2, tile_bbox[1] + (tile_bbox[3]-tile_bbox[1])/2 ) centroid = grid.srs.transform_to(SRS(4326), centroid) doc[key] = centroid elif value == '{{tile_centroid}}': tile_bbox = grid.tile_bbox(tile.coord) centroid = ( tile_bbox[0] + (tile_bbox[2]-tile_bbox[0])/2, tile_bbox[1] + (tile_bbox[3]-tile_bbox[1])/2 ) doc[key] = centroid else: raise ValueError('unknown CouchDB tile_metadata value: %r' % (value, )) return doc
def test_get_map(self, source, mock_http_client): source.get_map(MapQuery((-180, -90, 180, 90), (300, 150), SRS(4326))) assert query_eq(mock_http_client.requested[0], "http://localhost/service?" "layers=foo&width=300&version=1.1.1&bbox=-180,-90,180,90&service=WMS" "&format=image%2Fpng&styles=&srs=EPSG%3A4326&request=GetMap&height=150")
def test_get_map(self, layer, mock_wms_client): result = layer.get_map(MapQuery((-180, -90, 180, 90), (300, 150), SRS(4326), 'png')) assert mock_wms_client.requested == [((-180, -90, 180, 90), (300, 150), SRS(4326))] assert result.size == (300, 150)
class ConfigGeoJSONGrid(object): def __init__(self, request_bbox=[], grid_bbox=[], level=None, grid_srs=None, grid_bbox_srs=None, map_srs=None, res=[], scales=[], origin='ll', units='m', dpi=None): self.grid_srs = SRS(grid_srs) if grid_srs else None self.grid_bbox_srs = SRS(grid_bbox_srs) if grid_bbox_srs else None self.map_srs = SRS(map_srs) if map_srs else None self.request_bbox = map(float, request_bbox) if request_bbox else None self.origin = origin self._res = list(map(float, res)) if res else None self._scales = list(map(float, scales)) if scales else None self._units = 1 if units == 'm' else constants.UNIT_FACTOR self._dpi = float(dpi) if dpi else constants.OGC_DPI _grid_bbox = list(map(float, grid_bbox)) if grid_bbox else None self.grid_bbox = self.transform_grid_bbox(_grid_bbox) if self._res: self._num_levels = len(self._res) elif self._scales: self._num_levels = len(self._scales) else: self._num_levels = None try: self.level = int(level) except TypeError: self.level = None if self.grid_srs: self.tilegrid = tile_grid(srs=self.grid_srs, bbox=_grid_bbox, bbox_srs=self.grid_bbox_srs, origin=self.origin, res=self.res, num_levels=self._num_levels) self.validate_tile_bbox_for_level_0() else: self.tilegrid = None def transform_grid_bbox(self, _grid_bbox=None): if not _grid_bbox: return None if self.grid_bbox_srs: _grid_bbox = self.grid_bbox_srs.align_bbox(_grid_bbox) if self.grid_srs: if is_valid_transformation(_grid_bbox, self.grid_bbox_srs, self.grid_srs): return self.grid_bbox_srs.transform_bbox_to(self.grid_srs, _grid_bbox) else: raise InvalidGridBBoxTransformationException( 'Invalid transformation for grid_bbox') return _grid_bbox if _grid_bbox else self._grid_bbox def validate_tile_bbox_for_level_0(self): tile_bbox = self.tilegrid.tile_bbox((0, 0, 0)) if not is_valid_transformation(tile_bbox, self.grid_srs, self.map_srs): raise InvalidTileBBoxTransformationException( 'Invalid transformation for tile in level 0') @property def res(self): if not self._res: if not self._scales: return None return [scale_to_res(scale, self._dpi, self._units) for scale in self._scales] return self._res @property def map_bbox(self): if not self.map_srs or not self.grid_srs: return None if self.map_srs == 'EPSG:4326': self.request_bbox = self.map_srs.align_bbox(self.request_bbox) else: (minx, miny, maxx, maxy) = self.request_bbox self.request_bbox = minx, miny, maxx, maxy if not is_valid_transformation(self.request_bbox, self.map_srs, self.grid_srs): return None temp = self.map_srs.transform_bbox_to(self.grid_srs, self.request_bbox) return temp @property def view_bbox(self): gridbbox = self.grid_bbox if self.grid_bbox else self.tilegrid.bbox() mapbbox = self.map_bbox if not mapbbox: return gridbbox return [ max(gridbbox[0], mapbbox[0]), max(gridbbox[1], mapbbox[1]), min(gridbbox[2], mapbbox[2]), min(gridbbox[3], mapbbox[3]) ] @property def scales(self): return [res_to_scale(res, self._dpi, self._units) for res in self.tilegrid.resolutions]
def test_srs_conditional_layers(): l4326 = MockLayer() l3857 = MockLayer() l25832 = MockLayer() preferred = PreferredSrcSRS() preferred.add(SRS(31467), [SRS(25832), SRS(3857)]) layer = SRSConditional([ (l4326, SRS(4326)), (l3857, SRS(3857)), (l25832, SRS(25832)), ], GLOBAL_GEOGRAPHIC_EXTENT, preferred_srs=preferred, ) # srs match assert layer._select_layer(SRS(4326)) == l4326 assert layer._select_layer(SRS(3857)) == l3857 assert layer._select_layer(SRS(25832)) == l25832 # type match (projected) assert layer._select_layer(SRS(31466)) == l3857 assert layer._select_layer(SRS(32633)) == l3857 assert layer._select_layer(SRS(4258)) == l4326 # preferred assert layer._select_layer(SRS(31467)) == l25832
def setup(self): self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.client = MockTileClient() self.source = TiledSource(self.grid, self.client)
def test_get_single(self, tile_mgr, file_cache, slow_source): tile_mgr.creator().create_tiles([Tile((0, 0, 1)), Tile((1, 0, 1))]) assert file_cache.stored_tiles == set([(0, 0, 1), (1, 0, 1)]) assert slow_source.requested == \ [((-180.0, -90.0, 180.0, 90.0), (512, 256), SRS(4326))]
def test_create_tile_multiple_fragmented(self, tile_mgr, mock_file_cache, mock_wms_client): tile_mgr.creator().create_tiles([Tile((4, 0, 3)), Tile((5, 2, 3))]) assert mock_file_cache.stored_tiles == \ set([(4, 0, 3), (4, 1, 3), (4, 2, 3), (5, 0, 3), (5, 1, 3), (5, 2, 3)]) assert sorted(mock_wms_client.requested) == \ [((-1.7578125, -90, 91.7578125, 46.7578125), (532, 778), SRS(4326))]
def test_create_tile(self, tile_mgr, mock_file_cache, mock_wms_client): tile_mgr.creator().create_tiles([Tile((0, 0, 2))]) assert mock_file_cache.stored_tiles == \ set([(0, 0, 2), (1, 0, 2), (0, 1, 2), (1, 1, 2)]) assert sorted(mock_wms_client.requested) == \ [((-180.0, -90.0, 0.0, 90.0), (512, 512), SRS(4326))]
def test_create_tile_first_level(self, tile_mgr, mock_file_cache, mock_wms_client): tile_mgr.creator().create_tiles([Tile((0, 0, 1)), Tile((1, 0, 1))]) assert mock_file_cache.stored_tiles == set([(0, 0, 1), (1, 0, 1)]) assert mock_wms_client.requested == \ [((-180.0, -90.0, 180.0, 90.0), (512, 256), SRS(4326))]
def test_create_tile(self, tile_mgr, mock_file_cache, mock_source): tile_mgr.creator().create_tiles([Tile((0, 0, 1)), Tile((1, 0, 1))]) assert mock_file_cache.stored_tiles == set([(0, 0, 1), (1, 0, 1)]) assert sorted(mock_source.requested) == \ [((-180.0, -90.0, 0.0, 90.0), (256, 256), SRS(4326)), ((0.0, -90.0, 180.0, 90.0), (256, 256), SRS(4326))]
def tile_mgr(self, file_cache, tile_locker): grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) client = MockTileClient() source = TiledSource(grid, client) tile_mgr = TileManager(grid, file_cache, [source], 'png', locker=tile_locker) return tile_mgr
def source(self, mock_http_client): req = WMS111MapRequest(url=TESTSERVER_URL + '/service?map=foo', param={'layers':'foo'}) wms = WMSClient(req, http_client=mock_http_client) return WMSSource(wms, supported_srs=SupportedSRS([SRS(4326)]), image_opts=ImageOptions(resampling='bilinear'))
def test_get_map_small(self, layer, mock_file_cache): result = layer.get_map(MapQuery((-180, -90, 180, 90), (300, 150), SRS(4326), 'png')) assert mock_file_cache.stored_tiles == set([(0, 0, 1), (1, 0, 1)]) assert result.size == (300, 150)
def test_match(self): self.source.get_map(MapQuery([-180, -90, 0, 90], (256, 256), SRS(4326))) self.source.get_map(MapQuery([0, -90, 180, 90], (256, 256), SRS(4326))) assert self.client.requested_tiles == [(0, 0, 1), (1, 0, 1)]
def __init__(self, srs=900913, bbox=None, tile_size=(256, 256), res=None, threshold_res=None, is_geodetic=False, levels=None, stretch_factor=1.15, max_shrink_factor=4.0, origin='ll', name=None): """ :param stretch_factor: allow images to be scaled up by this factor before the next level will be selected :param max_shrink_factor: allow images to be scaled down by this factor before NoTiles is raised >>> grid = TileGrid(srs=900913) >>> [round(x, 2) for x in grid.bbox] [-20037508.34, -20037508.34, 20037508.34, 20037508.34] """ if isinstance(srs, (int, basestring)): srs = SRS(srs) self.srs = srs self.tile_size = tile_size self.origin = origin_from_string(origin) self.name = name if self.origin == 'ul': self.flipped_y_axis = True self.is_geodetic = is_geodetic self.stretch_factor = stretch_factor self.max_shrink_factor = max_shrink_factor if levels is None: self.levels = 20 else: self.levels = levels if bbox is None: bbox = self._calc_bbox() self.bbox = bbox factor = None if res is None: factor = 2.0 res = self._calc_res(factor=factor) elif res == 'sqrt2': if levels is None: self.levels = 40 factor = math.sqrt(2) res = self._calc_res(factor=factor) elif is_float(res): factor = float(res) res = self._calc_res(factor=factor) self.levels = len(res) self.resolutions = NamedGridList(res) self.threshold_res = threshold_res self.grid_sizes = self._calc_grids()
def grid_bbox(bbox, bbox_srs, srs): bbox = bbox_tuple(bbox) if bbox_srs: bbox = SRS(bbox_srs).transform_bbox_to(srs, bbox) return bbox
def featureinfo(self, request): infos = [] self.check_featureinfo_request(request) p = request.params query = InfoQuery(p.bbox, p.size, SRS(p.srs), p.pos, p['info_format'], format=request.params.format or None, feature_count=p.get('feature_count')) actual_layers = odict() for layer_name in request.params.query_layers: layer = self.layers[layer_name] if not layer.queryable: raise RequestError('layer %s is not queryable' % layer_name, request=request) for layer_name, info_layers in layer.info_layers_for_query(query): actual_layers[layer_name] = info_layers authorized_layers, coverage = self.authorized_layers( 'featureinfo', actual_layers.keys(), request.http.environ, query_extent=(query.srs.srs_code, query.bbox)) self.filter_actual_layers(actual_layers, request.params.layers, authorized_layers) # outside of auth-coverage if coverage and not coverage.contains(query.coord, query.srs): infos = [] else: info_layers = [] for layers in actual_layers.values(): info_layers.extend(layers) for layer in info_layers: info = layer.get_info(query) if info is None: continue infos.append(info) mimetype = None if 'info_format' in request.params: mimetype = request.params.info_format if not infos: return Response('', mimetype=mimetype) if self.fi_transformers: doc = infos[0].combine(infos) if doc.info_type == 'text': resp = doc.as_string() mimetype = 'text/plain' else: if not mimetype: if 'xml' in self.fi_transformers: info_type = 'xml' elif 'html' in self.fi_transformers: info_type = 'html' else: info_type = 'text' mimetype = mimetype_from_infotype(request.version, info_type) else: info_type = infotype_from_mimetype(request.version, mimetype) resp = self.fi_transformers[info_type](doc).as_string() else: mimetype = mimetype_from_infotype(request.version, infos[0].info_type) if len(infos) > 1: resp = infos[0].combine(infos).as_string() else: resp = infos[0].as_string() return Response(resp, mimetype=mimetype)
def mask_image(img, bbox, bbox_srs, coverage): geom = mask_polygons(bbox, SRS(bbox_srs), coverage) mask = image_mask_from_geom(img, bbox, geom) img = img.convert('RGBA') img.paste((255, 255, 255, 0), (0, 0), mask) return img
def test_single_tile_no_match(self, layer): with pytest.raises(MapBBOXError): layer.get_map( MapQuery((0.1, 0, 90, 90), (256, 256), SRS(4326), 'png', tiled_only=True) )
def map(self, map_request): self.check_map_request(map_request) params = map_request.params query = MapQuery(params.bbox, params.size, SRS(params.srs), params.format) if map_request.params.get('tiled', 'false').lower() == 'true': query.tiled_only = True orig_query = query if self.srs_extents and params.srs in self.srs_extents: # limit query to srs_extent if query is larger query_extent = MapExtent(params.bbox, SRS(params.srs)) if not self.srs_extents[params.srs].contains(query_extent): limited_extent = self.srs_extents[params.srs].intersection( query_extent) if not limited_extent: img_opts = self.image_formats[ params.format_mime_type].copy() img_opts.bgcolor = params.bgcolor img_opts.transparent = params.transparent img = BlankImageSource(size=params.size, image_opts=img_opts, cacheable=True) return Response(img.as_buffer(), content_type=img_opts.format.mime_type) sub_size, offset, sub_bbox = bbox_position_in_image( params.bbox, params.size, limited_extent.bbox) query = MapQuery(sub_bbox, sub_size, SRS(params.srs), params.format) actual_layers = odict() for layer_name in map_request.params.layers: layer = self.layers[layer_name] # only add if layer renders the query if layer.renders_query(query): # if layer is not transparent and will be rendered, # remove already added (then hidden) layers if not layer.transparent: actual_layers = odict() for layer_name, map_layers in layer.map_layers_for_query( query): actual_layers[layer_name] = map_layers authorized_layers, coverage = self.authorized_layers( 'map', actual_layers.keys(), map_request.http.environ, query_extent=(query.srs.srs_code, query.bbox)) self.filter_actual_layers(actual_layers, map_request.params.layers, authorized_layers) render_layers = [] for layers in actual_layers.values(): render_layers.extend(layers) self.update_query_with_fwd_params(query, params=params, layers=render_layers) raise_source_errors = True if self.on_error == 'raise' else False renderer = LayerRenderer( render_layers, query, map_request, raise_source_errors=raise_source_errors, concurrent_rendering=self.concurrent_layer_renderer) merger = LayerMerger() renderer.render(merger) if self.attribution and self.attribution.get( 'text') and not query.tiled_only: merger.add(attribution_image(self.attribution['text'], query.size)) img_opts = self.image_formats[params.format_mime_type].copy() img_opts.bgcolor = params.bgcolor img_opts.transparent = params.transparent result = merger.merge(size=query.size, image_opts=img_opts, bbox=query.bbox, bbox_srs=params.srs, coverage=coverage) if query != orig_query: result = SubImageSource(result, size=orig_query.size, offset=offset, image_opts=img_opts) # Provide the wrapping WSGI app or filter the opportunity to process the # image before it's wrapped up in a response result = self.decorate_img(result, 'wms.map', actual_layers.keys(), map_request.http.environ, (query.srs.srs_code, query.bbox)) try: result_buf = result.as_buffer(img_opts) except IOError as ex: raise RequestError('error while processing image file: %s' % ex, request=map_request) resp = Response(result_buf, content_type=img_opts.format.mime_type) if query.tiled_only and isinstance(result.cacheable, CacheInfo): cache_info = result.cacheable resp.cache_headers(cache_info.timestamp, etag_data=(cache_info.timestamp, cache_info.size), max_age=self.max_tile_age) resp.make_conditional(map_request.http) if not result.cacheable: resp.cache_headers(no_cache=True) return resp
def test_get_outside_extent(self, layer): with pytest.raises(BlankImage): layer.get_map(MapQuery((-180, -90, 0, 0), (300, 150), SRS(4326), 'png'))
def test_single_tile_match(self, layer, mock_file_cache): result = layer.get_map(MapQuery( (0.001, 0, 90, 90), (256, 256), SRS(4326), 'png', tiled_only=True)) assert mock_file_cache.stored_tiles == \ set([(3, 0, 2), (2, 0, 2), (3, 1, 2), (2, 1, 2)]) assert result.size == (256, 256)
def test_get_map_small(self, layer, mock_file_cache, mock_wms_client): result = layer.get_map(MapQuery((-180, -90, 180, 90), (300, 150), SRS(4326), 'png')) assert mock_file_cache.stored_tiles == set([(1, 0, 1)]) # source requests one tile (no meta-tiling configured) assert mock_wms_client.requested == [((0.0, -90.0, 180.0, 90.0), (256, 256), SRS('EPSG:4326'))] assert result.size == (300, 150)