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,295 @@
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
+
17
+ import codecs
18
+ import datetime
19
+ import json
20
+ import socket
21
+ import time
22
+ import hashlib
23
+ import base64
24
+
25
+ from mapproxy.image import ImageSource
26
+ from mapproxy.cache.base import (
27
+ TileCacheBase,
28
+ tile_buffer, CacheBackendError,)
29
+ from mapproxy.source import SourceError
30
+ from mapproxy.srs import SRS
31
+ from mapproxy.compat import string_type, iteritems, BytesIO
32
+
33
+ from threading import Lock
34
+
35
+ try:
36
+ import requests
37
+ except ImportError:
38
+ requests = None
39
+
40
+
41
+ import logging
42
+ log = logging.getLogger(__name__)
43
+
44
+ class UnexpectedResponse(CacheBackendError):
45
+ pass
46
+
47
+ class CouchDBCache(TileCacheBase):
48
+ def __init__(self, url, db_name,
49
+ file_ext, tile_grid, md_template=None,
50
+ tile_id_template=None):
51
+
52
+ if requests is None:
53
+ raise ImportError("CouchDB backend requires 'requests' package.")
54
+
55
+ self.lock_cache_id = 'couchdb-' + hashlib.md5((url + db_name).encode('utf-8')).hexdigest()
56
+ self.file_ext = file_ext
57
+ self.tile_grid = tile_grid
58
+ self.md_template = md_template
59
+ self.couch_url = '%s/%s' % (url.rstrip('/'), db_name.lower())
60
+ self.req_session = requests.Session()
61
+ self.req_session.timeout = 5
62
+ self.db_initialised = False
63
+ self.app_init_db_lock = Lock()
64
+ self.tile_id_template = tile_id_template
65
+
66
+ def init_db(self):
67
+ with self.app_init_db_lock:
68
+ if self.db_initialised:
69
+ return
70
+ try:
71
+ self.req_session.put(self.couch_url)
72
+ self.db_initialised = True
73
+ except requests.exceptions.RequestException as ex:
74
+ log.warning('unable to initialize CouchDB: %s', ex)
75
+
76
+ def tile_url(self, coord):
77
+ return self.document_url(coord) + '/tile'
78
+
79
+ def document_url(self, coord, relative=False):
80
+ x, y, z = coord
81
+ grid_name = self.tile_grid.name
82
+ couch_url = self.couch_url
83
+ if relative:
84
+ if self.tile_id_template:
85
+ if self.tile_id_template.startswith('%(couch_url)s/'):
86
+ tile_id_template = self.tile_id_template[len('%(couch_url)s/'):]
87
+ else:
88
+ tile_id_template = self.tile_id_template
89
+ return tile_id_template % locals()
90
+ else:
91
+ return '%(grid_name)s-%(z)s-%(x)s-%(y)s' % locals()
92
+ else:
93
+ if self.tile_id_template:
94
+ return self.tile_id_template % locals()
95
+ else:
96
+ return '%(couch_url)s/%(grid_name)s-%(z)s-%(x)s-%(y)s' % locals()
97
+
98
+ def is_cached(self, tile, dimensions=None):
99
+ if tile.coord is None or tile.source:
100
+ return True
101
+ url = self.document_url(tile.coord)
102
+ try:
103
+ self.init_db()
104
+ resp = self.req_session.get(url)
105
+ if resp.status_code == 200:
106
+ doc = json.loads(codecs.decode(resp.content, 'utf-8'))
107
+ tile.timestamp = doc.get(self.md_template.timestamp_key)
108
+ return True
109
+ except (requests.exceptions.RequestException, socket.error) as ex:
110
+ # is_cached should not fail (would abort seeding for example),
111
+ # so we catch these errors here and just return False
112
+ log.warning('error while requesting %s: %s', url, ex)
113
+ return False
114
+ if resp.status_code == 404:
115
+ return False
116
+ raise SourceError('%r: %r' % (resp.status_code, resp.content))
117
+
118
+
119
+ def _tile_doc(self, tile):
120
+ tile_id = self.document_url(tile.coord, relative=True)
121
+ if self.md_template:
122
+ tile_doc = self.md_template.doc(tile, self.tile_grid)
123
+ else:
124
+ tile_doc = {}
125
+ tile_doc['_id'] = tile_id
126
+
127
+ with tile_buffer(tile) as buf:
128
+ data = buf.read()
129
+ tile_doc['_attachments'] = {
130
+ 'tile': {
131
+ 'content_type': 'image/' + self.file_ext,
132
+ 'data': codecs.decode(
133
+ base64.b64encode(data).replace(b'\n', b''),
134
+ 'ascii',
135
+ ),
136
+ }
137
+ }
138
+ return tile_id, tile_doc
139
+
140
+ def _store_bulk(self, tiles):
141
+ tile_docs = {}
142
+ for tile in tiles:
143
+ tile_id, tile_doc = self._tile_doc(tile)
144
+ tile_docs[tile_id] = tile_doc
145
+
146
+ duplicate_tiles = self._post_bulk(tile_docs)
147
+
148
+ if duplicate_tiles:
149
+ self._fill_rev_ids(duplicate_tiles)
150
+ self._post_bulk(duplicate_tiles, no_conflicts=True)
151
+
152
+ return True
153
+
154
+ def _post_bulk(self, tile_docs, no_conflicts=False):
155
+ """
156
+ POST multiple tiles, returns all tile docs with conflicts during POST.
157
+ """
158
+ doc = {'docs': list(tile_docs.values())}
159
+ data = json.dumps(doc)
160
+ self.init_db()
161
+ resp = self.req_session.post(self.couch_url + '/_bulk_docs', data=data, headers={'Content-type': 'application/json'})
162
+ if resp.status_code != 201:
163
+ raise UnexpectedResponse('got unexpected resp (%d) from CouchDB: %s' % (resp.status_code, resp.content))
164
+
165
+ resp_doc = json.loads(codecs.decode(resp.content, 'utf-8'))
166
+ duplicate_tiles = {}
167
+ for tile in resp_doc:
168
+ if tile.get('error', 'false') == 'conflict':
169
+ duplicate_tiles[tile['id']] = tile_docs[tile['id']]
170
+
171
+ if no_conflicts and duplicate_tiles:
172
+ raise UnexpectedResponse('got unexpected resp (%d) from CouchDB: %s' % (resp.status_code, resp.content))
173
+
174
+ return duplicate_tiles
175
+
176
+ def _fill_rev_ids(self, tile_docs):
177
+ """
178
+ Request all revs for tile_docs and insert it into the tile_docs.
179
+ """
180
+ keys_doc = {'keys': list(tile_docs.keys())}
181
+ data = json.dumps(keys_doc)
182
+ self.init_db()
183
+ resp = self.req_session.post(self.couch_url + '/_all_docs', data=data, headers={'Content-type': 'application/json'})
184
+ if resp.status_code != 200:
185
+ raise UnexpectedResponse('got unexpected resp (%d) from CouchDB: %s' % (resp.status_code, resp.content))
186
+
187
+ resp_doc = json.loads(codecs.decode(resp.content, 'utf-8'))
188
+ for tile in resp_doc['rows']:
189
+ tile_docs[tile['id']]['_rev'] = tile['value']['rev']
190
+
191
+ def store_tile(self, tile, dimensions=None):
192
+ if tile.stored:
193
+ return True
194
+
195
+ return self._store_bulk([tile])
196
+
197
+ def store_tiles(self, tiles, dimensions=None):
198
+ tiles = [t for t in tiles if not t.stored]
199
+ return self._store_bulk(tiles)
200
+
201
+ def load_tile_metadata(self, tile, dimensions=None):
202
+ if tile.timestamp:
203
+ return
204
+
205
+ # is_cached loads metadata
206
+ self.is_cached(tile, dimensions=None)
207
+
208
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
209
+ # bulk loading with load_tiles is not implemented, because
210
+ # CouchDB's /all_docs? does not include attachments
211
+
212
+ if tile.source or tile.coord is None:
213
+ return True
214
+ url = self.document_url(tile.coord) + '?attachments=true'
215
+ self.init_db()
216
+ resp = self.req_session.get(url, headers={'Accept': 'application/json'})
217
+ if resp.status_code == 200:
218
+ doc = json.loads(codecs.decode(resp.content, 'utf-8'))
219
+ tile_data = BytesIO(base64.b64decode(doc['_attachments']['tile']['data']))
220
+ tile.source = ImageSource(tile_data)
221
+ tile.timestamp = doc.get(self.md_template.timestamp_key)
222
+ return True
223
+ return False
224
+
225
+ def remove_tile(self, tile):
226
+ if tile.coord is None:
227
+ return True
228
+ url = self.document_url(tile.coord)
229
+ resp = requests.head(url)
230
+ if resp.status_code == 404:
231
+ # already removed
232
+ return True
233
+ rev_id = resp.headers['etag']
234
+ url += '?rev=' + rev_id.strip('"')
235
+ self.init_db()
236
+ resp = self.req_session.delete(url)
237
+ if resp.status_code == 200:
238
+ return True
239
+ return False
240
+
241
+
242
+ def utc_now_isoformat():
243
+ now = datetime.datetime.utcnow()
244
+ now = now.isoformat()
245
+ # remove milliseconds, add Zulu timezone
246
+ now = now.rsplit('.', 1)[0] + 'Z'
247
+ return now
248
+
249
+ class CouchDBMDTemplate(object):
250
+ def __init__(self, attributes):
251
+ self.attributes = attributes
252
+ for key, value in iteritems(attributes):
253
+ if value == '{{timestamp}}':
254
+ self.timestamp_key = key
255
+ break
256
+ else:
257
+ attributes['timestamp'] = '{{timestamp}}'
258
+ self.timestamp_key = 'timestamp'
259
+
260
+ def doc(self, tile, grid):
261
+ doc = {}
262
+ x, y, z = tile.coord
263
+ for key, value in iteritems(self.attributes):
264
+ if not isinstance(value, string_type) or not value.startswith('{{'):
265
+ doc[key] = value
266
+ continue
267
+
268
+ if value == '{{timestamp}}':
269
+ doc[key] = time.time()
270
+ elif value == '{{x}}':
271
+ doc[key] = x
272
+ elif value == '{{y}}':
273
+ doc[key] = y
274
+ elif value in ('{{z}}', '{{level}}'):
275
+ doc[key] = z
276
+ elif value == '{{utc_iso}}':
277
+ doc[key] = utc_now_isoformat()
278
+ elif value == '{{wgs_tile_centroid}}':
279
+ tile_bbox = grid.tile_bbox(tile.coord)
280
+ centroid = (
281
+ tile_bbox[0] + (tile_bbox[2]-tile_bbox[0])/2,
282
+ tile_bbox[1] + (tile_bbox[3]-tile_bbox[1])/2
283
+ )
284
+ centroid = grid.srs.transform_to(SRS(4326), centroid)
285
+ doc[key] = centroid
286
+ elif value == '{{tile_centroid}}':
287
+ tile_bbox = grid.tile_bbox(tile.coord)
288
+ centroid = (
289
+ tile_bbox[0] + (tile_bbox[2]-tile_bbox[0])/2,
290
+ tile_bbox[1] + (tile_bbox[3]-tile_bbox[1])/2
291
+ )
292
+ doc[key] = centroid
293
+ else:
294
+ raise ValueError('unknown CouchDB tile_metadata value: %r' % (value, ))
295
+ return doc
@@ -0,0 +1,34 @@
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
+ from mapproxy.cache.base import TileCacheBase
17
+ from mapproxy.util.lock import DummyLock
18
+
19
+ class DummyCache(TileCacheBase):
20
+ def is_cached(self, tile, dimensions=None):
21
+ return False
22
+
23
+ def lock(self, tile):
24
+ return DummyLock()
25
+
26
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
27
+ pass
28
+
29
+ def store_tile(self, tile, dimensions=None):
30
+ pass
31
+
32
+ class DummyLocker(object):
33
+ def lock(self, tile):
34
+ return DummyLock()
mapproxy/cache/file.py ADDED
@@ -0,0 +1,185 @@
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
+ import os
17
+ import errno
18
+ import hashlib
19
+
20
+ from mapproxy.util.fs import ensure_directory, write_atomic
21
+ from mapproxy.image import ImageSource, is_single_color_image
22
+ from mapproxy.cache import path
23
+ from mapproxy.cache.base import TileCacheBase, tile_buffer
24
+
25
+ import logging
26
+ log = logging.getLogger('mapproxy.cache.file')
27
+
28
+ class FileCache(TileCacheBase):
29
+ """
30
+ This class is responsible to store and load the actual tile data.
31
+ """
32
+ def __init__(self, cache_dir, file_ext, directory_layout='tc',
33
+ link_single_color_images=False):
34
+ """
35
+ :param cache_dir: the path where the tile will be stored
36
+ :param file_ext: the file extension that will be appended to
37
+ each tile (e.g. 'png')
38
+ """
39
+ super(FileCache, self).__init__()
40
+ self.lock_cache_id = hashlib.md5(cache_dir.encode('utf-8')).hexdigest()
41
+ self.cache_dir = cache_dir
42
+ self.file_ext = file_ext
43
+ self.link_single_color_images = link_single_color_images
44
+ self._tile_location, self._level_location = path.location_funcs(layout=directory_layout)
45
+ if self._level_location is None:
46
+ self.level_location = None # disable level based clean-ups
47
+
48
+ def tile_location(self, tile, create_dir=False, dimensions=None):
49
+ if dimensions is not None and len(dimensions)>0:
50
+ items = list(dimensions.keys())
51
+ items.sort()
52
+ dimensions_str = ['{key}-{value}'.format(key=i, value=dimensions[i].replace('/', '_')) for i in items]
53
+ cache_dir = os.path.join(self.cache_dir, '_'.join(dimensions_str))
54
+ return self._tile_location(tile, self.cache_dir, self.file_ext, create_dir=create_dir, dimensions=dimensions)
55
+
56
+ def level_location(self, level, dimensions=None):
57
+ """
58
+ Return the path where all tiles for `level` will be stored.
59
+
60
+ >>> c = FileCache(cache_dir='/tmp/cache/', file_ext='png')
61
+ >>> c.level_location(2)
62
+ '/tmp/cache/02'
63
+ """
64
+ return self._level_location(level, self.cache_dir, dimensions)
65
+
66
+ def _single_color_tile_location(self, color, create_dir=False):
67
+ """
68
+ >>> c = FileCache(cache_dir='/tmp/cache/', file_ext='png')
69
+ >>> c._single_color_tile_location((254, 0, 4)).replace('\\\\', '/')
70
+ '/tmp/cache/single_color_tiles/fe0004.png'
71
+ """
72
+ parts = (
73
+ self.cache_dir,
74
+ 'single_color_tiles',
75
+ ''.join('%02x' % v for v in color) + '.' + self.file_ext
76
+ )
77
+ location = os.path.join(*parts)
78
+ if create_dir:
79
+ ensure_directory(location)
80
+ return location
81
+
82
+ def load_tile_metadata(self, tile, dimensions=None):
83
+ location = self.tile_location(tile, dimensions=dimensions)
84
+ try:
85
+ stats = os.lstat(location)
86
+ tile.timestamp = stats.st_mtime
87
+ tile.size = stats.st_size
88
+ except OSError as ex:
89
+ if ex.errno != errno.ENOENT: raise
90
+ tile.timestamp = 0
91
+ tile.size = 0
92
+
93
+ def is_cached(self, tile, dimensions=None):
94
+ """
95
+ Returns ``True`` if the tile data is present.
96
+ """
97
+ if tile.is_missing():
98
+ location = self.tile_location(tile, dimensions=dimensions)
99
+ if os.path.exists(location):
100
+ return True
101
+ else:
102
+ return False
103
+ else:
104
+ return True
105
+
106
+ def load_tile(self, tile, with_metadata=False, dimensions=None):
107
+ """
108
+ Fills the `Tile.source` of the `tile` if it is cached.
109
+ If it is not cached or if the ``.coord`` is ``None``, nothing happens.
110
+ """
111
+ if not tile.is_missing():
112
+ return True
113
+
114
+ location = self.tile_location(tile, dimensions=dimensions)
115
+
116
+ if os.path.exists(location):
117
+ if with_metadata:
118
+ self.load_tile_metadata(tile, dimensions=dimensions)
119
+ tile.source = ImageSource(location)
120
+ return True
121
+ return False
122
+
123
+ def remove_tile(self, tile, dimensions=None):
124
+ location = self.tile_location(tile, dimensions=dimensions)
125
+ try:
126
+ os.remove(location)
127
+ except OSError as ex:
128
+ if ex.errno != errno.ENOENT: raise
129
+
130
+ def store_tile(self, tile, dimensions=None):
131
+ """
132
+ Add the given `tile` to the file cache. Stores the `Tile.source` to
133
+ `FileCache.tile_location`.
134
+ """
135
+ if tile.stored:
136
+ return
137
+
138
+ tile_loc = self.tile_location(tile, create_dir=True, dimensions=dimensions)
139
+
140
+ if self.link_single_color_images:
141
+ color = is_single_color_image(tile.source.as_image())
142
+ if color:
143
+ self._store_single_color_tile(tile, tile_loc, color)
144
+ else:
145
+ self._store(tile, tile_loc)
146
+ else:
147
+ self._store(tile, tile_loc)
148
+
149
+ def _store(self, tile, location):
150
+ if os.path.islink(location):
151
+ os.unlink(location)
152
+
153
+ with tile_buffer(tile) as buf:
154
+ log.debug('writing %r to %s' % (tile.coord, location))
155
+ write_atomic(location, buf.read())
156
+
157
+ def _store_single_color_tile(self, tile, tile_loc, color):
158
+ real_tile_loc = self._single_color_tile_location(color, create_dir=True)
159
+ if not os.path.exists(real_tile_loc):
160
+ self._store(tile, real_tile_loc)
161
+
162
+ log.debug('linking %r from %s to %s',
163
+ tile.coord, real_tile_loc, tile_loc)
164
+
165
+ # remove any file before symlinking.
166
+ # exists() returns False if it links to non-
167
+ # existing file, islink() test to check that
168
+ if os.path.exists(tile_loc) or os.path.islink(tile_loc):
169
+ os.unlink(tile_loc)
170
+
171
+ # Use relative path for the symlink
172
+ real_tile_loc = os.path.relpath(real_tile_loc, os.path.dirname(tile_loc))
173
+
174
+ try:
175
+ os.symlink(real_tile_loc, tile_loc)
176
+ except OSError as e:
177
+ # ignore error if link was created by other process
178
+ if e.errno != errno.EEXIST:
179
+ raise e
180
+
181
+ return
182
+
183
+ def __repr__(self):
184
+ return '%s(%r, %r)' % (self.__class__.__name__, self.cache_dir, self.file_ext)
185
+