MapProxy 1.16.1__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 (458) hide show
  1. mapproxy/__init__.py +0 -0
  2. mapproxy/cache/__init__.py +36 -0
  3. mapproxy/cache/azureblob.py +145 -0
  4. mapproxy/cache/base.py +111 -0
  5. mapproxy/cache/compact.py +664 -0
  6. mapproxy/cache/couchdb.py +295 -0
  7. mapproxy/cache/dummy.py +34 -0
  8. mapproxy/cache/file.py +185 -0
  9. mapproxy/cache/geopackage.py +609 -0
  10. mapproxy/cache/legend.py +83 -0
  11. mapproxy/cache/mbtiles.py +392 -0
  12. mapproxy/cache/meta.py +78 -0
  13. mapproxy/cache/path.py +250 -0
  14. mapproxy/cache/redis.py +88 -0
  15. mapproxy/cache/renderd.py +95 -0
  16. mapproxy/cache/riak.py +202 -0
  17. mapproxy/cache/s3.py +177 -0
  18. mapproxy/cache/tile.py +699 -0
  19. mapproxy/client/__init__.py +0 -0
  20. mapproxy/client/arcgis.py +79 -0
  21. mapproxy/client/cgi.py +139 -0
  22. mapproxy/client/http.py +315 -0
  23. mapproxy/client/log.py +33 -0
  24. mapproxy/client/tile.py +150 -0
  25. mapproxy/client/wms.py +254 -0
  26. mapproxy/compat/__init__.py +46 -0
  27. mapproxy/compat/image.py +79 -0
  28. mapproxy/compat/itertools.py +29 -0
  29. mapproxy/compat/modules.py +13 -0
  30. mapproxy/config/__init__.py +22 -0
  31. mapproxy/config/config.py +201 -0
  32. mapproxy/config/coverage.py +107 -0
  33. mapproxy/config/defaults.py +98 -0
  34. mapproxy/config/loader.py +2286 -0
  35. mapproxy/config/spec.py +644 -0
  36. mapproxy/config/validator.py +239 -0
  37. mapproxy/config_template/__init__.py +0 -0
  38. mapproxy/config_template/base_config/config.wsgi +10 -0
  39. mapproxy/config_template/base_config/full_example.yaml +593 -0
  40. mapproxy/config_template/base_config/full_seed_example.yaml +79 -0
  41. mapproxy/config_template/base_config/log.ini +35 -0
  42. mapproxy/config_template/base_config/mapproxy.yaml +60 -0
  43. mapproxy/config_template/base_config/seed.yaml +27 -0
  44. mapproxy/exception.py +142 -0
  45. mapproxy/featureinfo.py +252 -0
  46. mapproxy/grid.py +1170 -0
  47. mapproxy/image/__init__.py +536 -0
  48. mapproxy/image/fonts/DejaVuSans.ttf +0 -0
  49. mapproxy/image/fonts/DejaVuSansMono.ttf +0 -0
  50. mapproxy/image/fonts/LICENSE +99 -0
  51. mapproxy/image/fonts/__init__.py +0 -0
  52. mapproxy/image/mask.py +75 -0
  53. mapproxy/image/merge.py +316 -0
  54. mapproxy/image/message.py +347 -0
  55. mapproxy/image/opts.py +182 -0
  56. mapproxy/image/tile.py +167 -0
  57. mapproxy/image/transform.py +350 -0
  58. mapproxy/layer.py +470 -0
  59. mapproxy/multiapp.py +231 -0
  60. mapproxy/proj.py +302 -0
  61. mapproxy/request/__init__.py +18 -0
  62. mapproxy/request/arcgis.py +259 -0
  63. mapproxy/request/base.py +476 -0
  64. mapproxy/request/tile.py +128 -0
  65. mapproxy/request/wms/__init__.py +793 -0
  66. mapproxy/request/wms/exception.py +99 -0
  67. mapproxy/request/wmts.py +436 -0
  68. mapproxy/response.py +237 -0
  69. mapproxy/script/__init__.py +0 -0
  70. mapproxy/script/conf/__init__.py +0 -0
  71. mapproxy/script/conf/app.py +195 -0
  72. mapproxy/script/conf/caches.py +45 -0
  73. mapproxy/script/conf/layers.py +54 -0
  74. mapproxy/script/conf/seeds.py +37 -0
  75. mapproxy/script/conf/sources.py +86 -0
  76. mapproxy/script/conf/utils.py +143 -0
  77. mapproxy/script/defrag.py +184 -0
  78. mapproxy/script/export.py +333 -0
  79. mapproxy/script/grids.py +188 -0
  80. mapproxy/script/scales.py +126 -0
  81. mapproxy/script/util.py +406 -0
  82. mapproxy/script/wms_capabilities.py +152 -0
  83. mapproxy/seed/__init__.py +0 -0
  84. mapproxy/seed/cachelock.py +121 -0
  85. mapproxy/seed/cleanup.py +187 -0
  86. mapproxy/seed/config.py +469 -0
  87. mapproxy/seed/script.py +388 -0
  88. mapproxy/seed/seeder.py +538 -0
  89. mapproxy/seed/spec.py +64 -0
  90. mapproxy/seed/util.py +254 -0
  91. mapproxy/service/__init__.py +14 -0
  92. mapproxy/service/base.py +46 -0
  93. mapproxy/service/demo.py +356 -0
  94. mapproxy/service/kml.py +331 -0
  95. mapproxy/service/ows.py +38 -0
  96. mapproxy/service/template_helper.py +53 -0
  97. mapproxy/service/templates/demo/capabilities_demo.html +16 -0
  98. mapproxy/service/templates/demo/demo.html +181 -0
  99. mapproxy/service/templates/demo/openlayers-demo.cfg +16 -0
  100. mapproxy/service/templates/demo/static/img/blank.gif +0 -0
  101. mapproxy/service/templates/demo/static/img/east-mini.png +0 -0
  102. mapproxy/service/templates/demo/static/img/north-mini.png +0 -0
  103. mapproxy/service/templates/demo/static/img/south-mini.png +0 -0
  104. mapproxy/service/templates/demo/static/img/west-mini.png +0 -0
  105. mapproxy/service/templates/demo/static/img/zoom-minus-mini.png +0 -0
  106. mapproxy/service/templates/demo/static/img/zoom-plus-mini.png +0 -0
  107. mapproxy/service/templates/demo/static/img/zoom-world-mini.png +0 -0
  108. mapproxy/service/templates/demo/static/logo.png +0 -0
  109. mapproxy/service/templates/demo/static/ol.css +345 -0
  110. mapproxy/service/templates/demo/static/ol.js +4 -0
  111. mapproxy/service/templates/demo/static/proj4.min.js +1 -0
  112. mapproxy/service/templates/demo/static/proj4defs.js +1 -0
  113. mapproxy/service/templates/demo/static/site.css +137 -0
  114. mapproxy/service/templates/demo/static/theme/default/framedCloud.css +0 -0
  115. mapproxy/service/templates/demo/static/theme/default/google.css +17 -0
  116. mapproxy/service/templates/demo/static/theme/default/ie6-style.css +10 -0
  117. mapproxy/service/templates/demo/static/theme/default/style.css +482 -0
  118. mapproxy/service/templates/demo/static.html +34 -0
  119. mapproxy/service/templates/demo/tms_demo.html +103 -0
  120. mapproxy/service/templates/demo/wms_demo.html +140 -0
  121. mapproxy/service/templates/demo/wmts_demo.html +110 -0
  122. mapproxy/service/templates/tms_capabilities.xml +13 -0
  123. mapproxy/service/templates/tms_exception.xml +4 -0
  124. mapproxy/service/templates/tms_root_resource.xml +7 -0
  125. mapproxy/service/templates/tms_tilemap_capabilities.xml +14 -0
  126. mapproxy/service/templates/wms100capabilities.xml +112 -0
  127. mapproxy/service/templates/wms100exception.xml +4 -0
  128. mapproxy/service/templates/wms110capabilities.xml +152 -0
  129. mapproxy/service/templates/wms110exception.xml +5 -0
  130. mapproxy/service/templates/wms111capabilities.xml +183 -0
  131. mapproxy/service/templates/wms111exception.xml +5 -0
  132. mapproxy/service/templates/wms130capabilities.xml +326 -0
  133. mapproxy/service/templates/wms130exception.xml +8 -0
  134. mapproxy/service/templates/wmts100capabilities.xml +155 -0
  135. mapproxy/service/templates/wmts100exception.xml +9 -0
  136. mapproxy/service/tile.py +536 -0
  137. mapproxy/service/wms.py +851 -0
  138. mapproxy/service/wmts.py +381 -0
  139. mapproxy/source/__init__.py +75 -0
  140. mapproxy/source/arcgis.py +39 -0
  141. mapproxy/source/error.py +39 -0
  142. mapproxy/source/mapnik.py +259 -0
  143. mapproxy/source/tile.py +96 -0
  144. mapproxy/source/wms.py +270 -0
  145. mapproxy/srs.py +726 -0
  146. mapproxy/template.py +54 -0
  147. mapproxy/test/__init__.py +0 -0
  148. mapproxy/test/conftest.py +7 -0
  149. mapproxy/test/helper.py +247 -0
  150. mapproxy/test/http.py +494 -0
  151. mapproxy/test/image.py +210 -0
  152. mapproxy/test/mocker.py +2268 -0
  153. mapproxy/test/schemas/inspire/common/1.0/common.xsd +1461 -0
  154. mapproxy/test/schemas/inspire/common/1.0/enums/enum_bul.xsd +108 -0
  155. mapproxy/test/schemas/inspire/common/1.0/enums/enum_cze.xsd +108 -0
  156. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dan.xsd +108 -0
  157. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dut.xsd +108 -0
  158. mapproxy/test/schemas/inspire/common/1.0/enums/enum_eng.xsd +155 -0
  159. mapproxy/test/schemas/inspire/common/1.0/enums/enum_est.xsd +108 -0
  160. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fin.xsd +108 -0
  161. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fre.xsd +108 -0
  162. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ger.xsd +108 -0
  163. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gle.xsd +109 -0
  164. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gre.xsd +108 -0
  165. mapproxy/test/schemas/inspire/common/1.0/enums/enum_hun.xsd +108 -0
  166. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ita.xsd +108 -0
  167. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lav.xsd +108 -0
  168. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lit.xsd +108 -0
  169. mapproxy/test/schemas/inspire/common/1.0/enums/enum_mlt.xsd +108 -0
  170. mapproxy/test/schemas/inspire/common/1.0/enums/enum_pol.xsd +108 -0
  171. mapproxy/test/schemas/inspire/common/1.0/enums/enum_por.xsd +108 -0
  172. mapproxy/test/schemas/inspire/common/1.0/enums/enum_rum.xsd +108 -0
  173. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slo.xsd +108 -0
  174. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slv.xsd +108 -0
  175. mapproxy/test/schemas/inspire/common/1.0/enums/enum_spa.xsd +108 -0
  176. mapproxy/test/schemas/inspire/common/1.0/enums/enum_swe.xsd +108 -0
  177. mapproxy/test/schemas/inspire/common/1.0/network.xsd +521 -0
  178. mapproxy/test/schemas/inspire/inspire_vs/1.0/inspire_vs.xsd +19 -0
  179. mapproxy/test/schemas/kml/2.2.0/ReadMe.txt +14 -0
  180. mapproxy/test/schemas/kml/2.2.0/atom-author-link.xsd +66 -0
  181. mapproxy/test/schemas/kml/2.2.0/ogckml22.xsd +1646 -0
  182. mapproxy/test/schemas/kml/2.2.0/xAL.xsd +1680 -0
  183. mapproxy/test/schemas/ows/1.1.0/ReadMe.txt +87 -0
  184. mapproxy/test/schemas/ows/1.1.0/ows19115subset.xsd +235 -0
  185. mapproxy/test/schemas/ows/1.1.0/owsAll.xsd +23 -0
  186. mapproxy/test/schemas/ows/1.1.0/owsCommon.xsd +157 -0
  187. mapproxy/test/schemas/ows/1.1.0/owsContents.xsd +86 -0
  188. mapproxy/test/schemas/ows/1.1.0/owsDataIdentification.xsd +127 -0
  189. mapproxy/test/schemas/ows/1.1.0/owsDomainType.xsd +279 -0
  190. mapproxy/test/schemas/ows/1.1.0/owsExceptionReport.xsd +76 -0
  191. mapproxy/test/schemas/ows/1.1.0/owsGetCapabilities.xsd +112 -0
  192. mapproxy/test/schemas/ows/1.1.0/owsGetResourceByID.xsd +51 -0
  193. mapproxy/test/schemas/ows/1.1.0/owsInputOutputData.xsd +59 -0
  194. mapproxy/test/schemas/ows/1.1.0/owsManifest.xsd +125 -0
  195. mapproxy/test/schemas/ows/1.1.0/owsOperationsMetadata.xsd +140 -0
  196. mapproxy/test/schemas/ows/1.1.0/owsServiceIdentification.xsd +60 -0
  197. mapproxy/test/schemas/ows/1.1.0/owsServiceProvider.xsd +47 -0
  198. mapproxy/test/schemas/sld/1.1.0/sld_capabilities.xsd +27 -0
  199. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.dtd +353 -0
  200. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.xml +188 -0
  201. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.dtd +524 -0
  202. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.xml +260 -0
  203. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.dtd +273 -0
  204. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.xml +303 -0
  205. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.dtd +6 -0
  206. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.xml +33 -0
  207. mapproxy/test/schemas/wms/1.1.1/OGC-exception.xsd +68 -0
  208. mapproxy/test/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  209. mapproxy/test/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd +274 -0
  210. mapproxy/test/schemas/wms/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  211. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.dtd +276 -0
  212. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.xml +303 -0
  213. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.dtd +6 -0
  214. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.xml +33 -0
  215. mapproxy/test/schemas/wms/1.3.0/ReadMe.txt +8 -0
  216. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xml +277 -0
  217. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xsd +611 -0
  218. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xml +34 -0
  219. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xsd +28 -0
  220. mapproxy/test/schemas/wmsc/1.1.1/OGC-exception.xsd +68 -0
  221. mapproxy/test/schemas/wmsc/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  222. mapproxy/test/schemas/wmsc/1.1.1/WMS_MS_Capabilities.dtd +283 -0
  223. mapproxy/test/schemas/wmsc/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  224. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.dtd +276 -0
  225. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.xml +303 -0
  226. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.dtd +6 -0
  227. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.xml +33 -0
  228. mapproxy/test/schemas/wmts/1.0/ReadMe.txt +32 -0
  229. mapproxy/test/schemas/wmts/1.0/wmts.xsd +28 -0
  230. mapproxy/test/schemas/wmts/1.0/wmtsAbstract.wsdl +151 -0
  231. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_request.xsd +38 -0
  232. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_response.xsd +564 -0
  233. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_request.xsd +57 -0
  234. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_response.xsd +72 -0
  235. mapproxy/test/schemas/wmts/1.0/wmtsGetTile_request.xsd +91 -0
  236. mapproxy/test/schemas/wmts/1.0/wmtsKVP.xsd +76 -0
  237. mapproxy/test/schemas/wmts/1.0/wmtsPayload_response.xsd +70 -0
  238. mapproxy/test/schemas/xlink/1.0.0/ReadMe.txt +6 -0
  239. mapproxy/test/schemas/xlink/1.0.0/xlinks.xsd +122 -0
  240. mapproxy/test/schemas/xml.xsd +287 -0
  241. mapproxy/test/system/__init__.py +98 -0
  242. mapproxy/test/system/fixture/arcgis.yaml +57 -0
  243. mapproxy/test/system/fixture/auth.yaml +70 -0
  244. mapproxy/test/system/fixture/cache.mbtiles +0 -0
  245. mapproxy/test/system/fixture/cache_azureblob.yaml +59 -0
  246. mapproxy/test/system/fixture/cache_band_merge.yaml +73 -0
  247. mapproxy/test/system/fixture/cache_bulk_meta_tiles.yaml +24 -0
  248. mapproxy/test/system/fixture/cache_data/dop_cache_EPSG3857/00/000/000/000/000/000/000.png +0 -0
  249. mapproxy/test/system/fixture/cache_data/wms_cache_EPSG900913/01/000/000/000/000/000/001.jpeg +0 -0
  250. mapproxy/test/system/fixture/cache_data/wms_cache_transparent_EPSG900913/01/000/000/000/000/000/001.png +0 -0
  251. mapproxy/test/system/fixture/cache_geopackage.yaml +56 -0
  252. mapproxy/test/system/fixture/cache_grid_names.yaml +50 -0
  253. mapproxy/test/system/fixture/cache_mbtiles.yaml +28 -0
  254. mapproxy/test/system/fixture/cache_s3.yaml +58 -0
  255. mapproxy/test/system/fixture/cache_source.yaml +81 -0
  256. mapproxy/test/system/fixture/combined_sources.yaml +130 -0
  257. mapproxy/test/system/fixture/coverage.yaml +77 -0
  258. mapproxy/test/system/fixture/demo.yaml +135 -0
  259. mapproxy/test/system/fixture/dimension.yaml +59 -0
  260. mapproxy/test/system/fixture/disable_storage.yaml +25 -0
  261. mapproxy/test/system/fixture/empty_ogrdata.geojson +1 -0
  262. mapproxy/test/system/fixture/formats.yaml +72 -0
  263. mapproxy/test/system/fixture/inspire.yaml +101 -0
  264. mapproxy/test/system/fixture/inspire_full.yaml +124 -0
  265. mapproxy/test/system/fixture/kml_layer.yaml +66 -0
  266. mapproxy/test/system/fixture/layer.yaml +260 -0
  267. mapproxy/test/system/fixture/layergroups.yaml +57 -0
  268. mapproxy/test/system/fixture/layergroups_root.yaml +106 -0
  269. mapproxy/test/system/fixture/legendgraphic.yaml +93 -0
  270. mapproxy/test/system/fixture/mapnik_source.yaml +66 -0
  271. mapproxy/test/system/fixture/mapproxy_export.yaml +12 -0
  272. mapproxy/test/system/fixture/mapserver.yaml +23 -0
  273. mapproxy/test/system/fixture/minimal_cgi.py +16 -0
  274. mapproxy/test/system/fixture/mixed_mode.yaml +49 -0
  275. mapproxy/test/system/fixture/multi_cache_layers.yaml +100 -0
  276. mapproxy/test/system/fixture/multiapp1.yaml +20 -0
  277. mapproxy/test/system/fixture/multiapp2.yaml +19 -0
  278. mapproxy/test/system/fixture/renderd_client.yaml +55 -0
  279. mapproxy/test/system/fixture/scalehints.yaml +70 -0
  280. mapproxy/test/system/fixture/seed.yaml +94 -0
  281. mapproxy/test/system/fixture/seed_mapproxy.yaml +39 -0
  282. mapproxy/test/system/fixture/seed_old.yaml +12 -0
  283. mapproxy/test/system/fixture/seed_timeouts.yaml +12 -0
  284. mapproxy/test/system/fixture/seed_timeouts_mapproxy.yaml +27 -0
  285. mapproxy/test/system/fixture/seedonly.yaml +51 -0
  286. mapproxy/test/system/fixture/sld.yaml +35 -0
  287. mapproxy/test/system/fixture/source_errors.yaml +84 -0
  288. mapproxy/test/system/fixture/source_errors_raise.yaml +82 -0
  289. mapproxy/test/system/fixture/tileservice_origin.yaml +26 -0
  290. mapproxy/test/system/fixture/tileservice_refresh.yaml +59 -0
  291. mapproxy/test/system/fixture/tilesource_minmax_res.yaml +22 -0
  292. mapproxy/test/system/fixture/util-conf-base-grids.yaml +5 -0
  293. mapproxy/test/system/fixture/util-conf-overwrite.yaml +13 -0
  294. mapproxy/test/system/fixture/util-conf-wms-111-cap.xml +90 -0
  295. mapproxy/test/system/fixture/util_grids.yaml +30 -0
  296. mapproxy/test/system/fixture/util_wms_capabilities111.xml +130 -0
  297. mapproxy/test/system/fixture/util_wms_capabilities130.xml +100 -0
  298. mapproxy/test/system/fixture/util_wms_capabilities_service_exception.xml +5 -0
  299. mapproxy/test/system/fixture/watermark.yaml +50 -0
  300. mapproxy/test/system/fixture/wms_srs_extent.yaml +39 -0
  301. mapproxy/test/system/fixture/wms_versions.yaml +38 -0
  302. mapproxy/test/system/fixture/wmts.yaml +134 -0
  303. mapproxy/test/system/fixture/wmts_dimensions.yaml +57 -0
  304. mapproxy/test/system/fixture/xslt_featureinfo.yaml +54 -0
  305. mapproxy/test/system/fixture/xslt_featureinfo_input.yaml +51 -0
  306. mapproxy/test/system/test_arcgis.py +156 -0
  307. mapproxy/test/system/test_auth.py +1134 -0
  308. mapproxy/test/system/test_behind_proxy.py +75 -0
  309. mapproxy/test/system/test_bulk_meta_tiles.py +106 -0
  310. mapproxy/test/system/test_cache_azureblob.py +127 -0
  311. mapproxy/test/system/test_cache_band_merge.py +103 -0
  312. mapproxy/test/system/test_cache_geopackage.py +144 -0
  313. mapproxy/test/system/test_cache_grid_names.py +89 -0
  314. mapproxy/test/system/test_cache_mbtiles.py +85 -0
  315. mapproxy/test/system/test_cache_s3.py +115 -0
  316. mapproxy/test/system/test_cache_source.py +146 -0
  317. mapproxy/test/system/test_combined_sources.py +335 -0
  318. mapproxy/test/system/test_coverage.py +140 -0
  319. mapproxy/test/system/test_decorate_img.py +214 -0
  320. mapproxy/test/system/test_demo.py +106 -0
  321. mapproxy/test/system/test_demo_with_extra_service.py +53 -0
  322. mapproxy/test/system/test_dimensions.py +278 -0
  323. mapproxy/test/system/test_disable_storage.py +42 -0
  324. mapproxy/test/system/test_formats.py +219 -0
  325. mapproxy/test/system/test_inspire_vs.py +173 -0
  326. mapproxy/test/system/test_kml.py +262 -0
  327. mapproxy/test/system/test_layergroups.py +160 -0
  328. mapproxy/test/system/test_legendgraphic.py +308 -0
  329. mapproxy/test/system/test_mapnik.py +161 -0
  330. mapproxy/test/system/test_mapserver.py +81 -0
  331. mapproxy/test/system/test_mixed_mode_format.py +195 -0
  332. mapproxy/test/system/test_multi_cache_layers.py +167 -0
  333. mapproxy/test/system/test_multiapp.py +92 -0
  334. mapproxy/test/system/test_refresh.py +207 -0
  335. mapproxy/test/system/test_renderd_client.py +304 -0
  336. mapproxy/test/system/test_response_headers.py +54 -0
  337. mapproxy/test/system/test_scalehints.py +140 -0
  338. mapproxy/test/system/test_seed.py +422 -0
  339. mapproxy/test/system/test_seed_only.py +93 -0
  340. mapproxy/test/system/test_sld.py +120 -0
  341. mapproxy/test/system/test_source_errors.py +377 -0
  342. mapproxy/test/system/test_tilesource_minmax_res.py +54 -0
  343. mapproxy/test/system/test_tms.py +276 -0
  344. mapproxy/test/system/test_tms_origin.py +46 -0
  345. mapproxy/test/system/test_util_conf.py +304 -0
  346. mapproxy/test/system/test_util_export.py +210 -0
  347. mapproxy/test/system/test_util_grids.py +88 -0
  348. mapproxy/test/system/test_util_wms_capabilities.py +182 -0
  349. mapproxy/test/system/test_watermark.py +91 -0
  350. mapproxy/test/system/test_wms.py +1611 -0
  351. mapproxy/test/system/test_wms_srs_extent.py +165 -0
  352. mapproxy/test/system/test_wms_version.py +85 -0
  353. mapproxy/test/system/test_wmsc.py +116 -0
  354. mapproxy/test/system/test_wmts.py +334 -0
  355. mapproxy/test/system/test_wmts_dimensions.py +206 -0
  356. mapproxy/test/system/test_wmts_restful.py +198 -0
  357. mapproxy/test/system/test_xslt_featureinfo.py +425 -0
  358. mapproxy/test/test_http_helper.py +219 -0
  359. mapproxy/test/unit/__init__.py +0 -0
  360. mapproxy/test/unit/epsg +2 -0
  361. mapproxy/test/unit/polygons/polygons.dbf +0 -0
  362. mapproxy/test/unit/polygons/polygons.shp +0 -0
  363. mapproxy/test/unit/polygons/polygons.shx +0 -0
  364. mapproxy/test/unit/test_async.py +245 -0
  365. mapproxy/test/unit/test_auth.py +419 -0
  366. mapproxy/test/unit/test_cache.py +1193 -0
  367. mapproxy/test/unit/test_cache_azureblob.py +94 -0
  368. mapproxy/test/unit/test_cache_compact.py +319 -0
  369. mapproxy/test/unit/test_cache_couchdb.py +114 -0
  370. mapproxy/test/unit/test_cache_geopackage.py +221 -0
  371. mapproxy/test/unit/test_cache_redis.py +67 -0
  372. mapproxy/test/unit/test_cache_riak.py +76 -0
  373. mapproxy/test/unit/test_cache_s3.py +84 -0
  374. mapproxy/test/unit/test_cache_tile.py +427 -0
  375. mapproxy/test/unit/test_client.py +479 -0
  376. mapproxy/test/unit/test_client_arcgis.py +73 -0
  377. mapproxy/test/unit/test_client_cgi.py +136 -0
  378. mapproxy/test/unit/test_collections.py +116 -0
  379. mapproxy/test/unit/test_concat_legends.py +37 -0
  380. mapproxy/test/unit/test_conf_loader.py +1061 -0
  381. mapproxy/test/unit/test_conf_validator.py +416 -0
  382. mapproxy/test/unit/test_config.py +117 -0
  383. mapproxy/test/unit/test_decorate_img.py +185 -0
  384. mapproxy/test/unit/test_exceptions.py +258 -0
  385. mapproxy/test/unit/test_featureinfo.py +291 -0
  386. mapproxy/test/unit/test_file_lock_load.py +49 -0
  387. mapproxy/test/unit/test_geom.py +503 -0
  388. mapproxy/test/unit/test_grid.py +1258 -0
  389. mapproxy/test/unit/test_image.py +1053 -0
  390. mapproxy/test/unit/test_image_mask.py +181 -0
  391. mapproxy/test/unit/test_image_messages.py +197 -0
  392. mapproxy/test/unit/test_image_options.py +160 -0
  393. mapproxy/test/unit/test_isodate.py +122 -0
  394. mapproxy/test/unit/test_multiapp.py +163 -0
  395. mapproxy/test/unit/test_ogr_reader.py +50 -0
  396. mapproxy/test/unit/test_request.py +745 -0
  397. mapproxy/test/unit/test_request_wmts.py +178 -0
  398. mapproxy/test/unit/test_response.py +79 -0
  399. mapproxy/test/unit/test_seed.py +365 -0
  400. mapproxy/test/unit/test_seed_cachelock.py +90 -0
  401. mapproxy/test/unit/test_srs.py +215 -0
  402. mapproxy/test/unit/test_tiled_source.py +122 -0
  403. mapproxy/test/unit/test_tilefilter.py +31 -0
  404. mapproxy/test/unit/test_times.py +25 -0
  405. mapproxy/test/unit/test_timeutils.py +50 -0
  406. mapproxy/test/unit/test_util_conf_utils.py +75 -0
  407. mapproxy/test/unit/test_utils.py +476 -0
  408. mapproxy/test/unit/test_wms_capabilities.py +44 -0
  409. mapproxy/test/unit/test_wms_layer.py +113 -0
  410. mapproxy/test/unit/test_yaml.py +69 -0
  411. mapproxy/tilefilter.py +59 -0
  412. mapproxy/util/__init__.py +0 -0
  413. mapproxy/util/async_.py +227 -0
  414. mapproxy/util/collections.py +132 -0
  415. mapproxy/util/coverage.py +329 -0
  416. mapproxy/util/escape.py +10 -0
  417. mapproxy/util/ext/__init__.py +14 -0
  418. mapproxy/util/ext/dictspec/__init__.py +1 -0
  419. mapproxy/util/ext/dictspec/spec.py +124 -0
  420. mapproxy/util/ext/dictspec/test/__init__.py +0 -0
  421. mapproxy/util/ext/dictspec/test/test_validator.py +274 -0
  422. mapproxy/util/ext/dictspec/validator.py +189 -0
  423. mapproxy/util/ext/local.py +196 -0
  424. mapproxy/util/ext/lockfile.py +138 -0
  425. mapproxy/util/ext/odict.py +330 -0
  426. mapproxy/util/ext/serving.py +508 -0
  427. mapproxy/util/ext/tempita/__init__.py +1174 -0
  428. mapproxy/util/ext/tempita/_looper.py +163 -0
  429. mapproxy/util/ext/tempita/compat3.py +46 -0
  430. mapproxy/util/ext/wmsparse/__init__.py +3 -0
  431. mapproxy/util/ext/wmsparse/duration.py +597 -0
  432. mapproxy/util/ext/wmsparse/parse.py +305 -0
  433. mapproxy/util/ext/wmsparse/test/__init__.py +0 -0
  434. mapproxy/util/ext/wmsparse/test/test_parse.py +162 -0
  435. mapproxy/util/ext/wmsparse/test/test_util.py +23 -0
  436. mapproxy/util/ext/wmsparse/test/wms-large-111.xml +2114 -0
  437. mapproxy/util/ext/wmsparse/test/wms-omniscale-111.xml +90 -0
  438. mapproxy/util/ext/wmsparse/test/wms-omniscale-130.xml +120 -0
  439. mapproxy/util/ext/wmsparse/test/wms_nasa_cap.xml +386 -0
  440. mapproxy/util/ext/wmsparse/util.py +187 -0
  441. mapproxy/util/fs.py +156 -0
  442. mapproxy/util/geom.py +295 -0
  443. mapproxy/util/lib.py +115 -0
  444. mapproxy/util/lock.py +163 -0
  445. mapproxy/util/ogr.py +231 -0
  446. mapproxy/util/py.py +81 -0
  447. mapproxy/util/times.py +75 -0
  448. mapproxy/util/yaml.py +56 -0
  449. mapproxy/version.py +31 -0
  450. mapproxy/wsgiapp.py +164 -0
  451. mapproxy-1.16.1.dist-info/METADATA +151 -0
  452. mapproxy-1.16.1.dist-info/RECORD +458 -0
  453. mapproxy-1.16.1.dist-info/WHEEL +5 -0
  454. mapproxy-1.16.1.dist-info/entry_points.txt +3 -0
  455. mapproxy-1.16.1.dist-info/licenses/AUTHORS.txt +33 -0
  456. mapproxy-1.16.1.dist-info/licenses/COPYING.txt +60 -0
  457. mapproxy-1.16.1.dist-info/licenses/LICENSE.txt +202 -0
  458. mapproxy-1.16.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,94 @@
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(self):
35
+ TileCacheTestBase.setup(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(self):
58
+ TileCacheTestBase.teardown(self)
59
+ self.container_client.delete_container()
60
+
61
+ @pytest.mark.parametrize('layout,tile_coord,key', [
62
+ ['mp', (12345, 67890, 2), 'mycache/webmercator/02/0001/2345/0006/7890.png'],
63
+ ['mp', (12345, 67890, 12), 'mycache/webmercator/12/0001/2345/0006/7890.png'],
64
+
65
+ ['tc', (12345, 67890, 2), 'mycache/webmercator/02/000/012/345/000/067/890.png'],
66
+ ['tc', (12345, 67890, 12), 'mycache/webmercator/12/000/012/345/000/067/890.png'],
67
+
68
+ ['tms', (12345, 67890, 2), 'mycache/webmercator/2/12345/67890.png'],
69
+ ['tms', (12345, 67890, 12), 'mycache/webmercator/12/12345/67890.png'],
70
+
71
+ ['reverse_tms', (12345, 67890, 2), 'mycache/webmercator/67890/12345/2.png'],
72
+ ['reverse_tms', (12345, 67890, 12), 'mycache/webmercator/67890/12345/12.png'],
73
+
74
+ ['quadkey', (0, 0, 0), 'mycache/webmercator/.png'],
75
+ ['quadkey', (0, 0, 1), 'mycache/webmercator/0.png'],
76
+ ['quadkey', (1, 1, 1), 'mycache/webmercator/3.png'],
77
+ ['quadkey', (12345, 67890, 12), 'mycache/webmercator/200200331021.png'],
78
+
79
+ ['arcgis', (1, 2, 3), 'mycache/webmercator/L03/R00000002/C00000001.png'],
80
+ ['arcgis', (9, 2, 3), 'mycache/webmercator/L03/R00000002/C00000009.png'],
81
+ ['arcgis', (10, 2, 3), 'mycache/webmercator/L03/R00000002/C0000000a.png'],
82
+ ['arcgis', (12345, 67890, 12), 'mycache/webmercator/L12/R00010932/C00003039.png'],
83
+ ])
84
+ def test_tile_key(self, layout, tile_coord, key):
85
+ cache = AzureBlobCache(
86
+ base_path=self.base_path,
87
+ file_ext=self.file_ext,
88
+ container_name=self.container,
89
+ connection_string=self.connection_string,
90
+ directory_layout=layout
91
+ )
92
+ cache.store_tile(self.create_tile(tile_coord))
93
+
94
+ assert self.container_client.get_blob_client(key).exists()
@@ -0,0 +1,319 @@
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(self):
39
+ TileCacheTestBase.setup(self)
40
+ self.cache = CompactCacheV1(
41
+ cache_dir=self.cache_dir,
42
+ )
43
+
44
+ def test_bundle_files(self):
45
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
46
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
47
+ self.cache.store_tile(self.create_tile(coord=(0, 0, 0)))
48
+ assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
49
+ assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
50
+
51
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
52
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
53
+ self.cache.store_tile(self.create_tile(coord=(127, 127, 12)))
54
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
55
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
56
+
57
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
58
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundlx'))
59
+ self.cache.store_tile(self.create_tile(coord=(128, 256, 12)))
60
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
61
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundlx'))
62
+
63
+ def test_bundle_files_not_created_on_is_cached(self):
64
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
65
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundlx'))
66
+ self.cache.is_cached(Tile(coord=(0, 0, 0)))
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
+
70
+ def test_missing_tiles(self):
71
+ self.cache.store_tile(self.create_tile(coord=(130, 200, 8)))
72
+ assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundle'))
73
+ assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundlx'))
74
+
75
+ # test that all other tiles in this bundle are missing
76
+ assert self.cache.is_cached(Tile((130, 200, 8)))
77
+ for x in range(128, 255):
78
+ for y in range(128, 255):
79
+ if x == 130 and y == 200:
80
+ continue
81
+ assert not self.cache.is_cached(Tile((x, y, 8))), (x, y)
82
+ assert not self.cache.load_tile(Tile((x, y, 8))), (x, y)
83
+
84
+ def test_remove_level_tiles_before(self):
85
+ self.cache.store_tile(self.create_tile(coord=(0, 0, 12)))
86
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
87
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
88
+
89
+ # not removed with timestamp
90
+ self.cache.remove_level_tiles_before(12, time.time())
91
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
92
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundlx'))
93
+
94
+ # removed with timestamp=0 (remove_all:true in seed.yaml)
95
+ self.cache.remove_level_tiles_before(12, 0)
96
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12'))
97
+
98
+
99
+ def test_bundle_header(self):
100
+ t = Tile((5000, 1000, 12), ImageSource(BytesIO(b'a' * 4000), image_opts=ImageOptions(format='image/png')))
101
+ self.cache.store_tile(t)
102
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'))
103
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundlx'))
104
+
105
+ def assert_header(tile_bytes_written, max_tile_bytes):
106
+ with open(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'), 'r+b') as f:
107
+ header = struct.unpack('<lllllllllllllll', f.read(60))
108
+ assert header[11] == 896
109
+ assert header[12] == 1023
110
+ assert header[13] == 4992
111
+ assert header[14] == 5119
112
+ assert header[6] == 60 + 128*128*4 + sum(tile_bytes_written)
113
+ assert header[2] == max_tile_bytes
114
+ assert header[4] == len(tile_bytes_written)*4
115
+
116
+ assert_header([4000 + 4], 4000)
117
+
118
+ t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 6000), image_opts=ImageOptions(format='image/png')))
119
+ self.cache.store_tile(t)
120
+ assert_header([4000 + 4, 6000 + 4], 6000)
121
+
122
+ t = Tile((4992, 999, 12), ImageSource(BytesIO(b'a' * 1000), image_opts=ImageOptions(format='image/png')))
123
+ self.cache.store_tile(t)
124
+ assert_header([4000 + 4, 6000 + 4, 1000 + 4], 6000)
125
+
126
+ t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 3000), image_opts=ImageOptions(format='image/png')))
127
+ self.cache.store_tile(t)
128
+ assert_header([4000 + 4, 6000 + 4 + 3000 + 4, 1000 + 4], 6000) # still contains bytes from overwritten tile
129
+
130
+
131
+
132
+ class TestCompactCacheV2(TileCacheTestBase):
133
+
134
+ always_loads_metadata = True
135
+
136
+ def setup(self):
137
+ TileCacheTestBase.setup(self)
138
+ self.cache = CompactCacheV2(
139
+ cache_dir=self.cache_dir,
140
+ )
141
+
142
+ def test_bundle_files(self):
143
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
144
+ self.cache.store_tile(self.create_tile(coord=(0, 0, 0)))
145
+ assert os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
146
+
147
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
148
+ self.cache.store_tile(self.create_tile(coord=(127, 127, 12)))
149
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
150
+
151
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
152
+ self.cache.store_tile(self.create_tile(coord=(128, 256, 12)))
153
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0100C0080.bundle'))
154
+
155
+ def test_bundle_files_not_created_on_is_cached(self):
156
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
157
+ self.cache.is_cached(Tile(coord=(0, 0, 0)))
158
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L00', 'R0000C0000.bundle'))
159
+
160
+ def test_missing_tiles(self):
161
+ self.cache.store_tile(self.create_tile(coord=(130, 200, 8)))
162
+ assert os.path.exists(os.path.join(self.cache_dir, 'L08', 'R0080C0080.bundle'))
163
+
164
+ # test that all other tiles in this bundle are missing
165
+ assert self.cache.is_cached(Tile((130, 200, 8)))
166
+ for x in range(128, 255):
167
+ for y in range(128, 255):
168
+ if x == 130 and y == 200:
169
+ continue
170
+ assert not self.cache.is_cached(Tile((x, y, 8))), (x, y)
171
+ assert not self.cache.load_tile(Tile((x, y, 8))), (x, y)
172
+
173
+ def test_remove_level_tiles_before(self):
174
+ self.cache.store_tile(self.create_tile(coord=(0, 0, 12)))
175
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
176
+
177
+ # not removed with timestamp
178
+ self.cache.remove_level_tiles_before(12, time.time())
179
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0000C0000.bundle'))
180
+
181
+ # removed with timestamp=0 (remove_all:true in seed.yaml)
182
+ self.cache.remove_level_tiles_before(12, 0)
183
+ assert not os.path.exists(os.path.join(self.cache_dir, 'L12'))
184
+
185
+
186
+ def test_bundle_header(self):
187
+ t = Tile((5000, 1000, 12), ImageSource(BytesIO(b'a' * 4000), image_opts=ImageOptions(format='image/png')))
188
+ self.cache.store_tile(t)
189
+ assert os.path.exists(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'))
190
+
191
+ def assert_header(tile_bytes_written, max_tile_bytes):
192
+ with open(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'), 'r+b') as f:
193
+ header = struct.unpack('<4I3Q6I', f.read(64))
194
+ assert header[0] == 3 # version
195
+ assert header[1] == 128*128
196
+ assert header[2] == max_tile_bytes
197
+ assert header[5] == 64 + 128*128*8 + sum(tile_bytes_written)
198
+
199
+ assert_header([4000 + 4], 4000)
200
+
201
+ t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 6000), image_opts=ImageOptions(format='image/png')))
202
+ self.cache.store_tile(t)
203
+ assert_header([4000 + 4, 6000 + 4], 6000)
204
+
205
+ t = Tile((4992, 999, 12), ImageSource(BytesIO(b'a' * 1000), image_opts=ImageOptions(format='image/png')))
206
+ self.cache.store_tile(t)
207
+ assert_header([4000 + 4, 6000 + 4, 1000 + 4], 6000)
208
+
209
+ t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 3000), image_opts=ImageOptions(format='image/png')))
210
+ self.cache.store_tile(t)
211
+ assert_header([4000 + 4, 6000 + 4 + 3000 + 4, 1000 + 4], 6000) # still contains bytes from overwritten tile
212
+
213
+
214
+ class mockProgressLog(object):
215
+ def __init__(self):
216
+ self.logs = []
217
+
218
+ def log(self, fname, fragmentation, fragmentation_bytes, num, total, defrag):
219
+ self.logs.append({
220
+ 'fname': fname,
221
+ 'fragmentation': fragmentation,
222
+ 'fragmentation_bytes': fragmentation_bytes,
223
+ 'num': num,
224
+ 'total': total,
225
+ 'defrag': defrag,
226
+ })
227
+ self.logs.sort(key=lambda x: (x['fname'], 'num'))
228
+
229
+ class DefragmentationTestBase(object):
230
+ def setup(self):
231
+ self.cache_dir = tempfile.mkdtemp()
232
+
233
+ def teardown(self):
234
+ if os.path.exists(self.cache_dir):
235
+ shutil.rmtree(self.cache_dir)
236
+
237
+ def test_defragmentation_empty_bundle(self):
238
+ cache = self.cache_class(self.cache_dir)
239
+
240
+ t = Tile((5000, 1000, 12),
241
+ ImageSource(BytesIO(b'a' * 60*1024), image_opts=ImageOptions(format='image/png')))
242
+ cache.store_tile(t)
243
+ cache.remove_tile(t)
244
+
245
+ fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
246
+ assert os.path.exists(fname)
247
+
248
+ logger = mockProgressLog()
249
+ defrag_compact_cache(cache, min_bytes=50000, log_progress=logger)
250
+
251
+ assert not os.path.exists(fname)
252
+
253
+ def test_defragmentation_min_bytes(self):
254
+ cache = self.cache_class(self.cache_dir)
255
+
256
+ for _ in range(2):
257
+ t = Tile((5000, 1000, 12),
258
+ ImageSource(BytesIO(b'a' * 60*1024), image_opts=ImageOptions(format='image/png')))
259
+ cache.store_tile(t)
260
+
261
+ logger = mockProgressLog()
262
+ fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
263
+ before = os.path.getsize(fname)
264
+ defrag_compact_cache(cache, log_progress=logger)
265
+ assert len(logger.logs) == 1
266
+ assert logger.logs[0]['defrag'] == False
267
+ after = os.path.getsize(fname)
268
+ assert before == after
269
+
270
+ logger = mockProgressLog()
271
+ before = os.path.getsize(fname)
272
+ defrag_compact_cache(cache, min_bytes=50000, log_progress=logger)
273
+ assert len(logger.logs) == 1
274
+ assert logger.logs[0]['defrag'] == True
275
+ after = os.path.getsize(fname)
276
+ assert after < before
277
+
278
+ def test_defragmentation_min_percent(self):
279
+ cache = self.cache_class(self.cache_dir)
280
+
281
+ t = Tile((10000, 2000, 13),
282
+ ImageSource(
283
+ BytesIO(b'a' * 120 * 1024),
284
+ image_opts=ImageOptions(format='image/png')))
285
+ cache.store_tile(t)
286
+
287
+ for x in range(100):
288
+ for _ in range(2 if x < 10 else 1):
289
+ t = Tile((5000+x, 1000, 12),
290
+ ImageSource(
291
+ BytesIO(b'a' * 120 * 1024),
292
+ image_opts=ImageOptions(format='image/png')))
293
+ cache.store_tile(t)
294
+
295
+ logger = mockProgressLog()
296
+ fname = os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')
297
+ before = os.path.getsize(fname)
298
+ defrag_compact_cache(cache, log_progress=logger)
299
+ assert len(logger.logs) == 2
300
+ assert logger.logs[0]['defrag'] == False
301
+ assert logger.logs[1]['defrag'] == False
302
+ after = os.path.getsize(fname)
303
+ assert before == after
304
+
305
+ logger = mockProgressLog()
306
+ before = os.path.getsize(fname)
307
+ defrag_compact_cache(cache, min_percent=0.08, log_progress=logger)
308
+ assert len(logger.logs) == 2
309
+ assert logger.logs[0]['defrag'] == True
310
+ assert logger.logs[1]['defrag'] == False
311
+ after = os.path.getsize(fname)
312
+ assert after < before
313
+
314
+
315
+ class TestDefragmentationV1(DefragmentationTestBase):
316
+ cache_class = CompactCacheV1
317
+
318
+ class TestDefragmentationV2(DefragmentationTestBase):
319
+ cache_class = CompactCacheV2
@@ -0,0 +1,114 @@
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(self):
40
+ couch_address = os.environ['MAPPROXY_TEST_COUCHDB']
41
+ db_name = 'mapproxy_test_%d' % random.randint(0, 100000)
42
+
43
+ TileCacheTestBase.setup(self)
44
+
45
+ md_template = CouchDBMDTemplate({'row': '{{y}}', 'tile_column': '{{x}}',
46
+ 'zoom': '{{level}}', 'time': '{{timestamp}}', 'coord': '{{wgs_tile_centroid}}'})
47
+ self.cache = CouchDBCache(couch_address, db_name,
48
+ file_ext='png', tile_grid=tile_grid(3857, name='global-webmarcator'),
49
+ md_template=md_template)
50
+
51
+ def teardown(self):
52
+ import requests
53
+ requests.delete(self.cache.couch_url)
54
+ TileCacheTestBase.teardown(self)
55
+
56
+ def test_store_bulk_with_overwrite(self):
57
+ tile = self.create_tile((0, 0, 4))
58
+ self.create_cached_tile(tile)
59
+
60
+ assert self.cache.is_cached(Tile((0, 0, 4)))
61
+ loaded_tile = Tile((0, 0, 4))
62
+ assert self.cache.load_tile(loaded_tile)
63
+ assert loaded_tile.source_buffer().read() == tile.source_buffer().read()
64
+
65
+ assert not self.cache.is_cached(Tile((1, 0, 4)))
66
+
67
+ tiles = [self.create_another_tile((x, 0, 4)) for x in range(2)]
68
+ assert self.cache.store_tiles(tiles)
69
+
70
+ assert self.cache.is_cached(Tile((0, 0, 4)))
71
+ loaded_tile = Tile((0, 0, 4))
72
+ assert self.cache.load_tile(loaded_tile)
73
+ # check that tile is overwritten
74
+ assert loaded_tile.source_buffer().read() != tile.source_buffer().read()
75
+ assert loaded_tile.source_buffer().read() == tiles[0].source_buffer().read()
76
+
77
+ def test_double_remove(self):
78
+ tile = self.create_tile()
79
+ self.create_cached_tile(tile)
80
+ assert self.cache.remove_tile(tile)
81
+ assert self.cache.remove_tile(tile)
82
+
83
+
84
+ class TestCouchDBMDTemplate(object):
85
+ def test_empty(self):
86
+ template = CouchDBMDTemplate({})
87
+ doc = template.doc(Tile((0, 0, 1)), tile_grid(4326))
88
+
89
+ assert doc['timestamp'] == pytest.approx(time.time(), 0.1)
90
+
91
+ def test_fixed_values(self):
92
+ template = CouchDBMDTemplate({'hello': 'world', 'foo': 123})
93
+ doc = template.doc(Tile((0, 0, 1)), tile_grid(4326))
94
+
95
+ assert doc['timestamp'] == pytest.approx(time.time(), 0.1)
96
+ assert doc['hello'] == 'world'
97
+ assert doc['foo'] == 123
98
+
99
+ def test_template_values(self):
100
+ template = CouchDBMDTemplate({'row': '{{y}}', 'tile_column': '{{x}}',
101
+ 'zoom': '{{level}}', 'time': '{{timestamp}}', 'coord': '{{wgs_tile_centroid}}',
102
+ 'datetime': '{{utc_iso}}', 'coord_webmerc': '{{tile_centroid}}'})
103
+ doc = template.doc(Tile((1, 0, 2)), tile_grid(3857))
104
+
105
+ assert doc['time'] == pytest.approx(time.time(), 0.1)
106
+ assert 'timestamp' not in doc
107
+ assert doc['row'] == 0
108
+ assert doc['tile_column'] == 1
109
+ assert doc['zoom'] == 2
110
+ assert doc['coord'][0] == pytest.approx(-45.0)
111
+ assert doc['coord'][1] == pytest.approx(-79.17133464081945)
112
+ assert doc['coord_webmerc'][0] == pytest.approx(-5009377.085697311)
113
+ assert doc['coord_webmerc'][1] == pytest.approx(-15028131.25709193)
114
+ assert re.match(r'20\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ', doc['datetime']), doc['datetime']