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.
Files changed (459) hide show
  1. MapProxy-2.1.0.dist-info/AUTHORS.txt +33 -0
  2. MapProxy-2.1.0.dist-info/COPYING.txt +60 -0
  3. MapProxy-2.1.0.dist-info/LICENSE.txt +202 -0
  4. MapProxy-2.1.0.dist-info/METADATA +165 -0
  5. MapProxy-2.1.0.dist-info/RECORD +459 -0
  6. MapProxy-2.1.0.dist-info/WHEEL +5 -0
  7. MapProxy-2.1.0.dist-info/entry_points.txt +4 -0
  8. MapProxy-2.1.0.dist-info/top_level.txt +1 -0
  9. mapproxy/__init__.py +0 -0
  10. mapproxy/cache/__init__.py +36 -0
  11. mapproxy/cache/azureblob.py +145 -0
  12. mapproxy/cache/base.py +120 -0
  13. mapproxy/cache/compact.py +665 -0
  14. mapproxy/cache/couchdb.py +301 -0
  15. mapproxy/cache/dummy.py +36 -0
  16. mapproxy/cache/file.py +200 -0
  17. mapproxy/cache/geopackage.py +647 -0
  18. mapproxy/cache/legend.py +87 -0
  19. mapproxy/cache/mbtiles.py +411 -0
  20. mapproxy/cache/meta.py +80 -0
  21. mapproxy/cache/path.py +261 -0
  22. mapproxy/cache/redis.py +152 -0
  23. mapproxy/cache/renderd.py +100 -0
  24. mapproxy/cache/riak.py +206 -0
  25. mapproxy/cache/s3.py +209 -0
  26. mapproxy/cache/tile.py +736 -0
  27. mapproxy/client/__init__.py +0 -0
  28. mapproxy/client/arcgis.py +82 -0
  29. mapproxy/client/cgi.py +141 -0
  30. mapproxy/client/http.py +295 -0
  31. mapproxy/client/log.py +33 -0
  32. mapproxy/client/tile.py +158 -0
  33. mapproxy/client/wms.py +255 -0
  34. mapproxy/compat/__init__.py +0 -0
  35. mapproxy/compat/image.py +86 -0
  36. mapproxy/config/__init__.py +22 -0
  37. mapproxy/config/config-schema.json +813 -0
  38. mapproxy/config/config.py +213 -0
  39. mapproxy/config/coverage.py +108 -0
  40. mapproxy/config/defaults.py +102 -0
  41. mapproxy/config/loader.py +2399 -0
  42. mapproxy/config/spec.py +657 -0
  43. mapproxy/config/validator.py +242 -0
  44. mapproxy/config_template/__init__.py +0 -0
  45. mapproxy/config_template/base_config/config.wsgi +10 -0
  46. mapproxy/config_template/base_config/full_example.yaml +598 -0
  47. mapproxy/config_template/base_config/full_seed_example.yaml +79 -0
  48. mapproxy/config_template/base_config/log.ini +35 -0
  49. mapproxy/config_template/base_config/mapproxy.yaml +60 -0
  50. mapproxy/config_template/base_config/seed.yaml +27 -0
  51. mapproxy/exception.py +149 -0
  52. mapproxy/featureinfo.py +251 -0
  53. mapproxy/grid.py +1199 -0
  54. mapproxy/image/__init__.py +549 -0
  55. mapproxy/image/fonts/DejaVuSans.ttf +0 -0
  56. mapproxy/image/fonts/DejaVuSansMono.ttf +0 -0
  57. mapproxy/image/fonts/LICENSE +99 -0
  58. mapproxy/image/fonts/__init__.py +0 -0
  59. mapproxy/image/mask.py +79 -0
  60. mapproxy/image/merge.py +323 -0
  61. mapproxy/image/message.py +357 -0
  62. mapproxy/image/opts.py +185 -0
  63. mapproxy/image/tile.py +171 -0
  64. mapproxy/image/transform.py +350 -0
  65. mapproxy/layer.py +489 -0
  66. mapproxy/multiapp.py +230 -0
  67. mapproxy/proj.py +309 -0
  68. mapproxy/request/__init__.py +18 -0
  69. mapproxy/request/arcgis.py +268 -0
  70. mapproxy/request/base.py +466 -0
  71. mapproxy/request/tile.py +131 -0
  72. mapproxy/request/wms/__init__.py +829 -0
  73. mapproxy/request/wms/exception.py +107 -0
  74. mapproxy/request/wmts.py +442 -0
  75. mapproxy/response.py +237 -0
  76. mapproxy/script/__init__.py +0 -0
  77. mapproxy/script/conf/__init__.py +0 -0
  78. mapproxy/script/conf/app.py +222 -0
  79. mapproxy/script/conf/caches.py +44 -0
  80. mapproxy/script/conf/geopackage.py +136 -0
  81. mapproxy/script/conf/layers.py +54 -0
  82. mapproxy/script/conf/seeds.py +36 -0
  83. mapproxy/script/conf/sources.py +88 -0
  84. mapproxy/script/conf/utils.py +148 -0
  85. mapproxy/script/defrag.py +187 -0
  86. mapproxy/script/export.py +337 -0
  87. mapproxy/script/grids.py +198 -0
  88. mapproxy/script/scales.py +134 -0
  89. mapproxy/script/util.py +410 -0
  90. mapproxy/script/wms_capabilities.py +160 -0
  91. mapproxy/seed/__init__.py +0 -0
  92. mapproxy/seed/cachelock.py +127 -0
  93. mapproxy/seed/cleanup.py +191 -0
  94. mapproxy/seed/config.py +481 -0
  95. mapproxy/seed/script.py +391 -0
  96. mapproxy/seed/seeder.py +551 -0
  97. mapproxy/seed/spec.py +66 -0
  98. mapproxy/seed/util.py +266 -0
  99. mapproxy/service/__init__.py +14 -0
  100. mapproxy/service/base.py +45 -0
  101. mapproxy/service/demo.py +364 -0
  102. mapproxy/service/kml.py +333 -0
  103. mapproxy/service/ows.py +39 -0
  104. mapproxy/service/template_helper.py +55 -0
  105. mapproxy/service/templates/demo/capabilities_demo.html +18 -0
  106. mapproxy/service/templates/demo/demo.html +181 -0
  107. mapproxy/service/templates/demo/openlayers-demo.cfg +16 -0
  108. mapproxy/service/templates/demo/static/img/blank.gif +0 -0
  109. mapproxy/service/templates/demo/static/img/east-mini.png +0 -0
  110. mapproxy/service/templates/demo/static/img/north-mini.png +0 -0
  111. mapproxy/service/templates/demo/static/img/south-mini.png +0 -0
  112. mapproxy/service/templates/demo/static/img/west-mini.png +0 -0
  113. mapproxy/service/templates/demo/static/img/zoom-minus-mini.png +0 -0
  114. mapproxy/service/templates/demo/static/img/zoom-plus-mini.png +0 -0
  115. mapproxy/service/templates/demo/static/img/zoom-world-mini.png +0 -0
  116. mapproxy/service/templates/demo/static/logo.png +0 -0
  117. mapproxy/service/templates/demo/static/ol.css +345 -0
  118. mapproxy/service/templates/demo/static/ol.js +4 -0
  119. mapproxy/service/templates/demo/static/proj4.min.js +1 -0
  120. mapproxy/service/templates/demo/static/proj4defs.js +1 -0
  121. mapproxy/service/templates/demo/static/site.css +137 -0
  122. mapproxy/service/templates/demo/static/theme/default/framedCloud.css +0 -0
  123. mapproxy/service/templates/demo/static/theme/default/google.css +17 -0
  124. mapproxy/service/templates/demo/static/theme/default/ie6-style.css +10 -0
  125. mapproxy/service/templates/demo/static/theme/default/style.css +482 -0
  126. mapproxy/service/templates/demo/static.html +34 -0
  127. mapproxy/service/templates/demo/tms_demo.html +117 -0
  128. mapproxy/service/templates/demo/wms_demo.html +144 -0
  129. mapproxy/service/templates/demo/wmts_demo.html +118 -0
  130. mapproxy/service/templates/tms_capabilities.xml +13 -0
  131. mapproxy/service/templates/tms_exception.xml +4 -0
  132. mapproxy/service/templates/tms_root_resource.xml +7 -0
  133. mapproxy/service/templates/tms_tilemap_capabilities.xml +14 -0
  134. mapproxy/service/templates/wms100capabilities.xml +112 -0
  135. mapproxy/service/templates/wms100exception.xml +4 -0
  136. mapproxy/service/templates/wms110capabilities.xml +152 -0
  137. mapproxy/service/templates/wms110exception.xml +5 -0
  138. mapproxy/service/templates/wms111capabilities.xml +183 -0
  139. mapproxy/service/templates/wms111exception.xml +5 -0
  140. mapproxy/service/templates/wms130capabilities.xml +326 -0
  141. mapproxy/service/templates/wms130exception.xml +8 -0
  142. mapproxy/service/templates/wmts100capabilities.xml +155 -0
  143. mapproxy/service/templates/wmts100exception.xml +9 -0
  144. mapproxy/service/tile.py +540 -0
  145. mapproxy/service/wms.py +868 -0
  146. mapproxy/service/wmts.py +387 -0
  147. mapproxy/source/__init__.py +83 -0
  148. mapproxy/source/arcgis.py +39 -0
  149. mapproxy/source/error.py +40 -0
  150. mapproxy/source/mapnik.py +262 -0
  151. mapproxy/source/tile.py +97 -0
  152. mapproxy/source/wms.py +273 -0
  153. mapproxy/srs.py +734 -0
  154. mapproxy/template.py +54 -0
  155. mapproxy/test/__init__.py +0 -0
  156. mapproxy/test/conftest.py +8 -0
  157. mapproxy/test/helper.py +255 -0
  158. mapproxy/test/http.py +511 -0
  159. mapproxy/test/image.py +219 -0
  160. mapproxy/test/mocker.py +2291 -0
  161. mapproxy/test/schemas/inspire/common/1.0/common.xsd +1461 -0
  162. mapproxy/test/schemas/inspire/common/1.0/enums/enum_bul.xsd +108 -0
  163. mapproxy/test/schemas/inspire/common/1.0/enums/enum_cze.xsd +108 -0
  164. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dan.xsd +108 -0
  165. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dut.xsd +108 -0
  166. mapproxy/test/schemas/inspire/common/1.0/enums/enum_eng.xsd +155 -0
  167. mapproxy/test/schemas/inspire/common/1.0/enums/enum_est.xsd +108 -0
  168. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fin.xsd +108 -0
  169. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fre.xsd +108 -0
  170. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ger.xsd +108 -0
  171. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gle.xsd +109 -0
  172. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gre.xsd +108 -0
  173. mapproxy/test/schemas/inspire/common/1.0/enums/enum_hun.xsd +108 -0
  174. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ita.xsd +108 -0
  175. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lav.xsd +108 -0
  176. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lit.xsd +108 -0
  177. mapproxy/test/schemas/inspire/common/1.0/enums/enum_mlt.xsd +108 -0
  178. mapproxy/test/schemas/inspire/common/1.0/enums/enum_pol.xsd +108 -0
  179. mapproxy/test/schemas/inspire/common/1.0/enums/enum_por.xsd +108 -0
  180. mapproxy/test/schemas/inspire/common/1.0/enums/enum_rum.xsd +108 -0
  181. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slo.xsd +108 -0
  182. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slv.xsd +108 -0
  183. mapproxy/test/schemas/inspire/common/1.0/enums/enum_spa.xsd +108 -0
  184. mapproxy/test/schemas/inspire/common/1.0/enums/enum_swe.xsd +108 -0
  185. mapproxy/test/schemas/inspire/common/1.0/network.xsd +521 -0
  186. mapproxy/test/schemas/inspire/inspire_vs/1.0/inspire_vs.xsd +19 -0
  187. mapproxy/test/schemas/kml/2.2.0/ReadMe.txt +14 -0
  188. mapproxy/test/schemas/kml/2.2.0/atom-author-link.xsd +66 -0
  189. mapproxy/test/schemas/kml/2.2.0/ogckml22.xsd +1646 -0
  190. mapproxy/test/schemas/kml/2.2.0/xAL.xsd +1680 -0
  191. mapproxy/test/schemas/ows/1.1.0/ReadMe.txt +87 -0
  192. mapproxy/test/schemas/ows/1.1.0/ows19115subset.xsd +235 -0
  193. mapproxy/test/schemas/ows/1.1.0/owsAll.xsd +23 -0
  194. mapproxy/test/schemas/ows/1.1.0/owsCommon.xsd +157 -0
  195. mapproxy/test/schemas/ows/1.1.0/owsContents.xsd +86 -0
  196. mapproxy/test/schemas/ows/1.1.0/owsDataIdentification.xsd +127 -0
  197. mapproxy/test/schemas/ows/1.1.0/owsDomainType.xsd +279 -0
  198. mapproxy/test/schemas/ows/1.1.0/owsExceptionReport.xsd +76 -0
  199. mapproxy/test/schemas/ows/1.1.0/owsGetCapabilities.xsd +112 -0
  200. mapproxy/test/schemas/ows/1.1.0/owsGetResourceByID.xsd +51 -0
  201. mapproxy/test/schemas/ows/1.1.0/owsInputOutputData.xsd +59 -0
  202. mapproxy/test/schemas/ows/1.1.0/owsManifest.xsd +125 -0
  203. mapproxy/test/schemas/ows/1.1.0/owsOperationsMetadata.xsd +140 -0
  204. mapproxy/test/schemas/ows/1.1.0/owsServiceIdentification.xsd +60 -0
  205. mapproxy/test/schemas/ows/1.1.0/owsServiceProvider.xsd +47 -0
  206. mapproxy/test/schemas/sld/1.1.0/sld_capabilities.xsd +27 -0
  207. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.dtd +353 -0
  208. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.xml +188 -0
  209. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.dtd +524 -0
  210. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.xml +260 -0
  211. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.dtd +273 -0
  212. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.xml +303 -0
  213. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.dtd +6 -0
  214. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.xml +33 -0
  215. mapproxy/test/schemas/wms/1.1.1/OGC-exception.xsd +68 -0
  216. mapproxy/test/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  217. mapproxy/test/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd +274 -0
  218. mapproxy/test/schemas/wms/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  219. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.dtd +276 -0
  220. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.xml +303 -0
  221. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.dtd +6 -0
  222. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.xml +33 -0
  223. mapproxy/test/schemas/wms/1.3.0/ReadMe.txt +8 -0
  224. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xml +277 -0
  225. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xsd +611 -0
  226. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xml +34 -0
  227. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xsd +28 -0
  228. mapproxy/test/schemas/wmsc/1.1.1/OGC-exception.xsd +68 -0
  229. mapproxy/test/schemas/wmsc/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  230. mapproxy/test/schemas/wmsc/1.1.1/WMS_MS_Capabilities.dtd +283 -0
  231. mapproxy/test/schemas/wmsc/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  232. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.dtd +276 -0
  233. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.xml +303 -0
  234. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.dtd +6 -0
  235. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.xml +33 -0
  236. mapproxy/test/schemas/wmts/1.0/ReadMe.txt +32 -0
  237. mapproxy/test/schemas/wmts/1.0/wmts.xsd +28 -0
  238. mapproxy/test/schemas/wmts/1.0/wmtsAbstract.wsdl +151 -0
  239. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_request.xsd +38 -0
  240. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_response.xsd +564 -0
  241. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_request.xsd +57 -0
  242. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_response.xsd +72 -0
  243. mapproxy/test/schemas/wmts/1.0/wmtsGetTile_request.xsd +91 -0
  244. mapproxy/test/schemas/wmts/1.0/wmtsKVP.xsd +76 -0
  245. mapproxy/test/schemas/wmts/1.0/wmtsPayload_response.xsd +70 -0
  246. mapproxy/test/schemas/xlink/1.0.0/ReadMe.txt +6 -0
  247. mapproxy/test/schemas/xlink/1.0.0/xlinks.xsd +122 -0
  248. mapproxy/test/schemas/xml.xsd +287 -0
  249. mapproxy/test/system/__init__.py +98 -0
  250. mapproxy/test/system/fixture/arcgis.yaml +57 -0
  251. mapproxy/test/system/fixture/auth.yaml +70 -0
  252. mapproxy/test/system/fixture/cache.mbtiles +0 -0
  253. mapproxy/test/system/fixture/cache_azureblob.yaml +59 -0
  254. mapproxy/test/system/fixture/cache_band_merge.yaml +73 -0
  255. mapproxy/test/system/fixture/cache_bulk_meta_tiles.yaml +24 -0
  256. mapproxy/test/system/fixture/cache_coverage.yaml +84 -0
  257. mapproxy/test/system/fixture/cache_data/dop_cache_EPSG3857/00/000/000/000/000/000/000.png +0 -0
  258. mapproxy/test/system/fixture/cache_data/wms_cache_EPSG900913/01/000/000/000/000/000/001.jpeg +0 -0
  259. mapproxy/test/system/fixture/cache_data/wms_cache_transparent_EPSG900913/01/000/000/000/000/000/001.png +0 -0
  260. mapproxy/test/system/fixture/cache_geopackage.yaml +56 -0
  261. mapproxy/test/system/fixture/cache_grid_names.yaml +50 -0
  262. mapproxy/test/system/fixture/cache_mbtiles.yaml +28 -0
  263. mapproxy/test/system/fixture/cache_s3.yaml +58 -0
  264. mapproxy/test/system/fixture/cache_source.yaml +81 -0
  265. mapproxy/test/system/fixture/combined_sources.yaml +130 -0
  266. mapproxy/test/system/fixture/coverage.yaml +77 -0
  267. mapproxy/test/system/fixture/demo.yaml +135 -0
  268. mapproxy/test/system/fixture/dimension.yaml +59 -0
  269. mapproxy/test/system/fixture/disable_storage.yaml +25 -0
  270. mapproxy/test/system/fixture/empty_ogrdata.geojson +1 -0
  271. mapproxy/test/system/fixture/formats.yaml +72 -0
  272. mapproxy/test/system/fixture/inspire.yaml +101 -0
  273. mapproxy/test/system/fixture/inspire_full.yaml +124 -0
  274. mapproxy/test/system/fixture/kml_layer.yaml +66 -0
  275. mapproxy/test/system/fixture/layer.yaml +260 -0
  276. mapproxy/test/system/fixture/layergroups.yaml +57 -0
  277. mapproxy/test/system/fixture/layergroups_root.yaml +106 -0
  278. mapproxy/test/system/fixture/legendgraphic.yaml +93 -0
  279. mapproxy/test/system/fixture/mapnik_source.yaml +66 -0
  280. mapproxy/test/system/fixture/mapproxy_export.yaml +12 -0
  281. mapproxy/test/system/fixture/mapserver.yaml +23 -0
  282. mapproxy/test/system/fixture/minimal_cgi.py +16 -0
  283. mapproxy/test/system/fixture/mixed_mode.yaml +49 -0
  284. mapproxy/test/system/fixture/multi_cache_layers.yaml +111 -0
  285. mapproxy/test/system/fixture/multiapp1.yaml +20 -0
  286. mapproxy/test/system/fixture/multiapp2.yaml +19 -0
  287. mapproxy/test/system/fixture/renderd_client.yaml +55 -0
  288. mapproxy/test/system/fixture/scalehints.yaml +70 -0
  289. mapproxy/test/system/fixture/seed.yaml +94 -0
  290. mapproxy/test/system/fixture/seed_mapproxy.yaml +39 -0
  291. mapproxy/test/system/fixture/seed_old.yaml +12 -0
  292. mapproxy/test/system/fixture/seed_timeouts.yaml +12 -0
  293. mapproxy/test/system/fixture/seed_timeouts_mapproxy.yaml +27 -0
  294. mapproxy/test/system/fixture/seedonly.yaml +51 -0
  295. mapproxy/test/system/fixture/sld.yaml +35 -0
  296. mapproxy/test/system/fixture/source_errors.yaml +84 -0
  297. mapproxy/test/system/fixture/source_errors_raise.yaml +82 -0
  298. mapproxy/test/system/fixture/tileservice_origin.yaml +26 -0
  299. mapproxy/test/system/fixture/tileservice_refresh.yaml +59 -0
  300. mapproxy/test/system/fixture/tilesource_minmax_res.yaml +22 -0
  301. mapproxy/test/system/fixture/util-conf-base-grids.yaml +5 -0
  302. mapproxy/test/system/fixture/util-conf-overwrite.yaml +13 -0
  303. mapproxy/test/system/fixture/util-conf-wms-111-cap.xml +90 -0
  304. mapproxy/test/system/fixture/util_grids.yaml +29 -0
  305. mapproxy/test/system/fixture/util_wms_capabilities111.xml +130 -0
  306. mapproxy/test/system/fixture/util_wms_capabilities130.xml +100 -0
  307. mapproxy/test/system/fixture/util_wms_capabilities_service_exception.xml +5 -0
  308. mapproxy/test/system/fixture/watermark.yaml +50 -0
  309. mapproxy/test/system/fixture/wms_srs_extent.yaml +39 -0
  310. mapproxy/test/system/fixture/wms_versions.yaml +38 -0
  311. mapproxy/test/system/fixture/wmts.yaml +134 -0
  312. mapproxy/test/system/fixture/wmts_dimensions.yaml +57 -0
  313. mapproxy/test/system/fixture/xslt_featureinfo.yaml +54 -0
  314. mapproxy/test/system/fixture/xslt_featureinfo_input.yaml +51 -0
  315. mapproxy/test/system/test_arcgis.py +156 -0
  316. mapproxy/test/system/test_auth.py +1133 -0
  317. mapproxy/test/system/test_behind_proxy.py +75 -0
  318. mapproxy/test/system/test_bulk_meta_tiles.py +106 -0
  319. mapproxy/test/system/test_cache_azureblob.py +127 -0
  320. mapproxy/test/system/test_cache_band_merge.py +103 -0
  321. mapproxy/test/system/test_cache_coverage.py +168 -0
  322. mapproxy/test/system/test_cache_geopackage.py +144 -0
  323. mapproxy/test/system/test_cache_grid_names.py +89 -0
  324. mapproxy/test/system/test_cache_mbtiles.py +85 -0
  325. mapproxy/test/system/test_cache_s3.py +115 -0
  326. mapproxy/test/system/test_cache_source.py +146 -0
  327. mapproxy/test/system/test_combined_sources.py +335 -0
  328. mapproxy/test/system/test_coverage.py +140 -0
  329. mapproxy/test/system/test_decorate_img.py +214 -0
  330. mapproxy/test/system/test_demo.py +56 -0
  331. mapproxy/test/system/test_demo_with_extra_service.py +57 -0
  332. mapproxy/test/system/test_dimensions.py +279 -0
  333. mapproxy/test/system/test_disable_storage.py +42 -0
  334. mapproxy/test/system/test_formats.py +219 -0
  335. mapproxy/test/system/test_inspire_vs.py +173 -0
  336. mapproxy/test/system/test_kml.py +264 -0
  337. mapproxy/test/system/test_layergroups.py +160 -0
  338. mapproxy/test/system/test_legendgraphic.py +308 -0
  339. mapproxy/test/system/test_mapnik.py +162 -0
  340. mapproxy/test/system/test_mapserver.py +83 -0
  341. mapproxy/test/system/test_mixed_mode_format.py +201 -0
  342. mapproxy/test/system/test_multi_cache_layers.py +169 -0
  343. mapproxy/test/system/test_multiapp.py +92 -0
  344. mapproxy/test/system/test_refresh.py +206 -0
  345. mapproxy/test/system/test_renderd_client.py +304 -0
  346. mapproxy/test/system/test_response_headers.py +54 -0
  347. mapproxy/test/system/test_scalehints.py +140 -0
  348. mapproxy/test/system/test_seed.py +425 -0
  349. mapproxy/test/system/test_seed_only.py +93 -0
  350. mapproxy/test/system/test_sld.py +120 -0
  351. mapproxy/test/system/test_source_errors.py +377 -0
  352. mapproxy/test/system/test_tilesource_minmax_res.py +54 -0
  353. mapproxy/test/system/test_tms.py +277 -0
  354. mapproxy/test/system/test_tms_origin.py +46 -0
  355. mapproxy/test/system/test_util_conf.py +434 -0
  356. mapproxy/test/system/test_util_export.py +210 -0
  357. mapproxy/test/system/test_util_grids.py +88 -0
  358. mapproxy/test/system/test_util_wms_capabilities.py +182 -0
  359. mapproxy/test/system/test_watermark.py +91 -0
  360. mapproxy/test/system/test_wms.py +1616 -0
  361. mapproxy/test/system/test_wms_srs_extent.py +165 -0
  362. mapproxy/test/system/test_wms_version.py +85 -0
  363. mapproxy/test/system/test_wmsc.py +116 -0
  364. mapproxy/test/system/test_wmts.py +334 -0
  365. mapproxy/test/system/test_wmts_dimensions.py +206 -0
  366. mapproxy/test/system/test_wmts_restful.py +198 -0
  367. mapproxy/test/system/test_xslt_featureinfo.py +423 -0
  368. mapproxy/test/test_http_helper.py +217 -0
  369. mapproxy/test/unit/__init__.py +0 -0
  370. mapproxy/test/unit/epsg +2 -0
  371. mapproxy/test/unit/polygons/polygons.dbf +0 -0
  372. mapproxy/test/unit/polygons/polygons.shp +0 -0
  373. mapproxy/test/unit/polygons/polygons.shx +0 -0
  374. mapproxy/test/unit/test_async.py +242 -0
  375. mapproxy/test/unit/test_auth.py +430 -0
  376. mapproxy/test/unit/test_cache.py +1356 -0
  377. mapproxy/test/unit/test_cache_azureblob.py +97 -0
  378. mapproxy/test/unit/test_cache_compact.py +324 -0
  379. mapproxy/test/unit/test_cache_couchdb.py +118 -0
  380. mapproxy/test/unit/test_cache_geopackage.py +256 -0
  381. mapproxy/test/unit/test_cache_redis.py +123 -0
  382. mapproxy/test/unit/test_cache_riak.py +80 -0
  383. mapproxy/test/unit/test_cache_s3.py +93 -0
  384. mapproxy/test/unit/test_cache_tile.py +477 -0
  385. mapproxy/test/unit/test_client.py +488 -0
  386. mapproxy/test/unit/test_client_arcgis.py +74 -0
  387. mapproxy/test/unit/test_client_cgi.py +140 -0
  388. mapproxy/test/unit/test_collections.py +116 -0
  389. mapproxy/test/unit/test_concat_legends.py +37 -0
  390. mapproxy/test/unit/test_conf_loader.py +1267 -0
  391. mapproxy/test/unit/test_conf_validator.py +427 -0
  392. mapproxy/test/unit/test_config.py +118 -0
  393. mapproxy/test/unit/test_decorate_img.py +185 -0
  394. mapproxy/test/unit/test_exceptions.py +270 -0
  395. mapproxy/test/unit/test_featureinfo.py +313 -0
  396. mapproxy/test/unit/test_file_lock_load.py +49 -0
  397. mapproxy/test/unit/test_geom.py +512 -0
  398. mapproxy/test/unit/test_grid.py +1279 -0
  399. mapproxy/test/unit/test_image.py +1051 -0
  400. mapproxy/test/unit/test_image_mask.py +181 -0
  401. mapproxy/test/unit/test_image_messages.py +209 -0
  402. mapproxy/test/unit/test_image_options.py +160 -0
  403. mapproxy/test/unit/test_isodate.py +118 -0
  404. mapproxy/test/unit/test_multiapp.py +163 -0
  405. mapproxy/test/unit/test_ogr_reader.py +51 -0
  406. mapproxy/test/unit/test_request.py +745 -0
  407. mapproxy/test/unit/test_request_wmts.py +178 -0
  408. mapproxy/test/unit/test_response.py +78 -0
  409. mapproxy/test/unit/test_seed.py +365 -0
  410. mapproxy/test/unit/test_seed_cachelock.py +91 -0
  411. mapproxy/test/unit/test_srs.py +215 -0
  412. mapproxy/test/unit/test_tiled_source.py +122 -0
  413. mapproxy/test/unit/test_tilefilter.py +31 -0
  414. mapproxy/test/unit/test_times.py +25 -0
  415. mapproxy/test/unit/test_timeutils.py +50 -0
  416. mapproxy/test/unit/test_util_conf_utils.py +75 -0
  417. mapproxy/test/unit/test_utils.py +476 -0
  418. mapproxy/test/unit/test_wms_capabilities.py +44 -0
  419. mapproxy/test/unit/test_wms_layer.py +113 -0
  420. mapproxy/test/unit/test_yaml.py +68 -0
  421. mapproxy/tilefilter.py +61 -0
  422. mapproxy/util/__init__.py +0 -0
  423. mapproxy/util/async_.py +229 -0
  424. mapproxy/util/collections.py +134 -0
  425. mapproxy/util/coverage.py +337 -0
  426. mapproxy/util/ext/__init__.py +14 -0
  427. mapproxy/util/ext/dictspec/__init__.py +1 -0
  428. mapproxy/util/ext/dictspec/spec.py +131 -0
  429. mapproxy/util/ext/dictspec/test/__init__.py +0 -0
  430. mapproxy/util/ext/dictspec/test/test_validator.py +278 -0
  431. mapproxy/util/ext/dictspec/validator.py +194 -0
  432. mapproxy/util/ext/local.py +198 -0
  433. mapproxy/util/ext/lockfile.py +140 -0
  434. mapproxy/util/ext/odict.py +321 -0
  435. mapproxy/util/ext/serving.py +491 -0
  436. mapproxy/util/ext/tempita/__init__.py +1093 -0
  437. mapproxy/util/ext/tempita/_looper.py +163 -0
  438. mapproxy/util/ext/tempita/string_utils.py +24 -0
  439. mapproxy/util/ext/wmsparse/__init__.py +3 -0
  440. mapproxy/util/ext/wmsparse/duration.py +600 -0
  441. mapproxy/util/ext/wmsparse/parse.py +307 -0
  442. mapproxy/util/ext/wmsparse/test/__init__.py +0 -0
  443. mapproxy/util/ext/wmsparse/test/test_parse.py +111 -0
  444. mapproxy/util/ext/wmsparse/test/test_util.py +23 -0
  445. mapproxy/util/ext/wmsparse/test/wms-example-111.xml +90 -0
  446. mapproxy/util/ext/wmsparse/test/wms-example-130.xml +120 -0
  447. mapproxy/util/ext/wmsparse/test/wms-large-111.xml +2114 -0
  448. mapproxy/util/ext/wmsparse/test/wms_nasa_cap.xml +386 -0
  449. mapproxy/util/ext/wmsparse/util.py +189 -0
  450. mapproxy/util/fs.py +164 -0
  451. mapproxy/util/geom.py +307 -0
  452. mapproxy/util/lib.py +117 -0
  453. mapproxy/util/lock.py +171 -0
  454. mapproxy/util/ogr.py +247 -0
  455. mapproxy/util/py.py +75 -0
  456. mapproxy/util/times.py +78 -0
  457. mapproxy/util/yaml.py +58 -0
  458. mapproxy/version.py +33 -0
  459. 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