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