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
mapproxy/cache/path.py
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2010-2016 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
|
+
import os
|
|
17
|
+
from mapproxy.compat import string_type
|
|
18
|
+
from mapproxy.util.fs import ensure_directory
|
|
19
|
+
from mapproxy.request.base import NoCaseMultiDict
|
|
20
|
+
|
|
21
|
+
def location_funcs(layout):
|
|
22
|
+
if layout == 'tc':
|
|
23
|
+
return tile_location_tc, level_location
|
|
24
|
+
elif layout == 'mp':
|
|
25
|
+
return tile_location_mp, level_location
|
|
26
|
+
elif layout == 'tms':
|
|
27
|
+
return tile_location_tms, level_location
|
|
28
|
+
elif layout == 'reverse_tms':
|
|
29
|
+
return tile_location_reverse_tms, None
|
|
30
|
+
elif layout == 'quadkey':
|
|
31
|
+
return tile_location_quadkey, no_level_location
|
|
32
|
+
elif layout == 'arcgis':
|
|
33
|
+
return tile_location_arcgiscache, level_location_arcgiscache
|
|
34
|
+
else:
|
|
35
|
+
raise ValueError('unknown directory_layout "%s"' % layout)
|
|
36
|
+
|
|
37
|
+
def level_location(level, cache_dir, dimensions=None):
|
|
38
|
+
"""
|
|
39
|
+
Return the path where all tiles for `level` will be stored.
|
|
40
|
+
|
|
41
|
+
>>> os.path.abspath(level_location(2, '/tmp/cache')) == os.path.abspath('/tmp/cache/02')
|
|
42
|
+
True
|
|
43
|
+
"""
|
|
44
|
+
dim_path = dimensions_part(dimensions)
|
|
45
|
+
|
|
46
|
+
if isinstance(level, string_type):
|
|
47
|
+
return os.path.join(cache_dir, dim_path, level)
|
|
48
|
+
else:
|
|
49
|
+
return os.path.join(cache_dir, dim_path, "%02d" % level)
|
|
50
|
+
|
|
51
|
+
def dimensions_part(dimensions):
|
|
52
|
+
"""
|
|
53
|
+
Return the subpath where all tiles for `dimensions` will be stored.
|
|
54
|
+
Dimensions prefixed with "dim_" are sorted after the predefined elevation and time dimensions
|
|
55
|
+
>>> dimensions_part({'time': '2020-08-25T00:00:00Z'})
|
|
56
|
+
'time-2020-08-25T00:00:00Z'
|
|
57
|
+
>>> dimensions_part({'time': '2020-08-25T00:00:00Z', 'dim_reference_time': '2020-08-25T00:00:00Z', 'dim_level': '700'})
|
|
58
|
+
'time-2020-08-25T00:00:00Z/dim_level-700/dim_reference_time-2020-08-25T00:00:00Z'
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
if dimensions:
|
|
62
|
+
dims = NoCaseMultiDict(dimensions)
|
|
63
|
+
predefined_dims, custom_dims = [], []
|
|
64
|
+
for dim in dims.keys():
|
|
65
|
+
(custom_dims if dim.startswith('dim_') else predefined_dims).append(dim)
|
|
66
|
+
dim_keys = sorted(predefined_dims) + sorted(custom_dims)
|
|
67
|
+
return os.path.join(*(map(lambda k: k + "-" + str(dims.get(k, 'default')), dim_keys)))
|
|
68
|
+
else:
|
|
69
|
+
return ""
|
|
70
|
+
|
|
71
|
+
def level_part(level):
|
|
72
|
+
"""
|
|
73
|
+
Return the path where all tiles for `level` will be stored.
|
|
74
|
+
|
|
75
|
+
>>> level_part(2)
|
|
76
|
+
'02'
|
|
77
|
+
>>> level_part('2')
|
|
78
|
+
'2'
|
|
79
|
+
"""
|
|
80
|
+
if isinstance(level, string_type):
|
|
81
|
+
return level
|
|
82
|
+
else:
|
|
83
|
+
return "%02d" % level
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def tile_location_tc(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
87
|
+
"""
|
|
88
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
89
|
+
property of the `tile`.
|
|
90
|
+
|
|
91
|
+
:param tile: the tile object
|
|
92
|
+
:param create_dir: if True, create all necessary directories
|
|
93
|
+
:return: the full filename of the tile
|
|
94
|
+
|
|
95
|
+
>>> from mapproxy.cache.tile import Tile
|
|
96
|
+
>>> tile_location_tc(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
97
|
+
'/tmp/cache/02/000/000/003/000/000/004.png'
|
|
98
|
+
"""
|
|
99
|
+
if tile.location is None:
|
|
100
|
+
x, y, z = tile.coord
|
|
101
|
+
|
|
102
|
+
parts = (cache_dir,
|
|
103
|
+
dimensions_part(dimensions),
|
|
104
|
+
level_part(z),
|
|
105
|
+
"%03d" % int(x / 1000000),
|
|
106
|
+
"%03d" % (int(x / 1000) % 1000),
|
|
107
|
+
"%03d" % (int(x) % 1000),
|
|
108
|
+
"%03d" % int(y / 1000000),
|
|
109
|
+
"%03d" % (int(y / 1000) % 1000),
|
|
110
|
+
"%03d.%s" % (int(y) % 1000, file_ext))
|
|
111
|
+
tile.location = os.path.join(*parts)
|
|
112
|
+
if create_dir:
|
|
113
|
+
ensure_directory(tile.location)
|
|
114
|
+
return tile.location
|
|
115
|
+
|
|
116
|
+
def tile_location_mp(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
117
|
+
"""
|
|
118
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
119
|
+
property of the `tile`.
|
|
120
|
+
|
|
121
|
+
:param tile: the tile object
|
|
122
|
+
:param create_dir: if True, create all necessary directories
|
|
123
|
+
:return: the full filename of the tile
|
|
124
|
+
|
|
125
|
+
>>> from mapproxy.cache.tile import Tile
|
|
126
|
+
>>> tile_location_mp(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
127
|
+
'/tmp/cache/02/0000/0003/0000/0004.png'
|
|
128
|
+
>>> tile_location_mp(Tile((12345678, 98765432, 22)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
129
|
+
'/tmp/cache/22/1234/5678/9876/5432.png'
|
|
130
|
+
"""
|
|
131
|
+
if tile.location is None:
|
|
132
|
+
x, y, z = tile.coord
|
|
133
|
+
parts = (cache_dir,
|
|
134
|
+
dimensions_part(dimensions),
|
|
135
|
+
level_part(z),
|
|
136
|
+
"%04d" % int(x / 10000),
|
|
137
|
+
"%04d" % (int(x) % 10000),
|
|
138
|
+
"%04d" % int(y / 10000),
|
|
139
|
+
"%04d.%s" % (int(y) % 10000, file_ext))
|
|
140
|
+
tile.location = os.path.join(*parts)
|
|
141
|
+
if create_dir:
|
|
142
|
+
ensure_directory(tile.location)
|
|
143
|
+
return tile.location
|
|
144
|
+
|
|
145
|
+
def tile_location_tms(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
146
|
+
"""
|
|
147
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
148
|
+
property of the `tile`.
|
|
149
|
+
|
|
150
|
+
:param tile: the tile object
|
|
151
|
+
:param create_dir: if True, create all necessary directories
|
|
152
|
+
:return: the full filename of the tile
|
|
153
|
+
|
|
154
|
+
>>> from mapproxy.cache.tile import Tile
|
|
155
|
+
>>> tile_location_tms(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
156
|
+
'/tmp/cache/2/3/4.png'
|
|
157
|
+
"""
|
|
158
|
+
if tile.location is None:
|
|
159
|
+
x, y, z = tile.coord
|
|
160
|
+
tile.location = os.path.join(
|
|
161
|
+
cache_dir,dimensions_part(dimensions) ,level_part(str(z)),
|
|
162
|
+
str(x), str(y) + '.' + file_ext
|
|
163
|
+
)
|
|
164
|
+
if create_dir:
|
|
165
|
+
ensure_directory(tile.location)
|
|
166
|
+
return tile.location
|
|
167
|
+
|
|
168
|
+
def tile_location_reverse_tms(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
169
|
+
"""
|
|
170
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
171
|
+
property of the `tile`.
|
|
172
|
+
|
|
173
|
+
:param tile: the tile object
|
|
174
|
+
:param create_dir: if True, create all necessary directories
|
|
175
|
+
:return: the full filename of the tile
|
|
176
|
+
|
|
177
|
+
>>> from mapproxy.cache.tile import Tile
|
|
178
|
+
>>> tile_location_reverse_tms(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
179
|
+
'/tmp/cache/4/3/2.png'
|
|
180
|
+
"""
|
|
181
|
+
if tile.location is None:
|
|
182
|
+
x, y, z = tile.coord
|
|
183
|
+
tile.location = os.path.join(
|
|
184
|
+
cache_dir,dimensions_part(dimensions),str(y), str(x), str(z) + '.' + file_ext
|
|
185
|
+
)
|
|
186
|
+
if create_dir:
|
|
187
|
+
ensure_directory(tile.location)
|
|
188
|
+
return tile.location
|
|
189
|
+
|
|
190
|
+
def level_location_tms(level, cache_dir, dimensions=None):
|
|
191
|
+
return level_location(str(level), cache_dir=cache_dir)
|
|
192
|
+
|
|
193
|
+
def tile_location_quadkey(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
194
|
+
"""
|
|
195
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
196
|
+
property of the `tile`.
|
|
197
|
+
|
|
198
|
+
:param tile: the tile object
|
|
199
|
+
:param create_dir: if True, create all necessary directories
|
|
200
|
+
:return: the full filename of the tile
|
|
201
|
+
|
|
202
|
+
>>> from mapproxy.cache.tile import Tile
|
|
203
|
+
>>> tile_location_quadkey(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
204
|
+
'/tmp/cache/11.png'
|
|
205
|
+
"""
|
|
206
|
+
if tile.location is None:
|
|
207
|
+
x, y, z = tile.coord
|
|
208
|
+
quadKey = ""
|
|
209
|
+
for i in range(z,0,-1):
|
|
210
|
+
digit = 0
|
|
211
|
+
mask = 1 << (i-1)
|
|
212
|
+
if (x & mask) != 0:
|
|
213
|
+
digit += 1
|
|
214
|
+
if (y & mask) != 0:
|
|
215
|
+
digit += 2
|
|
216
|
+
quadKey += str(digit)
|
|
217
|
+
tile.location = os.path.join(
|
|
218
|
+
cache_dir, quadKey + '.' + file_ext
|
|
219
|
+
)
|
|
220
|
+
if create_dir:
|
|
221
|
+
ensure_directory(tile.location)
|
|
222
|
+
return tile.location
|
|
223
|
+
|
|
224
|
+
def no_level_location(level, cache_dir, dimensions=None):
|
|
225
|
+
# dummy for quadkey cache which stores all tiles in one directory
|
|
226
|
+
raise NotImplementedError('cache does not have any level location')
|
|
227
|
+
|
|
228
|
+
def tile_location_arcgiscache(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
|
|
229
|
+
"""
|
|
230
|
+
Return the location of the `tile`. Caches the result as ``location``
|
|
231
|
+
property of the `tile`.
|
|
232
|
+
|
|
233
|
+
:param tile: the tile object
|
|
234
|
+
:param create_dir: if True, create all necessary directories
|
|
235
|
+
:return: the full filename of the tile
|
|
236
|
+
|
|
237
|
+
>>> from mapproxy.cache.tile import Tile
|
|
238
|
+
>>> tile_location_arcgiscache(Tile((1234567, 87654321, 9)), '/tmp/cache', 'png').replace('\\\\', '/')
|
|
239
|
+
'/tmp/cache/L09/R05397fb1/C0012d687.png'
|
|
240
|
+
"""
|
|
241
|
+
if tile.location is None:
|
|
242
|
+
x, y, z = tile.coord
|
|
243
|
+
parts = (cache_dir, 'L%02d' % z, 'R%08x' % y, 'C%08x.%s' % (x, file_ext))
|
|
244
|
+
tile.location = os.path.join(*parts)
|
|
245
|
+
if create_dir:
|
|
246
|
+
ensure_directory(tile.location)
|
|
247
|
+
return tile.location
|
|
248
|
+
|
|
249
|
+
def level_location_arcgiscache(z, cache_dir, dimensions=None):
|
|
250
|
+
return level_location('L%02d' % z, cache_dir=cache_dir, dimensions=dimensions)
|
mapproxy/cache/redis.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
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 absolute_import
|
|
17
|
+
|
|
18
|
+
import hashlib
|
|
19
|
+
|
|
20
|
+
from mapproxy.image import ImageSource
|
|
21
|
+
from mapproxy.cache.base import (
|
|
22
|
+
TileCacheBase,
|
|
23
|
+
tile_buffer,
|
|
24
|
+
)
|
|
25
|
+
from mapproxy.compat import BytesIO
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
import redis
|
|
29
|
+
except ImportError:
|
|
30
|
+
redis = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
import logging
|
|
34
|
+
log = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RedisCache(TileCacheBase):
|
|
38
|
+
def __init__(self, host, port, prefix, ttl=0, db=0):
|
|
39
|
+
if redis is None:
|
|
40
|
+
raise ImportError("Redis backend requires 'redis' package.")
|
|
41
|
+
|
|
42
|
+
self.prefix = prefix
|
|
43
|
+
self.lock_cache_id = 'redis-' + hashlib.md5((host + str(port) + prefix + str(db)).encode('utf-8')).hexdigest()
|
|
44
|
+
self.ttl = ttl
|
|
45
|
+
self.r = redis.StrictRedis(host=host, port=port, db=db)
|
|
46
|
+
|
|
47
|
+
def _key(self, tile):
|
|
48
|
+
x, y, z = tile.coord
|
|
49
|
+
return self.prefix + '-%d-%d-%d' % (z, x, y)
|
|
50
|
+
|
|
51
|
+
def is_cached(self, tile, dimensions=None):
|
|
52
|
+
if tile.coord is None or tile.source:
|
|
53
|
+
return True
|
|
54
|
+
|
|
55
|
+
return self.r.exists(self._key(tile))
|
|
56
|
+
|
|
57
|
+
def store_tile(self, tile, dimensions=None):
|
|
58
|
+
if tile.stored:
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
key = self._key(tile)
|
|
62
|
+
|
|
63
|
+
with tile_buffer(tile) as buf:
|
|
64
|
+
data = buf.read()
|
|
65
|
+
|
|
66
|
+
r = self.r.set(key, data)
|
|
67
|
+
if self.ttl:
|
|
68
|
+
# use ms expire times for unit-tests
|
|
69
|
+
self.r.pexpire(key, int(self.ttl * 1000))
|
|
70
|
+
return r
|
|
71
|
+
|
|
72
|
+
def load_tile(self, tile, with_metadata=False, dimensions=None):
|
|
73
|
+
if tile.source or tile.coord is None:
|
|
74
|
+
return True
|
|
75
|
+
key = self._key(tile)
|
|
76
|
+
tile_data = self.r.get(key)
|
|
77
|
+
if tile_data:
|
|
78
|
+
tile.source = ImageSource(BytesIO(tile_data))
|
|
79
|
+
return True
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
def remove_tile(self, tile, dimensions=None):
|
|
83
|
+
if tile.coord is None:
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
key = self._key(tile)
|
|
87
|
+
self.r.delete(key)
|
|
88
|
+
return True
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2012, 2013 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
|
+
import time
|
|
17
|
+
import hashlib
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
import json; json
|
|
21
|
+
except ImportError:
|
|
22
|
+
json = None
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
import requests; requests
|
|
26
|
+
except ImportError:
|
|
27
|
+
requests = None
|
|
28
|
+
|
|
29
|
+
from mapproxy.client.log import log_request
|
|
30
|
+
from mapproxy.cache.tile import TileCreator, Tile
|
|
31
|
+
from mapproxy.source import SourceError
|
|
32
|
+
from mapproxy.util.lock import LockTimeout
|
|
33
|
+
|
|
34
|
+
def has_renderd_support():
|
|
35
|
+
if not json or not requests:
|
|
36
|
+
return False
|
|
37
|
+
return True
|
|
38
|
+
|
|
39
|
+
class RenderdTileCreator(TileCreator):
|
|
40
|
+
def __init__(self, renderd_address, tile_mgr, dimensions=None, priority=100, tile_locker=None):
|
|
41
|
+
TileCreator.__init__(self, tile_mgr, dimensions)
|
|
42
|
+
self.tile_locker = tile_locker.lock or self.tile_mgr.lock
|
|
43
|
+
self.renderd_address = renderd_address
|
|
44
|
+
self.priority = priority
|
|
45
|
+
|
|
46
|
+
def _create_single_tile(self, tile):
|
|
47
|
+
with self.tile_locker(tile):
|
|
48
|
+
if not self.is_cached(tile):
|
|
49
|
+
self._create_renderd_tile(tile.coord)
|
|
50
|
+
self.cache.load_tile(tile)
|
|
51
|
+
return [tile]
|
|
52
|
+
|
|
53
|
+
def _create_meta_tile(self, meta_tile):
|
|
54
|
+
main_tile = Tile(meta_tile.main_tile_coord)
|
|
55
|
+
with self.tile_locker(main_tile):
|
|
56
|
+
if not all(self.is_cached(t) for t in meta_tile.tiles if t is not None):
|
|
57
|
+
self._create_renderd_tile(main_tile.coord)
|
|
58
|
+
|
|
59
|
+
tiles = [Tile(coord) for coord in meta_tile.tiles]
|
|
60
|
+
self.cache.load_tiles(tiles)
|
|
61
|
+
return tiles
|
|
62
|
+
|
|
63
|
+
def _create_renderd_tile(self, tile_coord):
|
|
64
|
+
start_time = time.time()
|
|
65
|
+
result = self._send_tile_request(self.tile_mgr.identifier, [tile_coord])
|
|
66
|
+
duration = time.time()-start_time
|
|
67
|
+
|
|
68
|
+
address = '%s:%s:%r' % (self.renderd_address,
|
|
69
|
+
self.tile_mgr.identifier, tile_coord)
|
|
70
|
+
|
|
71
|
+
if result['status'] == 'error':
|
|
72
|
+
log_request(address, 500, None, duration=duration, method='RENDERD')
|
|
73
|
+
raise SourceError("Error from renderd: %s" % result.get('error_message', 'unknown error from renderd'))
|
|
74
|
+
elif result['status'] == 'lock':
|
|
75
|
+
log_request(address, 503, None, duration=duration, method='RENDERD')
|
|
76
|
+
raise LockTimeout("Lock timeout from renderd: %s" % result.get('error_message', 'unknown lock timeout error from renderd'))
|
|
77
|
+
|
|
78
|
+
log_request(address, 200, None, duration=duration, method='RENDERD')
|
|
79
|
+
|
|
80
|
+
def _send_tile_request(self, cache_identifier, tile_coords):
|
|
81
|
+
identifier = hashlib.sha1(str((cache_identifier, tile_coords)).encode('ascii')).hexdigest()
|
|
82
|
+
message = {
|
|
83
|
+
'command': 'tile',
|
|
84
|
+
'id': identifier,
|
|
85
|
+
'tiles': tile_coords,
|
|
86
|
+
'cache_identifier': cache_identifier,
|
|
87
|
+
'priority': self.priority
|
|
88
|
+
}
|
|
89
|
+
try:
|
|
90
|
+
resp = requests.post(self.renderd_address, data=json.dumps(message))
|
|
91
|
+
return resp.json()
|
|
92
|
+
except ValueError:
|
|
93
|
+
raise SourceError("Error while communicating with renderd: invalid JSON")
|
|
94
|
+
except requests.RequestException as ex:
|
|
95
|
+
raise SourceError("Error while communicating with renderd: %s" % ex)
|
mapproxy/cache/riak.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2013 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 absolute_import
|
|
17
|
+
|
|
18
|
+
import threading
|
|
19
|
+
import hashlib
|
|
20
|
+
|
|
21
|
+
from io import BytesIO
|
|
22
|
+
|
|
23
|
+
from mapproxy.image import ImageSource
|
|
24
|
+
from mapproxy.cache.tile import Tile
|
|
25
|
+
from mapproxy.cache.base import TileCacheBase, tile_buffer, CacheBackendError
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
import riak
|
|
29
|
+
except ImportError:
|
|
30
|
+
riak = None
|
|
31
|
+
except TypeError:
|
|
32
|
+
import warnings
|
|
33
|
+
warnings.warn("riak version not compatible with this Python version")
|
|
34
|
+
riak = None
|
|
35
|
+
|
|
36
|
+
import logging
|
|
37
|
+
log = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
class UnexpectedResponse(CacheBackendError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
class RiakCache(TileCacheBase):
|
|
43
|
+
def __init__(self, nodes, protocol, bucket, tile_grid, use_secondary_index=False, timeout=60):
|
|
44
|
+
if riak is None:
|
|
45
|
+
raise ImportError("Riak backend requires 'riak' package.")
|
|
46
|
+
|
|
47
|
+
self.nodes = nodes
|
|
48
|
+
self.protocol = protocol
|
|
49
|
+
self.lock_cache_id = 'riak-' + hashlib.md5(bucket.encode('utf-8')).hexdigest()
|
|
50
|
+
self.request_timeout = timeout * 1000
|
|
51
|
+
self.bucket_name = bucket
|
|
52
|
+
self.tile_grid = tile_grid
|
|
53
|
+
self.use_secondary_index = use_secondary_index
|
|
54
|
+
self._db_conn_cache = threading.local()
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def connection(self):
|
|
58
|
+
if not getattr(self._db_conn_cache, 'connection', None):
|
|
59
|
+
self._db_conn_cache.connection = riak.RiakClient(protocol=self.protocol, nodes=self.nodes)
|
|
60
|
+
return self._db_conn_cache.connection
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def bucket(self):
|
|
64
|
+
if not getattr(self._db_conn_cache, 'bucket', None):
|
|
65
|
+
self._db_conn_cache.bucket = self.connection.bucket(self.bucket_name)
|
|
66
|
+
return self._db_conn_cache.bucket
|
|
67
|
+
|
|
68
|
+
def _get_object(self, coord):
|
|
69
|
+
(x, y, z) = coord
|
|
70
|
+
key = '%(z)d_%(x)d_%(y)d' % locals()
|
|
71
|
+
obj = False
|
|
72
|
+
try:
|
|
73
|
+
obj = self.bucket.get(key, r=1, timeout=self.request_timeout)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
log.warning('error while requesting %s: %s', key, e)
|
|
76
|
+
|
|
77
|
+
if not obj:
|
|
78
|
+
obj = self.bucket.new(key=key, data=None, content_type='application/octet-stream')
|
|
79
|
+
return obj
|
|
80
|
+
|
|
81
|
+
def _get_timestamp(self, obj):
|
|
82
|
+
metadata = obj.usermeta
|
|
83
|
+
timestamp = metadata.get('timestamp')
|
|
84
|
+
if timestamp != None:
|
|
85
|
+
return float(timestamp)
|
|
86
|
+
|
|
87
|
+
obj.usermeta = {'timestamp': '0'}
|
|
88
|
+
return 0.0
|
|
89
|
+
|
|
90
|
+
def is_cached(self, tile, dimensions=None):
|
|
91
|
+
return self.load_tile(tile, True)
|
|
92
|
+
|
|
93
|
+
def _store_bulk(self, tiles):
|
|
94
|
+
for tile in tiles:
|
|
95
|
+
res = self._get_object(tile.coord)
|
|
96
|
+
with tile_buffer(tile) as buf:
|
|
97
|
+
data = buf.read()
|
|
98
|
+
res.encoded_data = data
|
|
99
|
+
res.usermeta = {
|
|
100
|
+
'timestamp': str(tile.timestamp),
|
|
101
|
+
'size': str(tile.size),
|
|
102
|
+
}
|
|
103
|
+
if self.use_secondary_index:
|
|
104
|
+
x, y, z = tile.coord
|
|
105
|
+
res.add_index('tile_coord_bin', '%02d-%07d-%07d' % (z, x, y))
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
res.store(w=1, dw=1, pw=1, return_body=False, timeout=self.request_timeout)
|
|
109
|
+
except riak.RiakError as ex:
|
|
110
|
+
log.warning('unable to store tile: %s', ex)
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
return True
|
|
114
|
+
|
|
115
|
+
def store_tile(self, tile,dimensions=None):
|
|
116
|
+
if tile.stored:
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
return self._store_bulk([tile])
|
|
120
|
+
|
|
121
|
+
def store_tiles(self, tiles,dimensions=None):
|
|
122
|
+
tiles = [t for t in tiles if not t.stored]
|
|
123
|
+
return self._store_bulk(tiles)
|
|
124
|
+
|
|
125
|
+
def load_tile_metadata(self, tile,dimensions=None):
|
|
126
|
+
if tile.timestamp:
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
# is_cached loads metadata
|
|
130
|
+
self.load_tile(tile, True)
|
|
131
|
+
|
|
132
|
+
def load_tile(self, tile, with_metadata=False, dimensions=None):
|
|
133
|
+
if tile.timestamp is None:
|
|
134
|
+
tile.timestamp = 0
|
|
135
|
+
if tile.source or tile.coord is None:
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
res = self._get_object(tile.coord)
|
|
139
|
+
if res.exists:
|
|
140
|
+
tile_data = BytesIO(res.encoded_data)
|
|
141
|
+
tile.source = ImageSource(tile_data)
|
|
142
|
+
if with_metadata:
|
|
143
|
+
tile.timestamp = self._get_timestamp(res)
|
|
144
|
+
tile.size = len(res.encoded_data)
|
|
145
|
+
return True
|
|
146
|
+
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
def remove_tile(self, tile):
|
|
150
|
+
if tile.coord is None:
|
|
151
|
+
return True
|
|
152
|
+
|
|
153
|
+
res = self._get_object(tile.coord)
|
|
154
|
+
if not res.exists:
|
|
155
|
+
# already removed
|
|
156
|
+
return True
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
res.delete(w=1, r=1, dw=1, pw=1, timeout=self.request_timeout)
|
|
160
|
+
except riak.RiakError as ex:
|
|
161
|
+
log.warning('unable to remove tile: %s', ex)
|
|
162
|
+
return False
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
def _fill_metadata_from_obj(self, obj, tile):
|
|
166
|
+
tile_md = obj.usermeta
|
|
167
|
+
timestamp = tile_md.get('timestamp')
|
|
168
|
+
if timestamp:
|
|
169
|
+
tile.timestamp = float(timestamp)
|
|
170
|
+
|
|
171
|
+
def _key_iterator(self, level):
|
|
172
|
+
"""
|
|
173
|
+
Generator for all tile keys in `level`.
|
|
174
|
+
"""
|
|
175
|
+
# index() returns a list of all keys so we check for tiles in
|
|
176
|
+
# batches of `chunk_size`*`chunk_size`.
|
|
177
|
+
grid_size = self.tile_grid.grid_sizes[level]
|
|
178
|
+
chunk_size = 256
|
|
179
|
+
for x in range(grid_size[0]/chunk_size):
|
|
180
|
+
start_x = x * chunk_size
|
|
181
|
+
end_x = start_x + chunk_size - 1
|
|
182
|
+
for y in range(grid_size[1]/chunk_size):
|
|
183
|
+
start_y = y * chunk_size
|
|
184
|
+
end_y = start_y + chunk_size - 1
|
|
185
|
+
query = self.bucket.get_index('tile_coord_bin',
|
|
186
|
+
'%02d-%07d-%07d' % (level, start_x, start_y),
|
|
187
|
+
'%02d-%07d-%07d' % (level, end_x, end_y))
|
|
188
|
+
for link in query.run():
|
|
189
|
+
yield link.get_key()
|
|
190
|
+
|
|
191
|
+
def remove_tiles_for_level(self, level, before_timestamp=None):
|
|
192
|
+
bucket = self.bucket
|
|
193
|
+
client = self.connection
|
|
194
|
+
for key in self._key_iterator(level):
|
|
195
|
+
if before_timestamp:
|
|
196
|
+
obj = self.bucket.get(key, r=1)
|
|
197
|
+
dummy_tile = Tile((0, 0, 0))
|
|
198
|
+
self._fill_metadata_from_obj(obj, dummy_tile)
|
|
199
|
+
if dummy_tile.timestamp < before_timestamp:
|
|
200
|
+
obj.delete()
|
|
201
|
+
else:
|
|
202
|
+
riak.RiakObject(client, bucket, key).delete()
|