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,83 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+
17
+ import os
18
+ import hashlib
19
+
20
+ from mapproxy.image import ImageSource
21
+ from mapproxy.image.opts import ImageOptions
22
+ from mapproxy.util.fs import ensure_directory, write_atomic
23
+
24
+ import logging
25
+ log = logging.getLogger(__name__)
26
+
27
+ def legend_identifier(legends):
28
+ """
29
+ >>> legend_identifier([("http://example/?", "foo"), ("http://example/?", "bar")])
30
+ 'http://example/?foohttp://example/?bar'
31
+
32
+ :param legends: list of legend URL and layer tuples
33
+ """
34
+ parts = []
35
+ for url, layer in legends:
36
+ parts.append(url)
37
+ if layer:
38
+ parts.append(layer)
39
+ return ''.join(parts)
40
+
41
+ def legend_hash(identifier, scale):
42
+ md5 = hashlib.md5()
43
+ md5.update(identifier.encode('utf-8'))
44
+ md5.update(str(scale).encode('ascii'))
45
+ return md5.hexdigest()
46
+
47
+ class LegendCache(object):
48
+ def __init__(self, cache_dir=None, file_ext='png'):
49
+ self.cache_dir = cache_dir
50
+ self.file_ext = file_ext
51
+
52
+ def store(self, legend):
53
+ if legend.stored:
54
+ return
55
+
56
+ if legend.location is None:
57
+ hash = legend_hash(legend.id, legend.scale)
58
+ legend.location = os.path.join(self.cache_dir, hash) + '.' + self.file_ext
59
+ ensure_directory(legend.location)
60
+
61
+ data = legend.source.as_buffer(ImageOptions(format='image/' + self.file_ext), seekable=True)
62
+ data.seek(0)
63
+ log.debug('writing to %s' % (legend.location))
64
+ write_atomic(legend.location, data.read())
65
+ data.seek(0)
66
+ legend.stored = True
67
+
68
+ def load(self, legend):
69
+ hash = legend_hash(legend.id, legend.scale)
70
+ legend.location = os.path.join(self.cache_dir, hash) + '.' + self.file_ext
71
+
72
+ if os.path.exists(legend.location):
73
+ legend.source = ImageSource(legend.location)
74
+ return True
75
+ return False
76
+
77
+ class Legend(object):
78
+ def __init__(self, source=None, id=None, scale=None):
79
+ self.source = source
80
+ self.stored = None
81
+ self.location = None
82
+ self.id = id
83
+ self.scale = scale
@@ -0,0 +1,392 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2011-2013 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 glob
17
+ import hashlib
18
+ import os
19
+ import sqlite3
20
+ import threading
21
+ import time
22
+
23
+ from mapproxy.image import ImageSource
24
+ from mapproxy.cache.base import TileCacheBase, tile_buffer, REMOVE_ON_UNLOCK
25
+ from mapproxy.util.fs import ensure_directory
26
+ from mapproxy.util.lock import FileLock
27
+ from mapproxy.compat import BytesIO, PY2, itertools
28
+
29
+ import logging
30
+ log = logging.getLogger(__name__)
31
+
32
+ if not hasattr(glob, 'escape'):
33
+ import re
34
+ glob.escape = lambda pathname: re.sub(r'([*?[])', r'[\1]', pathname)
35
+
36
+ def sqlite_datetime_to_timestamp(datetime):
37
+ if datetime is None:
38
+ return None
39
+ d = time.strptime(datetime, "%Y-%m-%d %H:%M:%S")
40
+ return time.mktime(d)
41
+
42
+ class MBTilesCache(TileCacheBase):
43
+ supports_timestamp = False
44
+
45
+ def __init__(self, mbtile_file, with_timestamps=False, timeout=30, wal=False):
46
+ self.lock_cache_id = 'mbtiles-' + hashlib.md5(mbtile_file.encode('utf-8')).hexdigest()
47
+ self.mbtile_file = mbtile_file
48
+ self.supports_timestamp = with_timestamps
49
+ self.timeout = timeout
50
+ self.wal = wal
51
+ self.ensure_mbtile()
52
+ self._db_conn_cache = threading.local()
53
+
54
+ @property
55
+ def db(self):
56
+ if not getattr(self._db_conn_cache, 'db', None):
57
+ self.ensure_mbtile()
58
+ self._db_conn_cache.db = sqlite3.connect(self.mbtile_file, self.timeout)
59
+ return self._db_conn_cache.db
60
+
61
+ def cleanup(self):
62
+ """
63
+ Close all open connection and remove them from cache.
64
+ """
65
+ if getattr(self._db_conn_cache, 'db', None):
66
+ self._db_conn_cache.db.close()
67
+ self._db_conn_cache.db = None
68
+
69
+ def ensure_mbtile(self):
70
+ if not os.path.exists(self.mbtile_file):
71
+ with FileLock(self.mbtile_file + '.init.lck',
72
+ remove_on_unlock=REMOVE_ON_UNLOCK):
73
+ if not os.path.exists(self.mbtile_file):
74
+ ensure_directory(self.mbtile_file)
75
+ self._initialize_mbtile()
76
+
77
+ def _initialize_mbtile(self):
78
+ log.info('initializing MBTile file %s', self.mbtile_file)
79
+ db = sqlite3.connect(self.mbtile_file)
80
+
81
+ if self.wal:
82
+ db.execute('PRAGMA journal_mode=wal')
83
+
84
+ stmt = """
85
+ CREATE TABLE tiles (
86
+ zoom_level integer,
87
+ tile_column integer,
88
+ tile_row integer,
89
+ tile_data blob
90
+ """
91
+
92
+ if self.supports_timestamp:
93
+ stmt += """
94
+ , last_modified datetime DEFAULT (datetime('now','localtime'))
95
+ """
96
+ stmt += """
97
+ );
98
+ """
99
+ db.execute(stmt)
100
+
101
+ db.execute("""
102
+ CREATE TABLE metadata (name text, value text);
103
+ """)
104
+ db.execute("""
105
+ CREATE UNIQUE INDEX idx_tile on tiles
106
+ (zoom_level, tile_column, tile_row);
107
+ """)
108
+ db.commit()
109
+ db.close()
110
+
111
+ def update_metadata(self, name='', description='', version=1, overlay=True, format='png'):
112
+ db = sqlite3.connect(self.mbtile_file)
113
+ db.execute("""
114
+ CREATE TABLE IF NOT EXISTS metadata (name text, value text);
115
+ """)
116
+ db.execute("""DELETE FROM metadata;""")
117
+
118
+ if overlay:
119
+ layer_type = 'overlay'
120
+ else:
121
+ layer_type = 'baselayer'
122
+
123
+ db.executemany("""
124
+ INSERT INTO metadata (name, value) VALUES (?,?)
125
+ """,
126
+ (
127
+ ('name', name),
128
+ ('description', description),
129
+ ('version', version),
130
+ ('type', layer_type),
131
+ ('format', format),
132
+ )
133
+ )
134
+ db.commit()
135
+ db.close()
136
+
137
+ def is_cached(self, tile, dimensions=None):
138
+ if tile.coord is None:
139
+ return True
140
+ if tile.source:
141
+ return True
142
+
143
+ return self.load_tile(tile, dimensions=dimensions)
144
+
145
+ def store_tile(self, tile, dimensions=None):
146
+ if tile.stored:
147
+ return True
148
+ return self._store_bulk([tile])
149
+
150
+ def store_tiles(self, tiles, dimensions=None):
151
+ tiles = [t for t in tiles if not t.stored]
152
+ return self._store_bulk(tiles)
153
+
154
+ def _store_bulk(self, tiles):
155
+ records = []
156
+ # tile_buffer (as_buffer) will encode the tile to the target format
157
+ # we collect all tiles before, to avoid having the db transaction
158
+ # open during this slow encoding
159
+ for tile in tiles:
160
+ with tile_buffer(tile) as buf:
161
+ if PY2:
162
+ content = buffer(buf.read())
163
+ else:
164
+ content = buf.read()
165
+ x, y, level = tile.coord
166
+ if self.supports_timestamp:
167
+ records.append((level, x, y, content, time.time()))
168
+ else:
169
+ records.append((level, x, y, content))
170
+
171
+ cursor = self.db.cursor()
172
+ try:
173
+ if self.supports_timestamp:
174
+ stmt = "INSERT OR REPLACE INTO tiles (zoom_level, tile_column, tile_row, tile_data, last_modified) VALUES (?,?,?,?, datetime(?, 'unixepoch', 'localtime'))"
175
+ cursor.executemany(stmt, records)
176
+ else:
177
+ stmt = "INSERT OR REPLACE INTO tiles (zoom_level, tile_column, tile_row, tile_data) VALUES (?,?,?,?)"
178
+ cursor.executemany(stmt, records)
179
+ self.db.commit()
180
+ except sqlite3.OperationalError as ex:
181
+ log.warning('unable to store tile: %s', ex)
182
+ return False
183
+ return True
184
+
185
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
186
+ if tile.source or tile.coord is None:
187
+ return True
188
+
189
+ cur = self.db.cursor()
190
+ if self.supports_timestamp:
191
+ cur.execute('''SELECT tile_data, last_modified
192
+ FROM tiles
193
+ WHERE tile_column = ? AND
194
+ tile_row = ? AND
195
+ zoom_level = ?''', tile.coord)
196
+ else:
197
+ cur.execute('''SELECT tile_data FROM tiles
198
+ WHERE tile_column = ? AND
199
+ tile_row = ? AND
200
+ zoom_level = ?''', tile.coord)
201
+
202
+ content = cur.fetchone()
203
+ if content:
204
+ tile.source = ImageSource(BytesIO(content[0]))
205
+ if self.supports_timestamp:
206
+ tile.timestamp = sqlite_datetime_to_timestamp(content[1])
207
+ return True
208
+ else:
209
+ return False
210
+
211
+ def load_tiles(self, tiles, with_metadata=False, dimensions=None):
212
+ #associate the right tiles with the cursor
213
+ tile_dict = {}
214
+ coords = []
215
+ for tile in tiles:
216
+ if tile.source or tile.coord is None:
217
+ continue
218
+ x, y, level = tile.coord
219
+ coords.append(x)
220
+ coords.append(y)
221
+ coords.append(level)
222
+ tile_dict[(x, y)] = tile
223
+
224
+ if not tile_dict:
225
+ # all tiles loaded or coords are None
226
+ return True
227
+
228
+ if self.supports_timestamp:
229
+ stmt_base = "SELECT tile_column, tile_row, tile_data, last_modified FROM tiles WHERE "
230
+ else:
231
+ stmt_base = "SELECT tile_column, tile_row, tile_data FROM tiles WHERE "
232
+
233
+ loaded_tiles = 0
234
+
235
+ # SQLite is limited to 1000 args -> split into multiple requests if more arguments are needed
236
+ while coords:
237
+ cur_coords = coords[:999]
238
+
239
+ stmt = stmt_base + ' OR '.join(
240
+ ['(tile_column = ? AND tile_row = ? AND zoom_level = ?)'] * (len(cur_coords) // 3))
241
+
242
+ cursor = self.db.cursor()
243
+ cursor.execute(stmt, cur_coords)
244
+
245
+ for row in cursor:
246
+ loaded_tiles += 1
247
+ tile = tile_dict[(row[0], row[1])]
248
+ data = row[2]
249
+ tile.size = len(data)
250
+ tile.source = ImageSource(BytesIO(data))
251
+ if self.supports_timestamp:
252
+ tile.timestamp = sqlite_datetime_to_timestamp(row[3])
253
+ cursor.close()
254
+
255
+ coords = coords[999:]
256
+
257
+ return loaded_tiles == len(tile_dict)
258
+
259
+ def remove_tile(self, tile):
260
+ cursor = self.db.cursor()
261
+ cursor.execute(
262
+ "DELETE FROM tiles WHERE (tile_column = ? AND tile_row = ? AND zoom_level = ?)",
263
+ tile.coord)
264
+ self.db.commit()
265
+ if cursor.rowcount:
266
+ return True
267
+ return False
268
+
269
+ def remove_level_tiles_before(self, level, timestamp):
270
+ if timestamp == 0:
271
+ cursor = self.db.cursor()
272
+ cursor.execute(
273
+ "DELETE FROM tiles WHERE (zoom_level = ?)",
274
+ (level, ))
275
+ self.db.commit()
276
+ if cursor.rowcount:
277
+ return True
278
+ return False
279
+
280
+ if self.supports_timestamp:
281
+ cursor = self.db.cursor()
282
+ cursor.execute(
283
+ "DELETE FROM tiles WHERE (zoom_level = ? AND last_modified < datetime(?, 'unixepoch', 'localtime'))",
284
+ (level, timestamp))
285
+ self.db.commit()
286
+ if cursor.rowcount:
287
+ return True
288
+ return False
289
+
290
+ def load_tile_metadata(self, tile, dimensions=None):
291
+ if not self.supports_timestamp:
292
+ # MBTiles specification does not include timestamps.
293
+ # This sets the timestamp of the tile to epoch (1970s)
294
+ tile.timestamp = -1
295
+ else:
296
+ self.load_tile(tile, dimensions=dimensions)
297
+
298
+ class MBTilesLevelCache(TileCacheBase):
299
+ supports_timestamp = True
300
+
301
+ def __init__(self, mbtiles_dir, timeout=30, wal=False):
302
+ self.lock_cache_id = 'sqlite-' + hashlib.md5(mbtiles_dir.encode('utf-8')).hexdigest()
303
+ self.cache_dir = mbtiles_dir
304
+ self._mbtiles = {}
305
+ self.timeout = timeout
306
+ self.wal = wal
307
+ self._mbtiles_lock = threading.Lock()
308
+
309
+ def _get_level(self, level):
310
+ if level in self._mbtiles:
311
+ return self._mbtiles[level]
312
+
313
+ with self._mbtiles_lock:
314
+ if level not in self._mbtiles:
315
+ mbtile_filename = os.path.join(self.cache_dir, '%s.mbtile' % level)
316
+ self._mbtiles[level] = MBTilesCache(
317
+ mbtile_filename,
318
+ with_timestamps=True,
319
+ timeout=self.timeout,
320
+ wal=self.wal,
321
+ )
322
+
323
+ return self._mbtiles[level]
324
+
325
+ def cleanup(self):
326
+ """
327
+ Close all open connection and remove them from cache.
328
+ """
329
+ with self._mbtiles_lock:
330
+ for mbtile in self._mbtiles.values():
331
+ mbtile.cleanup()
332
+
333
+ def is_cached(self, tile, dimensions=None):
334
+ if tile.coord is None:
335
+ return True
336
+ if tile.source:
337
+ return True
338
+
339
+ return self._get_level(tile.coord[2]).is_cached(tile, dimensions=dimensions)
340
+
341
+ def store_tile(self, tile, dimensions=None):
342
+ if tile.stored:
343
+ return True
344
+
345
+ return self._get_level(tile.coord[2]).store_tile(tile, dimensions=dimensions)
346
+
347
+ def store_tiles(self, tiles, dimensions=None):
348
+ failed = False
349
+ for level, tiles in itertools.groupby(tiles, key=lambda t: t.coord[2]):
350
+ tiles = [t for t in tiles if not t.stored]
351
+ res = self._get_level(level).store_tiles(tiles, dimensions=dimensions)
352
+ if not res: failed = True
353
+ return failed
354
+
355
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
356
+ if tile.source or tile.coord is None:
357
+ return True
358
+
359
+ return self._get_level(tile.coord[2]).load_tile(tile, with_metadata=with_metadata, dimensions=dimensions)
360
+
361
+ def load_tiles(self, tiles, with_metadata=False, dimensions=None):
362
+ level = None
363
+ for tile in tiles:
364
+ if tile.source or tile.coord is None:
365
+ continue
366
+ level = tile.coord[2]
367
+ break
368
+
369
+ if not level:
370
+ return True
371
+
372
+ return self._get_level(level).load_tiles(tiles, with_metadata=with_metadata, dimensions=dimensions)
373
+
374
+ def remove_tile(self, tile):
375
+ if tile.coord is None:
376
+ return True
377
+
378
+ return self._get_level(tile.coord[2]).remove_tile(tile)
379
+
380
+ def load_tile_metadata(self, tile, dimensions=None):
381
+ self.load_tile(tile, dimensions=dimensions)
382
+
383
+ def remove_level_tiles_before(self, level, timestamp):
384
+ level_cache = self._get_level(level)
385
+ if timestamp == 0:
386
+ level_cache.cleanup()
387
+ os.unlink(level_cache.mbtile_file)
388
+ for file in glob.glob("%s-*" % glob.escape(level_cache.mbtile_file)):
389
+ os.unlink(file)
390
+ return True
391
+ else:
392
+ return level_cache.remove_level_tiles_before(level, timestamp)
mapproxy/cache/meta.py ADDED
@@ -0,0 +1,78 @@
1
+ from __future__ import print_function
2
+ import struct
3
+ from mapproxy.cache.base import tile_buffer
4
+ from mapproxy.image import ImageSource
5
+
6
+ class MetaTileFile(object):
7
+ def __init__(self, meta_tile):
8
+ self.meta_tile = meta_tile
9
+
10
+ def write_tiles(self, tiles):
11
+ tile_positions = []
12
+ count = len(tiles) # self.meta_tile.grid_size[0]
13
+ header_size = (
14
+ 4 # META
15
+ + 4 # metasize**2
16
+ + 3*4 # x, y, z
17
+ + count * 8 #offset/size * tiles
18
+ )
19
+ with open('/tmp/foo.metatile', 'wb') as f:
20
+ f.write("META")
21
+ f.write(struct.pack('i', count))
22
+ f.write(struct.pack('iii', *tiles[0].coord))
23
+ offsets_header_pos = f.tell()
24
+ f.seek(header_size, 0)
25
+
26
+ for tile in tiles:
27
+ offset = f.tell()
28
+ with tile_buffer(tile) as buf:
29
+ tile_data = buf.read()
30
+ f.write(tile_data)
31
+ tile_positions.append((offset, len(tile_data)))
32
+
33
+ f.seek(offsets_header_pos, 0)
34
+ for offset, size in tile_positions:
35
+ f.write(struct.pack('ii', offset, size))
36
+
37
+ def _read_header(self, f):
38
+ f.seek(0, 0)
39
+ assert f.read(4) == "META"
40
+ count, x, y, z = struct.unpack('iiii', f.read(4*4))
41
+ tile_positions = []
42
+ for i in range(count):
43
+ offset, size = struct.unpack('ii', f.read(4*2))
44
+ tile_positions.append((offset, size))
45
+
46
+ return tile_positions
47
+
48
+ def read_tiles(self):
49
+ with open('/tmp/foo.metatile', 'rb') as f:
50
+ tile_positions = self._read_header(f)
51
+
52
+ for i, (offset, size) in enumerate(tile_positions):
53
+ f.seek(offset, 0)
54
+ # img = ImageSource(BytesIO(f.read(size)))
55
+ open('/tmp/img-%02d.png' % i, 'wb').write(f.read(size))
56
+
57
+ if __name__ == '__main__':
58
+ from io import BytesIO
59
+ from mapproxy.cache.tile import Tile
60
+ from mapproxy.test.image import create_tmp_image
61
+
62
+ tiles = []
63
+ img = create_tmp_image((256, 256))
64
+ for x in range(8):
65
+ for y in range(8):
66
+ tiles.append(Tile((x, y, 4), ImageSource(BytesIO(img))))
67
+
68
+ m = MetaTileFile(None)
69
+ print('!')
70
+ m.write_tiles(tiles)
71
+ print('!')
72
+ m.read_tiles()
73
+ print('!')
74
+
75
+ x = y = 0
76
+ METATILE = 8
77
+ for meta in range(METATILE ** 2):
78
+ print(x + (meta / METATILE), y + (meta % METATILE));