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,201 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from __future__ import division
17
+
18
+ from contextlib import contextmanager
19
+ from io import BytesIO
20
+
21
+ import pytest
22
+
23
+ from mapproxy.compat.image import Image, ImageDraw, ImageColor
24
+ from mapproxy.request.wms import WMS111MapRequest
25
+ from mapproxy.request.wmts import WMTS100TileRequest
26
+ from mapproxy.test.image import check_format, is_transparent
27
+ from mapproxy.test.http import mock_httpd
28
+ from mapproxy.test.system import SysTest
29
+
30
+
31
+ @pytest.fixture(scope="module")
32
+ def config_file():
33
+ return "mixed_mode.yaml"
34
+
35
+
36
+ class TestWMS(SysTest):
37
+
38
+ def setup_method(self):
39
+ self.common_map_req = WMS111MapRequest(
40
+ url="/service?",
41
+ param=dict(
42
+ service="WMS",
43
+ version="1.1.1",
44
+ bbox="0,0,180,80",
45
+ width="200",
46
+ height="200",
47
+ layers="mixed_mode",
48
+ srs="EPSG:4326",
49
+ format="image/png",
50
+ styles="",
51
+ request="GetMap",
52
+ transparent="true",
53
+ ),
54
+ )
55
+ self.expected_base_path = "/service?SERVICE=WMS&REQUEST=GetMap&HEIGHT=256"\
56
+ "&SRS=EPSG%3A900913&styles=&VERSION=1.1.1&WIDTH=512"\
57
+ "&BBOX=-20037508.3428,0.0,20037508.3428,20037508.3428"
58
+
59
+ def test_mixed_mode(self, app, cache_dir):
60
+ req_format = "png"
61
+ transparent = "True"
62
+ with create_mixed_mode_img((512, 256)) as img:
63
+ expected_req = (
64
+ {
65
+ "path": self.expected_base_path
66
+ + "&layers=mixedsource"
67
+ + "&format=image%2F"
68
+ + req_format
69
+ + "&transparent="
70
+ + transparent
71
+ },
72
+ {
73
+ "body": img.read(),
74
+ "headers": {"content-type": "image/" + req_format},
75
+ },
76
+ )
77
+ with mock_httpd(
78
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
79
+ ):
80
+ self.common_map_req.params["format"] = "image/" + req_format
81
+ resp = app.get(self.common_map_req)
82
+
83
+ assert resp.content_type == "image/" + req_format
84
+ check_format(BytesIO(resp.body), req_format)
85
+ # GetMap Request is fully within the opaque tile
86
+ assert not is_transparent(resp.body)
87
+
88
+ # check cache formats
89
+ for f, format in [
90
+ ["mixed_cache_EPSG900913/01/000/000/000/000/000/001.mixed", "png"],
91
+ ["mixed_cache_EPSG900913/01/000/000/001/000/000/001.mixed", "jpeg"],
92
+ ]:
93
+ assert cache_dir.join(f).check()
94
+ check_format(cache_dir.join(f).read_binary(), format)
95
+
96
+
97
+ class TestTMS(SysTest):
98
+
99
+ def setup_method(self):
100
+ self.expected_base_path = "/service?SERVICE=WMS&REQUEST=GetMap&HEIGHT=256"\
101
+ "&SRS=EPSG%3A900913&styles=&VERSION=1.1.1&WIDTH=512"\
102
+ "&BBOX=-20037508.3428,-20037508.3428,20037508.3428,0.0"
103
+
104
+ def test_mixed_mode(self, app, cache_dir):
105
+ with create_mixed_mode_img((512, 256)) as img:
106
+ expected_req = (
107
+ {
108
+ "path": self.expected_base_path
109
+ + "&layers=mixedsource"
110
+ + "&format=image%2Fpng"
111
+ + "&transparent=True"
112
+ },
113
+ {"body": img.read(), "headers": {"content-type": "image/png"}},
114
+ )
115
+ with mock_httpd(
116
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
117
+ ):
118
+ resp = app.get("/tms/1.0.0/mixed_mode/0/0/0.png")
119
+ assert resp.content_type == "image/png"
120
+ assert is_transparent(resp.body)
121
+
122
+ resp = app.get("/tms/1.0.0/mixed_mode/0/1/0.png")
123
+
124
+ assert resp.content_type == "image/jpeg"
125
+ assert cache_dir.join(
126
+ "mixed_cache_EPSG900913/01/000/000/000/000/000/000.mixed"
127
+ ).check()
128
+ assert cache_dir.join(
129
+ "mixed_cache_EPSG900913/01/000/000/001/000/000/000.mixed"
130
+ ).check()
131
+
132
+
133
+ class TestWMTS(SysTest):
134
+
135
+ def setup_method(self):
136
+ self.common_tile_req = WMTS100TileRequest(
137
+ url="/service?",
138
+ param=dict(
139
+ service="WMTS",
140
+ version="1.0.0",
141
+ tilerow="0",
142
+ tilecol="0",
143
+ tilematrix="01",
144
+ tilematrixset="GLOBAL_MERCATOR",
145
+ layer="mixed_mode",
146
+ format="image/png",
147
+ style="",
148
+ request="GetTile",
149
+ transparent="True",
150
+ ),
151
+ )
152
+ self.expected_base_path = "/service?SERVICE=WMS&REQUEST=GetMap&HEIGHT=256"\
153
+ "&SRS=EPSG%3A900913&styles=&VERSION=1.1.1&WIDTH=512"\
154
+ "&BBOX=-20037508.3428,0.0,20037508.3428,20037508.3428"
155
+
156
+ def test_mixed_mode(self, app, cache_dir):
157
+ with create_mixed_mode_img((512, 256)) as img:
158
+ expected_req = (
159
+ {
160
+ "path": self.expected_base_path
161
+ + "&layers=mixedsource"
162
+ + "&format=image%2Fpng"
163
+ + "&transparent=True"
164
+ },
165
+ {"body": img.read(), "headers": {"content-type": "image/png"}},
166
+ )
167
+ with mock_httpd(
168
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
169
+ ):
170
+ resp = app.get(self.common_tile_req)
171
+ assert resp.content_type == "image/png"
172
+ assert is_transparent(resp.body)
173
+
174
+ self.common_tile_req.params["tilecol"] = "1"
175
+ resp = app.get(self.common_tile_req)
176
+ assert resp.content_type == "image/jpeg"
177
+ assert cache_dir.join(
178
+ "mixed_cache_EPSG900913/01/000/000/000/000/000/001.mixed"
179
+ ).check()
180
+ assert cache_dir.join(
181
+ "mixed_cache_EPSG900913/01/000/000/001/000/000/001.mixed"
182
+ ).check()
183
+
184
+
185
+ @contextmanager
186
+ def create_mixed_mode_img(size, format="png"):
187
+ img = Image.new("RGBA", size)
188
+
189
+ # draw a black rectangle into the image, rect_width = 3/4 img_width
190
+ # thus 1/4 of the image is transparent and with square tiles, one of two
191
+ # tiles (img size = 512x256) will be fully opaque and the other
192
+ # has transparency
193
+ draw = ImageDraw.Draw(img)
194
+ w, h = size
195
+ red_color = ImageColor.getrgb("red")
196
+ draw.rectangle((w / 4, 0, w, h), fill=red_color)
197
+
198
+ data = BytesIO()
199
+ img.save(data, format)
200
+ data.seek(0)
201
+ yield data
@@ -0,0 +1,169 @@
1
+ # -:- encoding: utf8 -:-
2
+ # This file is part of the MapProxy project.
3
+ # Copyright (C) 2015 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 division
18
+
19
+ from io import BytesIO
20
+
21
+ import pytest
22
+
23
+ from mapproxy.request.wmts import WMTS100TileRequest, WMTS100CapabilitiesRequest
24
+ from mapproxy.request.wms import WMS111CapabilitiesRequest
25
+ from mapproxy.test.image import is_png, create_tmp_image
26
+ from mapproxy.test.http import MockServ
27
+ from mapproxy.test.helper import validate_with_xsd
28
+ from mapproxy.test.system import SysTest
29
+
30
+
31
+ @pytest.fixture(scope="module")
32
+ def config_file():
33
+ return "multi_cache_layers.yaml"
34
+
35
+
36
+ ns_wmts = {
37
+ "wmts": "http://www.opengis.net/wmts/1.0",
38
+ "ows": "http://www.opengis.net/ows/1.1",
39
+ "xlink": "http://www.w3.org/1999/xlink",
40
+ }
41
+
42
+
43
+ TEST_TILE = create_tmp_image((256, 256))
44
+
45
+
46
+ class TestMultiCacheLayer(SysTest):
47
+
48
+ def setup_method(self):
49
+ self.common_cap_req = WMTS100CapabilitiesRequest(
50
+ url="/service?",
51
+ param=dict(service="WMTS", version="1.0.0", request="GetCapabilities"),
52
+ )
53
+ self.common_tile_req = WMTS100TileRequest(
54
+ url="/service?",
55
+ param=dict(
56
+ service="WMTS",
57
+ version="1.0.0",
58
+ tilerow="0",
59
+ tilecol="0",
60
+ tilematrix="01",
61
+ tilematrixset="GLOBAL_WEBMERCATOR",
62
+ layer="multi_cache",
63
+ format="image/png",
64
+ style="",
65
+ request="GetTile",
66
+ ),
67
+ )
68
+
69
+ def test_image_config(self, app):
70
+ resp = app.get("/tms/1.0.0/")
71
+ assert "http://localhost/tms/1.0.0/cache_image/EPSG25832" in resp
72
+
73
+ def test_tms_capabilities(self, app):
74
+ resp = app.get("/tms/1.0.0/")
75
+ assert "http://localhost/tms/1.0.0/multi_cache/EPSG25832" in resp
76
+ assert "http://localhost/tms/1.0.0/multi_cache/EPSG3857" in resp
77
+ assert "http://localhost/tms/1.0.0/multi_cache/CRS84" in resp
78
+ assert "http://localhost/tms/1.0.0/multi_cache/EPSG31467" in resp
79
+ assert "http://localhost/tms/1.0.0/cache/EPSG25832" in resp
80
+ xml = resp.lxml
81
+ assert xml.xpath("count(//TileMap)") == 8
82
+
83
+ def test_wmts_capabilities(self, app):
84
+ req = str(self.common_cap_req)
85
+ resp = app.get(req)
86
+ assert resp.content_type == "application/xml"
87
+ xml = resp.lxml
88
+
89
+ assert validate_with_xsd(
90
+ xml, xsd_name="wmts/1.0/wmtsGetCapabilities_response.xsd"
91
+ )
92
+ assert set(
93
+ xml.xpath("//wmts:Layer/ows:Identifier/text()", namespaces=ns_wmts)
94
+ ) == set(["cache", "multi_cache", "cache_image"])
95
+ assert set(
96
+ xml.xpath(
97
+ "//wmts:Contents/wmts:TileMatrixSet/ows:Identifier/text()",
98
+ namespaces=ns_wmts,
99
+ )
100
+ ) == set(["gk3", "GLOBAL_WEBMERCATOR", "utm32", "InspireCrs84Quad"])
101
+
102
+ def test_wms_capabilities(self, app):
103
+ req = WMS111CapabilitiesRequest(url="/service?")
104
+ resp = app.get(req)
105
+ assert resp.content_type == "application/vnd.ogc.wms_xml"
106
+ xml = resp.lxml
107
+ assert (
108
+ xml.xpath(
109
+ "//GetMap//OnlineResource/@xlink:href",
110
+ namespaces=dict(xlink="http://www.w3.org/1999/xlink"),
111
+ )[0]
112
+ == "http://localhost/service?"
113
+ )
114
+
115
+ layer_names = set(xml.xpath("//Layer/Layer/Name/text()"))
116
+ expected_names = set(["wms_only", "cache", "cache_image"])
117
+ assert layer_names == expected_names
118
+
119
+ def test_get_tile_webmerc(self, app):
120
+ serv = MockServ(42423, bbox_aware_query_comparator=True)
121
+ serv.expects(
122
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=-20037508.3428,0.0,0.0,20037508.3428&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A3857&request=GetMap&height=256" # noqa
123
+ ).returns(TEST_TILE)
124
+ with serv:
125
+ resp = app.get(str(self.common_tile_req))
126
+ assert resp.content_type == "image/png"
127
+ data = BytesIO(resp.body)
128
+ assert is_png(data)
129
+
130
+ def test_get_tile_utm(self, app):
131
+ serv = MockServ(42423, bbox_aware_query_comparator=True)
132
+ serv.expects(
133
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=-46133.17,5675047.40429,580038.965712,6301219.54&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
134
+ ).returns(TEST_TILE)
135
+ self.common_tile_req.params["tilematrixset"] = "utm32"
136
+
137
+ with serv:
138
+ resp = app.get(str(self.common_tile_req))
139
+ assert resp.content_type == "image/png"
140
+ data = BytesIO(resp.body)
141
+ assert is_png(data)
142
+
143
+ def test_get_tile_cascaded_cache(self, app):
144
+ serv = MockServ(42423, bbox_aware_query_comparator=True, unordered=True)
145
+ # gk3 cache requests UTM tiles
146
+ serv.expects(
147
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=423495.931784,5596775.88732,501767.448748,5675047.40429&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
148
+ ).returns(TEST_TILE)
149
+ serv.expects(
150
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=345224.41482,5596775.88732,423495.931784,5675047.40429&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
151
+ ).returns(TEST_TILE)
152
+ serv.expects(
153
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=345224.41482,5518504.37036,423495.931784,5596775.88732&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
154
+ ).returns(TEST_TILE)
155
+ serv.expects(
156
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=423495.931784,5518504.37036,501767.448748,5596775.88732&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
157
+ ).returns(TEST_TILE)
158
+ serv.expects(
159
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=345224.41482,5440232.8534,423495.931784,5518504.37036&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
160
+ ).returns(TEST_TILE)
161
+ serv.expects(
162
+ "/service?layers=foo,bar&width=256&version=1.1.1&bbox=423495.931784,5440232.8534,501767.448748,5518504.37036&service=WMS&format=image%2Fpng&styles=&srs=EPSG%3A25832&request=GetMap&height=256" # noqa
163
+ ).returns(TEST_TILE)
164
+ self.common_tile_req.params["tilematrixset"] = "gk3"
165
+ with serv:
166
+ resp = app.get(str(self.common_tile_req))
167
+ assert resp.content_type == "image/png"
168
+ data = BytesIO(resp.body)
169
+ assert is_png(data)
@@ -0,0 +1,92 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from __future__ import division
17
+
18
+ import io
19
+ import os
20
+ import shutil
21
+
22
+ import pytest
23
+
24
+ from mapproxy.multiapp import make_wsgi_app
25
+
26
+ from mapproxy.test.system import SysTest, WSGITestApp
27
+
28
+
29
+ class TestMultiapp(SysTest):
30
+
31
+ @pytest.fixture(scope="class")
32
+ def app(self, base_dir):
33
+ app = make_wsgi_app(base_dir.strpath, allow_listing=False)
34
+ return WSGITestApp(app, use_unicode=False)
35
+
36
+ @pytest.fixture(scope="class")
37
+ def base_dir(self, tmpdir_factory):
38
+ dir = tmpdir_factory.mktemp("base_dir")
39
+
40
+ fixture_dir = os.path.join(os.path.dirname(__file__), "fixture")
41
+ shutil.copy(os.path.join(fixture_dir, "multiapp1.yaml"), dir.strpath)
42
+ shutil.copy(os.path.join(fixture_dir, "multiapp2.yaml"), dir.strpath)
43
+
44
+ return dir
45
+
46
+ def test_index_without_list(self, app):
47
+ resp = app.get("/")
48
+ assert "MapProxy" in resp
49
+ assert "multiapp1" not in resp
50
+
51
+ def test_index_with_list(self, app):
52
+ try:
53
+ app.app.list_apps = True
54
+ resp = app.get("/")
55
+ assert "MapProxy" in resp
56
+ assert "multiapp1" in resp
57
+ finally:
58
+ app.app.list_apps = False
59
+
60
+ def test_unknown_app(self, app):
61
+ app.get("/unknownapp", status=404)
62
+ # assert status == 404 Not Found in app.get
63
+
64
+ def test_known_app(self, app):
65
+ resp = app.get("/multiapp1")
66
+ assert "demo" in resp
67
+
68
+ def test_reloading(self, app, base_dir):
69
+ resp = app.get("/multiapp1")
70
+ assert "demo" in resp
71
+ app_config = base_dir.join("multiapp1.yaml").strpath
72
+
73
+ replace_text_in_file(app_config, " demo:", " #demo:", ts_delta=5)
74
+
75
+ resp = app.get("/multiapp1")
76
+ assert "demo" not in resp
77
+
78
+ replace_text_in_file(app_config, " #demo:", " demo:", ts_delta=10)
79
+
80
+ resp = app.get("/multiapp1")
81
+ assert "demo" in resp
82
+
83
+
84
+ def replace_text_in_file(filename, old, new, ts_delta=2):
85
+ text = io.open(filename, encoding="utf-8").read()
86
+ text = text.replace(old, new)
87
+ io.open(filename, "w", encoding="utf-8").write(text)
88
+
89
+ # file timestamps are not precise enough (1sec)
90
+ # add larger delta to force reload
91
+ m_time = os.path.getmtime(filename)
92
+ os.utime(filename, (m_time + ts_delta, m_time + ts_delta))
@@ -0,0 +1,206 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010-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
+ import time
17
+
18
+ from io import BytesIO
19
+ import pytest
20
+
21
+ from mapproxy.compat.image import Image
22
+ from mapproxy.test.image import tmp_image
23
+ from mapproxy.test.http import mock_httpd
24
+ from mapproxy.test.system import SysTest
25
+ from mapproxy.util.times import timestamp_from_isodate
26
+
27
+
28
+ @pytest.fixture(scope="module")
29
+ def config_file():
30
+ return "tileservice_refresh.yaml"
31
+
32
+
33
+ class TestRefresh(SysTest):
34
+
35
+ def test_refresh_tile_1s(self, app, cache_dir):
36
+ with tmp_image((256, 256), format="jpeg") as img:
37
+ expected_req = (
38
+ {
39
+ "path": r"/service?LAYERs=bar&SERVICE=WMS&FORMAT=image%2Fjpeg"
40
+ "&REQUEST=GetMap&HEIGHT=256&SRS=EPSG%3A900913&styles="
41
+ "&VERSION=1.1.1&BBOX=-20037508.3428,-20037508.3428,0.0,0.0"
42
+ "&WIDTH=256"
43
+ },
44
+ {"body": img.read(), "headers": {"content-type": "image/jpeg"}},
45
+ )
46
+ with mock_httpd(
47
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
48
+ ):
49
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
50
+ assert resp.content_type == "image/jpeg"
51
+ file_path = cache_dir.join(
52
+ "wms_cache_EPSG900913/01/000/000/000/000/000/000.jpeg"
53
+ )
54
+ assert file_path.check()
55
+ t1 = file_path.mtime()
56
+ # file_path.remove()
57
+ # assert not file_path.check()
58
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
59
+ assert resp.content_type == "image/jpeg"
60
+ assert file_path.check()
61
+ t2 = file_path.mtime()
62
+ # tile is expired after 1 sec, so it will be fetched again from mock server
63
+ time.sleep(1.2)
64
+ with mock_httpd(
65
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
66
+ ):
67
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
68
+ assert resp.content_type == "image/jpeg"
69
+ assert file_path.check()
70
+ t3 = file_path.mtime()
71
+ assert t2 == t1
72
+ assert t3 > t2
73
+
74
+ def test_refresh_tile_mtime(self, app, cache_dir):
75
+ with tmp_image((256, 256), format="jpeg") as img:
76
+ expected_req = (
77
+ {
78
+ "path": r"/service?LAYERs=bar&SERVICE=WMS&FORMAT=image%2Fjpeg"
79
+ "&REQUEST=GetMap&HEIGHT=256&SRS=EPSG%3A900913&styles="
80
+ "&VERSION=1.1.1&BBOX=-20037508.3428,-20037508.3428,0.0,0.0"
81
+ "&WIDTH=256"
82
+ },
83
+ {"body": img.read(), "headers": {"content-type": "image/jpeg"}},
84
+ )
85
+ with mock_httpd(
86
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
87
+ ):
88
+ resp = app.get("/tiles/wms_cache_isotime/1/0/0.jpeg")
89
+ assert resp.content_type == "image/jpeg"
90
+ file_path = cache_dir.join(
91
+ "wms_cache_isotime_EPSG900913/01/000/000/000/000/000/000.jpeg"
92
+ )
93
+ assert file_path.check()
94
+ timestamp = timestamp_from_isodate("2009-02-15T23:31:30")
95
+ file_path.setmtime(timestamp + 1.2)
96
+ t1 = file_path.mtime()
97
+ resp = app.get("/tiles/wms_cache_isotime/1/0/0.jpeg")
98
+ assert resp.content_type == "image/jpeg"
99
+ t2 = file_path.mtime()
100
+ file_path.setmtime(timestamp - 1.2)
101
+ with mock_httpd(
102
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
103
+ ):
104
+ resp = app.get("/tiles/wms_cache_isotime/1/0/0.jpeg")
105
+ assert resp.content_type == "image/jpeg"
106
+ assert file_path.check()
107
+ t3 = file_path.mtime()
108
+ assert t2 == t1
109
+ assert t3 > t2
110
+
111
+ def test_refresh_tile_source_error_no_stale(self, app, cache_dir):
112
+ source_request = {
113
+ "path": r"/service?LAYERs=bar&SERVICE=WMS&FORMAT=image%2Fpng"
114
+ "&REQUEST=GetMap&HEIGHT=256&SRS=EPSG%3A900913&styles="
115
+ "&VERSION=1.1.1&BBOX=-20037508.3428,-20037508.3428,0.0,0.0"
116
+ "&WIDTH=256"
117
+ }
118
+ with tmp_image((256, 256), format="png") as img:
119
+ expected_req = (
120
+ source_request,
121
+ {"body": img.read(), "headers": {"content-type": "image/png"}},
122
+ )
123
+ with mock_httpd(
124
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
125
+ ):
126
+ resp = app.get("/tiles/wms_cache_png/1/0/0.png")
127
+ assert resp.content_type == "image/png"
128
+ img.seek(0)
129
+ assert resp.body == img.read()
130
+ resp = app.get("/tiles/wms_cache_png/1/0/0.png")
131
+ assert resp.content_type == "image/png"
132
+ img.seek(0)
133
+ assert resp.body == img.read()
134
+ # tile is expired after 1 sec, so it will be requested again from mock server
135
+ time.sleep(1.2)
136
+ expected_req = (
137
+ source_request,
138
+ {"body": "", "status": 404},
139
+ )
140
+ with mock_httpd(
141
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
142
+ ):
143
+ resp = app.get("/tiles/wms_cache_png/1/0/0.png")
144
+ assert resp.content_type == "image/png"
145
+ # error handler for 404 does not authorise stale tiles, so transparent tile will be rendered
146
+ resp_img = Image.open(BytesIO(resp.body))
147
+ # check response transparency
148
+ assert resp_img.getbands() == ('R', 'G', 'B', 'A')
149
+ assert resp_img.getextrema()[3] == (0, 0)
150
+
151
+ expected_req = (
152
+ source_request,
153
+ {"body": "", "status": 405},
154
+ )
155
+ with mock_httpd(
156
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
157
+ ):
158
+ resp = app.get("/tiles/wms_cache_png/1/0/0.png")
159
+ assert resp.content_type == "image/png"
160
+ # error handler for 405 does not authorise stale tiles, so red tile will be rendered
161
+ resp_img = Image.open(BytesIO(resp.body))
162
+ # check response red color
163
+ assert resp_img.getbands() == ('R', 'G', 'B')
164
+ assert resp_img.getextrema() == ((255, 255), (0, 0), (0, 0))
165
+
166
+ def test_refresh_tile_source_error_stale(self, app, cache_dir):
167
+ with tmp_image((256, 256), format="jpeg") as img:
168
+ expected_req = (
169
+ {
170
+ "path": r"/service?LAYERs=bar&SERVICE=WMS&FORMAT=image%2Fjpeg"
171
+ "&REQUEST=GetMap&HEIGHT=256&SRS=EPSG%3A900913&styles="
172
+ "&VERSION=1.1.1&BBOX=-20037508.3428,-20037508.3428,0.0,0.0"
173
+ "&WIDTH=256"
174
+ },
175
+ {"body": img.read(), "headers": {"content-type": "image/jpeg"}},
176
+ )
177
+ with mock_httpd(
178
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
179
+ ):
180
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
181
+ assert resp.content_type == "image/jpeg"
182
+ img.seek(0)
183
+ assert resp.body == img.read()
184
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
185
+ assert resp.content_type == "image/jpeg"
186
+ img.seek(0)
187
+ assert resp.body == img.read()
188
+ # tile is expired after 1 sec, so it will be fetched again from mock server
189
+ time.sleep(1.2)
190
+ expected_req = (
191
+ {
192
+ "path": r"/service?LAYERs=bar&SERVICE=WMS&FORMAT=image%2Fjpeg"
193
+ "&REQUEST=GetMap&HEIGHT=256&SRS=EPSG%3A900913&styles="
194
+ "&VERSION=1.1.1&BBOX=-20037508.3428,-20037508.3428,0.0,0.0"
195
+ "&WIDTH=256"
196
+ },
197
+ {"body": "", "status": 406},
198
+ )
199
+ with mock_httpd(
200
+ ("localhost", 42423), [expected_req], bbox_aware_query_comparator=True
201
+ ):
202
+ resp = app.get("/tiles/wms_cache/1/0/0.jpeg")
203
+ assert resp.content_type == "image/jpeg"
204
+ # Check that initial non empty img is served as a stale tile
205
+ img.seek(0)
206
+ assert resp.body == img.read()