MapProxy 1.16.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapproxy/__init__.py +0 -0
- mapproxy/cache/__init__.py +36 -0
- mapproxy/cache/azureblob.py +145 -0
- mapproxy/cache/base.py +111 -0
- mapproxy/cache/compact.py +664 -0
- mapproxy/cache/couchdb.py +295 -0
- mapproxy/cache/dummy.py +34 -0
- mapproxy/cache/file.py +185 -0
- mapproxy/cache/geopackage.py +609 -0
- mapproxy/cache/legend.py +83 -0
- mapproxy/cache/mbtiles.py +392 -0
- mapproxy/cache/meta.py +78 -0
- mapproxy/cache/path.py +250 -0
- mapproxy/cache/redis.py +88 -0
- mapproxy/cache/renderd.py +95 -0
- mapproxy/cache/riak.py +202 -0
- mapproxy/cache/s3.py +177 -0
- mapproxy/cache/tile.py +699 -0
- mapproxy/client/__init__.py +0 -0
- mapproxy/client/arcgis.py +79 -0
- mapproxy/client/cgi.py +139 -0
- mapproxy/client/http.py +315 -0
- mapproxy/client/log.py +33 -0
- mapproxy/client/tile.py +150 -0
- mapproxy/client/wms.py +254 -0
- mapproxy/compat/__init__.py +46 -0
- mapproxy/compat/image.py +79 -0
- mapproxy/compat/itertools.py +29 -0
- mapproxy/compat/modules.py +13 -0
- mapproxy/config/__init__.py +22 -0
- mapproxy/config/config.py +201 -0
- mapproxy/config/coverage.py +107 -0
- mapproxy/config/defaults.py +98 -0
- mapproxy/config/loader.py +2286 -0
- mapproxy/config/spec.py +644 -0
- mapproxy/config/validator.py +239 -0
- mapproxy/config_template/__init__.py +0 -0
- mapproxy/config_template/base_config/config.wsgi +10 -0
- mapproxy/config_template/base_config/full_example.yaml +593 -0
- mapproxy/config_template/base_config/full_seed_example.yaml +79 -0
- mapproxy/config_template/base_config/log.ini +35 -0
- mapproxy/config_template/base_config/mapproxy.yaml +60 -0
- mapproxy/config_template/base_config/seed.yaml +27 -0
- mapproxy/exception.py +142 -0
- mapproxy/featureinfo.py +252 -0
- mapproxy/grid.py +1170 -0
- mapproxy/image/__init__.py +536 -0
- mapproxy/image/fonts/DejaVuSans.ttf +0 -0
- mapproxy/image/fonts/DejaVuSansMono.ttf +0 -0
- mapproxy/image/fonts/LICENSE +99 -0
- mapproxy/image/fonts/__init__.py +0 -0
- mapproxy/image/mask.py +75 -0
- mapproxy/image/merge.py +316 -0
- mapproxy/image/message.py +347 -0
- mapproxy/image/opts.py +182 -0
- mapproxy/image/tile.py +167 -0
- mapproxy/image/transform.py +350 -0
- mapproxy/layer.py +470 -0
- mapproxy/multiapp.py +231 -0
- mapproxy/proj.py +302 -0
- mapproxy/request/__init__.py +18 -0
- mapproxy/request/arcgis.py +259 -0
- mapproxy/request/base.py +476 -0
- mapproxy/request/tile.py +128 -0
- mapproxy/request/wms/__init__.py +793 -0
- mapproxy/request/wms/exception.py +99 -0
- mapproxy/request/wmts.py +436 -0
- mapproxy/response.py +237 -0
- mapproxy/script/__init__.py +0 -0
- mapproxy/script/conf/__init__.py +0 -0
- mapproxy/script/conf/app.py +195 -0
- mapproxy/script/conf/caches.py +45 -0
- mapproxy/script/conf/layers.py +54 -0
- mapproxy/script/conf/seeds.py +37 -0
- mapproxy/script/conf/sources.py +86 -0
- mapproxy/script/conf/utils.py +143 -0
- mapproxy/script/defrag.py +184 -0
- mapproxy/script/export.py +333 -0
- mapproxy/script/grids.py +188 -0
- mapproxy/script/scales.py +126 -0
- mapproxy/script/util.py +406 -0
- mapproxy/script/wms_capabilities.py +152 -0
- mapproxy/seed/__init__.py +0 -0
- mapproxy/seed/cachelock.py +121 -0
- mapproxy/seed/cleanup.py +187 -0
- mapproxy/seed/config.py +469 -0
- mapproxy/seed/script.py +388 -0
- mapproxy/seed/seeder.py +538 -0
- mapproxy/seed/spec.py +64 -0
- mapproxy/seed/util.py +254 -0
- mapproxy/service/__init__.py +14 -0
- mapproxy/service/base.py +46 -0
- mapproxy/service/demo.py +356 -0
- mapproxy/service/kml.py +331 -0
- mapproxy/service/ows.py +38 -0
- mapproxy/service/template_helper.py +53 -0
- mapproxy/service/templates/demo/capabilities_demo.html +16 -0
- mapproxy/service/templates/demo/demo.html +181 -0
- mapproxy/service/templates/demo/openlayers-demo.cfg +16 -0
- mapproxy/service/templates/demo/static/img/blank.gif +0 -0
- mapproxy/service/templates/demo/static/img/east-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/north-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/south-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/west-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/zoom-minus-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/zoom-plus-mini.png +0 -0
- mapproxy/service/templates/demo/static/img/zoom-world-mini.png +0 -0
- mapproxy/service/templates/demo/static/logo.png +0 -0
- mapproxy/service/templates/demo/static/ol.css +345 -0
- mapproxy/service/templates/demo/static/ol.js +4 -0
- mapproxy/service/templates/demo/static/proj4.min.js +1 -0
- mapproxy/service/templates/demo/static/proj4defs.js +1 -0
- mapproxy/service/templates/demo/static/site.css +137 -0
- mapproxy/service/templates/demo/static/theme/default/framedCloud.css +0 -0
- mapproxy/service/templates/demo/static/theme/default/google.css +17 -0
- mapproxy/service/templates/demo/static/theme/default/ie6-style.css +10 -0
- mapproxy/service/templates/demo/static/theme/default/style.css +482 -0
- mapproxy/service/templates/demo/static.html +34 -0
- mapproxy/service/templates/demo/tms_demo.html +103 -0
- mapproxy/service/templates/demo/wms_demo.html +140 -0
- mapproxy/service/templates/demo/wmts_demo.html +110 -0
- mapproxy/service/templates/tms_capabilities.xml +13 -0
- mapproxy/service/templates/tms_exception.xml +4 -0
- mapproxy/service/templates/tms_root_resource.xml +7 -0
- mapproxy/service/templates/tms_tilemap_capabilities.xml +14 -0
- mapproxy/service/templates/wms100capabilities.xml +112 -0
- mapproxy/service/templates/wms100exception.xml +4 -0
- mapproxy/service/templates/wms110capabilities.xml +152 -0
- mapproxy/service/templates/wms110exception.xml +5 -0
- mapproxy/service/templates/wms111capabilities.xml +183 -0
- mapproxy/service/templates/wms111exception.xml +5 -0
- mapproxy/service/templates/wms130capabilities.xml +326 -0
- mapproxy/service/templates/wms130exception.xml +8 -0
- mapproxy/service/templates/wmts100capabilities.xml +155 -0
- mapproxy/service/templates/wmts100exception.xml +9 -0
- mapproxy/service/tile.py +536 -0
- mapproxy/service/wms.py +851 -0
- mapproxy/service/wmts.py +381 -0
- mapproxy/source/__init__.py +75 -0
- mapproxy/source/arcgis.py +39 -0
- mapproxy/source/error.py +39 -0
- mapproxy/source/mapnik.py +259 -0
- mapproxy/source/tile.py +96 -0
- mapproxy/source/wms.py +270 -0
- mapproxy/srs.py +726 -0
- mapproxy/template.py +54 -0
- mapproxy/test/__init__.py +0 -0
- mapproxy/test/conftest.py +7 -0
- mapproxy/test/helper.py +247 -0
- mapproxy/test/http.py +494 -0
- mapproxy/test/image.py +210 -0
- mapproxy/test/mocker.py +2268 -0
- mapproxy/test/schemas/inspire/common/1.0/common.xsd +1461 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_bul.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_cze.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_dan.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_dut.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_eng.xsd +155 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_est.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_fin.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_fre.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_ger.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_gle.xsd +109 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_gre.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_hun.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_ita.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_lav.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_lit.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_mlt.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_pol.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_por.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_rum.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_slo.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_slv.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_spa.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/enums/enum_swe.xsd +108 -0
- mapproxy/test/schemas/inspire/common/1.0/network.xsd +521 -0
- mapproxy/test/schemas/inspire/inspire_vs/1.0/inspire_vs.xsd +19 -0
- mapproxy/test/schemas/kml/2.2.0/ReadMe.txt +14 -0
- mapproxy/test/schemas/kml/2.2.0/atom-author-link.xsd +66 -0
- mapproxy/test/schemas/kml/2.2.0/ogckml22.xsd +1646 -0
- mapproxy/test/schemas/kml/2.2.0/xAL.xsd +1680 -0
- mapproxy/test/schemas/ows/1.1.0/ReadMe.txt +87 -0
- mapproxy/test/schemas/ows/1.1.0/ows19115subset.xsd +235 -0
- mapproxy/test/schemas/ows/1.1.0/owsAll.xsd +23 -0
- mapproxy/test/schemas/ows/1.1.0/owsCommon.xsd +157 -0
- mapproxy/test/schemas/ows/1.1.0/owsContents.xsd +86 -0
- mapproxy/test/schemas/ows/1.1.0/owsDataIdentification.xsd +127 -0
- mapproxy/test/schemas/ows/1.1.0/owsDomainType.xsd +279 -0
- mapproxy/test/schemas/ows/1.1.0/owsExceptionReport.xsd +76 -0
- mapproxy/test/schemas/ows/1.1.0/owsGetCapabilities.xsd +112 -0
- mapproxy/test/schemas/ows/1.1.0/owsGetResourceByID.xsd +51 -0
- mapproxy/test/schemas/ows/1.1.0/owsInputOutputData.xsd +59 -0
- mapproxy/test/schemas/ows/1.1.0/owsManifest.xsd +125 -0
- mapproxy/test/schemas/ows/1.1.0/owsOperationsMetadata.xsd +140 -0
- mapproxy/test/schemas/ows/1.1.0/owsServiceIdentification.xsd +60 -0
- mapproxy/test/schemas/ows/1.1.0/owsServiceProvider.xsd +47 -0
- mapproxy/test/schemas/sld/1.1.0/sld_capabilities.xsd +27 -0
- mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.dtd +353 -0
- mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.xml +188 -0
- mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.dtd +524 -0
- mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.xml +260 -0
- mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.dtd +273 -0
- mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.xml +303 -0
- mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.dtd +6 -0
- mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.xml +33 -0
- mapproxy/test/schemas/wms/1.1.1/OGC-exception.xsd +68 -0
- mapproxy/test/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
- mapproxy/test/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd +274 -0
- mapproxy/test/schemas/wms/1.1.1/WMS_exception_1_1_1.dtd +5 -0
- mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.dtd +276 -0
- mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.xml +303 -0
- mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.dtd +6 -0
- mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.xml +33 -0
- mapproxy/test/schemas/wms/1.3.0/ReadMe.txt +8 -0
- mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xml +277 -0
- mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xsd +611 -0
- mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xml +34 -0
- mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xsd +28 -0
- mapproxy/test/schemas/wmsc/1.1.1/OGC-exception.xsd +68 -0
- mapproxy/test/schemas/wmsc/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
- mapproxy/test/schemas/wmsc/1.1.1/WMS_MS_Capabilities.dtd +283 -0
- mapproxy/test/schemas/wmsc/1.1.1/WMS_exception_1_1_1.dtd +5 -0
- mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.dtd +276 -0
- mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.xml +303 -0
- mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.dtd +6 -0
- mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.xml +33 -0
- mapproxy/test/schemas/wmts/1.0/ReadMe.txt +32 -0
- mapproxy/test/schemas/wmts/1.0/wmts.xsd +28 -0
- mapproxy/test/schemas/wmts/1.0/wmtsAbstract.wsdl +151 -0
- mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_request.xsd +38 -0
- mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_response.xsd +564 -0
- mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_request.xsd +57 -0
- mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_response.xsd +72 -0
- mapproxy/test/schemas/wmts/1.0/wmtsGetTile_request.xsd +91 -0
- mapproxy/test/schemas/wmts/1.0/wmtsKVP.xsd +76 -0
- mapproxy/test/schemas/wmts/1.0/wmtsPayload_response.xsd +70 -0
- mapproxy/test/schemas/xlink/1.0.0/ReadMe.txt +6 -0
- mapproxy/test/schemas/xlink/1.0.0/xlinks.xsd +122 -0
- mapproxy/test/schemas/xml.xsd +287 -0
- mapproxy/test/system/__init__.py +98 -0
- mapproxy/test/system/fixture/arcgis.yaml +57 -0
- mapproxy/test/system/fixture/auth.yaml +70 -0
- mapproxy/test/system/fixture/cache.mbtiles +0 -0
- mapproxy/test/system/fixture/cache_azureblob.yaml +59 -0
- mapproxy/test/system/fixture/cache_band_merge.yaml +73 -0
- mapproxy/test/system/fixture/cache_bulk_meta_tiles.yaml +24 -0
- mapproxy/test/system/fixture/cache_data/dop_cache_EPSG3857/00/000/000/000/000/000/000.png +0 -0
- mapproxy/test/system/fixture/cache_data/wms_cache_EPSG900913/01/000/000/000/000/000/001.jpeg +0 -0
- mapproxy/test/system/fixture/cache_data/wms_cache_transparent_EPSG900913/01/000/000/000/000/000/001.png +0 -0
- mapproxy/test/system/fixture/cache_geopackage.yaml +56 -0
- mapproxy/test/system/fixture/cache_grid_names.yaml +50 -0
- mapproxy/test/system/fixture/cache_mbtiles.yaml +28 -0
- mapproxy/test/system/fixture/cache_s3.yaml +58 -0
- mapproxy/test/system/fixture/cache_source.yaml +81 -0
- mapproxy/test/system/fixture/combined_sources.yaml +130 -0
- mapproxy/test/system/fixture/coverage.yaml +77 -0
- mapproxy/test/system/fixture/demo.yaml +135 -0
- mapproxy/test/system/fixture/dimension.yaml +59 -0
- mapproxy/test/system/fixture/disable_storage.yaml +25 -0
- mapproxy/test/system/fixture/empty_ogrdata.geojson +1 -0
- mapproxy/test/system/fixture/formats.yaml +72 -0
- mapproxy/test/system/fixture/inspire.yaml +101 -0
- mapproxy/test/system/fixture/inspire_full.yaml +124 -0
- mapproxy/test/system/fixture/kml_layer.yaml +66 -0
- mapproxy/test/system/fixture/layer.yaml +260 -0
- mapproxy/test/system/fixture/layergroups.yaml +57 -0
- mapproxy/test/system/fixture/layergroups_root.yaml +106 -0
- mapproxy/test/system/fixture/legendgraphic.yaml +93 -0
- mapproxy/test/system/fixture/mapnik_source.yaml +66 -0
- mapproxy/test/system/fixture/mapproxy_export.yaml +12 -0
- mapproxy/test/system/fixture/mapserver.yaml +23 -0
- mapproxy/test/system/fixture/minimal_cgi.py +16 -0
- mapproxy/test/system/fixture/mixed_mode.yaml +49 -0
- mapproxy/test/system/fixture/multi_cache_layers.yaml +100 -0
- mapproxy/test/system/fixture/multiapp1.yaml +20 -0
- mapproxy/test/system/fixture/multiapp2.yaml +19 -0
- mapproxy/test/system/fixture/renderd_client.yaml +55 -0
- mapproxy/test/system/fixture/scalehints.yaml +70 -0
- mapproxy/test/system/fixture/seed.yaml +94 -0
- mapproxy/test/system/fixture/seed_mapproxy.yaml +39 -0
- mapproxy/test/system/fixture/seed_old.yaml +12 -0
- mapproxy/test/system/fixture/seed_timeouts.yaml +12 -0
- mapproxy/test/system/fixture/seed_timeouts_mapproxy.yaml +27 -0
- mapproxy/test/system/fixture/seedonly.yaml +51 -0
- mapproxy/test/system/fixture/sld.yaml +35 -0
- mapproxy/test/system/fixture/source_errors.yaml +84 -0
- mapproxy/test/system/fixture/source_errors_raise.yaml +82 -0
- mapproxy/test/system/fixture/tileservice_origin.yaml +26 -0
- mapproxy/test/system/fixture/tileservice_refresh.yaml +59 -0
- mapproxy/test/system/fixture/tilesource_minmax_res.yaml +22 -0
- mapproxy/test/system/fixture/util-conf-base-grids.yaml +5 -0
- mapproxy/test/system/fixture/util-conf-overwrite.yaml +13 -0
- mapproxy/test/system/fixture/util-conf-wms-111-cap.xml +90 -0
- mapproxy/test/system/fixture/util_grids.yaml +30 -0
- mapproxy/test/system/fixture/util_wms_capabilities111.xml +130 -0
- mapproxy/test/system/fixture/util_wms_capabilities130.xml +100 -0
- mapproxy/test/system/fixture/util_wms_capabilities_service_exception.xml +5 -0
- mapproxy/test/system/fixture/watermark.yaml +50 -0
- mapproxy/test/system/fixture/wms_srs_extent.yaml +39 -0
- mapproxy/test/system/fixture/wms_versions.yaml +38 -0
- mapproxy/test/system/fixture/wmts.yaml +134 -0
- mapproxy/test/system/fixture/wmts_dimensions.yaml +57 -0
- mapproxy/test/system/fixture/xslt_featureinfo.yaml +54 -0
- mapproxy/test/system/fixture/xslt_featureinfo_input.yaml +51 -0
- mapproxy/test/system/test_arcgis.py +156 -0
- mapproxy/test/system/test_auth.py +1134 -0
- mapproxy/test/system/test_behind_proxy.py +75 -0
- mapproxy/test/system/test_bulk_meta_tiles.py +106 -0
- mapproxy/test/system/test_cache_azureblob.py +127 -0
- mapproxy/test/system/test_cache_band_merge.py +103 -0
- mapproxy/test/system/test_cache_geopackage.py +144 -0
- mapproxy/test/system/test_cache_grid_names.py +89 -0
- mapproxy/test/system/test_cache_mbtiles.py +85 -0
- mapproxy/test/system/test_cache_s3.py +115 -0
- mapproxy/test/system/test_cache_source.py +146 -0
- mapproxy/test/system/test_combined_sources.py +335 -0
- mapproxy/test/system/test_coverage.py +140 -0
- mapproxy/test/system/test_decorate_img.py +214 -0
- mapproxy/test/system/test_demo.py +106 -0
- mapproxy/test/system/test_demo_with_extra_service.py +53 -0
- mapproxy/test/system/test_dimensions.py +278 -0
- mapproxy/test/system/test_disable_storage.py +42 -0
- mapproxy/test/system/test_formats.py +219 -0
- mapproxy/test/system/test_inspire_vs.py +173 -0
- mapproxy/test/system/test_kml.py +262 -0
- mapproxy/test/system/test_layergroups.py +160 -0
- mapproxy/test/system/test_legendgraphic.py +308 -0
- mapproxy/test/system/test_mapnik.py +161 -0
- mapproxy/test/system/test_mapserver.py +81 -0
- mapproxy/test/system/test_mixed_mode_format.py +195 -0
- mapproxy/test/system/test_multi_cache_layers.py +167 -0
- mapproxy/test/system/test_multiapp.py +92 -0
- mapproxy/test/system/test_refresh.py +207 -0
- mapproxy/test/system/test_renderd_client.py +304 -0
- mapproxy/test/system/test_response_headers.py +54 -0
- mapproxy/test/system/test_scalehints.py +140 -0
- mapproxy/test/system/test_seed.py +422 -0
- mapproxy/test/system/test_seed_only.py +93 -0
- mapproxy/test/system/test_sld.py +120 -0
- mapproxy/test/system/test_source_errors.py +377 -0
- mapproxy/test/system/test_tilesource_minmax_res.py +54 -0
- mapproxy/test/system/test_tms.py +276 -0
- mapproxy/test/system/test_tms_origin.py +46 -0
- mapproxy/test/system/test_util_conf.py +304 -0
- mapproxy/test/system/test_util_export.py +210 -0
- mapproxy/test/system/test_util_grids.py +88 -0
- mapproxy/test/system/test_util_wms_capabilities.py +182 -0
- mapproxy/test/system/test_watermark.py +91 -0
- mapproxy/test/system/test_wms.py +1611 -0
- mapproxy/test/system/test_wms_srs_extent.py +165 -0
- mapproxy/test/system/test_wms_version.py +85 -0
- mapproxy/test/system/test_wmsc.py +116 -0
- mapproxy/test/system/test_wmts.py +334 -0
- mapproxy/test/system/test_wmts_dimensions.py +206 -0
- mapproxy/test/system/test_wmts_restful.py +198 -0
- mapproxy/test/system/test_xslt_featureinfo.py +425 -0
- mapproxy/test/test_http_helper.py +219 -0
- mapproxy/test/unit/__init__.py +0 -0
- mapproxy/test/unit/epsg +2 -0
- mapproxy/test/unit/polygons/polygons.dbf +0 -0
- mapproxy/test/unit/polygons/polygons.shp +0 -0
- mapproxy/test/unit/polygons/polygons.shx +0 -0
- mapproxy/test/unit/test_async.py +245 -0
- mapproxy/test/unit/test_auth.py +419 -0
- mapproxy/test/unit/test_cache.py +1193 -0
- mapproxy/test/unit/test_cache_azureblob.py +94 -0
- mapproxy/test/unit/test_cache_compact.py +319 -0
- mapproxy/test/unit/test_cache_couchdb.py +114 -0
- mapproxy/test/unit/test_cache_geopackage.py +221 -0
- mapproxy/test/unit/test_cache_redis.py +67 -0
- mapproxy/test/unit/test_cache_riak.py +76 -0
- mapproxy/test/unit/test_cache_s3.py +84 -0
- mapproxy/test/unit/test_cache_tile.py +427 -0
- mapproxy/test/unit/test_client.py +479 -0
- mapproxy/test/unit/test_client_arcgis.py +73 -0
- mapproxy/test/unit/test_client_cgi.py +136 -0
- mapproxy/test/unit/test_collections.py +116 -0
- mapproxy/test/unit/test_concat_legends.py +37 -0
- mapproxy/test/unit/test_conf_loader.py +1061 -0
- mapproxy/test/unit/test_conf_validator.py +416 -0
- mapproxy/test/unit/test_config.py +117 -0
- mapproxy/test/unit/test_decorate_img.py +185 -0
- mapproxy/test/unit/test_exceptions.py +258 -0
- mapproxy/test/unit/test_featureinfo.py +291 -0
- mapproxy/test/unit/test_file_lock_load.py +49 -0
- mapproxy/test/unit/test_geom.py +503 -0
- mapproxy/test/unit/test_grid.py +1258 -0
- mapproxy/test/unit/test_image.py +1053 -0
- mapproxy/test/unit/test_image_mask.py +181 -0
- mapproxy/test/unit/test_image_messages.py +197 -0
- mapproxy/test/unit/test_image_options.py +160 -0
- mapproxy/test/unit/test_isodate.py +122 -0
- mapproxy/test/unit/test_multiapp.py +163 -0
- mapproxy/test/unit/test_ogr_reader.py +50 -0
- mapproxy/test/unit/test_request.py +745 -0
- mapproxy/test/unit/test_request_wmts.py +178 -0
- mapproxy/test/unit/test_response.py +79 -0
- mapproxy/test/unit/test_seed.py +365 -0
- mapproxy/test/unit/test_seed_cachelock.py +90 -0
- mapproxy/test/unit/test_srs.py +215 -0
- mapproxy/test/unit/test_tiled_source.py +122 -0
- mapproxy/test/unit/test_tilefilter.py +31 -0
- mapproxy/test/unit/test_times.py +25 -0
- mapproxy/test/unit/test_timeutils.py +50 -0
- mapproxy/test/unit/test_util_conf_utils.py +75 -0
- mapproxy/test/unit/test_utils.py +476 -0
- mapproxy/test/unit/test_wms_capabilities.py +44 -0
- mapproxy/test/unit/test_wms_layer.py +113 -0
- mapproxy/test/unit/test_yaml.py +69 -0
- mapproxy/tilefilter.py +59 -0
- mapproxy/util/__init__.py +0 -0
- mapproxy/util/async_.py +227 -0
- mapproxy/util/collections.py +132 -0
- mapproxy/util/coverage.py +329 -0
- mapproxy/util/escape.py +10 -0
- mapproxy/util/ext/__init__.py +14 -0
- mapproxy/util/ext/dictspec/__init__.py +1 -0
- mapproxy/util/ext/dictspec/spec.py +124 -0
- mapproxy/util/ext/dictspec/test/__init__.py +0 -0
- mapproxy/util/ext/dictspec/test/test_validator.py +274 -0
- mapproxy/util/ext/dictspec/validator.py +189 -0
- mapproxy/util/ext/local.py +196 -0
- mapproxy/util/ext/lockfile.py +138 -0
- mapproxy/util/ext/odict.py +330 -0
- mapproxy/util/ext/serving.py +508 -0
- mapproxy/util/ext/tempita/__init__.py +1174 -0
- mapproxy/util/ext/tempita/_looper.py +163 -0
- mapproxy/util/ext/tempita/compat3.py +46 -0
- mapproxy/util/ext/wmsparse/__init__.py +3 -0
- mapproxy/util/ext/wmsparse/duration.py +597 -0
- mapproxy/util/ext/wmsparse/parse.py +305 -0
- mapproxy/util/ext/wmsparse/test/__init__.py +0 -0
- mapproxy/util/ext/wmsparse/test/test_parse.py +162 -0
- mapproxy/util/ext/wmsparse/test/test_util.py +23 -0
- mapproxy/util/ext/wmsparse/test/wms-large-111.xml +2114 -0
- mapproxy/util/ext/wmsparse/test/wms-omniscale-111.xml +90 -0
- mapproxy/util/ext/wmsparse/test/wms-omniscale-130.xml +120 -0
- mapproxy/util/ext/wmsparse/test/wms_nasa_cap.xml +386 -0
- mapproxy/util/ext/wmsparse/util.py +187 -0
- mapproxy/util/fs.py +156 -0
- mapproxy/util/geom.py +295 -0
- mapproxy/util/lib.py +115 -0
- mapproxy/util/lock.py +163 -0
- mapproxy/util/ogr.py +231 -0
- mapproxy/util/py.py +81 -0
- mapproxy/util/times.py +75 -0
- mapproxy/util/yaml.py +56 -0
- mapproxy/version.py +31 -0
- mapproxy/wsgiapp.py +164 -0
- mapproxy-1.16.1.dist-info/METADATA +151 -0
- mapproxy-1.16.1.dist-info/RECORD +458 -0
- mapproxy-1.16.1.dist-info/WHEEL +5 -0
- mapproxy-1.16.1.dist-info/entry_points.txt +3 -0
- mapproxy-1.16.1.dist-info/licenses/AUTHORS.txt +33 -0
- mapproxy-1.16.1.dist-info/licenses/COPYING.txt +60 -0
- mapproxy-1.16.1.dist-info/licenses/LICENSE.txt +202 -0
- mapproxy-1.16.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# -:- encoding: utf-8 -:-
|
|
2
|
+
# This file is part of the MapProxy project.
|
|
3
|
+
# Copyright (C) 2013 Omniscale <http://omniscale.de>
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from copy import copy
|
|
18
|
+
from mapproxy.compat import iteritems
|
|
19
|
+
|
|
20
|
+
__all__ = ['update_config', 'MapProxyYAMLDumper']
|
|
21
|
+
|
|
22
|
+
def update_config(conf, overwrites):
|
|
23
|
+
wildcard_keys = []
|
|
24
|
+
for k, v in iteritems(overwrites):
|
|
25
|
+
if k == '__all__':
|
|
26
|
+
continue
|
|
27
|
+
if k.startswith('___') or k.endswith('___'):
|
|
28
|
+
wildcard_keys.append(k)
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
if k.endswith('__extend__'):
|
|
32
|
+
k = k[:-len('__extend__')]
|
|
33
|
+
if k not in conf:
|
|
34
|
+
conf[k] = v
|
|
35
|
+
elif isinstance(v, list):
|
|
36
|
+
conf[k].extend(v)
|
|
37
|
+
else:
|
|
38
|
+
raise ValueError('cannot extend non-list:', v)
|
|
39
|
+
elif k not in conf:
|
|
40
|
+
conf[k] = copy(v)
|
|
41
|
+
else:
|
|
42
|
+
if isinstance(conf[k], dict) and isinstance(v, dict):
|
|
43
|
+
conf[k] = update_config(conf[k], v)
|
|
44
|
+
else:
|
|
45
|
+
conf[k] = copy(v)
|
|
46
|
+
|
|
47
|
+
if '__all__' in overwrites:
|
|
48
|
+
v = overwrites['__all__']
|
|
49
|
+
for conf_k, conf_v in iteritems(conf):
|
|
50
|
+
if isinstance(conf_v, dict):
|
|
51
|
+
conf[conf_k] = update_config(conf_v, v)
|
|
52
|
+
else:
|
|
53
|
+
conf[conf_k] = v
|
|
54
|
+
|
|
55
|
+
if wildcard_keys:
|
|
56
|
+
for key in wildcard_keys:
|
|
57
|
+
v = overwrites[key]
|
|
58
|
+
if key.startswith('___'):
|
|
59
|
+
key = key[3:]
|
|
60
|
+
key_check = lambda x: x.endswith(key)
|
|
61
|
+
else:
|
|
62
|
+
key = key[:-3]
|
|
63
|
+
key_check = lambda x: x.startswith(key)
|
|
64
|
+
for conf_k, conf_v in iteritems(conf):
|
|
65
|
+
if not key_check(conf_k):
|
|
66
|
+
continue
|
|
67
|
+
if isinstance(conf_v, dict):
|
|
68
|
+
conf[conf_k] = update_config(conf_v, v)
|
|
69
|
+
else:
|
|
70
|
+
conf[conf_k] = v
|
|
71
|
+
|
|
72
|
+
return conf
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
from yaml.serializer import Serializer
|
|
76
|
+
from yaml.nodes import ScalarNode, SequenceNode, MappingNode
|
|
77
|
+
from yaml.emitter import Emitter
|
|
78
|
+
from yaml.representer import SafeRepresenter
|
|
79
|
+
from yaml.resolver import Resolver
|
|
80
|
+
|
|
81
|
+
class _MixedFlowSortedSerializer(Serializer):
|
|
82
|
+
def serialize_node(self, node, parent, index):
|
|
83
|
+
# reset any anchors
|
|
84
|
+
if parent is None:
|
|
85
|
+
for k in self.anchors:
|
|
86
|
+
self.anchors[k] = None
|
|
87
|
+
self.serialized_nodes = {}
|
|
88
|
+
|
|
89
|
+
if isinstance(node, SequenceNode) and all(isinstance(item, ScalarNode) for item in node.value):
|
|
90
|
+
node.flow_style = True
|
|
91
|
+
elif isinstance(node, MappingNode):
|
|
92
|
+
node.value.sort(key=lambda x: x[0].value)
|
|
93
|
+
return Serializer.serialize_node(self, node, parent, index)
|
|
94
|
+
|
|
95
|
+
class _EmptyNoneRepresenter(SafeRepresenter):
|
|
96
|
+
def represent_none(self, data):
|
|
97
|
+
return self.represent_scalar(u'tag:yaml.org,2002:null',
|
|
98
|
+
u'')
|
|
99
|
+
_EmptyNoneRepresenter.add_representer(type(None), _EmptyNoneRepresenter.represent_none)
|
|
100
|
+
|
|
101
|
+
class MapProxyYAMLDumper(Emitter, _MixedFlowSortedSerializer, _EmptyNoneRepresenter, Resolver):
|
|
102
|
+
"""
|
|
103
|
+
YAML dumper that uses block style by default, except for
|
|
104
|
+
node-only sequences. Also sorts dicts by key, prevents `none`
|
|
105
|
+
for empty entries and prevents any anchors.
|
|
106
|
+
"""
|
|
107
|
+
def __init__(self, stream,
|
|
108
|
+
default_style=None, default_flow_style=False,
|
|
109
|
+
canonical=None, indent=None, width=None,
|
|
110
|
+
allow_unicode=None, line_break=None,
|
|
111
|
+
encoding=None, explicit_start=None, explicit_end=None,
|
|
112
|
+
version=None, tags=None, sort_keys=None):
|
|
113
|
+
Emitter.__init__(self, stream, canonical=canonical,
|
|
114
|
+
indent=indent, width=width,
|
|
115
|
+
allow_unicode=allow_unicode, line_break=line_break)
|
|
116
|
+
Serializer.__init__(self, encoding=encoding,
|
|
117
|
+
explicit_start=explicit_start, explicit_end=explicit_end,
|
|
118
|
+
version=version, tags=tags)
|
|
119
|
+
_EmptyNoneRepresenter.__init__(self, default_style=default_style,
|
|
120
|
+
default_flow_style=default_flow_style)
|
|
121
|
+
Resolver.__init__(self)
|
|
122
|
+
|
|
123
|
+
from mapproxy.request.base import BaseRequest, url_decode
|
|
124
|
+
from mapproxy.client.http import open_url
|
|
125
|
+
from mapproxy.compat.modules import urlparse
|
|
126
|
+
|
|
127
|
+
def wms_capapilities_url(url):
|
|
128
|
+
parsed_url = urlparse.urlparse(url)
|
|
129
|
+
base_req = BaseRequest(
|
|
130
|
+
url=url.split('?', 1)[0],
|
|
131
|
+
param=url_decode(parsed_url.query),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
base_req.params['service'] = 'WMS'
|
|
135
|
+
if not base_req.params['version']:
|
|
136
|
+
base_req.params['version'] = '1.1.1'
|
|
137
|
+
base_req.params['request'] = 'GetCapabilities'
|
|
138
|
+
return base_req.complete_url
|
|
139
|
+
|
|
140
|
+
def download_capabilities(url):
|
|
141
|
+
capabilities_url = wms_capapilities_url(url)
|
|
142
|
+
return open_url(capabilities_url)
|
|
143
|
+
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2017 Omniscale <http://omniscale.de>
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from __future__ import print_function
|
|
17
|
+
|
|
18
|
+
import glob
|
|
19
|
+
import optparse
|
|
20
|
+
import os.path
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from collections import OrderedDict
|
|
24
|
+
|
|
25
|
+
from mapproxy.cache.compact import CompactCacheV1, CompactCacheV2
|
|
26
|
+
from mapproxy.cache.tile import Tile
|
|
27
|
+
from mapproxy.config import local_base_config
|
|
28
|
+
from mapproxy.config.loader import load_configuration, ConfigurationError
|
|
29
|
+
|
|
30
|
+
import logging
|
|
31
|
+
log = logging.getLogger('mapproxy.defrag')
|
|
32
|
+
|
|
33
|
+
def defrag_command(args=None):
|
|
34
|
+
parser = optparse.OptionParser("%prog defrag-compact [options] -f mapproxy_conf")
|
|
35
|
+
parser.add_option("-f", "--mapproxy-conf", dest="mapproxy_conf",
|
|
36
|
+
help="MapProxy configuration.")
|
|
37
|
+
|
|
38
|
+
parser.add_option("--min-percent", type=float, default=10.0,
|
|
39
|
+
help="Only defrag if fragmentation is larger (10 means at least 10% of the file does not have to be used)")
|
|
40
|
+
|
|
41
|
+
parser.add_option("--min-mb", type=float, default=1.0,
|
|
42
|
+
help="Only defrag if fragmentation is larger (2 means at least 2MB the file does not have to be used)")
|
|
43
|
+
|
|
44
|
+
parser.add_option("--dry-run", "-n", action="store_true",
|
|
45
|
+
help="Do not de-fragment, only print output")
|
|
46
|
+
|
|
47
|
+
parser.add_option("--caches", dest="cache_names", metavar='cache1,cache2,...',
|
|
48
|
+
help="only defragment the named caches")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
from mapproxy.script.util import setup_logging
|
|
52
|
+
import logging
|
|
53
|
+
setup_logging(logging.INFO, format="[%(asctime)s] %(msg)s")
|
|
54
|
+
|
|
55
|
+
if args:
|
|
56
|
+
args = args[1:] # remove script name
|
|
57
|
+
|
|
58
|
+
(options, args) = parser.parse_args(args)
|
|
59
|
+
if not options.mapproxy_conf:
|
|
60
|
+
parser.print_help()
|
|
61
|
+
sys.exit(1)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
proxy_configuration = load_configuration(options.mapproxy_conf)
|
|
65
|
+
except IOError as e:
|
|
66
|
+
print('ERROR: ', "%s: '%s'" % (e.strerror, e.filename), file=sys.stderr)
|
|
67
|
+
sys.exit(2)
|
|
68
|
+
except ConfigurationError as e:
|
|
69
|
+
print(e, file=sys.stderr)
|
|
70
|
+
print('ERROR: invalid configuration (see above)', file=sys.stderr)
|
|
71
|
+
sys.exit(2)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
with local_base_config(proxy_configuration.base_config):
|
|
75
|
+
available_caches = OrderedDict()
|
|
76
|
+
for name, cache_conf in proxy_configuration.caches.items():
|
|
77
|
+
for grid, extent, tile_mgr in cache_conf.caches():
|
|
78
|
+
if isinstance(tile_mgr.cache, (CompactCacheV1, CompactCacheV2)):
|
|
79
|
+
available_caches.setdefault(name, []).append(tile_mgr.cache)
|
|
80
|
+
|
|
81
|
+
if options.cache_names:
|
|
82
|
+
defrag_caches = options.cache_names.split(',')
|
|
83
|
+
missing = set(defrag_caches).difference(available_caches.keys())
|
|
84
|
+
if missing:
|
|
85
|
+
print('unknown caches: %s' % (', '.join(missing), ))
|
|
86
|
+
print('available compact caches: %s' %
|
|
87
|
+
(', '.join(available_caches.keys()), ))
|
|
88
|
+
sys.exit(1)
|
|
89
|
+
else:
|
|
90
|
+
defrag_caches = None
|
|
91
|
+
|
|
92
|
+
for name, caches in available_caches.items():
|
|
93
|
+
if defrag_caches and name not in defrag_caches:
|
|
94
|
+
continue
|
|
95
|
+
for cache in caches:
|
|
96
|
+
logger = DefragLog(name)
|
|
97
|
+
defrag_compact_cache(cache,
|
|
98
|
+
min_percent=options.min_percent/100,
|
|
99
|
+
min_bytes=options.min_mb*1024*1024,
|
|
100
|
+
dry_run=options.dry_run,
|
|
101
|
+
log_progress=logger,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def bundle_offset(fname):
|
|
105
|
+
"""
|
|
106
|
+
>>> bundle_offset("path/to/R0000C0000.bundle")
|
|
107
|
+
(0, 0)
|
|
108
|
+
>>> bundle_offset("path/to/R0380C1380.bundle")
|
|
109
|
+
(4992, 896)
|
|
110
|
+
"""
|
|
111
|
+
match = re.search(r'R([A-F0-9]{4,})C([A-F0-9]{4,}).bundle$', fname, re.IGNORECASE)
|
|
112
|
+
if match:
|
|
113
|
+
r = int(match.group(1), 16)
|
|
114
|
+
c = int(match.group(2), 16)
|
|
115
|
+
return c, r
|
|
116
|
+
|
|
117
|
+
class DefragLog(object):
|
|
118
|
+
def __init__(self, cache_name):
|
|
119
|
+
self.cache_name = cache_name
|
|
120
|
+
def log(self, fname, fragmentation, fragmentation_bytes, num, total, defrag):
|
|
121
|
+
msg = "%s: %3d/%d (%s) fragmentation is %.1f%% (%dkb)" % (
|
|
122
|
+
self.cache_name, num, total, fname, fragmentation, fragmentation_bytes/1024
|
|
123
|
+
)
|
|
124
|
+
if defrag:
|
|
125
|
+
msg += " - defragmenting"
|
|
126
|
+
else:
|
|
127
|
+
msg += " - skipping"
|
|
128
|
+
log.info(msg)
|
|
129
|
+
|
|
130
|
+
def defrag_compact_cache(cache, min_percent=0.1, min_bytes=1024*1024, log_progress=None, dry_run=False):
|
|
131
|
+
bundles = glob.glob(os.path.join(cache.cache_dir, 'L??', 'R????C????.bundle'))
|
|
132
|
+
|
|
133
|
+
for i, bundle_file in enumerate(bundles):
|
|
134
|
+
offset = bundle_offset(bundle_file)
|
|
135
|
+
b = cache.bundle_class(bundle_file.rstrip('.bundle'), offset)
|
|
136
|
+
size, file_size = b.size()
|
|
137
|
+
|
|
138
|
+
defrag = 1 - float(size) / file_size
|
|
139
|
+
defrag_bytes = file_size - size
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
skip = False
|
|
143
|
+
if defrag < min_percent or defrag_bytes < min_bytes:
|
|
144
|
+
skip = True
|
|
145
|
+
|
|
146
|
+
if log_progress:
|
|
147
|
+
log_progress.log(
|
|
148
|
+
fname=bundle_file,
|
|
149
|
+
fragmentation=defrag * 100,
|
|
150
|
+
fragmentation_bytes=defrag_bytes,
|
|
151
|
+
num=i+1, total=len(bundles),
|
|
152
|
+
defrag=not skip,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
if skip or dry_run:
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
tmp_bundle = os.path.join(cache.cache_dir, 'tmp_defrag')
|
|
159
|
+
defb = cache.bundle_class(tmp_bundle, offset)
|
|
160
|
+
stored_tiles = False
|
|
161
|
+
|
|
162
|
+
for y in range(128):
|
|
163
|
+
tiles = [Tile((x, y, 0)) for x in range(128)]
|
|
164
|
+
b.load_tiles(tiles)
|
|
165
|
+
tiles = [t for t in tiles if t.source]
|
|
166
|
+
if tiles:
|
|
167
|
+
stored_tiles = True
|
|
168
|
+
defb.store_tiles(tiles)
|
|
169
|
+
|
|
170
|
+
# remove first
|
|
171
|
+
# - in case bundle is empty
|
|
172
|
+
# - windows does not support rename to existing files
|
|
173
|
+
if os.path.exists(bundle_file):
|
|
174
|
+
os.remove(bundle_file)
|
|
175
|
+
if os.path.exists(bundle_file[:-1] + 'x'):
|
|
176
|
+
os.remove(bundle_file[:-1] + 'x')
|
|
177
|
+
|
|
178
|
+
if stored_tiles:
|
|
179
|
+
os.rename(tmp_bundle + '.bundle', bundle_file)
|
|
180
|
+
if os.path.exists(tmp_bundle + '.bundlx'):
|
|
181
|
+
os.rename(tmp_bundle + '.bundlx', bundle_file[:-1] + 'x')
|
|
182
|
+
if os.path.exists(tmp_bundle + '.lck'):
|
|
183
|
+
os.unlink(tmp_bundle + '.lck')
|
|
184
|
+
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2012 Omniscale <http://omniscale.de>
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from __future__ import print_function, division
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import re
|
|
20
|
+
import shlex
|
|
21
|
+
import sys
|
|
22
|
+
import optparse
|
|
23
|
+
|
|
24
|
+
import yaml
|
|
25
|
+
|
|
26
|
+
from mapproxy.srs import SRS
|
|
27
|
+
from mapproxy.config.coverage import load_coverage
|
|
28
|
+
from mapproxy.config.loader import (
|
|
29
|
+
load_configuration, ConfigurationError,
|
|
30
|
+
CacheConfiguration, GridConfiguration,
|
|
31
|
+
ProxyConfiguration,
|
|
32
|
+
)
|
|
33
|
+
from mapproxy.util.coverage import BBOXCoverage
|
|
34
|
+
from mapproxy.seed.util import ProgressLog, format_bbox
|
|
35
|
+
from mapproxy.seed.seeder import SeedTask, seed_task
|
|
36
|
+
from mapproxy.config import spec as conf_spec
|
|
37
|
+
from mapproxy.util.ext.dictspec.validator import validate, ValidationError
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_levels(level_str):
|
|
41
|
+
"""
|
|
42
|
+
>>> parse_levels('1,2,3,6')
|
|
43
|
+
[1, 2, 3, 6]
|
|
44
|
+
>>> parse_levels('1..6')
|
|
45
|
+
[1, 2, 3, 4, 5, 6]
|
|
46
|
+
>>> parse_levels('1..6, 8, 9, 13..14')
|
|
47
|
+
[1, 2, 3, 4, 5, 6, 8, 9, 13, 14]
|
|
48
|
+
"""
|
|
49
|
+
levels = set()
|
|
50
|
+
for part in level_str.split(','):
|
|
51
|
+
part = part.strip()
|
|
52
|
+
if re.match(r'\d+..\d+', part):
|
|
53
|
+
from_level, to_level = part.split('..')
|
|
54
|
+
levels.update(list(range(int(from_level), int(to_level) + 1)))
|
|
55
|
+
else:
|
|
56
|
+
levels.add(int(part))
|
|
57
|
+
|
|
58
|
+
return sorted(levels)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def resolve_source(source_name, conf):
|
|
62
|
+
"""
|
|
63
|
+
Resolves the source with the given name.
|
|
64
|
+
|
|
65
|
+
>>> config = ProxyConfiguration({'sources': {'mysource': {'type': 'wms'}}})
|
|
66
|
+
>>> resolve_source('mysource', config)
|
|
67
|
+
(<mapproxy.config.loader.WMSSourceConfiguration object at 0x...>, False)
|
|
68
|
+
|
|
69
|
+
>>> config = ProxyConfiguration({'caches': {'mysource': {}}})
|
|
70
|
+
>>> resolve_source('mysource', config)
|
|
71
|
+
(<mapproxy.config.loader.CacheConfiguration object at 0x...>, True)
|
|
72
|
+
|
|
73
|
+
>>> config = ProxyConfiguration({'caches': {'mysource': {'type': 'foo'}}})
|
|
74
|
+
>>> resolve_source('nonexistingsource', config)
|
|
75
|
+
(None, None)
|
|
76
|
+
|
|
77
|
+
:param source_name: The name of the source to resolve.
|
|
78
|
+
:param conf: The mapproxy config to resolve from.
|
|
79
|
+
:rtype: (dict, bool) A tuple containing the resolved source and a boolean
|
|
80
|
+
indicating if the resolved source is a cache (True), or a source (False).
|
|
81
|
+
"""
|
|
82
|
+
resolved_source = conf.sources.get(source_name)
|
|
83
|
+
if resolved_source is not None:
|
|
84
|
+
return resolved_source, False
|
|
85
|
+
resolved_source = conf.caches.get(source_name)
|
|
86
|
+
if resolved_source is not None:
|
|
87
|
+
return resolved_source, True
|
|
88
|
+
return None, None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def parse_grid_definition(definition):
|
|
92
|
+
"""
|
|
93
|
+
>>> sorted(parse_grid_definition("res=[10000,1000,100,10] srs=EPSG:4326 bbox=5,50,10,60").items())
|
|
94
|
+
[('bbox', '5,50,10,60'), ('res', [10000, 1000, 100, 10]), ('srs', 'EPSG:4326')]
|
|
95
|
+
"""
|
|
96
|
+
args = shlex.split(definition)
|
|
97
|
+
grid_conf = {}
|
|
98
|
+
for arg in args:
|
|
99
|
+
key, value = arg.split('=')
|
|
100
|
+
value = yaml.safe_load(value)
|
|
101
|
+
grid_conf[key] = value
|
|
102
|
+
|
|
103
|
+
validate(conf_spec.grid_opts, grid_conf)
|
|
104
|
+
return grid_conf
|
|
105
|
+
|
|
106
|
+
def supports_tiled_access(mgr):
|
|
107
|
+
if len(mgr.sources) == 1 and getattr(mgr.sources[0], 'supports_meta_tiles') == False:
|
|
108
|
+
return True
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def format_export_task(task, custom_grid):
|
|
113
|
+
info = []
|
|
114
|
+
if custom_grid:
|
|
115
|
+
grid = "custom grid"
|
|
116
|
+
else:
|
|
117
|
+
grid = "grid '%s'" % task.md['grid_name']
|
|
118
|
+
|
|
119
|
+
info.append("Exporting cache '%s' to '%s' with %s in %s" % (
|
|
120
|
+
task.md['cache_name'], task.md['dest'], grid, task.grid.srs.srs_code))
|
|
121
|
+
if task.coverage:
|
|
122
|
+
info.append(' Limited to: %s (EPSG:4326)' % (format_bbox(task.coverage.extent.llbbox), ))
|
|
123
|
+
info.append(' Levels: %s' % (task.levels, ))
|
|
124
|
+
|
|
125
|
+
return '\n'.join(info)
|
|
126
|
+
|
|
127
|
+
def export_command(args=None):
|
|
128
|
+
parser = optparse.OptionParser("%prog export [options] mapproxy_conf")
|
|
129
|
+
parser.add_option("-f", "--mapproxy-conf", dest="mapproxy_conf",
|
|
130
|
+
help="MapProxy configuration")
|
|
131
|
+
|
|
132
|
+
parser.add_option("-q", "--quiet",
|
|
133
|
+
action="count", dest="quiet", default=0,
|
|
134
|
+
help="reduce number of messages to stdout, repeat to disable progress output")
|
|
135
|
+
|
|
136
|
+
parser.add_option("--source", dest="source",
|
|
137
|
+
help="source to export (source or cache)")
|
|
138
|
+
|
|
139
|
+
parser.add_option("--grid",
|
|
140
|
+
help="grid for export. either the name of an existing grid or "
|
|
141
|
+
"the grid definition as a string")
|
|
142
|
+
|
|
143
|
+
parser.add_option("--dest",
|
|
144
|
+
help="destination of the export (directory or filename)")
|
|
145
|
+
|
|
146
|
+
parser.add_option("--type",
|
|
147
|
+
help="type of the export format")
|
|
148
|
+
|
|
149
|
+
parser.add_option("--levels",
|
|
150
|
+
help="levels to export: e.g 1,2,3 or 1..10")
|
|
151
|
+
|
|
152
|
+
parser.add_option("--fetch-missing-tiles", dest="fetch_missing_tiles",
|
|
153
|
+
action='store_true', default=False,
|
|
154
|
+
help="if missing tiles should be fetched from the sources")
|
|
155
|
+
|
|
156
|
+
parser.add_option("--force",
|
|
157
|
+
action='store_true', default=False,
|
|
158
|
+
help="overwrite/append to existing --dest files/directories")
|
|
159
|
+
|
|
160
|
+
parser.add_option("-n", "--dry-run",
|
|
161
|
+
action="store_true", default=False,
|
|
162
|
+
help="do not export, just print output")
|
|
163
|
+
|
|
164
|
+
parser.add_option("-c", "--concurrency", type="int",
|
|
165
|
+
dest="concurrency", default=1,
|
|
166
|
+
help="number of parallel export processes")
|
|
167
|
+
|
|
168
|
+
parser.add_option("--coverage",
|
|
169
|
+
help="the coverage for the export as a BBOX string, WKT file "
|
|
170
|
+
"or OGR datasource")
|
|
171
|
+
parser.add_option("--srs",
|
|
172
|
+
help="the SRS of the coverage")
|
|
173
|
+
parser.add_option("--where",
|
|
174
|
+
help="filter for OGR coverages")
|
|
175
|
+
|
|
176
|
+
from mapproxy.script.util import setup_logging
|
|
177
|
+
import logging
|
|
178
|
+
setup_logging(logging.WARN)
|
|
179
|
+
|
|
180
|
+
if args:
|
|
181
|
+
args = args[1:] # remove script name
|
|
182
|
+
|
|
183
|
+
(options, args) = parser.parse_args(args)
|
|
184
|
+
|
|
185
|
+
if not options.mapproxy_conf:
|
|
186
|
+
if len(args) != 1:
|
|
187
|
+
parser.print_help()
|
|
188
|
+
sys.exit(1)
|
|
189
|
+
else:
|
|
190
|
+
options.mapproxy_conf = args[0]
|
|
191
|
+
|
|
192
|
+
required_options = ['mapproxy_conf', 'grid', 'source', 'dest', 'levels']
|
|
193
|
+
for required in required_options:
|
|
194
|
+
if not getattr(options, required):
|
|
195
|
+
print('ERROR: missing required option --%s' % required.replace('_', '-'), file=sys.stderr)
|
|
196
|
+
parser.print_help()
|
|
197
|
+
sys.exit(1)
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
conf = load_configuration(options.mapproxy_conf)
|
|
201
|
+
except IOError as e:
|
|
202
|
+
print('ERROR: ', "%s: '%s'" % (e.strerror, e.filename), file=sys.stderr)
|
|
203
|
+
sys.exit(2)
|
|
204
|
+
except ConfigurationError as e:
|
|
205
|
+
print(e, file=sys.stderr)
|
|
206
|
+
print('ERROR: invalid configuration (see above)', file=sys.stderr)
|
|
207
|
+
sys.exit(2)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
if '=' in options.grid:
|
|
211
|
+
try:
|
|
212
|
+
grid_conf = parse_grid_definition(options.grid)
|
|
213
|
+
except ValidationError as ex:
|
|
214
|
+
print('ERROR: invalid grid configuration', file=sys.stderr)
|
|
215
|
+
for error in ex.errors:
|
|
216
|
+
print(' ', error, file=sys.stderr)
|
|
217
|
+
sys.exit(2)
|
|
218
|
+
except ValueError:
|
|
219
|
+
print('ERROR: invalid grid configuration', file=sys.stderr)
|
|
220
|
+
sys.exit(2)
|
|
221
|
+
options.grid = 'tmp_mapproxy_export_grid'
|
|
222
|
+
grid_conf['name'] = options.grid
|
|
223
|
+
custom_grid = True
|
|
224
|
+
conf.grids[options.grid] = GridConfiguration(grid_conf, conf)
|
|
225
|
+
else:
|
|
226
|
+
custom_grid = False
|
|
227
|
+
|
|
228
|
+
if os.path.exists(options.dest) and not options.force:
|
|
229
|
+
print('ERROR: destination exists, remove first or use --force', file=sys.stderr)
|
|
230
|
+
sys.exit(2)
|
|
231
|
+
|
|
232
|
+
cache_conf = {
|
|
233
|
+
'name': 'export',
|
|
234
|
+
'grids': [options.grid],
|
|
235
|
+
'sources': [options.source],
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
resolved_source, source_is_cache = resolve_source(options.source, conf)
|
|
239
|
+
if source_is_cache:
|
|
240
|
+
image_format = resolved_source.conf.get('format') or resolved_source.defaults.get('format')
|
|
241
|
+
if image_format is not None:
|
|
242
|
+
cache_conf['format'] = image_format
|
|
243
|
+
if image_format == 'mixed':
|
|
244
|
+
request_format = resolved_source.conf.get('request_format') or 'image/png'
|
|
245
|
+
cache_conf['request_format'] = request_format
|
|
246
|
+
|
|
247
|
+
if options.type == 'mbtile':
|
|
248
|
+
cache_conf['cache'] = {
|
|
249
|
+
'type': 'mbtiles',
|
|
250
|
+
'filename': options.dest,
|
|
251
|
+
}
|
|
252
|
+
elif options.type == 'sqlite':
|
|
253
|
+
cache_conf['cache'] = {
|
|
254
|
+
'type': 'sqlite',
|
|
255
|
+
'directory': options.dest,
|
|
256
|
+
}
|
|
257
|
+
elif options.type == 'geopackage':
|
|
258
|
+
cache_conf['cache'] = {
|
|
259
|
+
'type': 'geopackage',
|
|
260
|
+
'filename': options.dest,
|
|
261
|
+
}
|
|
262
|
+
elif options.type == 'compact-v1':
|
|
263
|
+
cache_conf['cache'] = {
|
|
264
|
+
'type': 'compact',
|
|
265
|
+
'version': 1,
|
|
266
|
+
'directory': options.dest,
|
|
267
|
+
}
|
|
268
|
+
elif options.type == 'compact-v2':
|
|
269
|
+
cache_conf['cache'] = {
|
|
270
|
+
'type': 'compact',
|
|
271
|
+
'version': 2,
|
|
272
|
+
'directory': options.dest,
|
|
273
|
+
}
|
|
274
|
+
elif options.type in ('tc', 'mapproxy'):
|
|
275
|
+
cache_conf['cache'] = {
|
|
276
|
+
'type': 'file',
|
|
277
|
+
'directory': options.dest,
|
|
278
|
+
}
|
|
279
|
+
elif options.type == 'arcgis':
|
|
280
|
+
cache_conf['cache'] = {
|
|
281
|
+
'type': 'file',
|
|
282
|
+
'directory_layout': 'arcgis',
|
|
283
|
+
'directory': options.dest,
|
|
284
|
+
}
|
|
285
|
+
elif options.type in ('tms', None): # default
|
|
286
|
+
cache_conf['cache'] = {
|
|
287
|
+
'type': 'file',
|
|
288
|
+
'directory_layout': 'tms',
|
|
289
|
+
'directory': options.dest,
|
|
290
|
+
}
|
|
291
|
+
else:
|
|
292
|
+
print('ERROR: unsupported --type %s' % (options.type, ), file=sys.stderr)
|
|
293
|
+
sys.exit(2)
|
|
294
|
+
|
|
295
|
+
if not options.fetch_missing_tiles:
|
|
296
|
+
for source in conf.sources.values():
|
|
297
|
+
source.conf['seed_only'] = True
|
|
298
|
+
|
|
299
|
+
tile_grid, extent, mgr = CacheConfiguration(cache_conf, conf).caches()[0]
|
|
300
|
+
|
|
301
|
+
levels = parse_levels(options.levels)
|
|
302
|
+
if levels[-1] >= tile_grid.levels:
|
|
303
|
+
print('ERROR: destination grid only has %d levels' % tile_grid.levels, file=sys.stderr)
|
|
304
|
+
sys.exit(2)
|
|
305
|
+
|
|
306
|
+
if options.srs:
|
|
307
|
+
srs = SRS(options.srs)
|
|
308
|
+
else:
|
|
309
|
+
srs = tile_grid.srs
|
|
310
|
+
|
|
311
|
+
if options.coverage:
|
|
312
|
+
seed_coverage = load_coverage(
|
|
313
|
+
{'datasource': options.coverage, 'srs': srs, 'where': options.where},
|
|
314
|
+
base_path=os.getcwd())
|
|
315
|
+
else:
|
|
316
|
+
seed_coverage = BBOXCoverage(tile_grid.bbox, tile_grid.srs)
|
|
317
|
+
|
|
318
|
+
if not supports_tiled_access(mgr):
|
|
319
|
+
print('WARN: grids are incompatible. needs to scale/reproject tiles for export.', file=sys.stderr)
|
|
320
|
+
|
|
321
|
+
md = dict(name='export', cache_name='cache', grid_name=options.grid, dest=options.dest)
|
|
322
|
+
task = SeedTask(md, mgr, levels, 1, seed_coverage)
|
|
323
|
+
|
|
324
|
+
print(format_export_task(task, custom_grid=custom_grid))
|
|
325
|
+
|
|
326
|
+
logger = ProgressLog(verbose=options.quiet==0, silent=options.quiet>=2)
|
|
327
|
+
try:
|
|
328
|
+
seed_task(task, progress_logger=logger, dry_run=options.dry_run,
|
|
329
|
+
concurrency=options.concurrency)
|
|
330
|
+
except KeyboardInterrupt:
|
|
331
|
+
print('stopping...', file=sys.stderr)
|
|
332
|
+
sys.exit(2)
|
|
333
|
+
|