MapProxy 2.1.0__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-2.1.0.dist-info/AUTHORS.txt +33 -0
- MapProxy-2.1.0.dist-info/COPYING.txt +60 -0
- MapProxy-2.1.0.dist-info/LICENSE.txt +202 -0
- MapProxy-2.1.0.dist-info/METADATA +165 -0
- MapProxy-2.1.0.dist-info/RECORD +459 -0
- MapProxy-2.1.0.dist-info/WHEEL +5 -0
- MapProxy-2.1.0.dist-info/entry_points.txt +4 -0
- MapProxy-2.1.0.dist-info/top_level.txt +1 -0
- mapproxy/__init__.py +0 -0
- mapproxy/cache/__init__.py +36 -0
- mapproxy/cache/azureblob.py +145 -0
- mapproxy/cache/base.py +120 -0
- mapproxy/cache/compact.py +665 -0
- mapproxy/cache/couchdb.py +301 -0
- mapproxy/cache/dummy.py +36 -0
- mapproxy/cache/file.py +200 -0
- mapproxy/cache/geopackage.py +647 -0
- mapproxy/cache/legend.py +87 -0
- mapproxy/cache/mbtiles.py +411 -0
- mapproxy/cache/meta.py +80 -0
- mapproxy/cache/path.py +261 -0
- mapproxy/cache/redis.py +152 -0
- mapproxy/cache/renderd.py +100 -0
- mapproxy/cache/riak.py +206 -0
- mapproxy/cache/s3.py +209 -0
- mapproxy/cache/tile.py +736 -0
- mapproxy/client/__init__.py +0 -0
- mapproxy/client/arcgis.py +82 -0
- mapproxy/client/cgi.py +141 -0
- mapproxy/client/http.py +295 -0
- mapproxy/client/log.py +33 -0
- mapproxy/client/tile.py +158 -0
- mapproxy/client/wms.py +255 -0
- mapproxy/compat/__init__.py +0 -0
- mapproxy/compat/image.py +86 -0
- mapproxy/config/__init__.py +22 -0
- mapproxy/config/config-schema.json +813 -0
- mapproxy/config/config.py +213 -0
- mapproxy/config/coverage.py +108 -0
- mapproxy/config/defaults.py +102 -0
- mapproxy/config/loader.py +2399 -0
- mapproxy/config/spec.py +657 -0
- mapproxy/config/validator.py +242 -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 +598 -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 +149 -0
- mapproxy/featureinfo.py +251 -0
- mapproxy/grid.py +1199 -0
- mapproxy/image/__init__.py +549 -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 +79 -0
- mapproxy/image/merge.py +323 -0
- mapproxy/image/message.py +357 -0
- mapproxy/image/opts.py +185 -0
- mapproxy/image/tile.py +171 -0
- mapproxy/image/transform.py +350 -0
- mapproxy/layer.py +489 -0
- mapproxy/multiapp.py +230 -0
- mapproxy/proj.py +309 -0
- mapproxy/request/__init__.py +18 -0
- mapproxy/request/arcgis.py +268 -0
- mapproxy/request/base.py +466 -0
- mapproxy/request/tile.py +131 -0
- mapproxy/request/wms/__init__.py +829 -0
- mapproxy/request/wms/exception.py +107 -0
- mapproxy/request/wmts.py +442 -0
- mapproxy/response.py +237 -0
- mapproxy/script/__init__.py +0 -0
- mapproxy/script/conf/__init__.py +0 -0
- mapproxy/script/conf/app.py +222 -0
- mapproxy/script/conf/caches.py +44 -0
- mapproxy/script/conf/geopackage.py +136 -0
- mapproxy/script/conf/layers.py +54 -0
- mapproxy/script/conf/seeds.py +36 -0
- mapproxy/script/conf/sources.py +88 -0
- mapproxy/script/conf/utils.py +148 -0
- mapproxy/script/defrag.py +187 -0
- mapproxy/script/export.py +337 -0
- mapproxy/script/grids.py +198 -0
- mapproxy/script/scales.py +134 -0
- mapproxy/script/util.py +410 -0
- mapproxy/script/wms_capabilities.py +160 -0
- mapproxy/seed/__init__.py +0 -0
- mapproxy/seed/cachelock.py +127 -0
- mapproxy/seed/cleanup.py +191 -0
- mapproxy/seed/config.py +481 -0
- mapproxy/seed/script.py +391 -0
- mapproxy/seed/seeder.py +551 -0
- mapproxy/seed/spec.py +66 -0
- mapproxy/seed/util.py +266 -0
- mapproxy/service/__init__.py +14 -0
- mapproxy/service/base.py +45 -0
- mapproxy/service/demo.py +364 -0
- mapproxy/service/kml.py +333 -0
- mapproxy/service/ows.py +39 -0
- mapproxy/service/template_helper.py +55 -0
- mapproxy/service/templates/demo/capabilities_demo.html +18 -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 +117 -0
- mapproxy/service/templates/demo/wms_demo.html +144 -0
- mapproxy/service/templates/demo/wmts_demo.html +118 -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 +540 -0
- mapproxy/service/wms.py +868 -0
- mapproxy/service/wmts.py +387 -0
- mapproxy/source/__init__.py +83 -0
- mapproxy/source/arcgis.py +39 -0
- mapproxy/source/error.py +40 -0
- mapproxy/source/mapnik.py +262 -0
- mapproxy/source/tile.py +97 -0
- mapproxy/source/wms.py +273 -0
- mapproxy/srs.py +734 -0
- mapproxy/template.py +54 -0
- mapproxy/test/__init__.py +0 -0
- mapproxy/test/conftest.py +8 -0
- mapproxy/test/helper.py +255 -0
- mapproxy/test/http.py +511 -0
- mapproxy/test/image.py +219 -0
- mapproxy/test/mocker.py +2291 -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_coverage.yaml +84 -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 +111 -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 +29 -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 +1133 -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_coverage.py +168 -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 +56 -0
- mapproxy/test/system/test_demo_with_extra_service.py +57 -0
- mapproxy/test/system/test_dimensions.py +279 -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 +264 -0
- mapproxy/test/system/test_layergroups.py +160 -0
- mapproxy/test/system/test_legendgraphic.py +308 -0
- mapproxy/test/system/test_mapnik.py +162 -0
- mapproxy/test/system/test_mapserver.py +83 -0
- mapproxy/test/system/test_mixed_mode_format.py +201 -0
- mapproxy/test/system/test_multi_cache_layers.py +169 -0
- mapproxy/test/system/test_multiapp.py +92 -0
- mapproxy/test/system/test_refresh.py +206 -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 +425 -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 +277 -0
- mapproxy/test/system/test_tms_origin.py +46 -0
- mapproxy/test/system/test_util_conf.py +434 -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 +1616 -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 +423 -0
- mapproxy/test/test_http_helper.py +217 -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 +242 -0
- mapproxy/test/unit/test_auth.py +430 -0
- mapproxy/test/unit/test_cache.py +1356 -0
- mapproxy/test/unit/test_cache_azureblob.py +97 -0
- mapproxy/test/unit/test_cache_compact.py +324 -0
- mapproxy/test/unit/test_cache_couchdb.py +118 -0
- mapproxy/test/unit/test_cache_geopackage.py +256 -0
- mapproxy/test/unit/test_cache_redis.py +123 -0
- mapproxy/test/unit/test_cache_riak.py +80 -0
- mapproxy/test/unit/test_cache_s3.py +93 -0
- mapproxy/test/unit/test_cache_tile.py +477 -0
- mapproxy/test/unit/test_client.py +488 -0
- mapproxy/test/unit/test_client_arcgis.py +74 -0
- mapproxy/test/unit/test_client_cgi.py +140 -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 +1267 -0
- mapproxy/test/unit/test_conf_validator.py +427 -0
- mapproxy/test/unit/test_config.py +118 -0
- mapproxy/test/unit/test_decorate_img.py +185 -0
- mapproxy/test/unit/test_exceptions.py +270 -0
- mapproxy/test/unit/test_featureinfo.py +313 -0
- mapproxy/test/unit/test_file_lock_load.py +49 -0
- mapproxy/test/unit/test_geom.py +512 -0
- mapproxy/test/unit/test_grid.py +1279 -0
- mapproxy/test/unit/test_image.py +1051 -0
- mapproxy/test/unit/test_image_mask.py +181 -0
- mapproxy/test/unit/test_image_messages.py +209 -0
- mapproxy/test/unit/test_image_options.py +160 -0
- mapproxy/test/unit/test_isodate.py +118 -0
- mapproxy/test/unit/test_multiapp.py +163 -0
- mapproxy/test/unit/test_ogr_reader.py +51 -0
- mapproxy/test/unit/test_request.py +745 -0
- mapproxy/test/unit/test_request_wmts.py +178 -0
- mapproxy/test/unit/test_response.py +78 -0
- mapproxy/test/unit/test_seed.py +365 -0
- mapproxy/test/unit/test_seed_cachelock.py +91 -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 +68 -0
- mapproxy/tilefilter.py +61 -0
- mapproxy/util/__init__.py +0 -0
- mapproxy/util/async_.py +229 -0
- mapproxy/util/collections.py +134 -0
- mapproxy/util/coverage.py +337 -0
- mapproxy/util/ext/__init__.py +14 -0
- mapproxy/util/ext/dictspec/__init__.py +1 -0
- mapproxy/util/ext/dictspec/spec.py +131 -0
- mapproxy/util/ext/dictspec/test/__init__.py +0 -0
- mapproxy/util/ext/dictspec/test/test_validator.py +278 -0
- mapproxy/util/ext/dictspec/validator.py +194 -0
- mapproxy/util/ext/local.py +198 -0
- mapproxy/util/ext/lockfile.py +140 -0
- mapproxy/util/ext/odict.py +321 -0
- mapproxy/util/ext/serving.py +491 -0
- mapproxy/util/ext/tempita/__init__.py +1093 -0
- mapproxy/util/ext/tempita/_looper.py +163 -0
- mapproxy/util/ext/tempita/string_utils.py +24 -0
- mapproxy/util/ext/wmsparse/__init__.py +3 -0
- mapproxy/util/ext/wmsparse/duration.py +600 -0
- mapproxy/util/ext/wmsparse/parse.py +307 -0
- mapproxy/util/ext/wmsparse/test/__init__.py +0 -0
- mapproxy/util/ext/wmsparse/test/test_parse.py +111 -0
- mapproxy/util/ext/wmsparse/test/test_util.py +23 -0
- mapproxy/util/ext/wmsparse/test/wms-example-111.xml +90 -0
- mapproxy/util/ext/wmsparse/test/wms-example-130.xml +120 -0
- mapproxy/util/ext/wmsparse/test/wms-large-111.xml +2114 -0
- mapproxy/util/ext/wmsparse/test/wms_nasa_cap.xml +386 -0
- mapproxy/util/ext/wmsparse/util.py +189 -0
- mapproxy/util/fs.py +164 -0
- mapproxy/util/geom.py +307 -0
- mapproxy/util/lib.py +117 -0
- mapproxy/util/lock.py +171 -0
- mapproxy/util/ogr.py +247 -0
- mapproxy/util/py.py +75 -0
- mapproxy/util/times.py +78 -0
- mapproxy/util/yaml.py +58 -0
- mapproxy/version.py +33 -0
- mapproxy/wsgiapp.py +167 -0
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
def layers(cap, caches):
|
|
18
|
+
return [_layer(cap.layers(), caches)]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _layer(layer, caches):
|
|
22
|
+
name, conf = for_layer(layer, caches)
|
|
23
|
+
child_layers = []
|
|
24
|
+
|
|
25
|
+
for child_layer in layer['layers']:
|
|
26
|
+
child_layers.append(_layer(child_layer, caches))
|
|
27
|
+
|
|
28
|
+
if child_layers:
|
|
29
|
+
conf['layers'] = child_layers
|
|
30
|
+
|
|
31
|
+
return conf
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def for_layer(layer, caches):
|
|
35
|
+
conf = {
|
|
36
|
+
'title': layer['title'],
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if layer['name']:
|
|
40
|
+
conf['name'] = layer['name']
|
|
41
|
+
|
|
42
|
+
if layer['name'] + '_cache' in caches:
|
|
43
|
+
conf['sources'] = [layer['name'] + '_cache']
|
|
44
|
+
else:
|
|
45
|
+
conf['sources'] = [layer['name'] + '_wms']
|
|
46
|
+
|
|
47
|
+
md = {}
|
|
48
|
+
if layer['abstract']:
|
|
49
|
+
md['abstract'] = layer['abstract']
|
|
50
|
+
|
|
51
|
+
if md:
|
|
52
|
+
conf['md'] = md
|
|
53
|
+
|
|
54
|
+
return layer['name'], conf
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
|
|
18
|
+
def seeds(cap, caches):
|
|
19
|
+
seeds = {}
|
|
20
|
+
cleanups = {}
|
|
21
|
+
|
|
22
|
+
for cache_name, cache in caches.items():
|
|
23
|
+
for grid in cache['grids']:
|
|
24
|
+
seeds[cache_name + '_' + grid] = {
|
|
25
|
+
'caches': [cache_name],
|
|
26
|
+
'grids': [grid],
|
|
27
|
+
}
|
|
28
|
+
cleanups[cache_name + '_' + grid] = {
|
|
29
|
+
'caches': [cache_name],
|
|
30
|
+
'grids': [grid],
|
|
31
|
+
'remove_before': {
|
|
32
|
+
'time': '1900-01-01T00:00:00',
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return seeds, cleanups
|
|
@@ -0,0 +1,88 @@
|
|
|
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 mapproxy.srs import SRS
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def sources(cap):
|
|
23
|
+
sources = {}
|
|
24
|
+
for layer in cap.layers_list():
|
|
25
|
+
name, conf = for_layer(cap, layer)
|
|
26
|
+
sources[name+'_wms'] = conf
|
|
27
|
+
|
|
28
|
+
return sources
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
_checked_srs = {}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def check_srs(srs):
|
|
35
|
+
if srs not in _checked_srs:
|
|
36
|
+
try:
|
|
37
|
+
SRS(srs)
|
|
38
|
+
_checked_srs[srs] = True
|
|
39
|
+
except Exception as ex:
|
|
40
|
+
logging.getLogger(__name__).warning('unable to initialize srs for %s: %s', srs, ex)
|
|
41
|
+
_checked_srs[srs] = False
|
|
42
|
+
|
|
43
|
+
return _checked_srs[srs]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def for_layer(cap, layer):
|
|
47
|
+
source = {'type': 'wms'}
|
|
48
|
+
|
|
49
|
+
req = {
|
|
50
|
+
'url': layer['url'],
|
|
51
|
+
'layers': layer['name'],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if not layer['opaque']:
|
|
55
|
+
req['transparent'] = True
|
|
56
|
+
|
|
57
|
+
wms_opts = {}
|
|
58
|
+
if cap.version != '1.1.1':
|
|
59
|
+
wms_opts['version'] = cap.version
|
|
60
|
+
if layer['queryable']:
|
|
61
|
+
wms_opts['featureinfo'] = True
|
|
62
|
+
if layer['legend']:
|
|
63
|
+
wms_opts['legendurl'] = layer['legend']['url']
|
|
64
|
+
if wms_opts:
|
|
65
|
+
source['wms_opts'] = wms_opts
|
|
66
|
+
|
|
67
|
+
source['req'] = req
|
|
68
|
+
|
|
69
|
+
source['supported_srs'] = []
|
|
70
|
+
for srs in layer['srs']:
|
|
71
|
+
if check_srs(srs):
|
|
72
|
+
source['supported_srs'].append(srs)
|
|
73
|
+
source['supported_srs'].sort()
|
|
74
|
+
|
|
75
|
+
if layer['llbbox']:
|
|
76
|
+
source['coverage'] = {
|
|
77
|
+
'srs': 'EPSG:4326',
|
|
78
|
+
'bbox': layer['llbbox'],
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
res_hint = layer['res_hint']
|
|
82
|
+
if res_hint:
|
|
83
|
+
if res_hint[0]:
|
|
84
|
+
source['min_res'] = res_hint[0]
|
|
85
|
+
if res_hint[1]:
|
|
86
|
+
source['max_res'] = res_hint[1]
|
|
87
|
+
|
|
88
|
+
return layer['name'], source
|
|
@@ -0,0 +1,148 @@
|
|
|
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 mapproxy.client.http import open_url
|
|
18
|
+
from mapproxy.request.base import BaseRequest, url_decode
|
|
19
|
+
from yaml.resolver import Resolver
|
|
20
|
+
from yaml.representer import SafeRepresenter
|
|
21
|
+
from yaml.emitter import Emitter
|
|
22
|
+
from yaml.nodes import ScalarNode, SequenceNode, MappingNode
|
|
23
|
+
from yaml.serializer import Serializer
|
|
24
|
+
from copy import copy
|
|
25
|
+
from urllib.parse import urlparse
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
__all__ = ['update_config', 'MapProxyYAMLDumper']
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def update_config(conf, overwrites):
|
|
32
|
+
wildcard_keys = []
|
|
33
|
+
for k, v in overwrites.items():
|
|
34
|
+
if k == '__all__':
|
|
35
|
+
continue
|
|
36
|
+
if k.startswith('___') or k.endswith('___'):
|
|
37
|
+
wildcard_keys.append(k)
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
if k.endswith('__extend__'):
|
|
41
|
+
k = k[:-len('__extend__')]
|
|
42
|
+
if k not in conf:
|
|
43
|
+
conf[k] = v
|
|
44
|
+
elif isinstance(v, list):
|
|
45
|
+
conf[k].extend(v)
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError('cannot extend non-list:', v)
|
|
48
|
+
elif k not in conf:
|
|
49
|
+
conf[k] = copy(v)
|
|
50
|
+
else:
|
|
51
|
+
if isinstance(conf[k], dict) and isinstance(v, dict):
|
|
52
|
+
conf[k] = update_config(conf[k], v)
|
|
53
|
+
else:
|
|
54
|
+
conf[k] = copy(v)
|
|
55
|
+
|
|
56
|
+
if '__all__' in overwrites:
|
|
57
|
+
v = overwrites['__all__']
|
|
58
|
+
for conf_k, conf_v in conf.items():
|
|
59
|
+
if isinstance(conf_v, dict):
|
|
60
|
+
conf[conf_k] = update_config(conf_v, v)
|
|
61
|
+
else:
|
|
62
|
+
conf[conf_k] = v
|
|
63
|
+
|
|
64
|
+
if wildcard_keys:
|
|
65
|
+
for key in wildcard_keys:
|
|
66
|
+
v = overwrites[key]
|
|
67
|
+
if key.startswith('___'):
|
|
68
|
+
key = key[3:]
|
|
69
|
+
def key_check(x): return x.endswith(key)
|
|
70
|
+
else:
|
|
71
|
+
key = key[:-3]
|
|
72
|
+
def key_check(x): return x.startswith(key)
|
|
73
|
+
for conf_k, conf_v in conf.items():
|
|
74
|
+
if not key_check(conf_k):
|
|
75
|
+
continue
|
|
76
|
+
if isinstance(conf_v, dict):
|
|
77
|
+
conf[conf_k] = update_config(conf_v, v)
|
|
78
|
+
else:
|
|
79
|
+
conf[conf_k] = v
|
|
80
|
+
|
|
81
|
+
return conf
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class _MixedFlowSortedSerializer(Serializer):
|
|
85
|
+
def serialize_node(self, node, parent, index):
|
|
86
|
+
# reset any anchors
|
|
87
|
+
if parent is None:
|
|
88
|
+
for k in self.anchors:
|
|
89
|
+
self.anchors[k] = None
|
|
90
|
+
self.serialized_nodes = {}
|
|
91
|
+
|
|
92
|
+
if isinstance(node, SequenceNode) and all(isinstance(item, ScalarNode) for item in node.value):
|
|
93
|
+
node.flow_style = True
|
|
94
|
+
elif isinstance(node, MappingNode):
|
|
95
|
+
node.value.sort(key=lambda x: x[0].value)
|
|
96
|
+
return Serializer.serialize_node(self, node, parent, index)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class _EmptyNoneRepresenter(SafeRepresenter):
|
|
100
|
+
def represent_none(self, data):
|
|
101
|
+
return self.represent_scalar(u'tag:yaml.org,2002:null',
|
|
102
|
+
u'')
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
_EmptyNoneRepresenter.add_representer(type(None), _EmptyNoneRepresenter.represent_none)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class MapProxyYAMLDumper(Emitter, _MixedFlowSortedSerializer, _EmptyNoneRepresenter, Resolver):
|
|
109
|
+
"""
|
|
110
|
+
YAML dumper that uses block style by default, except for
|
|
111
|
+
node-only sequences. Also sorts dicts by key, prevents `none`
|
|
112
|
+
for empty entries and prevents any anchors.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(self, stream,
|
|
116
|
+
default_style=None, default_flow_style=False,
|
|
117
|
+
canonical=None, indent=None, width=None,
|
|
118
|
+
allow_unicode=None, line_break=None,
|
|
119
|
+
encoding=None, explicit_start=None, explicit_end=None,
|
|
120
|
+
version=None, tags=None, sort_keys=None):
|
|
121
|
+
Emitter.__init__(self, stream, canonical=canonical,
|
|
122
|
+
indent=indent, width=width,
|
|
123
|
+
allow_unicode=allow_unicode, line_break=line_break)
|
|
124
|
+
Serializer.__init__(self, encoding=encoding,
|
|
125
|
+
explicit_start=explicit_start, explicit_end=explicit_end,
|
|
126
|
+
version=version, tags=tags)
|
|
127
|
+
_EmptyNoneRepresenter.__init__(self, default_style=default_style,
|
|
128
|
+
default_flow_style=default_flow_style)
|
|
129
|
+
Resolver.__init__(self)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def wms_capapilities_url(url):
|
|
133
|
+
parsed_url = urlparse(url)
|
|
134
|
+
base_req = BaseRequest(
|
|
135
|
+
url=url.split('?', 1)[0],
|
|
136
|
+
param=url_decode(parsed_url.query),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
base_req.params['service'] = 'WMS'
|
|
140
|
+
if not base_req.params['version']:
|
|
141
|
+
base_req.params['version'] = '1.1.1'
|
|
142
|
+
base_req.params['request'] = 'GetCapabilities'
|
|
143
|
+
return base_req.complete_url
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def download_capabilities(url):
|
|
147
|
+
capabilities_url = wms_capapilities_url(url)
|
|
148
|
+
return open_url(capabilities_url)
|
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
|
|
34
|
+
def defrag_command(args=None):
|
|
35
|
+
parser = optparse.OptionParser("%prog defrag-compact [options] -f mapproxy_conf")
|
|
36
|
+
parser.add_option("-f", "--mapproxy-conf", dest="mapproxy_conf",
|
|
37
|
+
help="MapProxy configuration.")
|
|
38
|
+
|
|
39
|
+
parser.add_option(
|
|
40
|
+
"--min-percent", type=float, default=10.0,
|
|
41
|
+
help="Only defrag if fragmentation is larger (10 means at least 10% of the file does not have to be used)")
|
|
42
|
+
|
|
43
|
+
parser.add_option(
|
|
44
|
+
"--min-mb", type=float, default=1.0,
|
|
45
|
+
help="Only defrag if fragmentation is larger (2 means at least 2MB the file does not have to be used)")
|
|
46
|
+
|
|
47
|
+
parser.add_option("--dry-run", "-n", action="store_true",
|
|
48
|
+
help="Do not de-fragment, only print output")
|
|
49
|
+
|
|
50
|
+
parser.add_option("--caches", dest="cache_names", metavar='cache1,cache2,...',
|
|
51
|
+
help="only defragment the named caches")
|
|
52
|
+
|
|
53
|
+
from mapproxy.script.util import setup_logging
|
|
54
|
+
import logging
|
|
55
|
+
setup_logging(logging.INFO, format="[%(asctime)s] %(msg)s")
|
|
56
|
+
|
|
57
|
+
if args:
|
|
58
|
+
args = args[1:] # remove script name
|
|
59
|
+
|
|
60
|
+
(options, args) = parser.parse_args(args)
|
|
61
|
+
if not options.mapproxy_conf:
|
|
62
|
+
parser.print_help()
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
proxy_configuration = load_configuration(options.mapproxy_conf)
|
|
67
|
+
except IOError as e:
|
|
68
|
+
print('ERROR: ', "%s: '%s'" % (e.strerror, e.filename), file=sys.stderr)
|
|
69
|
+
sys.exit(2)
|
|
70
|
+
except ConfigurationError as e:
|
|
71
|
+
print(e, file=sys.stderr)
|
|
72
|
+
print('ERROR: invalid configuration (see above)', file=sys.stderr)
|
|
73
|
+
sys.exit(2)
|
|
74
|
+
|
|
75
|
+
with local_base_config(proxy_configuration.base_config):
|
|
76
|
+
available_caches = OrderedDict()
|
|
77
|
+
for name, cache_conf in proxy_configuration.caches.items():
|
|
78
|
+
for grid, extent, tile_mgr in cache_conf.caches():
|
|
79
|
+
if isinstance(tile_mgr.cache, (CompactCacheV1, CompactCacheV2)):
|
|
80
|
+
available_caches.setdefault(name, []).append(tile_mgr.cache)
|
|
81
|
+
|
|
82
|
+
if options.cache_names:
|
|
83
|
+
defrag_caches = options.cache_names.split(',')
|
|
84
|
+
missing = set(defrag_caches).difference(available_caches.keys())
|
|
85
|
+
if missing:
|
|
86
|
+
print('unknown caches: %s' % (', '.join(missing), ))
|
|
87
|
+
print('available compact caches: %s' %
|
|
88
|
+
(', '.join(available_caches.keys()), ))
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
else:
|
|
91
|
+
defrag_caches = None
|
|
92
|
+
|
|
93
|
+
for name, caches in available_caches.items():
|
|
94
|
+
if defrag_caches and name not in defrag_caches:
|
|
95
|
+
continue
|
|
96
|
+
for cache in caches:
|
|
97
|
+
logger = DefragLog(name)
|
|
98
|
+
defrag_compact_cache(cache,
|
|
99
|
+
min_percent=options.min_percent/100,
|
|
100
|
+
min_bytes=options.min_mb*1024*1024,
|
|
101
|
+
dry_run=options.dry_run,
|
|
102
|
+
log_progress=logger,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def bundle_offset(fname):
|
|
107
|
+
"""
|
|
108
|
+
>>> bundle_offset("path/to/R0000C0000.bundle")
|
|
109
|
+
(0, 0)
|
|
110
|
+
>>> bundle_offset("path/to/R0380C1380.bundle")
|
|
111
|
+
(4992, 896)
|
|
112
|
+
"""
|
|
113
|
+
match = re.search(r'R([A-F0-9]{4,})C([A-F0-9]{4,}).bundle$', fname, re.IGNORECASE)
|
|
114
|
+
if match:
|
|
115
|
+
r = int(match.group(1), 16)
|
|
116
|
+
c = int(match.group(2), 16)
|
|
117
|
+
return c, r
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class DefragLog(object):
|
|
121
|
+
def __init__(self, cache_name):
|
|
122
|
+
self.cache_name = cache_name
|
|
123
|
+
|
|
124
|
+
def log(self, fname, fragmentation, fragmentation_bytes, num, total, defrag):
|
|
125
|
+
msg = "%s: %3d/%d (%s) fragmentation is %.1f%% (%dkb)" % (
|
|
126
|
+
self.cache_name, num, total, fname, fragmentation, fragmentation_bytes/1024
|
|
127
|
+
)
|
|
128
|
+
if defrag:
|
|
129
|
+
msg += " - defragmenting"
|
|
130
|
+
else:
|
|
131
|
+
msg += " - skipping"
|
|
132
|
+
log.info(msg)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def defrag_compact_cache(cache, min_percent=0.1, min_bytes=1024*1024, log_progress=None, dry_run=False):
|
|
136
|
+
bundles = glob.glob(os.path.join(cache.cache_dir, 'L??', 'R????C????.bundle'))
|
|
137
|
+
|
|
138
|
+
for i, bundle_file in enumerate(bundles):
|
|
139
|
+
offset = bundle_offset(bundle_file)
|
|
140
|
+
b = cache.bundle_class(bundle_file.rstrip('.bundle'), offset)
|
|
141
|
+
size, file_size = b.size()
|
|
142
|
+
|
|
143
|
+
defrag = 1 - float(size) / file_size
|
|
144
|
+
defrag_bytes = file_size - size
|
|
145
|
+
|
|
146
|
+
skip = False
|
|
147
|
+
if defrag < min_percent or defrag_bytes < min_bytes:
|
|
148
|
+
skip = True
|
|
149
|
+
|
|
150
|
+
if log_progress:
|
|
151
|
+
log_progress.log(
|
|
152
|
+
fname=bundle_file,
|
|
153
|
+
fragmentation=defrag * 100,
|
|
154
|
+
fragmentation_bytes=defrag_bytes,
|
|
155
|
+
num=i+1, total=len(bundles),
|
|
156
|
+
defrag=not skip,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if skip or dry_run:
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
tmp_bundle = os.path.join(cache.cache_dir, 'tmp_defrag')
|
|
163
|
+
defb = cache.bundle_class(tmp_bundle, offset)
|
|
164
|
+
stored_tiles = False
|
|
165
|
+
|
|
166
|
+
for y in range(128):
|
|
167
|
+
tiles = [Tile((x, y, 0)) for x in range(128)]
|
|
168
|
+
b.load_tiles(tiles)
|
|
169
|
+
tiles = [t for t in tiles if t.source]
|
|
170
|
+
if tiles:
|
|
171
|
+
stored_tiles = True
|
|
172
|
+
defb.store_tiles(tiles)
|
|
173
|
+
|
|
174
|
+
# remove first
|
|
175
|
+
# - in case bundle is empty
|
|
176
|
+
# - windows does not support rename to existing files
|
|
177
|
+
if os.path.exists(bundle_file):
|
|
178
|
+
os.remove(bundle_file)
|
|
179
|
+
if os.path.exists(bundle_file[:-1] + 'x'):
|
|
180
|
+
os.remove(bundle_file[:-1] + 'x')
|
|
181
|
+
|
|
182
|
+
if stored_tiles:
|
|
183
|
+
os.rename(tmp_bundle + '.bundle', bundle_file)
|
|
184
|
+
if os.path.exists(tmp_bundle + '.bundlx'):
|
|
185
|
+
os.rename(tmp_bundle + '.bundlx', bundle_file[:-1] + 'x')
|
|
186
|
+
if os.path.exists(tmp_bundle + '.lck'):
|
|
187
|
+
os.unlink(tmp_bundle + '.lck')
|