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,181 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Copyright (C) 2012 Omniscale <http://omniscale.de>
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from mapproxy.compat.image import Image, ImageDraw
|
|
17
|
+
from mapproxy.image import ImageSource
|
|
18
|
+
from mapproxy.image.mask import mask_image_source_from_coverage
|
|
19
|
+
from mapproxy.image.merge import LayerMerger
|
|
20
|
+
from mapproxy.image.opts import ImageOptions
|
|
21
|
+
from mapproxy.srs import SRS
|
|
22
|
+
from mapproxy.test.image import assert_img_colors_eq, create_image
|
|
23
|
+
from mapproxy.util.coverage import load_limited_to
|
|
24
|
+
|
|
25
|
+
import pytest
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
from shapely.geometry import Polygon
|
|
29
|
+
|
|
30
|
+
geom_support = True
|
|
31
|
+
except ImportError:
|
|
32
|
+
geom_support = False
|
|
33
|
+
|
|
34
|
+
pytestmark = pytest.mark.skipif(not geom_support, reason="requires shapely")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def coverage(geom, srs="EPSG:4326"):
|
|
38
|
+
return load_limited_to({"srs": srs, "geometry": geom})
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestMaskImage(object):
|
|
42
|
+
|
|
43
|
+
def test_mask_outside_of_image_transparent(self):
|
|
44
|
+
img = ImageSource(
|
|
45
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
46
|
+
image_opts=ImageOptions(transparent=True),
|
|
47
|
+
)
|
|
48
|
+
result = mask_image_source_from_coverage(
|
|
49
|
+
img, [0, 0, 10, 10], SRS(4326), coverage([20, 20, 30, 30])
|
|
50
|
+
)
|
|
51
|
+
assert_img_colors_eq(
|
|
52
|
+
result.as_image().getcolors(), [((100 * 100), (255, 255, 255, 0))]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def test_mask_outside_of_image_bgcolor(self):
|
|
56
|
+
img = ImageSource(
|
|
57
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
58
|
+
image_opts=ImageOptions(bgcolor=(200, 30, 120)),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
result = mask_image_source_from_coverage(
|
|
62
|
+
img, [0, 0, 10, 10], SRS(4326), coverage([20, 20, 30, 30])
|
|
63
|
+
)
|
|
64
|
+
assert_img_colors_eq(
|
|
65
|
+
result.as_image().getcolors(), [((100 * 100), (200, 30, 120))]
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def test_mask_partial_image_bgcolor(self):
|
|
69
|
+
img = ImageSource(
|
|
70
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
71
|
+
image_opts=ImageOptions(bgcolor=(200, 30, 120)),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
result = mask_image_source_from_coverage(
|
|
75
|
+
img, [0, 0, 10, 10], SRS(4326), coverage([5, 5, 30, 30])
|
|
76
|
+
)
|
|
77
|
+
assert_img_colors_eq(
|
|
78
|
+
result.as_image().getcolors(),
|
|
79
|
+
[(7500, (200, 30, 120)), (2500, (100, 0, 200))],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def test_mask_partial_image_transparent(self):
|
|
83
|
+
img = ImageSource(
|
|
84
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
85
|
+
image_opts=ImageOptions(transparent=True),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
result = mask_image_source_from_coverage(
|
|
89
|
+
img, [0, 0, 10, 10], SRS(4326), coverage([5, 5, 30, 30])
|
|
90
|
+
)
|
|
91
|
+
assert_img_colors_eq(
|
|
92
|
+
result.as_image().getcolors(),
|
|
93
|
+
[(7500, (255, 255, 255, 0)), (2500, (100, 0, 200, 255))],
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def test_wkt_mask_partial_image_transparent(self):
|
|
97
|
+
img = ImageSource(
|
|
98
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
99
|
+
image_opts=ImageOptions(transparent=True),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# polygon with hole
|
|
103
|
+
geom = "POLYGON((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4))"
|
|
104
|
+
|
|
105
|
+
result = mask_image_source_from_coverage(
|
|
106
|
+
img, [0, 0, 10, 10], SRS(4326), coverage(geom)
|
|
107
|
+
)
|
|
108
|
+
# 60*60 - 20*20 = 3200
|
|
109
|
+
assert_img_colors_eq(
|
|
110
|
+
result.as_image().getcolors(),
|
|
111
|
+
[(10000 - 3200, (255, 255, 255, 0)), (3200, (100, 0, 200, 255))],
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def test_shapely_mask_with_transform_partial_image_transparent(self):
|
|
115
|
+
img = ImageSource(
|
|
116
|
+
Image.new("RGB", (100, 100), color=(100, 0, 200)),
|
|
117
|
+
image_opts=ImageOptions(transparent=True),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
p = Polygon(
|
|
121
|
+
[(0, 0), (222000, 0), (222000, 222000), (0, 222000)]
|
|
122
|
+
) # ~ 2x2 degres
|
|
123
|
+
|
|
124
|
+
result = mask_image_source_from_coverage(
|
|
125
|
+
img, [0, 0, 10, 10], SRS(4326), coverage(p, "EPSG:3857")
|
|
126
|
+
)
|
|
127
|
+
# 20*20 = 400
|
|
128
|
+
assert_img_colors_eq(
|
|
129
|
+
result.as_image().getcolors(),
|
|
130
|
+
[(10000 - 400, (255, 255, 255, 0)), (400, (100, 0, 200, 255))],
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class TestLayerCoverageMerge(object):
|
|
135
|
+
|
|
136
|
+
def setup_method(self):
|
|
137
|
+
self.coverage1 = coverage(
|
|
138
|
+
Polygon([(0, 0), (0, 10), (10, 10), (10, 0)]), 3857
|
|
139
|
+
)
|
|
140
|
+
self.coverage2 = coverage([2, 2, 8, 8], 3857)
|
|
141
|
+
|
|
142
|
+
def test_merge_single_coverage(self):
|
|
143
|
+
merger = LayerMerger()
|
|
144
|
+
merger.add(
|
|
145
|
+
ImageSource(Image.new("RGB", (10, 10), (255, 255, 255))),
|
|
146
|
+
self.coverage1,
|
|
147
|
+
)
|
|
148
|
+
result = merger.merge(
|
|
149
|
+
image_opts=ImageOptions(transparent=True),
|
|
150
|
+
bbox=(5, 0, 15, 10),
|
|
151
|
+
bbox_srs=3857,
|
|
152
|
+
)
|
|
153
|
+
img = result.as_image()
|
|
154
|
+
assert img.mode == "RGBA"
|
|
155
|
+
assert img.getpixel((4, 0)) == (255, 255, 255, 255)
|
|
156
|
+
assert img.getpixel((6, 0)) == (255, 255, 255, 0)
|
|
157
|
+
|
|
158
|
+
def test_merge_overlapping_coverage(self):
|
|
159
|
+
color1 = (255, 255, 0)
|
|
160
|
+
color2 = (0, 255, 255)
|
|
161
|
+
merger = LayerMerger()
|
|
162
|
+
merger.add(
|
|
163
|
+
ImageSource(Image.new("RGB", (10, 10), color1)), self.coverage1
|
|
164
|
+
)
|
|
165
|
+
merger.add(
|
|
166
|
+
ImageSource(Image.new("RGB", (10, 10), color2)), self.coverage2
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
result = merger.merge(
|
|
170
|
+
image_opts=ImageOptions(), bbox=(0, 0, 10, 10), bbox_srs=3857
|
|
171
|
+
)
|
|
172
|
+
img = result.as_image()
|
|
173
|
+
assert img.mode == "RGB"
|
|
174
|
+
|
|
175
|
+
expected = create_image((10, 10), color1, "RGB")
|
|
176
|
+
draw = ImageDraw.Draw(expected)
|
|
177
|
+
draw.polygon([(2, 2), (7, 2), (7, 7), (2, 7)], fill=color2)
|
|
178
|
+
|
|
179
|
+
for x in range(0, 9):
|
|
180
|
+
for y in range(0, 9):
|
|
181
|
+
assert img.getpixel((x, y)) == expected.getpixel((x, y))
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# -:- encoding: utf8 -:-
|
|
2
|
+
# This file is part of the MapProxy project.
|
|
3
|
+
# Copyright (C) 2010 Omniscale <http://omniscale.de>
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from __future__ import print_function
|
|
18
|
+
|
|
19
|
+
from mapproxy.compat.image import Image, ImageDraw, ImageColor, ImageFont
|
|
20
|
+
from mapproxy.cache.tile import Tile
|
|
21
|
+
from mapproxy.image import ImageSource
|
|
22
|
+
from mapproxy.image.message import TextDraw, message_image
|
|
23
|
+
from mapproxy.image.opts import ImageOptions
|
|
24
|
+
from mapproxy.tilefilter import watermark_filter
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
27
|
+
|
|
28
|
+
PNG_FORMAT = ImageOptions(format="image/png")
|
|
29
|
+
|
|
30
|
+
requires_freetype = pytest.mark.skipif(
|
|
31
|
+
not isinstance(ImageFont.load_default(), ImageFont.FreeTypeFont),
|
|
32
|
+
reason="Test expects the default Pillow FreeTypeFont")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TestTextDraw(object):
|
|
36
|
+
|
|
37
|
+
def test_ul(self):
|
|
38
|
+
font = ImageFont.load_default()
|
|
39
|
+
td = TextDraw("Hello", font)
|
|
40
|
+
img = Image.new("RGB", (100, 100))
|
|
41
|
+
draw = ImageDraw.Draw(img)
|
|
42
|
+
total_box, boxes = td.text_boxes(draw, (100, 100))
|
|
43
|
+
assert total_box == boxes[0]
|
|
44
|
+
assert len(boxes) == 1
|
|
45
|
+
|
|
46
|
+
@requires_freetype
|
|
47
|
+
def test_multiline_ul(self):
|
|
48
|
+
font = ImageFont.load_default()
|
|
49
|
+
td = TextDraw("Hello\nWorld", font)
|
|
50
|
+
img = Image.new("RGB", (100, 100))
|
|
51
|
+
draw = ImageDraw.Draw(img)
|
|
52
|
+
total_box, boxes = td.text_boxes(draw, (100, 100))
|
|
53
|
+
assert total_box == (5, 7, 33, 28)
|
|
54
|
+
assert boxes == [(5, 7, 30, 15), (5, 20, 33, 28)]
|
|
55
|
+
|
|
56
|
+
@requires_freetype
|
|
57
|
+
def test_multiline_lr(self):
|
|
58
|
+
font = ImageFont.load_default()
|
|
59
|
+
td = TextDraw("Hello\nWorld", font, placement="lr")
|
|
60
|
+
img = Image.new("RGB", (100, 100))
|
|
61
|
+
draw = ImageDraw.Draw(img)
|
|
62
|
+
total_box, boxes = td.text_boxes(draw, (100, 100))
|
|
63
|
+
assert total_box == (67, 76, 95, 97)
|
|
64
|
+
assert boxes == [(67, 76, 92, 84), (67, 89, 95, 97)]
|
|
65
|
+
|
|
66
|
+
@requires_freetype
|
|
67
|
+
def test_multiline_center(self):
|
|
68
|
+
font = ImageFont.load_default()
|
|
69
|
+
td = TextDraw("Hello\nWorld", font, placement="cc")
|
|
70
|
+
img = Image.new("RGB", (100, 100))
|
|
71
|
+
draw = ImageDraw.Draw(img)
|
|
72
|
+
total_box, boxes = td.text_boxes(draw, (100, 100))
|
|
73
|
+
assert total_box == (36, 42, 64, 63)
|
|
74
|
+
assert boxes == [(36, 42, 61, 50), (36, 55, 64, 63)]
|
|
75
|
+
|
|
76
|
+
@requires_freetype
|
|
77
|
+
def test_unicode(self):
|
|
78
|
+
font = ImageFont.load_default()
|
|
79
|
+
td = TextDraw(u"Héllö\nWørld", font, placement="cc")
|
|
80
|
+
img = Image.new("RGB", (100, 100))
|
|
81
|
+
draw = ImageDraw.Draw(img)
|
|
82
|
+
total_box, boxes = td.text_boxes(draw, (100, 100))
|
|
83
|
+
assert total_box == (36, 42, 64, 63)
|
|
84
|
+
assert boxes == [(36, 42, 60, 50), (36, 55, 64, 63)]
|
|
85
|
+
|
|
86
|
+
def _test_all(self):
|
|
87
|
+
for x in "c":
|
|
88
|
+
for y in "LR":
|
|
89
|
+
yield self.check_placement, x, y
|
|
90
|
+
|
|
91
|
+
def check_placement(self, x, y):
|
|
92
|
+
font = ImageFont.load_default()
|
|
93
|
+
td = TextDraw(
|
|
94
|
+
"Hello\nWorld\n%s %s" % (x, y),
|
|
95
|
+
font,
|
|
96
|
+
placement=x + y,
|
|
97
|
+
padding=5,
|
|
98
|
+
linespacing=2,
|
|
99
|
+
)
|
|
100
|
+
img = Image.new("RGB", (100, 100))
|
|
101
|
+
draw = ImageDraw.Draw(img)
|
|
102
|
+
td.draw(draw, img.size)
|
|
103
|
+
img.show()
|
|
104
|
+
|
|
105
|
+
def test_transparent(self):
|
|
106
|
+
font = ImageFont.load_default()
|
|
107
|
+
td = TextDraw("Hello\nWorld", font, placement="cc")
|
|
108
|
+
img = Image.new("RGBA", (100, 100), (0, 0, 0, 0))
|
|
109
|
+
draw = ImageDraw.Draw(img)
|
|
110
|
+
td.draw(draw, img.size)
|
|
111
|
+
# override the alpha value as pillow >= 10.1.0 uses a new default font with transparency
|
|
112
|
+
img.putalpha(255)
|
|
113
|
+
|
|
114
|
+
assert len(img.getcolors()) == 2
|
|
115
|
+
# top color (bg) is transparent
|
|
116
|
+
assert sorted(img.getcolors())[1][1] == (0, 0, 0, 255)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class TestMessageImage(object):
|
|
120
|
+
|
|
121
|
+
def test_blank(self):
|
|
122
|
+
image_opts = PNG_FORMAT.copy()
|
|
123
|
+
image_opts.bgcolor = "#113399"
|
|
124
|
+
img = message_image("", size=(100, 150), image_opts=image_opts)
|
|
125
|
+
assert isinstance(img, ImageSource)
|
|
126
|
+
assert img.size == (100, 150)
|
|
127
|
+
pil_img = img.as_image()
|
|
128
|
+
assert pil_img.getpixel((0, 0)) == ImageColor.getrgb("#113399")
|
|
129
|
+
# 3 values in histogram (RGB)
|
|
130
|
+
assert [x for x in pil_img.histogram() if x > 0] == [
|
|
131
|
+
15000,
|
|
132
|
+
15000,
|
|
133
|
+
15000,
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
@requires_freetype
|
|
137
|
+
def test_message(self):
|
|
138
|
+
image_opts = PNG_FORMAT.copy()
|
|
139
|
+
image_opts.bgcolor = "#113399"
|
|
140
|
+
img = message_image("test", size=(100, 150), image_opts=image_opts)
|
|
141
|
+
text_pixels = 75
|
|
142
|
+
image_pixels = 100 * 150
|
|
143
|
+
assert isinstance(img, ImageSource)
|
|
144
|
+
assert img.size == (100, 150)
|
|
145
|
+
# expect the large histogram count values to be the amount of background pixels
|
|
146
|
+
assert [x for x in img.as_image().histogram() if x > 10] == [
|
|
147
|
+
image_pixels - text_pixels,
|
|
148
|
+
image_pixels - text_pixels,
|
|
149
|
+
image_pixels - text_pixels,
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
def test_transparent(self):
|
|
153
|
+
image_opts = ImageOptions(transparent=True)
|
|
154
|
+
print(image_opts)
|
|
155
|
+
img = message_image("", size=(100, 150), image_opts=image_opts)
|
|
156
|
+
assert isinstance(img, ImageSource)
|
|
157
|
+
assert img.size == (100, 150)
|
|
158
|
+
pil_img = img.as_image()
|
|
159
|
+
assert pil_img.getpixel((0, 0)) == (255, 255, 255, 0)
|
|
160
|
+
# 6 values in histogram (3xRGB for background, 3xRGB for text message)
|
|
161
|
+
assert [x for x in pil_img.histogram() if x > 0] == [
|
|
162
|
+
15000,
|
|
163
|
+
15000,
|
|
164
|
+
15000,
|
|
165
|
+
15000,
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class TestWatermarkTileFilter(object):
|
|
170
|
+
|
|
171
|
+
def setup_method(self):
|
|
172
|
+
self.tile = Tile((0, 0, 0))
|
|
173
|
+
self.filter = watermark_filter("Test")
|
|
174
|
+
|
|
175
|
+
def test_filter(self):
|
|
176
|
+
img = Image.new("RGB", (200, 200))
|
|
177
|
+
orig_source = ImageSource(img)
|
|
178
|
+
self.tile.source = orig_source
|
|
179
|
+
filtered_tile = self.filter(self.tile)
|
|
180
|
+
|
|
181
|
+
assert self.tile is filtered_tile
|
|
182
|
+
assert orig_source != filtered_tile.source
|
|
183
|
+
|
|
184
|
+
pil_img = filtered_tile.source.as_image()
|
|
185
|
+
assert pil_img.getpixel((0, 0)) == (0, 0, 0)
|
|
186
|
+
|
|
187
|
+
colors = pil_img.getcolors()
|
|
188
|
+
colors.sort()
|
|
189
|
+
# most but not all parts are bg color
|
|
190
|
+
assert 39950 > colors[-1][0] > 39000
|
|
191
|
+
assert colors[-1][1] == (0, 0, 0)
|
|
192
|
+
|
|
193
|
+
def test_filter_with_alpha(self):
|
|
194
|
+
img = Image.new("RGBA", (200, 200), (10, 15, 20, 0))
|
|
195
|
+
orig_source = ImageSource(img)
|
|
196
|
+
self.tile.source = orig_source
|
|
197
|
+
filtered_tile = self.filter(self.tile)
|
|
198
|
+
|
|
199
|
+
assert self.tile is filtered_tile
|
|
200
|
+
assert orig_source != filtered_tile.source
|
|
201
|
+
|
|
202
|
+
pil_img = filtered_tile.source.as_image()
|
|
203
|
+
assert pil_img.getpixel((0, 0)) == (10, 15, 20, 0)
|
|
204
|
+
|
|
205
|
+
colors = pil_img.getcolors()
|
|
206
|
+
colors.sort()
|
|
207
|
+
# most but not all parts are bg color
|
|
208
|
+
assert 39950 > colors[-1][0] > 39000
|
|
209
|
+
assert colors[-1][1] == (10, 15, 20, 0)
|
|
@@ -0,0 +1,160 @@
|
|
|
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
|
+
|
|
17
|
+
from mapproxy.image.opts import (
|
|
18
|
+
ImageOptions,
|
|
19
|
+
create_image,
|
|
20
|
+
compatible_image_options,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestCreateImage(object):
|
|
25
|
+
|
|
26
|
+
def test_default(self):
|
|
27
|
+
img = create_image((100, 100))
|
|
28
|
+
assert img.size == (100, 100)
|
|
29
|
+
assert img.mode == "RGB"
|
|
30
|
+
assert img.getcolors() == [(100 * 100, (255, 255, 255))]
|
|
31
|
+
|
|
32
|
+
def test_transparent(self):
|
|
33
|
+
img = create_image((100, 100), ImageOptions(transparent=True))
|
|
34
|
+
assert img.size == (100, 100)
|
|
35
|
+
assert img.mode == "RGBA"
|
|
36
|
+
assert img.getcolors() == [(100 * 100, (255, 255, 255, 0))]
|
|
37
|
+
|
|
38
|
+
def test_transparent_rgb(self):
|
|
39
|
+
img = create_image(
|
|
40
|
+
(100, 100), ImageOptions(mode="RGB", transparent=True)
|
|
41
|
+
)
|
|
42
|
+
assert img.size == (100, 100)
|
|
43
|
+
assert img.mode == "RGB"
|
|
44
|
+
assert img.getcolors() == [(100 * 100, (255, 255, 255))]
|
|
45
|
+
|
|
46
|
+
def test_bgcolor(self):
|
|
47
|
+
img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0)))
|
|
48
|
+
assert img.size == (100, 100)
|
|
49
|
+
assert img.mode == "RGB"
|
|
50
|
+
assert img.getcolors() == [(100 * 100, (200, 100, 0))]
|
|
51
|
+
|
|
52
|
+
def test_rgba_bgcolor(self):
|
|
53
|
+
img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30)))
|
|
54
|
+
assert img.size == (100, 100)
|
|
55
|
+
assert img.mode == "RGB"
|
|
56
|
+
assert img.getcolors() == [(100 * 100, (200, 100, 0))]
|
|
57
|
+
|
|
58
|
+
def test_rgba_bgcolor_transparent(self):
|
|
59
|
+
img = create_image(
|
|
60
|
+
(100, 100),
|
|
61
|
+
ImageOptions(bgcolor=(200, 100, 0, 30), transparent=True),
|
|
62
|
+
)
|
|
63
|
+
assert img.size == (100, 100)
|
|
64
|
+
assert img.mode == "RGBA"
|
|
65
|
+
assert img.getcolors() == [(100 * 100, (200, 100, 0, 30))]
|
|
66
|
+
|
|
67
|
+
def test_rgba_bgcolor_rgba_mode(self):
|
|
68
|
+
img = create_image(
|
|
69
|
+
(100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), mode="RGBA")
|
|
70
|
+
)
|
|
71
|
+
assert img.size == (100, 100)
|
|
72
|
+
assert img.mode == "RGBA"
|
|
73
|
+
assert img.getcolors() == [(100 * 100, (200, 100, 0, 30))]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TestCompatibleImageOptions(object):
|
|
77
|
+
|
|
78
|
+
def test_formats(self):
|
|
79
|
+
img_opts = compatible_image_options(
|
|
80
|
+
[
|
|
81
|
+
ImageOptions(format="image/png"),
|
|
82
|
+
ImageOptions(format="image/jpeg"),
|
|
83
|
+
]
|
|
84
|
+
)
|
|
85
|
+
assert img_opts.format == "image/png"
|
|
86
|
+
|
|
87
|
+
img_opts = compatible_image_options(
|
|
88
|
+
[
|
|
89
|
+
ImageOptions(format="image/png"),
|
|
90
|
+
ImageOptions(format="image/jpeg"),
|
|
91
|
+
],
|
|
92
|
+
ImageOptions(format="image/tiff"),
|
|
93
|
+
)
|
|
94
|
+
assert img_opts.format == "image/tiff"
|
|
95
|
+
|
|
96
|
+
def test_colors(self):
|
|
97
|
+
img_opts = compatible_image_options(
|
|
98
|
+
[ImageOptions(colors=None), ImageOptions(colors=16)]
|
|
99
|
+
)
|
|
100
|
+
assert img_opts.colors == 16
|
|
101
|
+
|
|
102
|
+
img_opts = compatible_image_options(
|
|
103
|
+
[ImageOptions(colors=256), ImageOptions(colors=16)]
|
|
104
|
+
)
|
|
105
|
+
assert img_opts.colors == 256
|
|
106
|
+
|
|
107
|
+
img_opts = compatible_image_options(
|
|
108
|
+
[ImageOptions(colors=256), ImageOptions(colors=16)],
|
|
109
|
+
ImageOptions(colors=4),
|
|
110
|
+
)
|
|
111
|
+
assert img_opts.colors == 4
|
|
112
|
+
|
|
113
|
+
img_opts = compatible_image_options(
|
|
114
|
+
[ImageOptions(colors=256), ImageOptions(colors=0)]
|
|
115
|
+
)
|
|
116
|
+
assert img_opts.colors == 0
|
|
117
|
+
|
|
118
|
+
def test_transparent(self):
|
|
119
|
+
img_opts = compatible_image_options(
|
|
120
|
+
[ImageOptions(transparent=False), ImageOptions(transparent=True)]
|
|
121
|
+
)
|
|
122
|
+
assert not img_opts.transparent
|
|
123
|
+
|
|
124
|
+
img_opts = compatible_image_options(
|
|
125
|
+
[ImageOptions(transparent=None), ImageOptions(transparent=True)]
|
|
126
|
+
)
|
|
127
|
+
assert img_opts.transparent
|
|
128
|
+
|
|
129
|
+
img_opts = compatible_image_options(
|
|
130
|
+
[ImageOptions(transparent=None), ImageOptions(transparent=True)],
|
|
131
|
+
ImageOptions(transparent=None),
|
|
132
|
+
)
|
|
133
|
+
assert img_opts.transparent
|
|
134
|
+
|
|
135
|
+
img_opts = compatible_image_options(
|
|
136
|
+
[ImageOptions(transparent=True), ImageOptions(transparent=True)]
|
|
137
|
+
)
|
|
138
|
+
assert img_opts.transparent
|
|
139
|
+
|
|
140
|
+
def test_mode(self):
|
|
141
|
+
img_opts = compatible_image_options(
|
|
142
|
+
[ImageOptions(mode="RGB"), ImageOptions(mode="P")]
|
|
143
|
+
)
|
|
144
|
+
assert img_opts.mode == "RGB"
|
|
145
|
+
|
|
146
|
+
img_opts = compatible_image_options(
|
|
147
|
+
[ImageOptions(mode="RGBA"), ImageOptions(mode="P")]
|
|
148
|
+
)
|
|
149
|
+
assert img_opts.mode == "RGBA"
|
|
150
|
+
|
|
151
|
+
img_opts = compatible_image_options(
|
|
152
|
+
[ImageOptions(mode="RGB"), ImageOptions(mode="P")]
|
|
153
|
+
)
|
|
154
|
+
assert img_opts.mode == "RGB"
|
|
155
|
+
|
|
156
|
+
img_opts = compatible_image_options(
|
|
157
|
+
[ImageOptions(mode="RGB"), ImageOptions(mode="P")],
|
|
158
|
+
ImageOptions(mode="P"),
|
|
159
|
+
)
|
|
160
|
+
assert img_opts.mode == "P"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# This file is part of the MapProxy project.
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
# See the License for the specific language governing permissions and
|
|
12
|
+
# limitations under the License.
|
|
13
|
+
|
|
14
|
+
from __future__ import division
|
|
15
|
+
import pytest
|
|
16
|
+
from mapproxy.util.ext.wmsparse.util import parse_datetime_range, parse_duration
|
|
17
|
+
from mapproxy.util.ext.wmsparse.duration import parse_datetime
|
|
18
|
+
|
|
19
|
+
expected_dim = {'time': {
|
|
20
|
+
'values': '2020-09-22T11:20:00Z,2020-09-22T13:20:00Z,2020-09-22T15:20:00Z',
|
|
21
|
+
'default': '2020-09-22T14:20:00Z'},
|
|
22
|
+
'dim_reference_time': {
|
|
23
|
+
'values': '2020-09-22T11:20:00Z,2020-09-22T13:20:00Z,2020-09-22T15:20:00Z',
|
|
24
|
+
'default': '2020-09-22T14:20:00Z'}}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture(scope="module")
|
|
28
|
+
def config_file():
|
|
29
|
+
return "dimension.yaml"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TestIsoDate(object):
|
|
33
|
+
|
|
34
|
+
@pytest.mark.parametrize("test_input,expected_value", [
|
|
35
|
+
|
|
36
|
+
# test_input should be string
|
|
37
|
+
# expected array ==> [year,month,day,hour,mins,secs,tz]
|
|
38
|
+
|
|
39
|
+
("2020-08-01T12:43:38Z", [2020, 8, 1, 12, 43, 38]),
|
|
40
|
+
|
|
41
|
+
("1999-12-30T01:59:03Z", [1999, 12, 30, 1, 59, 3]),
|
|
42
|
+
|
|
43
|
+
])
|
|
44
|
+
def test_parsing_datetime(self, test_input, expected_value):
|
|
45
|
+
# test = "2020-08-01T12:43:38Z"
|
|
46
|
+
expected_year = expected_value[0]
|
|
47
|
+
expected_month = expected_value[1]
|
|
48
|
+
expected_day = expected_value[2]
|
|
49
|
+
expected_hour = expected_value[3]
|
|
50
|
+
expected_mins = expected_value[4]
|
|
51
|
+
expected_secs = expected_value[5]
|
|
52
|
+
|
|
53
|
+
result = parse_datetime(test_input)
|
|
54
|
+
test_tz = result.tzinfo
|
|
55
|
+
test_tz = test_tz.tzname(test_tz)
|
|
56
|
+
|
|
57
|
+
assert result.year == expected_year
|
|
58
|
+
assert result.month == expected_month
|
|
59
|
+
assert result.day == expected_day
|
|
60
|
+
assert result.hour == expected_hour
|
|
61
|
+
assert result.minute == expected_mins
|
|
62
|
+
assert result.second == expected_secs
|
|
63
|
+
assert test_tz == "UTC"
|
|
64
|
+
|
|
65
|
+
@pytest.mark.parametrize("test_input,only_time,expected_values", [
|
|
66
|
+
|
|
67
|
+
# test_input should be string
|
|
68
|
+
# only_time flag to indicate only time parsing
|
|
69
|
+
# expected array ==> [year,month,day,secs]
|
|
70
|
+
|
|
71
|
+
("PT1H", True, [0, 0, 0, 3600]),
|
|
72
|
+
("PT1H30M45S", True, [0, 0, 0, 5445]),
|
|
73
|
+
("P6MT", False, [0, 6, 0, 0]),
|
|
74
|
+
("P1MT", False, [0, 1, 0, 0]),
|
|
75
|
+
("P1Y2M1W3DT", False, [1, 2, 10, 0]),
|
|
76
|
+
])
|
|
77
|
+
def test_parse_duration(self, test_input, only_time, expected_values):
|
|
78
|
+
if only_time:
|
|
79
|
+
expect = expected_values[-1]
|
|
80
|
+
result = parse_duration(test_input).seconds
|
|
81
|
+
assert expect == result
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
expected_years = expected_values[0]
|
|
85
|
+
expected_months = expected_values[1]
|
|
86
|
+
expected_days = expected_values[2]
|
|
87
|
+
expected_seconds = expected_values[3]
|
|
88
|
+
|
|
89
|
+
result = parse_duration(test_input)
|
|
90
|
+
|
|
91
|
+
result_years = int(result.years)
|
|
92
|
+
result_months = int(result.months)
|
|
93
|
+
result_days = int(result.days)
|
|
94
|
+
result_seconds = int(result.seconds)
|
|
95
|
+
|
|
96
|
+
assert expected_years == result_years
|
|
97
|
+
assert expected_months == result_months
|
|
98
|
+
assert expected_days == result_days
|
|
99
|
+
assert expected_seconds == result_seconds
|
|
100
|
+
|
|
101
|
+
@pytest.mark.parametrize("test_input,exp_values", [
|
|
102
|
+
|
|
103
|
+
# test_input should be string
|
|
104
|
+
# only_time flag to indicate only time parsing
|
|
105
|
+
# exp_values array ==> [time range values]
|
|
106
|
+
("2020-09-22T00:00:00Z/2020-09-23T00:00:00Z/PT12H", ['2020-09-22T00:00:00Z',
|
|
107
|
+
'2020-09-22T12:00:00Z', '2020-09-23T00:00:00Z']),
|
|
108
|
+
("2020-08-01T00:00:00Z/P1DT2H30M", ['2020-08-01T00:00:00Z',
|
|
109
|
+
'2020-08-02T02:30:00Z']),
|
|
110
|
+
("P1DT2H30M/2020-08-30T00:00:00Z", ['2020-08-28T21:30:00Z',
|
|
111
|
+
'2020-08-30T00:00:00Z'])
|
|
112
|
+
])
|
|
113
|
+
def test_parse_datetime_range(self, test_input, exp_values):
|
|
114
|
+
|
|
115
|
+
exp_values = set(exp_values)
|
|
116
|
+
result = set(parse_datetime_range(test_input))
|
|
117
|
+
|
|
118
|
+
assert exp_values == result
|