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
mapproxy/cache/path.py ADDED
@@ -0,0 +1,250 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010-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
+ import os
17
+ from mapproxy.compat import string_type
18
+ from mapproxy.util.fs import ensure_directory
19
+ from mapproxy.request.base import NoCaseMultiDict
20
+
21
+ def location_funcs(layout):
22
+ if layout == 'tc':
23
+ return tile_location_tc, level_location
24
+ elif layout == 'mp':
25
+ return tile_location_mp, level_location
26
+ elif layout == 'tms':
27
+ return tile_location_tms, level_location
28
+ elif layout == 'reverse_tms':
29
+ return tile_location_reverse_tms, None
30
+ elif layout == 'quadkey':
31
+ return tile_location_quadkey, no_level_location
32
+ elif layout == 'arcgis':
33
+ return tile_location_arcgiscache, level_location_arcgiscache
34
+ else:
35
+ raise ValueError('unknown directory_layout "%s"' % layout)
36
+
37
+ def level_location(level, cache_dir, dimensions=None):
38
+ """
39
+ Return the path where all tiles for `level` will be stored.
40
+
41
+ >>> os.path.abspath(level_location(2, '/tmp/cache')) == os.path.abspath('/tmp/cache/02')
42
+ True
43
+ """
44
+ dim_path = dimensions_part(dimensions)
45
+
46
+ if isinstance(level, string_type):
47
+ return os.path.join(cache_dir, dim_path, level)
48
+ else:
49
+ return os.path.join(cache_dir, dim_path, "%02d" % level)
50
+
51
+ def dimensions_part(dimensions):
52
+ """
53
+ Return the subpath where all tiles for `dimensions` will be stored.
54
+ Dimensions prefixed with "dim_" are sorted after the predefined elevation and time dimensions
55
+ >>> dimensions_part({'time': '2020-08-25T00:00:00Z'})
56
+ 'time-2020-08-25T00:00:00Z'
57
+ >>> dimensions_part({'time': '2020-08-25T00:00:00Z', 'dim_reference_time': '2020-08-25T00:00:00Z', 'dim_level': '700'})
58
+ 'time-2020-08-25T00:00:00Z/dim_level-700/dim_reference_time-2020-08-25T00:00:00Z'
59
+
60
+ """
61
+ if dimensions:
62
+ dims = NoCaseMultiDict(dimensions)
63
+ predefined_dims, custom_dims = [], []
64
+ for dim in dims.keys():
65
+ (custom_dims if dim.startswith('dim_') else predefined_dims).append(dim)
66
+ dim_keys = sorted(predefined_dims) + sorted(custom_dims)
67
+ return os.path.join(*(map(lambda k: k + "-" + str(dims.get(k, 'default')), dim_keys)))
68
+ else:
69
+ return ""
70
+
71
+ def level_part(level):
72
+ """
73
+ Return the path where all tiles for `level` will be stored.
74
+
75
+ >>> level_part(2)
76
+ '02'
77
+ >>> level_part('2')
78
+ '2'
79
+ """
80
+ if isinstance(level, string_type):
81
+ return level
82
+ else:
83
+ return "%02d" % level
84
+
85
+
86
+ def tile_location_tc(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
87
+ """
88
+ Return the location of the `tile`. Caches the result as ``location``
89
+ property of the `tile`.
90
+
91
+ :param tile: the tile object
92
+ :param create_dir: if True, create all necessary directories
93
+ :return: the full filename of the tile
94
+
95
+ >>> from mapproxy.cache.tile import Tile
96
+ >>> tile_location_tc(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
97
+ '/tmp/cache/02/000/000/003/000/000/004.png'
98
+ """
99
+ if tile.location is None:
100
+ x, y, z = tile.coord
101
+
102
+ parts = (cache_dir,
103
+ dimensions_part(dimensions),
104
+ level_part(z),
105
+ "%03d" % int(x / 1000000),
106
+ "%03d" % (int(x / 1000) % 1000),
107
+ "%03d" % (int(x) % 1000),
108
+ "%03d" % int(y / 1000000),
109
+ "%03d" % (int(y / 1000) % 1000),
110
+ "%03d.%s" % (int(y) % 1000, file_ext))
111
+ tile.location = os.path.join(*parts)
112
+ if create_dir:
113
+ ensure_directory(tile.location)
114
+ return tile.location
115
+
116
+ def tile_location_mp(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
117
+ """
118
+ Return the location of the `tile`. Caches the result as ``location``
119
+ property of the `tile`.
120
+
121
+ :param tile: the tile object
122
+ :param create_dir: if True, create all necessary directories
123
+ :return: the full filename of the tile
124
+
125
+ >>> from mapproxy.cache.tile import Tile
126
+ >>> tile_location_mp(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
127
+ '/tmp/cache/02/0000/0003/0000/0004.png'
128
+ >>> tile_location_mp(Tile((12345678, 98765432, 22)), '/tmp/cache', 'png').replace('\\\\', '/')
129
+ '/tmp/cache/22/1234/5678/9876/5432.png'
130
+ """
131
+ if tile.location is None:
132
+ x, y, z = tile.coord
133
+ parts = (cache_dir,
134
+ dimensions_part(dimensions),
135
+ level_part(z),
136
+ "%04d" % int(x / 10000),
137
+ "%04d" % (int(x) % 10000),
138
+ "%04d" % int(y / 10000),
139
+ "%04d.%s" % (int(y) % 10000, file_ext))
140
+ tile.location = os.path.join(*parts)
141
+ if create_dir:
142
+ ensure_directory(tile.location)
143
+ return tile.location
144
+
145
+ def tile_location_tms(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
146
+ """
147
+ Return the location of the `tile`. Caches the result as ``location``
148
+ property of the `tile`.
149
+
150
+ :param tile: the tile object
151
+ :param create_dir: if True, create all necessary directories
152
+ :return: the full filename of the tile
153
+
154
+ >>> from mapproxy.cache.tile import Tile
155
+ >>> tile_location_tms(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
156
+ '/tmp/cache/2/3/4.png'
157
+ """
158
+ if tile.location is None:
159
+ x, y, z = tile.coord
160
+ tile.location = os.path.join(
161
+ cache_dir,dimensions_part(dimensions) ,level_part(str(z)),
162
+ str(x), str(y) + '.' + file_ext
163
+ )
164
+ if create_dir:
165
+ ensure_directory(tile.location)
166
+ return tile.location
167
+
168
+ def tile_location_reverse_tms(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
169
+ """
170
+ Return the location of the `tile`. Caches the result as ``location``
171
+ property of the `tile`.
172
+
173
+ :param tile: the tile object
174
+ :param create_dir: if True, create all necessary directories
175
+ :return: the full filename of the tile
176
+
177
+ >>> from mapproxy.cache.tile import Tile
178
+ >>> tile_location_reverse_tms(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
179
+ '/tmp/cache/4/3/2.png'
180
+ """
181
+ if tile.location is None:
182
+ x, y, z = tile.coord
183
+ tile.location = os.path.join(
184
+ cache_dir,dimensions_part(dimensions),str(y), str(x), str(z) + '.' + file_ext
185
+ )
186
+ if create_dir:
187
+ ensure_directory(tile.location)
188
+ return tile.location
189
+
190
+ def level_location_tms(level, cache_dir, dimensions=None):
191
+ return level_location(str(level), cache_dir=cache_dir)
192
+
193
+ def tile_location_quadkey(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
194
+ """
195
+ Return the location of the `tile`. Caches the result as ``location``
196
+ property of the `tile`.
197
+
198
+ :param tile: the tile object
199
+ :param create_dir: if True, create all necessary directories
200
+ :return: the full filename of the tile
201
+
202
+ >>> from mapproxy.cache.tile import Tile
203
+ >>> tile_location_quadkey(Tile((3, 4, 2)), '/tmp/cache', 'png').replace('\\\\', '/')
204
+ '/tmp/cache/11.png'
205
+ """
206
+ if tile.location is None:
207
+ x, y, z = tile.coord
208
+ quadKey = ""
209
+ for i in range(z,0,-1):
210
+ digit = 0
211
+ mask = 1 << (i-1)
212
+ if (x & mask) != 0:
213
+ digit += 1
214
+ if (y & mask) != 0:
215
+ digit += 2
216
+ quadKey += str(digit)
217
+ tile.location = os.path.join(
218
+ cache_dir, quadKey + '.' + file_ext
219
+ )
220
+ if create_dir:
221
+ ensure_directory(tile.location)
222
+ return tile.location
223
+
224
+ def no_level_location(level, cache_dir, dimensions=None):
225
+ # dummy for quadkey cache which stores all tiles in one directory
226
+ raise NotImplementedError('cache does not have any level location')
227
+
228
+ def tile_location_arcgiscache(tile, cache_dir, file_ext, create_dir=False, dimensions=None):
229
+ """
230
+ Return the location of the `tile`. Caches the result as ``location``
231
+ property of the `tile`.
232
+
233
+ :param tile: the tile object
234
+ :param create_dir: if True, create all necessary directories
235
+ :return: the full filename of the tile
236
+
237
+ >>> from mapproxy.cache.tile import Tile
238
+ >>> tile_location_arcgiscache(Tile((1234567, 87654321, 9)), '/tmp/cache', 'png').replace('\\\\', '/')
239
+ '/tmp/cache/L09/R05397fb1/C0012d687.png'
240
+ """
241
+ if tile.location is None:
242
+ x, y, z = tile.coord
243
+ parts = (cache_dir, 'L%02d' % z, 'R%08x' % y, 'C%08x.%s' % (x, file_ext))
244
+ tile.location = os.path.join(*parts)
245
+ if create_dir:
246
+ ensure_directory(tile.location)
247
+ return tile.location
248
+
249
+ def level_location_arcgiscache(z, cache_dir, dimensions=None):
250
+ return level_location('L%02d' % z, cache_dir=cache_dir, dimensions=dimensions)
@@ -0,0 +1,88 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2017 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 absolute_import
17
+
18
+ import hashlib
19
+
20
+ from mapproxy.image import ImageSource
21
+ from mapproxy.cache.base import (
22
+ TileCacheBase,
23
+ tile_buffer,
24
+ )
25
+ from mapproxy.compat import BytesIO
26
+
27
+ try:
28
+ import redis
29
+ except ImportError:
30
+ redis = None
31
+
32
+
33
+ import logging
34
+ log = logging.getLogger(__name__)
35
+
36
+
37
+ class RedisCache(TileCacheBase):
38
+ def __init__(self, host, port, prefix, ttl=0, db=0):
39
+ if redis is None:
40
+ raise ImportError("Redis backend requires 'redis' package.")
41
+
42
+ self.prefix = prefix
43
+ self.lock_cache_id = 'redis-' + hashlib.md5((host + str(port) + prefix + str(db)).encode('utf-8')).hexdigest()
44
+ self.ttl = ttl
45
+ self.r = redis.StrictRedis(host=host, port=port, db=db)
46
+
47
+ def _key(self, tile):
48
+ x, y, z = tile.coord
49
+ return self.prefix + '-%d-%d-%d' % (z, x, y)
50
+
51
+ def is_cached(self, tile, dimensions=None):
52
+ if tile.coord is None or tile.source:
53
+ return True
54
+
55
+ return self.r.exists(self._key(tile))
56
+
57
+ def store_tile(self, tile, dimensions=None):
58
+ if tile.stored:
59
+ return True
60
+
61
+ key = self._key(tile)
62
+
63
+ with tile_buffer(tile) as buf:
64
+ data = buf.read()
65
+
66
+ r = self.r.set(key, data)
67
+ if self.ttl:
68
+ # use ms expire times for unit-tests
69
+ self.r.pexpire(key, int(self.ttl * 1000))
70
+ return r
71
+
72
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
73
+ if tile.source or tile.coord is None:
74
+ return True
75
+ key = self._key(tile)
76
+ tile_data = self.r.get(key)
77
+ if tile_data:
78
+ tile.source = ImageSource(BytesIO(tile_data))
79
+ return True
80
+ return False
81
+
82
+ def remove_tile(self, tile, dimensions=None):
83
+ if tile.coord is None:
84
+ return True
85
+
86
+ key = self._key(tile)
87
+ self.r.delete(key)
88
+ return True
@@ -0,0 +1,95 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2012, 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 time
17
+ import hashlib
18
+
19
+ try:
20
+ import json; json
21
+ except ImportError:
22
+ json = None
23
+
24
+ try:
25
+ import requests; requests
26
+ except ImportError:
27
+ requests = None
28
+
29
+ from mapproxy.client.log import log_request
30
+ from mapproxy.cache.tile import TileCreator, Tile
31
+ from mapproxy.source import SourceError
32
+ from mapproxy.util.lock import LockTimeout
33
+
34
+ def has_renderd_support():
35
+ if not json or not requests:
36
+ return False
37
+ return True
38
+
39
+ class RenderdTileCreator(TileCreator):
40
+ def __init__(self, renderd_address, tile_mgr, dimensions=None, priority=100, tile_locker=None):
41
+ TileCreator.__init__(self, tile_mgr, dimensions)
42
+ self.tile_locker = tile_locker.lock or self.tile_mgr.lock
43
+ self.renderd_address = renderd_address
44
+ self.priority = priority
45
+
46
+ def _create_single_tile(self, tile):
47
+ with self.tile_locker(tile):
48
+ if not self.is_cached(tile):
49
+ self._create_renderd_tile(tile.coord)
50
+ self.cache.load_tile(tile)
51
+ return [tile]
52
+
53
+ def _create_meta_tile(self, meta_tile):
54
+ main_tile = Tile(meta_tile.main_tile_coord)
55
+ with self.tile_locker(main_tile):
56
+ if not all(self.is_cached(t) for t in meta_tile.tiles if t is not None):
57
+ self._create_renderd_tile(main_tile.coord)
58
+
59
+ tiles = [Tile(coord) for coord in meta_tile.tiles]
60
+ self.cache.load_tiles(tiles)
61
+ return tiles
62
+
63
+ def _create_renderd_tile(self, tile_coord):
64
+ start_time = time.time()
65
+ result = self._send_tile_request(self.tile_mgr.identifier, [tile_coord])
66
+ duration = time.time()-start_time
67
+
68
+ address = '%s:%s:%r' % (self.renderd_address,
69
+ self.tile_mgr.identifier, tile_coord)
70
+
71
+ if result['status'] == 'error':
72
+ log_request(address, 500, None, duration=duration, method='RENDERD')
73
+ raise SourceError("Error from renderd: %s" % result.get('error_message', 'unknown error from renderd'))
74
+ elif result['status'] == 'lock':
75
+ log_request(address, 503, None, duration=duration, method='RENDERD')
76
+ raise LockTimeout("Lock timeout from renderd: %s" % result.get('error_message', 'unknown lock timeout error from renderd'))
77
+
78
+ log_request(address, 200, None, duration=duration, method='RENDERD')
79
+
80
+ def _send_tile_request(self, cache_identifier, tile_coords):
81
+ identifier = hashlib.sha1(str((cache_identifier, tile_coords)).encode('ascii')).hexdigest()
82
+ message = {
83
+ 'command': 'tile',
84
+ 'id': identifier,
85
+ 'tiles': tile_coords,
86
+ 'cache_identifier': cache_identifier,
87
+ 'priority': self.priority
88
+ }
89
+ try:
90
+ resp = requests.post(self.renderd_address, data=json.dumps(message))
91
+ return resp.json()
92
+ except ValueError:
93
+ raise SourceError("Error while communicating with renderd: invalid JSON")
94
+ except requests.RequestException as ex:
95
+ raise SourceError("Error while communicating with renderd: %s" % ex)
mapproxy/cache/riak.py ADDED
@@ -0,0 +1,202 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 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
+ from __future__ import absolute_import
17
+
18
+ import threading
19
+ import hashlib
20
+
21
+ from io import BytesIO
22
+
23
+ from mapproxy.image import ImageSource
24
+ from mapproxy.cache.tile import Tile
25
+ from mapproxy.cache.base import TileCacheBase, tile_buffer, CacheBackendError
26
+
27
+ try:
28
+ import riak
29
+ except ImportError:
30
+ riak = None
31
+ except TypeError:
32
+ import warnings
33
+ warnings.warn("riak version not compatible with this Python version")
34
+ riak = None
35
+
36
+ import logging
37
+ log = logging.getLogger(__name__)
38
+
39
+ class UnexpectedResponse(CacheBackendError):
40
+ pass
41
+
42
+ class RiakCache(TileCacheBase):
43
+ def __init__(self, nodes, protocol, bucket, tile_grid, use_secondary_index=False, timeout=60):
44
+ if riak is None:
45
+ raise ImportError("Riak backend requires 'riak' package.")
46
+
47
+ self.nodes = nodes
48
+ self.protocol = protocol
49
+ self.lock_cache_id = 'riak-' + hashlib.md5(bucket.encode('utf-8')).hexdigest()
50
+ self.request_timeout = timeout * 1000
51
+ self.bucket_name = bucket
52
+ self.tile_grid = tile_grid
53
+ self.use_secondary_index = use_secondary_index
54
+ self._db_conn_cache = threading.local()
55
+
56
+ @property
57
+ def connection(self):
58
+ if not getattr(self._db_conn_cache, 'connection', None):
59
+ self._db_conn_cache.connection = riak.RiakClient(protocol=self.protocol, nodes=self.nodes)
60
+ return self._db_conn_cache.connection
61
+
62
+ @property
63
+ def bucket(self):
64
+ if not getattr(self._db_conn_cache, 'bucket', None):
65
+ self._db_conn_cache.bucket = self.connection.bucket(self.bucket_name)
66
+ return self._db_conn_cache.bucket
67
+
68
+ def _get_object(self, coord):
69
+ (x, y, z) = coord
70
+ key = '%(z)d_%(x)d_%(y)d' % locals()
71
+ obj = False
72
+ try:
73
+ obj = self.bucket.get(key, r=1, timeout=self.request_timeout)
74
+ except Exception as e:
75
+ log.warning('error while requesting %s: %s', key, e)
76
+
77
+ if not obj:
78
+ obj = self.bucket.new(key=key, data=None, content_type='application/octet-stream')
79
+ return obj
80
+
81
+ def _get_timestamp(self, obj):
82
+ metadata = obj.usermeta
83
+ timestamp = metadata.get('timestamp')
84
+ if timestamp != None:
85
+ return float(timestamp)
86
+
87
+ obj.usermeta = {'timestamp': '0'}
88
+ return 0.0
89
+
90
+ def is_cached(self, tile, dimensions=None):
91
+ return self.load_tile(tile, True)
92
+
93
+ def _store_bulk(self, tiles):
94
+ for tile in tiles:
95
+ res = self._get_object(tile.coord)
96
+ with tile_buffer(tile) as buf:
97
+ data = buf.read()
98
+ res.encoded_data = data
99
+ res.usermeta = {
100
+ 'timestamp': str(tile.timestamp),
101
+ 'size': str(tile.size),
102
+ }
103
+ if self.use_secondary_index:
104
+ x, y, z = tile.coord
105
+ res.add_index('tile_coord_bin', '%02d-%07d-%07d' % (z, x, y))
106
+
107
+ try:
108
+ res.store(w=1, dw=1, pw=1, return_body=False, timeout=self.request_timeout)
109
+ except riak.RiakError as ex:
110
+ log.warning('unable to store tile: %s', ex)
111
+ return False
112
+
113
+ return True
114
+
115
+ def store_tile(self, tile,dimensions=None):
116
+ if tile.stored:
117
+ return True
118
+
119
+ return self._store_bulk([tile])
120
+
121
+ def store_tiles(self, tiles,dimensions=None):
122
+ tiles = [t for t in tiles if not t.stored]
123
+ return self._store_bulk(tiles)
124
+
125
+ def load_tile_metadata(self, tile,dimensions=None):
126
+ if tile.timestamp:
127
+ return
128
+
129
+ # is_cached loads metadata
130
+ self.load_tile(tile, True)
131
+
132
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
133
+ if tile.timestamp is None:
134
+ tile.timestamp = 0
135
+ if tile.source or tile.coord is None:
136
+ return True
137
+
138
+ res = self._get_object(tile.coord)
139
+ if res.exists:
140
+ tile_data = BytesIO(res.encoded_data)
141
+ tile.source = ImageSource(tile_data)
142
+ if with_metadata:
143
+ tile.timestamp = self._get_timestamp(res)
144
+ tile.size = len(res.encoded_data)
145
+ return True
146
+
147
+ return False
148
+
149
+ def remove_tile(self, tile):
150
+ if tile.coord is None:
151
+ return True
152
+
153
+ res = self._get_object(tile.coord)
154
+ if not res.exists:
155
+ # already removed
156
+ return True
157
+
158
+ try:
159
+ res.delete(w=1, r=1, dw=1, pw=1, timeout=self.request_timeout)
160
+ except riak.RiakError as ex:
161
+ log.warning('unable to remove tile: %s', ex)
162
+ return False
163
+ return True
164
+
165
+ def _fill_metadata_from_obj(self, obj, tile):
166
+ tile_md = obj.usermeta
167
+ timestamp = tile_md.get('timestamp')
168
+ if timestamp:
169
+ tile.timestamp = float(timestamp)
170
+
171
+ def _key_iterator(self, level):
172
+ """
173
+ Generator for all tile keys in `level`.
174
+ """
175
+ # index() returns a list of all keys so we check for tiles in
176
+ # batches of `chunk_size`*`chunk_size`.
177
+ grid_size = self.tile_grid.grid_sizes[level]
178
+ chunk_size = 256
179
+ for x in range(grid_size[0]/chunk_size):
180
+ start_x = x * chunk_size
181
+ end_x = start_x + chunk_size - 1
182
+ for y in range(grid_size[1]/chunk_size):
183
+ start_y = y * chunk_size
184
+ end_y = start_y + chunk_size - 1
185
+ query = self.bucket.get_index('tile_coord_bin',
186
+ '%02d-%07d-%07d' % (level, start_x, start_y),
187
+ '%02d-%07d-%07d' % (level, end_x, end_y))
188
+ for link in query.run():
189
+ yield link.get_key()
190
+
191
+ def remove_tiles_for_level(self, level, before_timestamp=None):
192
+ bucket = self.bucket
193
+ client = self.connection
194
+ for key in self._key_iterator(level):
195
+ if before_timestamp:
196
+ obj = self.bucket.get(key, r=1)
197
+ dummy_tile = Tile((0, 0, 0))
198
+ self._fill_metadata_from_obj(obj, dummy_tile)
199
+ if dummy_tile.timestamp < before_timestamp:
200
+ obj.delete()
201
+ else:
202
+ riak.RiakObject(client, bucket, key).delete()