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,538 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010, 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 __future__ import print_function, division
17
+
18
+ import sys
19
+ from collections import deque
20
+ from contextlib import contextmanager
21
+ import time
22
+ try:
23
+ import Queue
24
+ except ImportError:
25
+ import queue as Queue
26
+
27
+ from mapproxy.config import base_config
28
+ from mapproxy.grid import MetaGrid
29
+ from mapproxy.source import SourceError
30
+ from mapproxy.config import local_base_config
31
+ from mapproxy.compat.itertools import izip_longest
32
+ from mapproxy.util.lock import LockTimeout
33
+ from mapproxy.seed.util import format_seed_task, timestamp
34
+ from mapproxy.seed.cachelock import DummyCacheLocker, CacheLockedError
35
+
36
+ from mapproxy.seed.util import (exp_backoff, limit_sub_bbox,
37
+ status_symbol, BackoffError)
38
+
39
+ import logging
40
+ log = logging.getLogger(__name__)
41
+
42
+ NONE = 0
43
+ CONTAINS = -1
44
+ INTERSECTS = 1
45
+
46
+ # Decide whether to use multiprocessing or threading. multiprocessing should be faster but
47
+ # it is not well supported on all platforms. Especially regarding lambdas and anonymous
48
+ # function/classes which are used in proj.py for example.
49
+ #
50
+ # Since Python 3.8, MacOS uses a non-forking start method for multiprocessing which
51
+ # inhibits similar restrictions to Windows.
52
+ if sys.platform == 'win32' or (sys.platform == 'darwin' and sys.version_info >= (3, 8)):
53
+ import threading
54
+ proc_class = threading.Thread
55
+ queue_class = Queue.Queue
56
+ else:
57
+ import multiprocessing
58
+ proc_class = multiprocessing.Process
59
+ queue_class = multiprocessing.Queue
60
+
61
+
62
+ class TileWorkerPool(object):
63
+ """
64
+ Manages multiple TileWorker.
65
+ """
66
+ def __init__(self, task, worker_class, size=2, dry_run=False, progress_logger=None):
67
+ self.tiles_queue = queue_class(size)
68
+ self.task = task
69
+ self.dry_run = dry_run
70
+ self.procs = []
71
+ self.progress_logger = progress_logger
72
+ conf = base_config()
73
+ for _ in range(size):
74
+ worker = worker_class(self.task, self.tiles_queue, conf)
75
+ worker.start()
76
+ self.procs.append(worker)
77
+
78
+ def process(self, tiles, progress):
79
+ if not self.dry_run:
80
+ while True:
81
+ try:
82
+ self.tiles_queue.put(tiles, timeout=5)
83
+ except Queue.Full:
84
+ alive = False
85
+ for proc in self.procs:
86
+ if proc.is_alive():
87
+ alive = True
88
+ break
89
+ if not alive:
90
+ log.warning('no workers left, stopping')
91
+ raise SeedInterrupted
92
+ continue
93
+ else:
94
+ break
95
+
96
+ if self.progress_logger:
97
+ self.progress_logger.log_step(progress)
98
+
99
+ def stop(self, force=False):
100
+ """
101
+ Stop seed workers by sending None-sentinel and joining the workers.
102
+
103
+ :param force: Skip sending None-sentinel and join with a timeout.
104
+ For use when workers might be shutdown already by KeyboardInterrupt.
105
+ """
106
+ if not force:
107
+ alives = 0
108
+ for proc in self.procs:
109
+ if proc.is_alive():
110
+ alives += 1
111
+
112
+ while alives:
113
+ # put None-sentinels to queue as long as we have workers alive
114
+ try:
115
+ self.tiles_queue.put(None, timeout=1)
116
+ alives -= 1
117
+ except Queue.Full:
118
+ alives = 0
119
+ for proc in self.procs:
120
+ if proc.is_alive():
121
+ alives += 1
122
+
123
+ if force:
124
+ timeout = 1.0
125
+ else:
126
+ timeout = None
127
+ for proc in self.procs:
128
+ proc.join(timeout)
129
+
130
+
131
+ class TileWorker(proc_class):
132
+ def __init__(self, task, tiles_queue, conf):
133
+ proc_class.__init__(self)
134
+ proc_class.daemon = True
135
+ self.task = task
136
+ self.tile_mgr = task.tile_manager
137
+ self.tiles_queue = tiles_queue
138
+ self.conf = conf
139
+
140
+ def run(self):
141
+ with local_base_config(self.conf):
142
+ try:
143
+ self.work_loop()
144
+ except KeyboardInterrupt:
145
+ return
146
+ except BackoffError:
147
+ return
148
+
149
+ class TileSeedWorker(TileWorker):
150
+ def work_loop(self):
151
+ while True:
152
+ tiles = self.tiles_queue.get()
153
+ if tiles is None:
154
+ return
155
+ with self.tile_mgr.session():
156
+ exp_backoff(self.tile_mgr.load_tile_coords, args=(tiles,),
157
+ max_repeat=100, max_backoff=600,
158
+ exceptions=(SourceError, IOError), ignore_exceptions=(LockTimeout, ))
159
+
160
+ class TileCleanupWorker(TileWorker):
161
+ def work_loop(self):
162
+ while True:
163
+ tiles = self.tiles_queue.get()
164
+ if tiles is None:
165
+ return
166
+ with self.tile_mgr.session():
167
+ self.tile_mgr.remove_tile_coords(tiles)
168
+
169
+ class SeedProgress(object):
170
+ def __init__(self, old_progress_identifier=None):
171
+ self.progress = 0.0
172
+ self.level_progress_percentages = [1.0]
173
+ self.level_progresses = None
174
+ self.level_progresses_level = 0
175
+ self.progress_str_parts = []
176
+ self.old_level_progresses = old_progress_identifier
177
+
178
+ def step_forward(self, subtiles=1):
179
+ self.progress += self.level_progress_percentages[-1] / subtiles
180
+
181
+ @property
182
+ def progress_str(self):
183
+ return ''.join(self.progress_str_parts)
184
+
185
+ @contextmanager
186
+ def step_down(self, i, subtiles):
187
+ if self.level_progresses is None:
188
+ self.level_progresses = []
189
+ self.level_progresses = self.level_progresses[:self.level_progresses_level]
190
+ self.level_progresses.append((i, subtiles))
191
+ self.level_progresses_level += 1
192
+ self.progress_str_parts.append(status_symbol(i, subtiles))
193
+ self.level_progress_percentages.append(self.level_progress_percentages[-1] / subtiles)
194
+
195
+ yield
196
+
197
+ self.level_progress_percentages.pop()
198
+ self.progress_str_parts.pop()
199
+
200
+ self.level_progresses_level -= 1
201
+ if self.level_progresses_level == 0:
202
+ self.level_progresses = []
203
+
204
+ def already_processed(self):
205
+ return self.can_skip(self.old_level_progresses, self.level_progresses)
206
+
207
+ def current_progress_identifier(self):
208
+ if self.already_processed() or self.level_progresses is None:
209
+ return self.old_level_progresses
210
+ return self.level_progresses[:]
211
+
212
+ @staticmethod
213
+ def can_skip(old_progress, current_progress):
214
+ """
215
+ Return True if the `current_progress` is behind the `old_progress` -
216
+ when it isn't as far as the old progress.
217
+
218
+ >>> SeedProgress.can_skip(None, [(0, 4)])
219
+ False
220
+ >>> SeedProgress.can_skip([], [(0, 4)])
221
+ True
222
+ >>> SeedProgress.can_skip([(0, 4)], None)
223
+ False
224
+ >>> SeedProgress.can_skip([(0, 4)], [(0, 4)])
225
+ False
226
+ >>> SeedProgress.can_skip([(1, 4)], [(0, 4)])
227
+ True
228
+ >>> SeedProgress.can_skip([(0, 4)], [(0, 4), (0, 4)])
229
+ False
230
+
231
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (0, 4)])
232
+ False
233
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (0, 4), (1, 4)])
234
+ True
235
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (0, 4), (2, 4)])
236
+ False
237
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (0, 4), (3, 4)])
238
+ False
239
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (1, 4)])
240
+ False
241
+ >>> SeedProgress.can_skip([(0, 4), (0, 4), (2, 4)], [(0, 4), (1, 4), (0, 4)])
242
+ False
243
+ """
244
+ if current_progress is None:
245
+ return False
246
+ if old_progress is None:
247
+ return False
248
+ if old_progress == []:
249
+ return True
250
+ for old, current in izip_longest(old_progress, current_progress, fillvalue=None):
251
+ if old is None:
252
+ return False
253
+ if current is None:
254
+ return False
255
+ if old < current:
256
+ return False
257
+ if old > current:
258
+ return True
259
+ return False
260
+
261
+ def running(self):
262
+ return True
263
+
264
+ class StopProcess(Exception):
265
+ pass
266
+
267
+ class SeedInterrupted(Exception):
268
+ pass
269
+
270
+
271
+ class TileWalker(object):
272
+ """
273
+ TileWalker traverses through all tiles in a tile grid and calls worker_pool.process
274
+ for each (meta) tile. It traverses the tile grid (pyramid) depth-first.
275
+ Intersection with coverages are checked before handling subtiles in the next level,
276
+ allowing to determine if all subtiles should be seeded or skipped.
277
+ """
278
+ def __init__(self, task, worker_pool, handle_stale=False, handle_uncached=False,
279
+ work_on_metatiles=True, skip_geoms_for_last_levels=0, progress_logger=None,
280
+ seed_progress=None):
281
+ self.tile_mgr = task.tile_manager
282
+ self.task = task
283
+ self.worker_pool = worker_pool
284
+ self.handle_stale = handle_stale
285
+ self.handle_uncached = handle_uncached
286
+ self.work_on_metatiles = work_on_metatiles
287
+ self.skip_geoms_for_last_levels = skip_geoms_for_last_levels
288
+ self.progress_logger = progress_logger
289
+
290
+ num_seed_levels = len(task.levels)
291
+ if num_seed_levels >= 4:
292
+ self.report_till_level = task.levels[num_seed_levels-2]
293
+ else:
294
+ self.report_till_level = task.levels[num_seed_levels-1]
295
+ meta_size = self.tile_mgr.meta_grid.meta_size if self.tile_mgr.meta_grid else (1, 1)
296
+ self.tiles_per_metatile = meta_size[0] * meta_size[1]
297
+ self.grid = MetaGrid(self.tile_mgr.grid, meta_size=meta_size, meta_buffer=0)
298
+ self.count = 0
299
+ self.seed_progress = seed_progress or SeedProgress()
300
+
301
+ # It is possible that we 'walk' through the same tile multiple times
302
+ # when seeding irregular tile grids[0]. limit_sub_bbox prevents that we
303
+ # recurse into the same area multiple times, but it is still possible
304
+ # that a tile is processed multiple times. Locking prevents that a tile
305
+ # is seeded multiple times, but it is possible that we count the same tile
306
+ # multiple times (in dry-mode, or while the tile is in the process queue).
307
+
308
+ # Tile counts can be off by 280% with sqrt2 grids.
309
+ # We keep a small cache of already processed tiles to skip most duplicates.
310
+ # A simple cache of 64 tile coordinates for each level already brings the
311
+ # difference down to ~8%, which is good enough and faster than a more
312
+ # sophisticated FIFO cache with O(1) lookup, or even caching all tiles.
313
+
314
+ # [0] irregular tile grids: where one tile does not have exactly 4 subtiles
315
+ # Typically when you use res_factor, or a custom res list.
316
+ self.seeded_tiles = {l: deque(maxlen=64) for l in task.levels}
317
+
318
+ def walk(self):
319
+ assert self.handle_stale or self.handle_uncached
320
+ bbox = self.task.coverage.extent.bbox_for(self.tile_mgr.grid.srs)
321
+ if self.seed_progress.already_processed():
322
+ # nothing to seed
323
+ self.seed_progress.step_forward()
324
+ else:
325
+ try:
326
+ self._walk(bbox, self.task.levels)
327
+ except StopProcess:
328
+ pass
329
+ self.report_progress(self.task.levels[0], self.task.coverage.bbox)
330
+
331
+ def _walk(self, cur_bbox, levels, current_level=0, all_subtiles=False):
332
+ """
333
+ :param cur_bbox: the bbox to seed in this call
334
+ :param levels: list of levels to seed
335
+ :param all_subtiles: seed all subtiles and do not check for
336
+ intersections with bbox/geom
337
+ """
338
+ bbox_, tiles, subtiles = self.grid.get_affected_level_tiles(cur_bbox, current_level)
339
+ total_subtiles = tiles[0] * tiles[1]
340
+ if len(levels) < self.skip_geoms_for_last_levels:
341
+ # do not filter in last levels
342
+ all_subtiles = True
343
+ subtiles = self._filter_subtiles(subtiles, all_subtiles)
344
+
345
+ if current_level in levels and current_level <= self.report_till_level:
346
+ self.report_progress(current_level, cur_bbox)
347
+
348
+ if not self.seed_progress.running():
349
+ if current_level in levels:
350
+ self.report_progress(current_level, cur_bbox)
351
+ self.tile_mgr.cleanup()
352
+ raise StopProcess()
353
+
354
+ process = False
355
+ if current_level in levels:
356
+ levels = levels[1:]
357
+ process = True
358
+
359
+ for i, (subtile, sub_bbox, intersection) in enumerate(subtiles):
360
+ if subtile is None: # no intersection
361
+ self.seed_progress.step_forward(total_subtiles)
362
+ continue
363
+ if levels: # recurse to next level
364
+ sub_bbox = limit_sub_bbox(cur_bbox, sub_bbox)
365
+ if intersection == CONTAINS:
366
+ all_subtiles = True
367
+ else:
368
+ all_subtiles = False
369
+
370
+ with self.seed_progress.step_down(i, total_subtiles):
371
+ if self.seed_progress.already_processed():
372
+ self.seed_progress.step_forward()
373
+ else:
374
+ self._walk(sub_bbox, levels, current_level=current_level+1,
375
+ all_subtiles=all_subtiles)
376
+
377
+ if not process:
378
+ continue
379
+
380
+ # check if subtile was already processed. see comment in __init__
381
+ if subtile in self.seeded_tiles[current_level]:
382
+ if not levels:
383
+ self.seed_progress.step_forward(total_subtiles)
384
+ continue
385
+ self.seeded_tiles[current_level].appendleft(subtile)
386
+
387
+ if not self.work_on_metatiles:
388
+ # collect actual tiles
389
+ handle_tiles = self.grid.tile_list(subtile)
390
+ else:
391
+ handle_tiles = [subtile]
392
+
393
+ if self.handle_uncached:
394
+ handle_tiles = [t for t in handle_tiles if
395
+ t is not None and
396
+ not self.tile_mgr.is_cached(t)]
397
+ elif self.handle_stale:
398
+ handle_tiles = [t for t in handle_tiles if
399
+ t is not None and
400
+ self.tile_mgr.is_stale(t)]
401
+ if handle_tiles:
402
+ self.count += 1
403
+ self.worker_pool.process(handle_tiles, self.seed_progress)
404
+
405
+ if not levels:
406
+ self.seed_progress.step_forward(total_subtiles)
407
+
408
+ if len(levels) >= 4:
409
+ # call cleanup to close open caches
410
+ # for connection based caches
411
+ self.tile_mgr.cleanup()
412
+
413
+ def report_progress(self, level, bbox):
414
+ if self.progress_logger:
415
+ self.progress_logger.log_progress(self.seed_progress, level, bbox,
416
+ self.count * self.tiles_per_metatile)
417
+
418
+ def _filter_subtiles(self, subtiles, all_subtiles):
419
+ """
420
+ Return an iterator with all sub tiles.
421
+ Yields (None, None, None) for non-intersecting tiles,
422
+ otherwise (subtile, subtile_bbox, intersection).
423
+ """
424
+ for subtile in subtiles:
425
+ if subtile is None:
426
+ yield None, None, None
427
+ else:
428
+ sub_bbox = self.grid.meta_tile(subtile).bbox
429
+ if all_subtiles:
430
+ intersection = CONTAINS
431
+ else:
432
+ intersection = self.task.intersects(sub_bbox)
433
+ if intersection:
434
+ yield subtile, sub_bbox, intersection
435
+ else:
436
+ yield None, None, None
437
+
438
+ class SeedTask(object):
439
+ def __init__(self, md, tile_manager, levels, refresh_timestamp, coverage):
440
+ self.md = md
441
+ self.tile_manager = tile_manager
442
+ self.grid = tile_manager.grid
443
+ self.levels = levels
444
+ self.refresh_timestamp = refresh_timestamp
445
+ self.coverage = coverage
446
+
447
+ @property
448
+ def id(self):
449
+ return self.md['name'], self.md['cache_name'], self.md['grid_name'], tuple(self.levels)
450
+
451
+ def intersects(self, bbox):
452
+ if self.coverage.contains(bbox, self.grid.srs): return CONTAINS
453
+ if self.coverage.intersects(bbox, self.grid.srs): return INTERSECTS
454
+ return NONE
455
+
456
+ class CleanupTask(object):
457
+ """
458
+ :param coverage: area for the cleanup
459
+ :param complete_extent: ``True`` if `coverage` equals the extent of the grid
460
+ """
461
+ def __init__(self, md, tile_manager, levels, remove_timestamp, coverage, complete_extent=False):
462
+ self.md = md
463
+ self.tile_manager = tile_manager
464
+ self.grid = tile_manager.grid
465
+ self.levels = levels
466
+ self.remove_timestamp = remove_timestamp
467
+ self.coverage = coverage
468
+ self.complete_extent = complete_extent
469
+
470
+ @property
471
+ def id(self):
472
+ return 'cleanup', self.md['name'], self.md['cache_name'], self.md['grid_name']
473
+
474
+ def intersects(self, bbox):
475
+ if self.coverage.contains(bbox, self.grid.srs): return CONTAINS
476
+ if self.coverage.intersects(bbox, self.grid.srs): return INTERSECTS
477
+ return NONE
478
+
479
+ def seed(tasks, concurrency=2, dry_run=False, skip_geoms_for_last_levels=0,
480
+ progress_logger=None, cache_locker=None, skip_uncached=False):
481
+ if cache_locker is None:
482
+ cache_locker = DummyCacheLocker()
483
+
484
+ active_tasks = tasks[::-1]
485
+ while active_tasks:
486
+ task = active_tasks[-1]
487
+ print(format_seed_task(task))
488
+
489
+ wait = len(active_tasks) == 1
490
+ try:
491
+ with cache_locker.lock(task.md['cache_name'], no_block=not wait):
492
+ if progress_logger and progress_logger.progress_store:
493
+ progress_logger.current_task_id = task.id
494
+ start_progress = progress_logger.progress_store.get(task.id)
495
+ else:
496
+ start_progress = None
497
+ seed_progress = SeedProgress(old_progress_identifier=start_progress)
498
+ seed_task(task, concurrency, dry_run, skip_geoms_for_last_levels, progress_logger,
499
+ seed_progress=seed_progress, skip_uncached=skip_uncached)
500
+ except CacheLockedError:
501
+ print(' ...cache is locked, skipping')
502
+ active_tasks = [task] + active_tasks[:-1]
503
+ else:
504
+ active_tasks.pop()
505
+
506
+
507
+ def seed_task(task, concurrency=2, dry_run=False, skip_geoms_for_last_levels=0,
508
+ progress_logger=None, seed_progress=None, skip_uncached=False):
509
+ if task.coverage is False:
510
+ return
511
+ if task.refresh_timestamp is not None:
512
+ task.tile_manager._expire_timestamp = task.refresh_timestamp
513
+ task.tile_manager.minimize_meta_requests = False
514
+
515
+ work_on_metatiles = True
516
+ if task.tile_manager.rescale_tiles:
517
+ work_on_metatiles = False
518
+
519
+ tile_worker_pool = TileWorkerPool(task, TileSeedWorker, dry_run=dry_run,
520
+ size=concurrency, progress_logger=progress_logger)
521
+ # If the configuration requests to only refresh tiles which are already in cache,
522
+ # tile walker parameters shall be adapted
523
+ handle_stale = skip_uncached
524
+ handle_uncached = not skip_uncached
525
+ tile_walker = TileWalker(task, tile_worker_pool, handle_uncached=handle_uncached, handle_stale=handle_stale,
526
+ skip_geoms_for_last_levels=skip_geoms_for_last_levels, progress_logger=progress_logger,
527
+ seed_progress=seed_progress,
528
+ work_on_metatiles=work_on_metatiles,
529
+ )
530
+ try:
531
+ tile_walker.walk()
532
+ except KeyboardInterrupt:
533
+ tile_worker_pool.stop(force=True)
534
+ raise
535
+ finally:
536
+ tile_worker_pool.stop()
537
+
538
+
mapproxy/seed/spec.py ADDED
@@ -0,0 +1,64 @@
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.util.ext.dictspec.validator import validate, ValidationError
17
+ from mapproxy.util.ext.dictspec.spec import one_off, anything, number
18
+ from mapproxy.util.ext.dictspec.spec import required
19
+
20
+ from mapproxy.config.spec import coverage, time_spec
21
+
22
+ def validate_seed_conf(conf_dict):
23
+ """
24
+ Validate `conf_dict` agains seed.yaml spec.
25
+ Returns lists with errors. List is empty when no errors where found.
26
+ """
27
+ try:
28
+ validate(seed_yaml_spec, conf_dict)
29
+ except ValidationError as ex:
30
+ return ex.errors, ex.informal_only
31
+ else:
32
+ return [], True
33
+
34
+ from_to_spec = {
35
+ 'from': number(),
36
+ 'to': number(),
37
+ }
38
+
39
+ seed_yaml_spec = {
40
+ 'coverages': {
41
+ anything(): coverage,
42
+ },
43
+ 'seeds': {
44
+ anything(): {
45
+ required('caches'): [str()],
46
+ 'grids': [str()],
47
+ 'coverages': [str()],
48
+ 'refresh_before': time_spec,
49
+ 'levels': one_off([int()], from_to_spec),
50
+ 'resolutions': one_off([int()], from_to_spec),
51
+ },
52
+ },
53
+ 'cleanups': {
54
+ anything(): {
55
+ required('caches'): [str()],
56
+ 'grids': [str()],
57
+ 'coverages': [str()],
58
+ 'remove_before': time_spec,
59
+ 'remove_all': bool(),
60
+ 'levels': one_off([int()], from_to_spec),
61
+ 'resolutions': one_off([int()], from_to_spec),
62
+ }
63
+ },
64
+ }