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,97 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2022 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
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from mapproxy.cache.azureblob import AzureBlobCache
|
|
22
|
+
except ImportError:
|
|
23
|
+
AzureBlobCache = None
|
|
24
|
+
|
|
25
|
+
from mapproxy.test.unit.test_cache_tile import TileCacheTestBase
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.skipif(not AzureBlobCache or not os.environ.get('MAPPROXY_TEST_AZURE_BLOB'),
|
|
29
|
+
reason="azure-storage-blob package and MAPPROXY_TEST_AZURE_BLOB env required")
|
|
30
|
+
class TestAzureBlobCache(TileCacheTestBase):
|
|
31
|
+
always_loads_metadata = True
|
|
32
|
+
uses_utc = True
|
|
33
|
+
|
|
34
|
+
def setup_method(self):
|
|
35
|
+
TileCacheTestBase.setup_method(self)
|
|
36
|
+
|
|
37
|
+
self.container = 'mapproxy-azure-unit-test'
|
|
38
|
+
self.base_path = '/mycache/webmercator'
|
|
39
|
+
self.file_ext = 'png'
|
|
40
|
+
|
|
41
|
+
# Use default storage account of Azurite emulator
|
|
42
|
+
self.host = os.environ['MAPPROXY_TEST_AZURE_BLOB']
|
|
43
|
+
self.connection_string = 'DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=' \
|
|
44
|
+
'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr' \
|
|
45
|
+
'/KBHBeksoGMGw==;BlobEndpoint=' + self.host + '/devstoreaccount1;'
|
|
46
|
+
|
|
47
|
+
self.cache = AzureBlobCache(
|
|
48
|
+
base_path=self.base_path,
|
|
49
|
+
file_ext=self.file_ext,
|
|
50
|
+
container_name=self.container,
|
|
51
|
+
connection_string=self.connection_string,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
self.container_client = self.cache.container_client
|
|
55
|
+
self.container_client.create_container()
|
|
56
|
+
|
|
57
|
+
def teardown_method(self):
|
|
58
|
+
TileCacheTestBase.teardown_method(self)
|
|
59
|
+
self.container_client.delete_container()
|
|
60
|
+
|
|
61
|
+
def test_default_coverage(self):
|
|
62
|
+
assert self.cache.coverage is None
|
|
63
|
+
|
|
64
|
+
@pytest.mark.parametrize('layout,tile_coord,key', [
|
|
65
|
+
['mp', (12345, 67890, 2), 'mycache/webmercator/02/0001/2345/0006/7890.png'],
|
|
66
|
+
['mp', (12345, 67890, 12), 'mycache/webmercator/12/0001/2345/0006/7890.png'],
|
|
67
|
+
|
|
68
|
+
['tc', (12345, 67890, 2), 'mycache/webmercator/02/000/012/345/000/067/890.png'],
|
|
69
|
+
['tc', (12345, 67890, 12), 'mycache/webmercator/12/000/012/345/000/067/890.png'],
|
|
70
|
+
|
|
71
|
+
['tms', (12345, 67890, 2), 'mycache/webmercator/2/12345/67890.png'],
|
|
72
|
+
['tms', (12345, 67890, 12), 'mycache/webmercator/12/12345/67890.png'],
|
|
73
|
+
|
|
74
|
+
['reverse_tms', (12345, 67890, 2), 'mycache/webmercator/67890/12345/2.png'],
|
|
75
|
+
['reverse_tms', (12345, 67890, 12), 'mycache/webmercator/67890/12345/12.png'],
|
|
76
|
+
|
|
77
|
+
['quadkey', (0, 0, 0), 'mycache/webmercator/.png'],
|
|
78
|
+
['quadkey', (0, 0, 1), 'mycache/webmercator/0.png'],
|
|
79
|
+
['quadkey', (1, 1, 1), 'mycache/webmercator/3.png'],
|
|
80
|
+
['quadkey', (12345, 67890, 12), 'mycache/webmercator/200200331021.png'],
|
|
81
|
+
|
|
82
|
+
['arcgis', (1, 2, 3), 'mycache/webmercator/L03/R00000002/C00000001.png'],
|
|
83
|
+
['arcgis', (9, 2, 3), 'mycache/webmercator/L03/R00000002/C00000009.png'],
|
|
84
|
+
['arcgis', (10, 2, 3), 'mycache/webmercator/L03/R00000002/C0000000a.png'],
|
|
85
|
+
['arcgis', (12345, 67890, 12), 'mycache/webmercator/L12/R00010932/C00003039.png'],
|
|
86
|
+
])
|
|
87
|
+
def test_tile_key(self, layout, tile_coord, key):
|
|
88
|
+
cache = AzureBlobCache(
|
|
89
|
+
base_path=self.base_path,
|
|
90
|
+
file_ext=self.file_ext,
|
|
91
|
+
container_name=self.container,
|
|
92
|
+
connection_string=self.connection_string,
|
|
93
|
+
directory_layout=layout
|
|
94
|
+
)
|
|
95
|
+
cache.store_tile(self.create_tile(tile_coord))
|
|
96
|
+
|
|
97
|
+
assert self.container_client.get_blob_client(key).exists()
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 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
|
+
from __future__ import division
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import time
|
|
20
|
+
import struct
|
|
21
|
+
import shutil
|
|
22
|
+
import tempfile
|
|
23
|
+
|
|
24
|
+
from io import BytesIO
|
|
25
|
+
|
|
26
|
+
from mapproxy.cache.compact import CompactCacheV1, CompactCacheV2
|
|
27
|
+
from mapproxy.cache.tile import Tile
|
|
28
|
+
from mapproxy.image import ImageSource
|
|
29
|
+
from mapproxy.image.opts import ImageOptions
|
|
30
|
+
from mapproxy.script.defrag import defrag_compact_cache
|
|
31
|
+
from mapproxy.test.unit.test_cache_tile import TileCacheTestBase
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestCompactCacheV1(TileCacheTestBase):
|
|
35
|
+
|
|
36
|
+
always_loads_metadata = True
|
|
37
|
+
|
|
38
|
+
def setup_method(self):
|
|
39
|
+
TileCacheTestBase.setup_method(self)
|
|
40
|
+
self.cache = CompactCacheV1(
|
|
41
|
+
cache_dir=self.cache_dir,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def test_default_coverage(self):
|
|
45
|
+
assert self.cache.coverage is None
|
|
46
|
+
|
|
47
|
+
def test_bundle_files(self):
|
|
48
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
49
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
|
|
50
|
+
self.cache.store_tile(self.create_tile(coord=(0, 0, 0)))
|
|
51
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
52
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
|
|
53
|
+
|
|
54
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
55
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
|
|
56
|
+
self.cache.store_tile(self.create_tile(coord=(127, 127, 12)))
|
|
57
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
58
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
|
|
59
|
+
|
|
60
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
|
|
61
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundlx'))
|
|
62
|
+
self.cache.store_tile(self.create_tile(coord=(128, 256, 12)))
|
|
63
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
|
|
64
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundlx'))
|
|
65
|
+
|
|
66
|
+
def test_bundle_files_not_created_on_is_cached(self):
|
|
67
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
68
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
|
|
69
|
+
self.cache.is_cached(Tile(coord=(0, 0, 0)))
|
|
70
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
71
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
|
|
72
|
+
|
|
73
|
+
def test_missing_tiles(self):
|
|
74
|
+
self.cache.store_tile(self.create_tile(coord=(130, 200, 8)))
|
|
75
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundle'))
|
|
76
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundlx'))
|
|
77
|
+
|
|
78
|
+
# test that all other tiles in this bundle are missing
|
|
79
|
+
assert self.cache.is_cached(Tile((130, 200, 8)))
|
|
80
|
+
for x in range(128, 255):
|
|
81
|
+
for y in range(128, 255):
|
|
82
|
+
if x == 130 and y == 200:
|
|
83
|
+
continue
|
|
84
|
+
assert not self.cache.is_cached(Tile((x, y, 8))), (x, y)
|
|
85
|
+
assert not self.cache.load_tile(Tile((x, y, 8))), (x, y)
|
|
86
|
+
|
|
87
|
+
def test_remove_level_tiles_before(self):
|
|
88
|
+
self.cache.store_tile(self.create_tile(coord=(0, 0, 12)))
|
|
89
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
90
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
|
|
91
|
+
|
|
92
|
+
# not removed with timestamp
|
|
93
|
+
self.cache.remove_level_tiles_before(12, time.time())
|
|
94
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
95
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
|
|
96
|
+
|
|
97
|
+
# removed with timestamp=0 (remove_all:true in seed.yaml)
|
|
98
|
+
self.cache.remove_level_tiles_before(12, 0)
|
|
99
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12'))
|
|
100
|
+
|
|
101
|
+
def test_bundle_header(self):
|
|
102
|
+
t = Tile((5000, 1000, 12), ImageSource(BytesIO(b'a' * 4000), image_opts=ImageOptions(format='image/png')))
|
|
103
|
+
self.cache.store_tile(t)
|
|
104
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'))
|
|
105
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundlx'))
|
|
106
|
+
|
|
107
|
+
def assert_header(tile_bytes_written, max_tile_bytes):
|
|
108
|
+
with open(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'), 'r+b') as f:
|
|
109
|
+
header = struct.unpack('<lllllllllllllll', f.read(60))
|
|
110
|
+
assert header[11] == 896
|
|
111
|
+
assert header[12] == 1023
|
|
112
|
+
assert header[13] == 4992
|
|
113
|
+
assert header[14] == 5119
|
|
114
|
+
assert header[6] == 60 + 128*128*4 + sum(tile_bytes_written)
|
|
115
|
+
assert header[2] == max_tile_bytes
|
|
116
|
+
assert header[4] == len(tile_bytes_written)*4
|
|
117
|
+
|
|
118
|
+
assert_header([4000 + 4], 4000)
|
|
119
|
+
|
|
120
|
+
t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 6000), image_opts=ImageOptions(format='image/png')))
|
|
121
|
+
self.cache.store_tile(t)
|
|
122
|
+
assert_header([4000 + 4, 6000 + 4], 6000)
|
|
123
|
+
|
|
124
|
+
t = Tile((4992, 999, 12), ImageSource(BytesIO(b'a' * 1000), image_opts=ImageOptions(format='image/png')))
|
|
125
|
+
self.cache.store_tile(t)
|
|
126
|
+
assert_header([4000 + 4, 6000 + 4, 1000 + 4], 6000)
|
|
127
|
+
|
|
128
|
+
t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 3000), image_opts=ImageOptions(format='image/png')))
|
|
129
|
+
self.cache.store_tile(t)
|
|
130
|
+
assert_header([4000 + 4, 6000 + 4 + 3000 + 4, 1000 + 4], 6000) # still contains bytes from overwritten tile
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class TestCompactCacheV2(TileCacheTestBase):
|
|
134
|
+
|
|
135
|
+
always_loads_metadata = True
|
|
136
|
+
|
|
137
|
+
def setup_method(self):
|
|
138
|
+
TileCacheTestBase.setup_method(self)
|
|
139
|
+
self.cache = CompactCacheV2(
|
|
140
|
+
cache_dir=self.cache_dir,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def test_default_coverage(self):
|
|
144
|
+
assert self.cache.coverage is None
|
|
145
|
+
|
|
146
|
+
def test_bundle_files(self):
|
|
147
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
148
|
+
self.cache.store_tile(self.create_tile(coord=(0, 0, 0)))
|
|
149
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
150
|
+
|
|
151
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
152
|
+
self.cache.store_tile(self.create_tile(coord=(127, 127, 12)))
|
|
153
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
154
|
+
|
|
155
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
|
|
156
|
+
self.cache.store_tile(self.create_tile(coord=(128, 256, 12)))
|
|
157
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
|
|
158
|
+
|
|
159
|
+
def test_bundle_files_not_created_on_is_cached(self):
|
|
160
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
161
|
+
self.cache.is_cached(Tile(coord=(0, 0, 0)))
|
|
162
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
|
|
163
|
+
|
|
164
|
+
def test_missing_tiles(self):
|
|
165
|
+
self.cache.store_tile(self.create_tile(coord=(130, 200, 8)))
|
|
166
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundle'))
|
|
167
|
+
|
|
168
|
+
# test that all other tiles in this bundle are missing
|
|
169
|
+
assert self.cache.is_cached(Tile((130, 200, 8)))
|
|
170
|
+
for x in range(128, 255):
|
|
171
|
+
for y in range(128, 255):
|
|
172
|
+
if x == 130 and y == 200:
|
|
173
|
+
continue
|
|
174
|
+
assert not self.cache.is_cached(Tile((x, y, 8))), (x, y)
|
|
175
|
+
assert not self.cache.load_tile(Tile((x, y, 8))), (x, y)
|
|
176
|
+
|
|
177
|
+
def test_remove_level_tiles_before(self):
|
|
178
|
+
self.cache.store_tile(self.create_tile(coord=(0, 0, 12)))
|
|
179
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
180
|
+
|
|
181
|
+
# not removed with timestamp
|
|
182
|
+
self.cache.remove_level_tiles_before(12, time.time())
|
|
183
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
|
|
184
|
+
|
|
185
|
+
# removed with timestamp=0 (remove_all:true in seed.yaml)
|
|
186
|
+
self.cache.remove_level_tiles_before(12, 0)
|
|
187
|
+
assert not os.path.exists(os.path.join(self.cache_dir, 'L12'))
|
|
188
|
+
|
|
189
|
+
def test_bundle_header(self):
|
|
190
|
+
t = Tile((5000, 1000, 12), ImageSource(BytesIO(b'a' * 4000), image_opts=ImageOptions(format='image/png')))
|
|
191
|
+
self.cache.store_tile(t)
|
|
192
|
+
assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'))
|
|
193
|
+
|
|
194
|
+
def assert_header(tile_bytes_written, max_tile_bytes):
|
|
195
|
+
with open(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'), 'r+b') as f:
|
|
196
|
+
header = struct.unpack('<4I3Q6I', f.read(64))
|
|
197
|
+
assert header[0] == 3 # version
|
|
198
|
+
assert header[1] == 128*128
|
|
199
|
+
assert header[2] == max_tile_bytes
|
|
200
|
+
assert header[5] == 64 + 128*128*8 + sum(tile_bytes_written)
|
|
201
|
+
|
|
202
|
+
assert_header([4000 + 4], 4000)
|
|
203
|
+
|
|
204
|
+
t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 6000), image_opts=ImageOptions(format='image/png')))
|
|
205
|
+
self.cache.store_tile(t)
|
|
206
|
+
assert_header([4000 + 4, 6000 + 4], 6000)
|
|
207
|
+
|
|
208
|
+
t = Tile((4992, 999, 12), ImageSource(BytesIO(b'a' * 1000), image_opts=ImageOptions(format='image/png')))
|
|
209
|
+
self.cache.store_tile(t)
|
|
210
|
+
assert_header([4000 + 4, 6000 + 4, 1000 + 4], 6000)
|
|
211
|
+
|
|
212
|
+
t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 3000), image_opts=ImageOptions(format='image/png')))
|
|
213
|
+
self.cache.store_tile(t)
|
|
214
|
+
assert_header([4000 + 4, 6000 + 4 + 3000 + 4, 1000 + 4], 6000) # still contains bytes from overwritten tile
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class mockProgressLog(object):
|
|
218
|
+
def __init__(self):
|
|
219
|
+
self.logs = []
|
|
220
|
+
|
|
221
|
+
def log(self, fname, fragmentation, fragmentation_bytes, num, total, defrag):
|
|
222
|
+
self.logs.append({
|
|
223
|
+
'fname': fname,
|
|
224
|
+
'fragmentation': fragmentation,
|
|
225
|
+
'fragmentation_bytes': fragmentation_bytes,
|
|
226
|
+
'num': num,
|
|
227
|
+
'total': total,
|
|
228
|
+
'defrag': defrag,
|
|
229
|
+
})
|
|
230
|
+
self.logs.sort(key=lambda x: (x['fname'], 'num'))
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class DefragmentationTestBase(object):
|
|
234
|
+
def setup_method(self):
|
|
235
|
+
self.cache_dir = tempfile.mkdtemp()
|
|
236
|
+
|
|
237
|
+
def teardown_method(self):
|
|
238
|
+
if os.path.exists(self.cache_dir):
|
|
239
|
+
shutil.rmtree(self.cache_dir)
|
|
240
|
+
|
|
241
|
+
def test_defragmentation_empty_bundle(self):
|
|
242
|
+
cache = self.cache_class(self.cache_dir)
|
|
243
|
+
|
|
244
|
+
t = Tile((5000, 1000, 12),
|
|
245
|
+
ImageSource(BytesIO(b'a' * 60*1024), image_opts=ImageOptions(format='image/png')))
|
|
246
|
+
cache.store_tile(t)
|
|
247
|
+
cache.remove_tile(t)
|
|
248
|
+
|
|
249
|
+
fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
|
|
250
|
+
assert os.path.exists(fname)
|
|
251
|
+
|
|
252
|
+
logger = mockProgressLog()
|
|
253
|
+
defrag_compact_cache(cache, min_bytes=50000, log_progress=logger)
|
|
254
|
+
|
|
255
|
+
assert not os.path.exists(fname)
|
|
256
|
+
|
|
257
|
+
def test_defragmentation_min_bytes(self):
|
|
258
|
+
cache = self.cache_class(self.cache_dir)
|
|
259
|
+
|
|
260
|
+
for _ in range(2):
|
|
261
|
+
t = Tile((5000, 1000, 12),
|
|
262
|
+
ImageSource(BytesIO(b'a' * 60*1024), image_opts=ImageOptions(format='image/png')))
|
|
263
|
+
cache.store_tile(t)
|
|
264
|
+
|
|
265
|
+
logger = mockProgressLog()
|
|
266
|
+
fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
|
|
267
|
+
before = os.path.getsize(fname)
|
|
268
|
+
defrag_compact_cache(cache, log_progress=logger)
|
|
269
|
+
assert len(logger.logs) == 1
|
|
270
|
+
assert logger.logs[0]['defrag'] is False
|
|
271
|
+
after = os.path.getsize(fname)
|
|
272
|
+
assert before == after
|
|
273
|
+
|
|
274
|
+
logger = mockProgressLog()
|
|
275
|
+
before = os.path.getsize(fname)
|
|
276
|
+
defrag_compact_cache(cache, min_bytes=50000, log_progress=logger)
|
|
277
|
+
assert len(logger.logs) == 1
|
|
278
|
+
assert logger.logs[0]['defrag'] is True
|
|
279
|
+
after = os.path.getsize(fname)
|
|
280
|
+
assert after < before
|
|
281
|
+
|
|
282
|
+
def test_defragmentation_min_percent(self):
|
|
283
|
+
cache = self.cache_class(self.cache_dir)
|
|
284
|
+
|
|
285
|
+
t = Tile((10000, 2000, 13),
|
|
286
|
+
ImageSource(
|
|
287
|
+
BytesIO(b'a' * 120 * 1024),
|
|
288
|
+
image_opts=ImageOptions(format='image/png')))
|
|
289
|
+
cache.store_tile(t)
|
|
290
|
+
|
|
291
|
+
for x in range(100):
|
|
292
|
+
for _ in range(2 if x < 10 else 1):
|
|
293
|
+
t = Tile((5000+x, 1000, 12),
|
|
294
|
+
ImageSource(
|
|
295
|
+
BytesIO(b'a' * 120 * 1024),
|
|
296
|
+
image_opts=ImageOptions(format='image/png')))
|
|
297
|
+
cache.store_tile(t)
|
|
298
|
+
|
|
299
|
+
logger = mockProgressLog()
|
|
300
|
+
fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
|
|
301
|
+
before = os.path.getsize(fname)
|
|
302
|
+
defrag_compact_cache(cache, log_progress=logger)
|
|
303
|
+
assert len(logger.logs) == 2
|
|
304
|
+
assert logger.logs[0]['defrag'] is False
|
|
305
|
+
assert logger.logs[1]['defrag'] is False
|
|
306
|
+
after = os.path.getsize(fname)
|
|
307
|
+
assert before == after
|
|
308
|
+
|
|
309
|
+
logger = mockProgressLog()
|
|
310
|
+
before = os.path.getsize(fname)
|
|
311
|
+
defrag_compact_cache(cache, min_percent=0.08, log_progress=logger)
|
|
312
|
+
assert len(logger.logs) == 2
|
|
313
|
+
assert logger.logs[0]['defrag'] is True
|
|
314
|
+
assert logger.logs[1]['defrag'] is False
|
|
315
|
+
after = os.path.getsize(fname)
|
|
316
|
+
assert after < before
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
class TestDefragmentationV1(DefragmentationTestBase):
|
|
320
|
+
cache_class = CompactCacheV1
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class TestDefragmentationV2(DefragmentationTestBase):
|
|
324
|
+
cache_class = CompactCacheV2
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2011 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
|
+
import random
|
|
18
|
+
import re
|
|
19
|
+
import time
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
22
|
+
|
|
23
|
+
from mapproxy.cache.couchdb import CouchDBCache, CouchDBMDTemplate
|
|
24
|
+
from mapproxy.cache.tile import Tile
|
|
25
|
+
from mapproxy.grid import tile_grid
|
|
26
|
+
from mapproxy.test.image import create_tmp_image_buf
|
|
27
|
+
from mapproxy.test.unit.test_cache_tile import TileCacheTestBase
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
tile_image = create_tmp_image_buf((256, 256), color='blue')
|
|
31
|
+
tile_image2 = create_tmp_image_buf((256, 256), color='red')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@pytest.mark.skipif('MAPPROXY_TEST_COUCHDB' not in os.environ,
|
|
35
|
+
reason="MAPPROXY_TEST_COUCHDB not set")
|
|
36
|
+
class TestCouchDBCache(TileCacheTestBase):
|
|
37
|
+
always_loads_metadata = True
|
|
38
|
+
|
|
39
|
+
def setup_method(self):
|
|
40
|
+
couch_address = os.environ['MAPPROXY_TEST_COUCHDB']
|
|
41
|
+
db_name = 'mapproxy_test_%d' % random.randint(0, 100000)
|
|
42
|
+
|
|
43
|
+
TileCacheTestBase.setup_method(self)
|
|
44
|
+
|
|
45
|
+
md_template = CouchDBMDTemplate({
|
|
46
|
+
'row': '{{y}}', 'tile_column': '{{x}}',
|
|
47
|
+
'zoom': '{{level}}', 'time': '{{timestamp}}', 'coord': '{{wgs_tile_centroid}}'})
|
|
48
|
+
self.cache = CouchDBCache(couch_address, db_name,
|
|
49
|
+
file_ext='png', tile_grid=tile_grid(3857, name='global-webmarcator'),
|
|
50
|
+
md_template=md_template)
|
|
51
|
+
|
|
52
|
+
def teardown_method(self):
|
|
53
|
+
import requests
|
|
54
|
+
requests.delete(self.cache.couch_url)
|
|
55
|
+
TileCacheTestBase.teardown_method(self)
|
|
56
|
+
|
|
57
|
+
def test_default_coverage(self):
|
|
58
|
+
assert self.cache.coverage is None
|
|
59
|
+
|
|
60
|
+
def test_store_bulk_with_overwrite(self):
|
|
61
|
+
tile = self.create_tile((0, 0, 4))
|
|
62
|
+
self.create_cached_tile(tile)
|
|
63
|
+
|
|
64
|
+
assert self.cache.is_cached(Tile((0, 0, 4)))
|
|
65
|
+
loaded_tile = Tile((0, 0, 4))
|
|
66
|
+
assert self.cache.load_tile(loaded_tile)
|
|
67
|
+
assert loaded_tile.source_buffer().read() == tile.source_buffer().read()
|
|
68
|
+
|
|
69
|
+
assert not self.cache.is_cached(Tile((1, 0, 4)))
|
|
70
|
+
|
|
71
|
+
tiles = [self.create_another_tile((x, 0, 4)) for x in range(2)]
|
|
72
|
+
assert self.cache.store_tiles(tiles)
|
|
73
|
+
|
|
74
|
+
assert self.cache.is_cached(Tile((0, 0, 4)))
|
|
75
|
+
loaded_tile = Tile((0, 0, 4))
|
|
76
|
+
assert self.cache.load_tile(loaded_tile)
|
|
77
|
+
# check that tile is overwritten
|
|
78
|
+
assert loaded_tile.source_buffer().read() != tile.source_buffer().read()
|
|
79
|
+
assert loaded_tile.source_buffer().read() == tiles[0].source_buffer().read()
|
|
80
|
+
|
|
81
|
+
def test_double_remove(self):
|
|
82
|
+
tile = self.create_tile()
|
|
83
|
+
self.create_cached_tile(tile)
|
|
84
|
+
assert self.cache.remove_tile(tile)
|
|
85
|
+
assert self.cache.remove_tile(tile)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TestCouchDBMDTemplate(object):
|
|
89
|
+
def test_empty(self):
|
|
90
|
+
template = CouchDBMDTemplate({})
|
|
91
|
+
doc = template.doc(Tile((0, 0, 1)), tile_grid(4326))
|
|
92
|
+
|
|
93
|
+
assert doc['timestamp'] == pytest.approx(time.time(), 0.1)
|
|
94
|
+
|
|
95
|
+
def test_fixed_values(self):
|
|
96
|
+
template = CouchDBMDTemplate({'hello': 'world', 'foo': 123})
|
|
97
|
+
doc = template.doc(Tile((0, 0, 1)), tile_grid(4326))
|
|
98
|
+
|
|
99
|
+
assert doc['timestamp'] == pytest.approx(time.time(), 0.1)
|
|
100
|
+
assert doc['hello'] == 'world'
|
|
101
|
+
assert doc['foo'] == 123
|
|
102
|
+
|
|
103
|
+
def test_template_values(self):
|
|
104
|
+
template = CouchDBMDTemplate({'row': '{{y}}', 'tile_column': '{{x}}',
|
|
105
|
+
'zoom': '{{level}}', 'time': '{{timestamp}}', 'coord': '{{wgs_tile_centroid}}',
|
|
106
|
+
'datetime': '{{utc_iso}}', 'coord_webmerc': '{{tile_centroid}}'})
|
|
107
|
+
doc = template.doc(Tile((1, 0, 2)), tile_grid(3857))
|
|
108
|
+
|
|
109
|
+
assert doc['time'] == pytest.approx(time.time(), 0.1)
|
|
110
|
+
assert 'timestamp' not in doc
|
|
111
|
+
assert doc['row'] == 0
|
|
112
|
+
assert doc['tile_column'] == 1
|
|
113
|
+
assert doc['zoom'] == 2
|
|
114
|
+
assert doc['coord'][0] == pytest.approx(-45.0)
|
|
115
|
+
assert doc['coord'][1] == pytest.approx(-79.17133464081945)
|
|
116
|
+
assert doc['coord_webmerc'][0] == pytest.approx(-5009377.085697311)
|
|
117
|
+
assert doc['coord_webmerc'][1] == pytest.approx(-15028131.25709193)
|
|
118
|
+
assert re.match(r'20\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ', doc['datetime']), doc['datetime']
|