def test_misconfigured_mapserver_source_without_globals(self): conf = self._test_conf(''' sources: one_source: type: mapserver req: map: foo.map mapserver: binary: /foo/bar/baz ''') errors = validate_references(conf) eq_(errors, [ 'Could not find mapserver binary (/foo/bar/baz)' ]) del conf['sources']['one_source']['mapserver']['binary'] errors = validate_references(conf) eq_(errors, [ "Missing mapserver binary for source 'one_source'" ]) del conf['sources']['one_source']['mapserver'] errors = validate_references(conf) eq_(errors, [ "Missing mapserver binary for source 'one_source'" ])
def test_band_merge_missing_source(self): conf = self._test_conf(''' caches: one_cache: sources: l: - source: dop band: 1 factor: 0.4 - source: missing1 band: 2 factor: 0.2 - source: cache_missing_source band: 2 factor: 0.2 grids: [GLOBAL_MERCATOR] cache_missing_source: sources: [missing2] grids: [GLOBAL_MERCATOR] sources: dop: type: wms req: url: http://localhost/service? layers: dop ''') errors = validate_references(conf) eq_(errors, [ "Source 'missing1' for cache 'one_cache' not found in config", "Source 'missing2' for cache 'cache_missing_source' not found in config", ])
def test_misconfigured_wms_source(self): conf = self._test_conf() del conf['sources']['one_source']['req']['layers'] errors = validate_references(conf) eq_(errors, ["Missing 'layers' for source 'one_source'"])
def test_missing_cache_source(self): conf = self._test_conf() del conf['sources']['one_source'] errors = validate_references(conf) eq_(errors, ["Source 'one_source' for cache 'one_cache' not found in config"])
def configure_mapproxy(extra_config, seed=False, ignore_warnings=True, renderd=False): """Create an validate mapproxy configuration based on a dict. """ # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Merge both load_config(conf_options, config_dict=extra_config) # Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: LOGGER.warn(error) if errors and not ignore_warnings: raise ConfigurationError('invalid configuration: %s' % ', '.join(errors)) errors = validate_references(conf_options) for error in errors: LOGGER.warn(error) if errors and not ignore_warnings: raise ConfigurationError('invalid references: %s' % ', '.join(errors)) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) return conf
def test_missing_services_section(self): conf = self._test_conf() del conf['services'] errors = validate_references(conf) eq_(errors, [ 'Missing services section' ])
def test_missing_layer_source(self): conf = self._test_conf() del conf['caches']['one_cache'] errors = validate_references(conf) eq_(errors, [ "Source 'one_cache' for layer 'one' not in cache or source section" ])
def test_missing_cache_source(self): conf = self._test_conf() del conf['sources']['one_source'] errors = validate_references(conf) eq_(errors, [ "Source 'one_source' for cache 'one_cache' not found in config" ])
def test_missing_layers_section(self): conf = self._test_conf() del conf['layers'] errors = validate_references(conf) eq_(errors, [ 'Missing layers section' ])
def test_misconfigured_wms_source(self): conf = self._test_conf() del conf['sources']['one_source']['req']['layers'] errors = validate_references(conf) eq_(errors, [ "Missing 'layers' for source 'one_source'" ])
def test_tile_source(self): conf = self._test_conf(''' layers: - name: one tile_sources: [missing] ''') errors = validate_references(conf) eq_(errors, ["Tile source 'missing' for layer 'one' not in cache section"])
def test_without_cache(self): conf = self._test_conf(''' layers: - name: one title: One sources: [one_source] ''') errors = validate_references(conf) eq_(errors, [])
def test_empty_layer_sources(self): conf = self._test_conf(''' layers: - name: one title: One sources: [] ''') errors = validate_references(conf) eq_(errors, ["Missing sources for layer 'one'"])
def test_misconfigured_mapserver_source_with_globals(self): conf = self._test_conf(''' sources: one_source: type: mapserver req: map: foo.map globals: mapserver: binary: /foo/bar/baz ''') errors = validate_references(conf) eq_(errors, ['Could not find mapserver binary (/foo/bar/baz)']) del conf['globals']['mapserver']['binary'] errors = validate_references(conf) eq_(errors, ["Missing mapserver binary for source 'one_source'"])
def test_tile_source(self): conf = self._test_conf(''' layers: - name: one tile_sources: [missing] ''') errors = validate_references(conf) eq_(errors, [ "Tile source 'missing' for layer 'one' not in cache section" ])
def test_tagged_layer_sources_without_layers(self): conf = self._test_conf(''' layers: - name: one title: One sources: ['one_source:foo,bar'] ''') del conf['sources']['one_source']['req']['layers'] errors = validate_references(conf) assert errors == []
def test_tagged_source_with_colons(self): conf = self._test_conf(''' caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:ns:foo,ns:bar'] ''') del conf['sources']['one_source']['req']['layers'] errors = validate_references(conf) assert errors == []
def test_empty_layer_sources(self): conf = self._test_conf(''' layers: - name: one title: One sources: [] ''') errors = validate_references(conf) eq_(errors, [ "Missing sources for layer 'one'" ])
def test_tagged_source_without_layers(self): conf = self._test_conf(''' caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:foo,bar'] ''') del conf['sources']['one_source']['req']['layers'] errors = validate_references(conf) eq_(errors, [])
def test_cascaded_caches(self): conf = self._test_conf(''' caches: one_cache: sources: [two_cache] two_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source'] ''') errors = validate_references(conf) eq_(errors, [])
def test_tagged_sources_with_layers(self): conf = self._test_conf(''' caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:foo,bar'] ''') errors = validate_references(conf) eq_(errors, [ "Supported layers for source 'one_source' are 'one' but tagged source " "requested layers 'foo, bar'" ])
def test_with_grouped_layer(self): conf = self._test_conf(''' layers: - name: group title: Group layers: - name: one title: One sources: [one_cache] ''') errors = validate_references(conf) eq_(errors, [])
def test_tagged_layer_sources_with_layers(self): conf = self._test_conf(''' layers: - name: one title: One sources: ['one_source:foo,bar'] ''') errors = validate_references(conf) assert errors == [ "Supported layers for source 'one_source' are 'one' but tagged source " "requested layers 'foo, bar'" ]
def test_missing_grid(self): conf = self._test_conf(''' caches: one_cache: grids: [MYGRID_OTHERGRID] grids: MYGRID: base: GLOBAL_GEODETIC ''') errors = validate_references(conf) eq_(errors, [ "Grid 'MYGRID_OTHERGRID' for cache 'one_cache' not found in config" ])
def test_tagged_layers_for_unsupported_source_type(self): conf = self._test_conf(''' sources: one_source: type: tile url: http://localhost/tiles/ caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:foo,bar'] ''') errors = validate_references(conf) eq_(errors, [ "Found tagged source 'one_source' in cache 'one_cache' but tagged sources " "only supported for 'wms, mapserver, mapnik' sources" ])
def test_mapnik_with_tagged_layers(self): conf = self._test_conf(''' sources: one_source: type: mapnik mapfile: foo.map layers: one caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:foo,bar'] ''') errors = validate_references(conf) assert errors == [ "Supported layers for source 'one_source' are 'one' but tagged source " "requested layers 'foo, bar'" ]
def test_mapserver_with_tagged_layers(self): conf = self._test_conf(''' sources: one_source: type: mapserver req: map: foo.map layers: one mapserver: binary: /foo/bar/baz caches: one_cache: grids: [GLOBAL_MERCATOR] sources: ['one_source:foo,bar'] ''') errors = validate_references(conf) eq_(errors, [ 'Could not find mapserver binary (/foo/bar/baz)', "Supported layers for source 'one_source' are 'one' but tagged source " "requested layers 'foo, bar'" ])
def test_with_int_0_as_names_and_layers(self): conf = self._test_conf(''' services: wms: md: title: MapProxy layers: - name: 0 title: One sources: [0] caches: 0: grids: [GLOBAL_MERCATOR] sources: [0] sources: 0: type: wms req: url: http://localhost/service? layers: 0 ''') errors = validate_references(conf) eq_(errors, [])
def test_valid_config(self): conf = self._test_conf() errors = validate_references(conf) assert errors == []
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False): """Creates a mapproxy config for a given layers """ bbox = [float(layer.bbox_x0), float(layer.bbox_y0), float(layer.bbox_x1), float(layer.bbox_y1)] url = str(layer.service.url) layer_name = simple_name(layer.name) srs = 'EPSG:4326' bbox_srs = 'EPSG:4326' grid_srs = 'EPSG:3857' if layer.type == 'ESRI:ArcGIS:MapServer' or layer.type == 'ESRI:ArcGIS:ImageServer': url = str(layer.service.url).split('?')[0] + 'WMSServer?' # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = 'EPSG:3857' bbox_srs = 'EPSG:3857' if layer.type == 'Hypermap:WARPER': url = str(layer.url.replace("maps//wms", "maps/wms")) grid_srs = 'EPSG:900913' if layer.type == 'Hypermap:WorldMap': url = str(layer.url.replace("maps//wms", "maps/wms")) default_source = { 'type': 'wms', 'coverage': { 'bbox': bbox, 'srs': srs, 'bbox_srs': bbox_srs, 'supported_srs': ['EPSG:4326', 'EPSG:900913', 'EPSG:3857'], }, 'req': { 'layers': layer_name, 'url': url, 'transparent': True, }, } if layer.type == 'ESRI:ArcGIS:MapServer': default_source = { 'type': 'tile', 'url': str(layer.service.url).split('?')[0] + 'tile/%(z)s/%(y)s/%(x)s', 'grid': 'default_grid', 'transparent': True, } # A source is the WMS config sources = { 'default_source': default_source } # A grid is where it will be projects (Mercator in our case) grids = { 'default_grid': { 'tile_size': [256, 256], 'srs': grid_srs, 'origin': 'nw', } } # A cache that does not store for now. It needs a grid and a source. caches = {'default_cache': { 'cache': { 'type': 'file', 'directory_layout': 'tms', 'directory': os.path.join(tempfile.gettempdir(), 'mapproxy', 'layer', '%s' % layer.id, 'map', 'wmts', layer_name, 'default_grid', ), }, 'grids': ['default_grid'], 'sources': ['default_source']}, } # The layer is connected to the cache layers = [ {'name': layer_name, 'sources': ['default_cache'], 'title': str(layer.title), }, ] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { 'wms': {'image_formats': ['image/png'], 'md': {'abstract': 'This is the Harvard HyperMap Proxy.', 'title': 'Harvard HyperMap Proxy'}, 'srs': ['EPSG:4326', 'EPSG:3857'], 'versions': ['1.1.1']}, 'wmts': { 'restful': True, 'restful_template': '/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png', }, 'tms': { 'origin': 'nw', }, 'demo': None, } global_config = { 'http': {'ssl_no_cert_checks': True}, } # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Populate a dictionary with custom config changes extra_config = { 'caches': caches, 'grids': grids, 'layers': layers, 'services': services, 'sources': sources, 'globals': global_config, } yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False # Merge both load_config(conf_options, config_dict=extra_config) # Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: log.warn(error) if not informal_only or (errors and not ignore_warnings): raise ConfigurationError('invalid configuration') errors = validate_references(conf_options) for error in errors: log.warn(error) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) # Wrap it in an object that allows to get requests by path as a string. return TestApp(app), yaml_config
def test_valid_config(self): conf = self._test_conf() errors = validate_references(conf) eq_(errors, [])
def test_missing_layers_section(self): conf = self._test_conf() del conf['layers'] errors = validate_references(conf) eq_(errors, ['Missing layers section'])
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False): """Creates a mapproxy config for a given layer-like object. Compatible with django-registry and GeoNode. """ bbox = list(wkt2geom(layer.wkt_geometry)) # TODO: Check for correct url url = 'http://test.registry.org' # url = str(layer.service.url) layer_name = str(layer.title) srs = 'EPSG:4326' bbox_srs = 'EPSG:4326' grid_srs = 'EPSG:3857' default_source = { 'type': 'wms', 'coverage': { 'bbox': bbox, 'srs': srs, 'bbox_srs': bbox_srs, 'supported_srs': ['EPSG:4326', 'EPSG:900913', 'EPSG:3857'], }, 'req': { 'layers': str(layer.title), 'url': url, 'transparent': True, }, } if layer.type == 'ESRI:ArcGIS:MapServer' or layer.type == 'ESRI:ArcGIS:ImageServer': # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = 'EPSG:3857' bbox_srs = 'EPSG:3857' default_source = { 'type': 'arcgis', 'req': { 'url': url, 'grid': 'default_grid', 'transparent': True, }, } # A source is the WMS config sources = {'default_source': default_source} # A grid is where it will be projects (Mercator in our case) grids = { 'default_grid': { 'tile_size': [256, 256], 'srs': grid_srs, 'origin': 'nw', } } # A cache that does not store for now. It needs a grid and a source. caches = { 'default_cache': { 'disable_storage': True, 'grids': ['default_grid'], 'sources': ['default_source'] }, } # The layer is connected to the cache layers = [ { 'name': layer_name, 'sources': ['default_cache'], 'title': str(layer.title), }, ] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { 'wms': { 'image_formats': ['image/png'], 'md': { 'abstract': 'This is the Harvard HyperMap Proxy.', 'title': 'Harvard HyperMap Proxy' }, 'srs': ['EPSG:4326', 'EPSG:3857'], 'versions': ['1.1.1'] }, 'wmts': { 'restful': True, 'restful_template': '/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png', }, 'tms': { 'origin': 'nw', }, 'demo': None, } global_config = { 'http': { 'ssl_no_cert_checks': True }, } # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Populate a dictionary with custom config changes extra_config = { 'caches': caches, 'grids': grids, 'layers': layers, 'services': services, 'sources': sources, 'globals': global_config, } yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False # Merge both load_config(conf_options, config_dict=extra_config) # TODO: Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: LOGGER.warn(error) if not informal_only or (errors and not ignore_warnings): raise ConfigurationError('invalid configuration') errors = validate_references(conf_options) for error in errors: LOGGER.warn(error) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) return app, yaml_config
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False): """Creates a mapproxy config for a given layers """ bbox = [float(layer.bbox_x0), float(layer.bbox_y0), float(layer.bbox_x1), float(layer.bbox_y1)] url = str(layer.service.url) layer_name = simple_name(layer.name) srs = "EPSG:4326" bbox_srs = "EPSG:4326" grid_srs = "EPSG:3857" if layer.service.type == "ESRI_MapServer" or layer.service.type == "ESRI_ImageServer": url = str(layer.service.url).split("?")[0] + "WMSServer?" # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = "EPSG:3857" bbox_srs = "EPSG:3857" if layer.service.type == "WARPER": url = str(layer.url.replace("maps//wms", "maps/wms")) grid_srs = "EPSG:900913" if layer.service.type == "WM": url = str(layer.url.replace("maps//wms", "maps/wms")) default_source = { "type": "wms", "coverage": { "bbox": bbox, "srs": srs, "bbox_srs": bbox_srs, "supported_srs": ["EPSG:4326", "EPSG:900913", "EPSG:3857"], }, "req": {"layers": layer_name, "url": url, "transparent": True}, } if layer.service.type == "ESRI_MapServer": default_source = { "type": "tile", "url": str(layer.service.url).split("?")[0] + "tile/%(z)s/%(y)s/%(x)s", "grid": "default_grid", "transparent": True, } # A source is the WMS config sources = {"default_source": default_source} # A grid is where it will be projects (Mercator in our case) grids = {"default_grid": {"tile_size": [256, 256], "srs": grid_srs, "origin": "nw"}} # A cache that does not store for now. It needs a grid and a source. caches = { "default_cache": { "cache": { "type": "file", "directory_layout": "tms", "directory": os.path.join( tempfile.gettempdir(), "mapproxy", "layer", "%s" % layer.id, "map", "wmts", layer_name, "default_grid", ), }, "grids": ["default_grid"], "sources": ["default_source"], } } # The layer is connected to the cache layers = [{"name": layer_name, "sources": ["default_cache"], "title": str(layer.title)}] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { "wms": { "image_formats": ["image/png"], "md": {"abstract": "This is the Harvard HyperMap Proxy.", "title": "Harvard HyperMap Proxy"}, "srs": ["EPSG:4326", "EPSG:3857"], "versions": ["1.1.1"], }, "wmts": {"restful": True, "restful_template": "/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png"}, "tms": {"origin": "nw"}, "demo": None, } # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Populate a dictionary with custom config changes extra_config = {"caches": caches, "grids": grids, "layers": layers, "services": services, "sources": sources} yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False # Merge both load_config(conf_options, config_dict=extra_config) # Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: log.warn(error) if not informal_only or (errors and not ignore_warnings): raise ConfigurationError("invalid configuration") errors = validate_references(conf_options) for error in errors: log.warn(error) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) # Wrap it in an object that allows to get requests by path as a string. return TestApp(app), yaml_config
def test_missing_services_section(self): conf = self._test_conf() del conf['services'] errors = validate_references(conf) eq_(errors, ['Missing services section'])
def get_mapproxy(layer, seed=False, ignore_warnings=True, renderd=False): """Creates a mapproxy config for a given layers """ bbox = [ float(layer.bbox_x0), float(layer.bbox_y0), float(layer.bbox_x1), float(layer.bbox_y1) ] url = str(layer.service.url) layer_name = simple_name(layer.name) srs = 'EPSG:4326' bbox_srs = 'EPSG:4326' grid_srs = 'EPSG:3857' if layer.type == 'ESRI:ArcGIS:MapServer' or layer.type == 'ESRI:ArcGIS:ImageServer': url = str(layer.service.url).split('?')[0] + 'WMSServer?' # blindly replace it with /arcgis/ url = url.replace("/ArcGIS/rest/", "/arcgis/") # same for uppercase url = url.replace("/arcgis/rest/", "/arcgis/") # and for old versions url = url.replace("ArcX/rest/services", "arcx/services") # in uppercase or lowercase url = url.replace("arcx/rest/services", "arcx/services") srs = 'EPSG:3857' bbox_srs = 'EPSG:3857' if layer.type == 'Hypermap:WARPER': url = str(layer.url.replace("maps//wms", "maps/wms")) grid_srs = 'EPSG:900913' if layer.type == 'Hypermap:WorldMap': url = str(layer.url.replace("maps//wms", "maps/wms")) default_source = { 'type': 'wms', 'coverage': { 'bbox': bbox, 'srs': srs, 'bbox_srs': bbox_srs, 'supported_srs': ['EPSG:4326', 'EPSG:900913', 'EPSG:3857'], }, 'req': { 'layers': layer_name, 'url': url, 'transparent': True, }, } if layer.type == 'ESRI:ArcGIS:MapServer': default_source = { 'type': 'tile', 'url': str(layer.service.url).split('?')[0] + 'tile/%(z)s/%(y)s/%(x)s', 'grid': 'default_grid', 'transparent': True, } # A source is the WMS config sources = {'default_source': default_source} # A grid is where it will be projects (Mercator in our case) grids = { 'default_grid': { 'tile_size': [256, 256], 'srs': grid_srs, 'origin': 'nw', } } # A cache that does not store for now. It needs a grid and a source. caches = { 'default_cache': { 'cache': { 'type': 'file', 'directory_layout': 'tms', 'directory': os.path.join( tempfile.gettempdir(), 'mapproxy', 'layer', '%s' % layer.id, 'map', 'wmts', layer_name, 'default_grid', ), }, 'grids': ['default_grid'], 'sources': ['default_source'] }, } # The layer is connected to the cache layers = [ { 'name': layer_name, 'sources': ['default_cache'], 'title': str(layer.title), }, ] # Services expose all layers. # WMS is used for reprojecting # TMS is used for easy tiles # Demo is used to test our installation, may be disabled in final version services = { 'wms': { 'image_formats': ['image/png'], 'md': { 'abstract': 'This is the Harvard HyperMap Proxy.', 'title': 'Harvard HyperMap Proxy' }, 'srs': ['EPSG:4326', 'EPSG:3857'], 'versions': ['1.1.1'] }, 'wmts': { 'restful': True, 'restful_template': '/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png', }, 'tms': { 'origin': 'nw', }, 'demo': None, } global_config = { 'http': { 'ssl_no_cert_checks': True }, } # Start with a sane configuration using MapProxy's defaults conf_options = load_default_config() # Populate a dictionary with custom config changes extra_config = { 'caches': caches, 'grids': grids, 'layers': layers, 'services': services, 'sources': sources, 'globals': global_config, } yaml_config = yaml.dump(extra_config, default_flow_style=False) # If you want to test the resulting configuration. Turn on the next # line and use that to generate a yaml config. # assert False # Merge both load_config(conf_options, config_dict=extra_config) # Make sure the config is valid. errors, informal_only = validate_options(conf_options) for error in errors: log.warn(error) if not informal_only or (errors and not ignore_warnings): raise ConfigurationError('invalid configuration') errors = validate_references(conf_options) for error in errors: log.warn(error) conf = ProxyConfiguration(conf_options, seed=seed, renderd=renderd) # Create a MapProxy App app = MapProxyApp(conf.configured_services(), conf.base_config) # Wrap it in an object that allows to get requests by path as a string. return TestApp(app), yaml_config