MapProxy 2.1.0__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 (459) hide show
  1. MapProxy-2.1.0.dist-info/AUTHORS.txt +33 -0
  2. MapProxy-2.1.0.dist-info/COPYING.txt +60 -0
  3. MapProxy-2.1.0.dist-info/LICENSE.txt +202 -0
  4. MapProxy-2.1.0.dist-info/METADATA +165 -0
  5. MapProxy-2.1.0.dist-info/RECORD +459 -0
  6. MapProxy-2.1.0.dist-info/WHEEL +5 -0
  7. MapProxy-2.1.0.dist-info/entry_points.txt +4 -0
  8. MapProxy-2.1.0.dist-info/top_level.txt +1 -0
  9. mapproxy/__init__.py +0 -0
  10. mapproxy/cache/__init__.py +36 -0
  11. mapproxy/cache/azureblob.py +145 -0
  12. mapproxy/cache/base.py +120 -0
  13. mapproxy/cache/compact.py +665 -0
  14. mapproxy/cache/couchdb.py +301 -0
  15. mapproxy/cache/dummy.py +36 -0
  16. mapproxy/cache/file.py +200 -0
  17. mapproxy/cache/geopackage.py +647 -0
  18. mapproxy/cache/legend.py +87 -0
  19. mapproxy/cache/mbtiles.py +411 -0
  20. mapproxy/cache/meta.py +80 -0
  21. mapproxy/cache/path.py +261 -0
  22. mapproxy/cache/redis.py +152 -0
  23. mapproxy/cache/renderd.py +100 -0
  24. mapproxy/cache/riak.py +206 -0
  25. mapproxy/cache/s3.py +209 -0
  26. mapproxy/cache/tile.py +736 -0
  27. mapproxy/client/__init__.py +0 -0
  28. mapproxy/client/arcgis.py +82 -0
  29. mapproxy/client/cgi.py +141 -0
  30. mapproxy/client/http.py +295 -0
  31. mapproxy/client/log.py +33 -0
  32. mapproxy/client/tile.py +158 -0
  33. mapproxy/client/wms.py +255 -0
  34. mapproxy/compat/__init__.py +0 -0
  35. mapproxy/compat/image.py +86 -0
  36. mapproxy/config/__init__.py +22 -0
  37. mapproxy/config/config-schema.json +813 -0
  38. mapproxy/config/config.py +213 -0
  39. mapproxy/config/coverage.py +108 -0
  40. mapproxy/config/defaults.py +102 -0
  41. mapproxy/config/loader.py +2399 -0
  42. mapproxy/config/spec.py +657 -0
  43. mapproxy/config/validator.py +242 -0
  44. mapproxy/config_template/__init__.py +0 -0
  45. mapproxy/config_template/base_config/config.wsgi +10 -0
  46. mapproxy/config_template/base_config/full_example.yaml +598 -0
  47. mapproxy/config_template/base_config/full_seed_example.yaml +79 -0
  48. mapproxy/config_template/base_config/log.ini +35 -0
  49. mapproxy/config_template/base_config/mapproxy.yaml +60 -0
  50. mapproxy/config_template/base_config/seed.yaml +27 -0
  51. mapproxy/exception.py +149 -0
  52. mapproxy/featureinfo.py +251 -0
  53. mapproxy/grid.py +1199 -0
  54. mapproxy/image/__init__.py +549 -0
  55. mapproxy/image/fonts/DejaVuSans.ttf +0 -0
  56. mapproxy/image/fonts/DejaVuSansMono.ttf +0 -0
  57. mapproxy/image/fonts/LICENSE +99 -0
  58. mapproxy/image/fonts/__init__.py +0 -0
  59. mapproxy/image/mask.py +79 -0
  60. mapproxy/image/merge.py +323 -0
  61. mapproxy/image/message.py +357 -0
  62. mapproxy/image/opts.py +185 -0
  63. mapproxy/image/tile.py +171 -0
  64. mapproxy/image/transform.py +350 -0
  65. mapproxy/layer.py +489 -0
  66. mapproxy/multiapp.py +230 -0
  67. mapproxy/proj.py +309 -0
  68. mapproxy/request/__init__.py +18 -0
  69. mapproxy/request/arcgis.py +268 -0
  70. mapproxy/request/base.py +466 -0
  71. mapproxy/request/tile.py +131 -0
  72. mapproxy/request/wms/__init__.py +829 -0
  73. mapproxy/request/wms/exception.py +107 -0
  74. mapproxy/request/wmts.py +442 -0
  75. mapproxy/response.py +237 -0
  76. mapproxy/script/__init__.py +0 -0
  77. mapproxy/script/conf/__init__.py +0 -0
  78. mapproxy/script/conf/app.py +222 -0
  79. mapproxy/script/conf/caches.py +44 -0
  80. mapproxy/script/conf/geopackage.py +136 -0
  81. mapproxy/script/conf/layers.py +54 -0
  82. mapproxy/script/conf/seeds.py +36 -0
  83. mapproxy/script/conf/sources.py +88 -0
  84. mapproxy/script/conf/utils.py +148 -0
  85. mapproxy/script/defrag.py +187 -0
  86. mapproxy/script/export.py +337 -0
  87. mapproxy/script/grids.py +198 -0
  88. mapproxy/script/scales.py +134 -0
  89. mapproxy/script/util.py +410 -0
  90. mapproxy/script/wms_capabilities.py +160 -0
  91. mapproxy/seed/__init__.py +0 -0
  92. mapproxy/seed/cachelock.py +127 -0
  93. mapproxy/seed/cleanup.py +191 -0
  94. mapproxy/seed/config.py +481 -0
  95. mapproxy/seed/script.py +391 -0
  96. mapproxy/seed/seeder.py +551 -0
  97. mapproxy/seed/spec.py +66 -0
  98. mapproxy/seed/util.py +266 -0
  99. mapproxy/service/__init__.py +14 -0
  100. mapproxy/service/base.py +45 -0
  101. mapproxy/service/demo.py +364 -0
  102. mapproxy/service/kml.py +333 -0
  103. mapproxy/service/ows.py +39 -0
  104. mapproxy/service/template_helper.py +55 -0
  105. mapproxy/service/templates/demo/capabilities_demo.html +18 -0
  106. mapproxy/service/templates/demo/demo.html +181 -0
  107. mapproxy/service/templates/demo/openlayers-demo.cfg +16 -0
  108. mapproxy/service/templates/demo/static/img/blank.gif +0 -0
  109. mapproxy/service/templates/demo/static/img/east-mini.png +0 -0
  110. mapproxy/service/templates/demo/static/img/north-mini.png +0 -0
  111. mapproxy/service/templates/demo/static/img/south-mini.png +0 -0
  112. mapproxy/service/templates/demo/static/img/west-mini.png +0 -0
  113. mapproxy/service/templates/demo/static/img/zoom-minus-mini.png +0 -0
  114. mapproxy/service/templates/demo/static/img/zoom-plus-mini.png +0 -0
  115. mapproxy/service/templates/demo/static/img/zoom-world-mini.png +0 -0
  116. mapproxy/service/templates/demo/static/logo.png +0 -0
  117. mapproxy/service/templates/demo/static/ol.css +345 -0
  118. mapproxy/service/templates/demo/static/ol.js +4 -0
  119. mapproxy/service/templates/demo/static/proj4.min.js +1 -0
  120. mapproxy/service/templates/demo/static/proj4defs.js +1 -0
  121. mapproxy/service/templates/demo/static/site.css +137 -0
  122. mapproxy/service/templates/demo/static/theme/default/framedCloud.css +0 -0
  123. mapproxy/service/templates/demo/static/theme/default/google.css +17 -0
  124. mapproxy/service/templates/demo/static/theme/default/ie6-style.css +10 -0
  125. mapproxy/service/templates/demo/static/theme/default/style.css +482 -0
  126. mapproxy/service/templates/demo/static.html +34 -0
  127. mapproxy/service/templates/demo/tms_demo.html +117 -0
  128. mapproxy/service/templates/demo/wms_demo.html +144 -0
  129. mapproxy/service/templates/demo/wmts_demo.html +118 -0
  130. mapproxy/service/templates/tms_capabilities.xml +13 -0
  131. mapproxy/service/templates/tms_exception.xml +4 -0
  132. mapproxy/service/templates/tms_root_resource.xml +7 -0
  133. mapproxy/service/templates/tms_tilemap_capabilities.xml +14 -0
  134. mapproxy/service/templates/wms100capabilities.xml +112 -0
  135. mapproxy/service/templates/wms100exception.xml +4 -0
  136. mapproxy/service/templates/wms110capabilities.xml +152 -0
  137. mapproxy/service/templates/wms110exception.xml +5 -0
  138. mapproxy/service/templates/wms111capabilities.xml +183 -0
  139. mapproxy/service/templates/wms111exception.xml +5 -0
  140. mapproxy/service/templates/wms130capabilities.xml +326 -0
  141. mapproxy/service/templates/wms130exception.xml +8 -0
  142. mapproxy/service/templates/wmts100capabilities.xml +155 -0
  143. mapproxy/service/templates/wmts100exception.xml +9 -0
  144. mapproxy/service/tile.py +540 -0
  145. mapproxy/service/wms.py +868 -0
  146. mapproxy/service/wmts.py +387 -0
  147. mapproxy/source/__init__.py +83 -0
  148. mapproxy/source/arcgis.py +39 -0
  149. mapproxy/source/error.py +40 -0
  150. mapproxy/source/mapnik.py +262 -0
  151. mapproxy/source/tile.py +97 -0
  152. mapproxy/source/wms.py +273 -0
  153. mapproxy/srs.py +734 -0
  154. mapproxy/template.py +54 -0
  155. mapproxy/test/__init__.py +0 -0
  156. mapproxy/test/conftest.py +8 -0
  157. mapproxy/test/helper.py +255 -0
  158. mapproxy/test/http.py +511 -0
  159. mapproxy/test/image.py +219 -0
  160. mapproxy/test/mocker.py +2291 -0
  161. mapproxy/test/schemas/inspire/common/1.0/common.xsd +1461 -0
  162. mapproxy/test/schemas/inspire/common/1.0/enums/enum_bul.xsd +108 -0
  163. mapproxy/test/schemas/inspire/common/1.0/enums/enum_cze.xsd +108 -0
  164. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dan.xsd +108 -0
  165. mapproxy/test/schemas/inspire/common/1.0/enums/enum_dut.xsd +108 -0
  166. mapproxy/test/schemas/inspire/common/1.0/enums/enum_eng.xsd +155 -0
  167. mapproxy/test/schemas/inspire/common/1.0/enums/enum_est.xsd +108 -0
  168. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fin.xsd +108 -0
  169. mapproxy/test/schemas/inspire/common/1.0/enums/enum_fre.xsd +108 -0
  170. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ger.xsd +108 -0
  171. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gle.xsd +109 -0
  172. mapproxy/test/schemas/inspire/common/1.0/enums/enum_gre.xsd +108 -0
  173. mapproxy/test/schemas/inspire/common/1.0/enums/enum_hun.xsd +108 -0
  174. mapproxy/test/schemas/inspire/common/1.0/enums/enum_ita.xsd +108 -0
  175. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lav.xsd +108 -0
  176. mapproxy/test/schemas/inspire/common/1.0/enums/enum_lit.xsd +108 -0
  177. mapproxy/test/schemas/inspire/common/1.0/enums/enum_mlt.xsd +108 -0
  178. mapproxy/test/schemas/inspire/common/1.0/enums/enum_pol.xsd +108 -0
  179. mapproxy/test/schemas/inspire/common/1.0/enums/enum_por.xsd +108 -0
  180. mapproxy/test/schemas/inspire/common/1.0/enums/enum_rum.xsd +108 -0
  181. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slo.xsd +108 -0
  182. mapproxy/test/schemas/inspire/common/1.0/enums/enum_slv.xsd +108 -0
  183. mapproxy/test/schemas/inspire/common/1.0/enums/enum_spa.xsd +108 -0
  184. mapproxy/test/schemas/inspire/common/1.0/enums/enum_swe.xsd +108 -0
  185. mapproxy/test/schemas/inspire/common/1.0/network.xsd +521 -0
  186. mapproxy/test/schemas/inspire/inspire_vs/1.0/inspire_vs.xsd +19 -0
  187. mapproxy/test/schemas/kml/2.2.0/ReadMe.txt +14 -0
  188. mapproxy/test/schemas/kml/2.2.0/atom-author-link.xsd +66 -0
  189. mapproxy/test/schemas/kml/2.2.0/ogckml22.xsd +1646 -0
  190. mapproxy/test/schemas/kml/2.2.0/xAL.xsd +1680 -0
  191. mapproxy/test/schemas/ows/1.1.0/ReadMe.txt +87 -0
  192. mapproxy/test/schemas/ows/1.1.0/ows19115subset.xsd +235 -0
  193. mapproxy/test/schemas/ows/1.1.0/owsAll.xsd +23 -0
  194. mapproxy/test/schemas/ows/1.1.0/owsCommon.xsd +157 -0
  195. mapproxy/test/schemas/ows/1.1.0/owsContents.xsd +86 -0
  196. mapproxy/test/schemas/ows/1.1.0/owsDataIdentification.xsd +127 -0
  197. mapproxy/test/schemas/ows/1.1.0/owsDomainType.xsd +279 -0
  198. mapproxy/test/schemas/ows/1.1.0/owsExceptionReport.xsd +76 -0
  199. mapproxy/test/schemas/ows/1.1.0/owsGetCapabilities.xsd +112 -0
  200. mapproxy/test/schemas/ows/1.1.0/owsGetResourceByID.xsd +51 -0
  201. mapproxy/test/schemas/ows/1.1.0/owsInputOutputData.xsd +59 -0
  202. mapproxy/test/schemas/ows/1.1.0/owsManifest.xsd +125 -0
  203. mapproxy/test/schemas/ows/1.1.0/owsOperationsMetadata.xsd +140 -0
  204. mapproxy/test/schemas/ows/1.1.0/owsServiceIdentification.xsd +60 -0
  205. mapproxy/test/schemas/ows/1.1.0/owsServiceProvider.xsd +47 -0
  206. mapproxy/test/schemas/sld/1.1.0/sld_capabilities.xsd +27 -0
  207. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.dtd +353 -0
  208. mapproxy/test/schemas/wms/1.0.0/capabilities_1_0_0.xml +188 -0
  209. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.dtd +524 -0
  210. mapproxy/test/schemas/wms/1.0.7/capabilities_1_0_7.xml +260 -0
  211. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.dtd +273 -0
  212. mapproxy/test/schemas/wms/1.1.0/capabilities_1_1_0.xml +303 -0
  213. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.dtd +6 -0
  214. mapproxy/test/schemas/wms/1.1.0/exception_1_1_0.xml +33 -0
  215. mapproxy/test/schemas/wms/1.1.1/OGC-exception.xsd +68 -0
  216. mapproxy/test/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  217. mapproxy/test/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd +274 -0
  218. mapproxy/test/schemas/wms/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  219. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.dtd +276 -0
  220. mapproxy/test/schemas/wms/1.1.1/capabilities_1_1_1.xml +303 -0
  221. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.dtd +6 -0
  222. mapproxy/test/schemas/wms/1.1.1/exception_1_1_1.xml +33 -0
  223. mapproxy/test/schemas/wms/1.3.0/ReadMe.txt +8 -0
  224. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xml +277 -0
  225. mapproxy/test/schemas/wms/1.3.0/capabilities_1_3_0.xsd +611 -0
  226. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xml +34 -0
  227. mapproxy/test/schemas/wms/1.3.0/exceptions_1_3_0.xsd +28 -0
  228. mapproxy/test/schemas/wmsc/1.1.1/OGC-exception.xsd +68 -0
  229. mapproxy/test/schemas/wmsc/1.1.1/WMS_DescribeLayerResponse.dtd +22 -0
  230. mapproxy/test/schemas/wmsc/1.1.1/WMS_MS_Capabilities.dtd +283 -0
  231. mapproxy/test/schemas/wmsc/1.1.1/WMS_exception_1_1_1.dtd +5 -0
  232. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.dtd +276 -0
  233. mapproxy/test/schemas/wmsc/1.1.1/capabilities_1_1_1.xml +303 -0
  234. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.dtd +6 -0
  235. mapproxy/test/schemas/wmsc/1.1.1/exception_1_1_1.xml +33 -0
  236. mapproxy/test/schemas/wmts/1.0/ReadMe.txt +32 -0
  237. mapproxy/test/schemas/wmts/1.0/wmts.xsd +28 -0
  238. mapproxy/test/schemas/wmts/1.0/wmtsAbstract.wsdl +151 -0
  239. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_request.xsd +38 -0
  240. mapproxy/test/schemas/wmts/1.0/wmtsGetCapabilities_response.xsd +564 -0
  241. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_request.xsd +57 -0
  242. mapproxy/test/schemas/wmts/1.0/wmtsGetFeatureInfo_response.xsd +72 -0
  243. mapproxy/test/schemas/wmts/1.0/wmtsGetTile_request.xsd +91 -0
  244. mapproxy/test/schemas/wmts/1.0/wmtsKVP.xsd +76 -0
  245. mapproxy/test/schemas/wmts/1.0/wmtsPayload_response.xsd +70 -0
  246. mapproxy/test/schemas/xlink/1.0.0/ReadMe.txt +6 -0
  247. mapproxy/test/schemas/xlink/1.0.0/xlinks.xsd +122 -0
  248. mapproxy/test/schemas/xml.xsd +287 -0
  249. mapproxy/test/system/__init__.py +98 -0
  250. mapproxy/test/system/fixture/arcgis.yaml +57 -0
  251. mapproxy/test/system/fixture/auth.yaml +70 -0
  252. mapproxy/test/system/fixture/cache.mbtiles +0 -0
  253. mapproxy/test/system/fixture/cache_azureblob.yaml +59 -0
  254. mapproxy/test/system/fixture/cache_band_merge.yaml +73 -0
  255. mapproxy/test/system/fixture/cache_bulk_meta_tiles.yaml +24 -0
  256. mapproxy/test/system/fixture/cache_coverage.yaml +84 -0
  257. mapproxy/test/system/fixture/cache_data/dop_cache_EPSG3857/00/000/000/000/000/000/000.png +0 -0
  258. mapproxy/test/system/fixture/cache_data/wms_cache_EPSG900913/01/000/000/000/000/000/001.jpeg +0 -0
  259. mapproxy/test/system/fixture/cache_data/wms_cache_transparent_EPSG900913/01/000/000/000/000/000/001.png +0 -0
  260. mapproxy/test/system/fixture/cache_geopackage.yaml +56 -0
  261. mapproxy/test/system/fixture/cache_grid_names.yaml +50 -0
  262. mapproxy/test/system/fixture/cache_mbtiles.yaml +28 -0
  263. mapproxy/test/system/fixture/cache_s3.yaml +58 -0
  264. mapproxy/test/system/fixture/cache_source.yaml +81 -0
  265. mapproxy/test/system/fixture/combined_sources.yaml +130 -0
  266. mapproxy/test/system/fixture/coverage.yaml +77 -0
  267. mapproxy/test/system/fixture/demo.yaml +135 -0
  268. mapproxy/test/system/fixture/dimension.yaml +59 -0
  269. mapproxy/test/system/fixture/disable_storage.yaml +25 -0
  270. mapproxy/test/system/fixture/empty_ogrdata.geojson +1 -0
  271. mapproxy/test/system/fixture/formats.yaml +72 -0
  272. mapproxy/test/system/fixture/inspire.yaml +101 -0
  273. mapproxy/test/system/fixture/inspire_full.yaml +124 -0
  274. mapproxy/test/system/fixture/kml_layer.yaml +66 -0
  275. mapproxy/test/system/fixture/layer.yaml +260 -0
  276. mapproxy/test/system/fixture/layergroups.yaml +57 -0
  277. mapproxy/test/system/fixture/layergroups_root.yaml +106 -0
  278. mapproxy/test/system/fixture/legendgraphic.yaml +93 -0
  279. mapproxy/test/system/fixture/mapnik_source.yaml +66 -0
  280. mapproxy/test/system/fixture/mapproxy_export.yaml +12 -0
  281. mapproxy/test/system/fixture/mapserver.yaml +23 -0
  282. mapproxy/test/system/fixture/minimal_cgi.py +16 -0
  283. mapproxy/test/system/fixture/mixed_mode.yaml +49 -0
  284. mapproxy/test/system/fixture/multi_cache_layers.yaml +111 -0
  285. mapproxy/test/system/fixture/multiapp1.yaml +20 -0
  286. mapproxy/test/system/fixture/multiapp2.yaml +19 -0
  287. mapproxy/test/system/fixture/renderd_client.yaml +55 -0
  288. mapproxy/test/system/fixture/scalehints.yaml +70 -0
  289. mapproxy/test/system/fixture/seed.yaml +94 -0
  290. mapproxy/test/system/fixture/seed_mapproxy.yaml +39 -0
  291. mapproxy/test/system/fixture/seed_old.yaml +12 -0
  292. mapproxy/test/system/fixture/seed_timeouts.yaml +12 -0
  293. mapproxy/test/system/fixture/seed_timeouts_mapproxy.yaml +27 -0
  294. mapproxy/test/system/fixture/seedonly.yaml +51 -0
  295. mapproxy/test/system/fixture/sld.yaml +35 -0
  296. mapproxy/test/system/fixture/source_errors.yaml +84 -0
  297. mapproxy/test/system/fixture/source_errors_raise.yaml +82 -0
  298. mapproxy/test/system/fixture/tileservice_origin.yaml +26 -0
  299. mapproxy/test/system/fixture/tileservice_refresh.yaml +59 -0
  300. mapproxy/test/system/fixture/tilesource_minmax_res.yaml +22 -0
  301. mapproxy/test/system/fixture/util-conf-base-grids.yaml +5 -0
  302. mapproxy/test/system/fixture/util-conf-overwrite.yaml +13 -0
  303. mapproxy/test/system/fixture/util-conf-wms-111-cap.xml +90 -0
  304. mapproxy/test/system/fixture/util_grids.yaml +29 -0
  305. mapproxy/test/system/fixture/util_wms_capabilities111.xml +130 -0
  306. mapproxy/test/system/fixture/util_wms_capabilities130.xml +100 -0
  307. mapproxy/test/system/fixture/util_wms_capabilities_service_exception.xml +5 -0
  308. mapproxy/test/system/fixture/watermark.yaml +50 -0
  309. mapproxy/test/system/fixture/wms_srs_extent.yaml +39 -0
  310. mapproxy/test/system/fixture/wms_versions.yaml +38 -0
  311. mapproxy/test/system/fixture/wmts.yaml +134 -0
  312. mapproxy/test/system/fixture/wmts_dimensions.yaml +57 -0
  313. mapproxy/test/system/fixture/xslt_featureinfo.yaml +54 -0
  314. mapproxy/test/system/fixture/xslt_featureinfo_input.yaml +51 -0
  315. mapproxy/test/system/test_arcgis.py +156 -0
  316. mapproxy/test/system/test_auth.py +1133 -0
  317. mapproxy/test/system/test_behind_proxy.py +75 -0
  318. mapproxy/test/system/test_bulk_meta_tiles.py +106 -0
  319. mapproxy/test/system/test_cache_azureblob.py +127 -0
  320. mapproxy/test/system/test_cache_band_merge.py +103 -0
  321. mapproxy/test/system/test_cache_coverage.py +168 -0
  322. mapproxy/test/system/test_cache_geopackage.py +144 -0
  323. mapproxy/test/system/test_cache_grid_names.py +89 -0
  324. mapproxy/test/system/test_cache_mbtiles.py +85 -0
  325. mapproxy/test/system/test_cache_s3.py +115 -0
  326. mapproxy/test/system/test_cache_source.py +146 -0
  327. mapproxy/test/system/test_combined_sources.py +335 -0
  328. mapproxy/test/system/test_coverage.py +140 -0
  329. mapproxy/test/system/test_decorate_img.py +214 -0
  330. mapproxy/test/system/test_demo.py +56 -0
  331. mapproxy/test/system/test_demo_with_extra_service.py +57 -0
  332. mapproxy/test/system/test_dimensions.py +279 -0
  333. mapproxy/test/system/test_disable_storage.py +42 -0
  334. mapproxy/test/system/test_formats.py +219 -0
  335. mapproxy/test/system/test_inspire_vs.py +173 -0
  336. mapproxy/test/system/test_kml.py +264 -0
  337. mapproxy/test/system/test_layergroups.py +160 -0
  338. mapproxy/test/system/test_legendgraphic.py +308 -0
  339. mapproxy/test/system/test_mapnik.py +162 -0
  340. mapproxy/test/system/test_mapserver.py +83 -0
  341. mapproxy/test/system/test_mixed_mode_format.py +201 -0
  342. mapproxy/test/system/test_multi_cache_layers.py +169 -0
  343. mapproxy/test/system/test_multiapp.py +92 -0
  344. mapproxy/test/system/test_refresh.py +206 -0
  345. mapproxy/test/system/test_renderd_client.py +304 -0
  346. mapproxy/test/system/test_response_headers.py +54 -0
  347. mapproxy/test/system/test_scalehints.py +140 -0
  348. mapproxy/test/system/test_seed.py +425 -0
  349. mapproxy/test/system/test_seed_only.py +93 -0
  350. mapproxy/test/system/test_sld.py +120 -0
  351. mapproxy/test/system/test_source_errors.py +377 -0
  352. mapproxy/test/system/test_tilesource_minmax_res.py +54 -0
  353. mapproxy/test/system/test_tms.py +277 -0
  354. mapproxy/test/system/test_tms_origin.py +46 -0
  355. mapproxy/test/system/test_util_conf.py +434 -0
  356. mapproxy/test/system/test_util_export.py +210 -0
  357. mapproxy/test/system/test_util_grids.py +88 -0
  358. mapproxy/test/system/test_util_wms_capabilities.py +182 -0
  359. mapproxy/test/system/test_watermark.py +91 -0
  360. mapproxy/test/system/test_wms.py +1616 -0
  361. mapproxy/test/system/test_wms_srs_extent.py +165 -0
  362. mapproxy/test/system/test_wms_version.py +85 -0
  363. mapproxy/test/system/test_wmsc.py +116 -0
  364. mapproxy/test/system/test_wmts.py +334 -0
  365. mapproxy/test/system/test_wmts_dimensions.py +206 -0
  366. mapproxy/test/system/test_wmts_restful.py +198 -0
  367. mapproxy/test/system/test_xslt_featureinfo.py +423 -0
  368. mapproxy/test/test_http_helper.py +217 -0
  369. mapproxy/test/unit/__init__.py +0 -0
  370. mapproxy/test/unit/epsg +2 -0
  371. mapproxy/test/unit/polygons/polygons.dbf +0 -0
  372. mapproxy/test/unit/polygons/polygons.shp +0 -0
  373. mapproxy/test/unit/polygons/polygons.shx +0 -0
  374. mapproxy/test/unit/test_async.py +242 -0
  375. mapproxy/test/unit/test_auth.py +430 -0
  376. mapproxy/test/unit/test_cache.py +1356 -0
  377. mapproxy/test/unit/test_cache_azureblob.py +97 -0
  378. mapproxy/test/unit/test_cache_compact.py +324 -0
  379. mapproxy/test/unit/test_cache_couchdb.py +118 -0
  380. mapproxy/test/unit/test_cache_geopackage.py +256 -0
  381. mapproxy/test/unit/test_cache_redis.py +123 -0
  382. mapproxy/test/unit/test_cache_riak.py +80 -0
  383. mapproxy/test/unit/test_cache_s3.py +93 -0
  384. mapproxy/test/unit/test_cache_tile.py +477 -0
  385. mapproxy/test/unit/test_client.py +488 -0
  386. mapproxy/test/unit/test_client_arcgis.py +74 -0
  387. mapproxy/test/unit/test_client_cgi.py +140 -0
  388. mapproxy/test/unit/test_collections.py +116 -0
  389. mapproxy/test/unit/test_concat_legends.py +37 -0
  390. mapproxy/test/unit/test_conf_loader.py +1267 -0
  391. mapproxy/test/unit/test_conf_validator.py +427 -0
  392. mapproxy/test/unit/test_config.py +118 -0
  393. mapproxy/test/unit/test_decorate_img.py +185 -0
  394. mapproxy/test/unit/test_exceptions.py +270 -0
  395. mapproxy/test/unit/test_featureinfo.py +313 -0
  396. mapproxy/test/unit/test_file_lock_load.py +49 -0
  397. mapproxy/test/unit/test_geom.py +512 -0
  398. mapproxy/test/unit/test_grid.py +1279 -0
  399. mapproxy/test/unit/test_image.py +1051 -0
  400. mapproxy/test/unit/test_image_mask.py +181 -0
  401. mapproxy/test/unit/test_image_messages.py +209 -0
  402. mapproxy/test/unit/test_image_options.py +160 -0
  403. mapproxy/test/unit/test_isodate.py +118 -0
  404. mapproxy/test/unit/test_multiapp.py +163 -0
  405. mapproxy/test/unit/test_ogr_reader.py +51 -0
  406. mapproxy/test/unit/test_request.py +745 -0
  407. mapproxy/test/unit/test_request_wmts.py +178 -0
  408. mapproxy/test/unit/test_response.py +78 -0
  409. mapproxy/test/unit/test_seed.py +365 -0
  410. mapproxy/test/unit/test_seed_cachelock.py +91 -0
  411. mapproxy/test/unit/test_srs.py +215 -0
  412. mapproxy/test/unit/test_tiled_source.py +122 -0
  413. mapproxy/test/unit/test_tilefilter.py +31 -0
  414. mapproxy/test/unit/test_times.py +25 -0
  415. mapproxy/test/unit/test_timeutils.py +50 -0
  416. mapproxy/test/unit/test_util_conf_utils.py +75 -0
  417. mapproxy/test/unit/test_utils.py +476 -0
  418. mapproxy/test/unit/test_wms_capabilities.py +44 -0
  419. mapproxy/test/unit/test_wms_layer.py +113 -0
  420. mapproxy/test/unit/test_yaml.py +68 -0
  421. mapproxy/tilefilter.py +61 -0
  422. mapproxy/util/__init__.py +0 -0
  423. mapproxy/util/async_.py +229 -0
  424. mapproxy/util/collections.py +134 -0
  425. mapproxy/util/coverage.py +337 -0
  426. mapproxy/util/ext/__init__.py +14 -0
  427. mapproxy/util/ext/dictspec/__init__.py +1 -0
  428. mapproxy/util/ext/dictspec/spec.py +131 -0
  429. mapproxy/util/ext/dictspec/test/__init__.py +0 -0
  430. mapproxy/util/ext/dictspec/test/test_validator.py +278 -0
  431. mapproxy/util/ext/dictspec/validator.py +194 -0
  432. mapproxy/util/ext/local.py +198 -0
  433. mapproxy/util/ext/lockfile.py +140 -0
  434. mapproxy/util/ext/odict.py +321 -0
  435. mapproxy/util/ext/serving.py +491 -0
  436. mapproxy/util/ext/tempita/__init__.py +1093 -0
  437. mapproxy/util/ext/tempita/_looper.py +163 -0
  438. mapproxy/util/ext/tempita/string_utils.py +24 -0
  439. mapproxy/util/ext/wmsparse/__init__.py +3 -0
  440. mapproxy/util/ext/wmsparse/duration.py +600 -0
  441. mapproxy/util/ext/wmsparse/parse.py +307 -0
  442. mapproxy/util/ext/wmsparse/test/__init__.py +0 -0
  443. mapproxy/util/ext/wmsparse/test/test_parse.py +111 -0
  444. mapproxy/util/ext/wmsparse/test/test_util.py +23 -0
  445. mapproxy/util/ext/wmsparse/test/wms-example-111.xml +90 -0
  446. mapproxy/util/ext/wmsparse/test/wms-example-130.xml +120 -0
  447. mapproxy/util/ext/wmsparse/test/wms-large-111.xml +2114 -0
  448. mapproxy/util/ext/wmsparse/test/wms_nasa_cap.xml +386 -0
  449. mapproxy/util/ext/wmsparse/util.py +189 -0
  450. mapproxy/util/fs.py +164 -0
  451. mapproxy/util/geom.py +307 -0
  452. mapproxy/util/lib.py +117 -0
  453. mapproxy/util/lock.py +171 -0
  454. mapproxy/util/ogr.py +247 -0
  455. mapproxy/util/py.py +75 -0
  456. mapproxy/util/times.py +78 -0
  457. mapproxy/util/yaml.py +58 -0
  458. mapproxy/version.py +33 -0
  459. mapproxy/wsgiapp.py +167 -0
@@ -0,0 +1,1267 @@
1
+ # -:- encoding: UTF8 -:-
2
+ # This file is part of the MapProxy project.
3
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ from __future__ import division
18
+
19
+ import copy
20
+ import time
21
+ from unittest import SkipTest
22
+
23
+ import yaml
24
+ import pytest
25
+
26
+ from mapproxy.config.coverage import load_coverage
27
+ from mapproxy.config.loader import (
28
+ ProxyConfiguration,
29
+ load_configuration,
30
+ merge_dict,
31
+ ConfigurationError,
32
+ )
33
+ from mapproxy.cache.tile import TileManager
34
+ from mapproxy.config.spec import validate_options
35
+ from mapproxy.layer import MapExtent
36
+ from mapproxy.seed.spec import validate_seed_conf
37
+ from mapproxy.srs import SRS
38
+ from mapproxy.test.helper import TempFile
39
+ from mapproxy.test.unit.test_grid import assert_almost_equal_bbox
40
+ from mapproxy.util.coverage import coverage
41
+ from mapproxy.util.geom import EmptyGeometryError
42
+
43
+
44
+ class TestLayerConfiguration(object):
45
+ def _test_conf(self, yaml_part):
46
+ base = {'sources': {'s': {'type': 'wms', 'req': {'url': ''}}}}
47
+ base.update(yaml.safe_load(yaml_part))
48
+ return base
49
+
50
+ def test_legacy_ordered(self):
51
+ conf = self._test_conf('''
52
+ layers:
53
+ - one:
54
+ title: Layer One
55
+ sources: [s]
56
+ - two:
57
+ title: Layer Two
58
+ sources: [s]
59
+ - three:
60
+ title: Layer Three
61
+ sources: [s]
62
+ ''')
63
+ with pytest.warns(RuntimeWarning):
64
+ conf = ProxyConfiguration(conf)
65
+ root = conf.wms_root_layer.wms_layer()
66
+
67
+ # no root layer defined
68
+ assert root.title is None
69
+ assert root.name is None
70
+ layers = root.child_layers()
71
+
72
+ # names are in order
73
+ assert layers.keys() == ['one', 'two', 'three']
74
+
75
+ assert len(layers) == 3
76
+ assert layers['one'].title == 'Layer One'
77
+ assert layers['two'].title == 'Layer Two'
78
+ assert layers['three'].title == 'Layer Three'
79
+
80
+ layers_conf = conf.layers
81
+ assert len(layers_conf) == 3
82
+
83
+ def test_legacy_unordered(self):
84
+ conf = self._test_conf('''
85
+ layers:
86
+ one:
87
+ title: Layer One
88
+ sources: [s]
89
+ two:
90
+ title: Layer Two
91
+ sources: [s]
92
+ three:
93
+ title: Layer Three
94
+ sources: [s]
95
+ ''')
96
+ with pytest.warns(RuntimeWarning):
97
+ conf = ProxyConfiguration(conf)
98
+ root = conf.wms_root_layer.wms_layer()
99
+
100
+ # no root layer defined
101
+ assert root.title is None
102
+ assert root.name is None
103
+ layers = root.child_layers()
104
+
105
+ # names might not be in order
106
+ # layers.keys() != ['one', 'two', 'three']
107
+
108
+ assert len(layers) == 3
109
+ assert layers['one'].title == 'Layer One'
110
+ assert layers['two'].title == 'Layer Two'
111
+ assert layers['three'].title == 'Layer Three'
112
+
113
+ def test_with_root(self):
114
+ conf = self._test_conf('''
115
+ layers:
116
+ name: root
117
+ title: Root Layer
118
+ layers:
119
+ - name: one
120
+ title: Layer One
121
+ sources: [s]
122
+ - name: two
123
+ title: Layer Two
124
+ sources: [s]
125
+ ''')
126
+ conf = ProxyConfiguration(conf)
127
+ root = conf.wms_root_layer.wms_layer()
128
+
129
+ assert root.title == 'Root Layer'
130
+ assert root.name == 'root'
131
+ layers = root.child_layers()
132
+
133
+ # names are in order
134
+ assert layers.keys() == ['root', 'one', 'two']
135
+
136
+ assert len(layers) == 3
137
+ assert layers['root'].title == 'Root Layer'
138
+ assert layers['one'].title == 'Layer One'
139
+ assert layers['two'].title == 'Layer Two'
140
+
141
+ layers_conf = conf.layers
142
+ assert len(layers_conf) == 2
143
+
144
+ def test_with_unnamed_root(self):
145
+ conf = self._test_conf('''
146
+ layers:
147
+ title: Root Layer
148
+ layers:
149
+ - name: one
150
+ title: Layer One
151
+ sources: [s]
152
+ - name: two
153
+ title: Layer Two
154
+ sources: [s]
155
+ ''')
156
+ conf = ProxyConfiguration(conf)
157
+ root = conf.wms_root_layer.wms_layer()
158
+
159
+ assert root.title == 'Root Layer'
160
+ assert root.name is None
161
+
162
+ layers = root.child_layers()
163
+ # names are in order
164
+ assert layers.keys() == ['one', 'two']
165
+
166
+ def test_without_root(self):
167
+ conf = self._test_conf('''
168
+ layers:
169
+ - name: one
170
+ title: Layer One
171
+ sources: [s]
172
+ - name: two
173
+ title: Layer Two
174
+ sources: [s]
175
+ ''')
176
+ conf = ProxyConfiguration(conf)
177
+ root = conf.wms_root_layer.wms_layer()
178
+
179
+ assert root.title is None
180
+ assert root.name is None
181
+
182
+ layers = root.child_layers()
183
+ # names are in order
184
+ assert layers.keys() == ['one', 'two']
185
+
186
+ def test_hierarchy(self):
187
+ conf = self._test_conf('''
188
+ layers:
189
+ title: Root Layer
190
+ layers:
191
+ - name: one
192
+ title: Layer One
193
+ layers:
194
+ - name: onea
195
+ title: Layer One A
196
+ sources: [s]
197
+ - name: oneb
198
+ title: Layer One B
199
+ layers:
200
+ - name: oneba
201
+ title: Layer One B A
202
+ sources: [s]
203
+ - name: onebb
204
+ title: Layer One B B
205
+ sources: [s]
206
+ - name: two
207
+ title: Layer Two
208
+ sources: [s]
209
+ ''')
210
+ conf = ProxyConfiguration(conf)
211
+ root = conf.wms_root_layer.wms_layer()
212
+
213
+ assert root.title == 'Root Layer'
214
+ assert root.name is None
215
+
216
+ layers = root.child_layers()
217
+ # names are in order
218
+ assert layers.keys() == ['one', 'onea', 'oneb', 'oneba', 'onebb', 'two']
219
+
220
+ layers_conf = conf.layers
221
+ assert len(layers_conf) == 4
222
+ assert layers_conf.keys() == ['onea', 'oneba', 'onebb', 'two']
223
+ assert layers_conf['onea'].conf['title'] == 'Layer One A'
224
+ assert layers_conf['onea'].conf['name'] == 'onea'
225
+ assert layers_conf['onea'].conf['sources'] == ['s']
226
+
227
+ def test_hierarchy_root_is_list(self):
228
+ conf = self._test_conf('''
229
+ layers:
230
+ - title: Root Layer
231
+ layers:
232
+ - name: one
233
+ title: Layer One
234
+ sources: [s]
235
+ - name: two
236
+ title: Layer Two
237
+ sources: [s]
238
+ ''')
239
+ conf = ProxyConfiguration(conf)
240
+ root = conf.wms_root_layer.wms_layer()
241
+
242
+ assert root.title == 'Root Layer'
243
+ assert root.name is None
244
+
245
+ layers = root.child_layers()
246
+ # names are in order
247
+ assert layers.keys() == ['one', 'two']
248
+
249
+ def test_without_sources_or_layers(self):
250
+ conf = self._test_conf('''
251
+ services:
252
+ wms:
253
+ layers:
254
+ title: Root Layer
255
+ layers:
256
+ - name: one
257
+ title: Layer One
258
+ ''')
259
+ conf = ProxyConfiguration(conf)
260
+ assert conf.wms_root_layer.wms_layer() is None
261
+ try:
262
+ conf.services.services()
263
+ except ConfigurationError:
264
+ # found no WMS layer
265
+ pass
266
+ else:
267
+ assert False, 'expected ConfigurationError'
268
+
269
+
270
+ class TestGridConfiguration(object):
271
+ def test_default_grids(self):
272
+ conf = {}
273
+ conf = ProxyConfiguration(conf)
274
+ grid = conf.grids['GLOBAL_MERCATOR'].tile_grid()
275
+ assert grid.srs == SRS(900913)
276
+
277
+ grid = conf.grids['GLOBAL_GEODETIC'].tile_grid()
278
+ assert grid.srs == SRS(4326)
279
+
280
+ def test_simple(self):
281
+ conf = {'grids': {'grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55]}}}
282
+ conf = ProxyConfiguration(conf)
283
+ grid = conf.grids['grid'].tile_grid()
284
+ assert grid.srs == SRS(4326)
285
+
286
+ def test_with_base(self):
287
+ conf = {'grids': {
288
+ 'base_grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55]},
289
+ 'grid': {'base': 'base_grid'}
290
+ }}
291
+ conf = ProxyConfiguration(conf)
292
+ grid = conf.grids['grid'].tile_grid()
293
+ assert grid.srs == SRS(4326)
294
+
295
+ def test_with_num_levels(self):
296
+ conf = {'grids': {'grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55], 'num_levels': 8}}}
297
+ conf = ProxyConfiguration(conf)
298
+ grid = conf.grids['grid'].tile_grid()
299
+ assert len(grid.resolutions) == 8
300
+
301
+ def test_with_bbox_srs(self):
302
+ conf = {'grids': {'grid': {'srs': 'EPSG:25832', 'bbox': [5, 50, 10, 55], 'bbox_srs': 'EPSG:4326'}}}
303
+ conf = ProxyConfiguration(conf)
304
+ grid = conf.grids['grid'].tile_grid()
305
+ assert_almost_equal_bbox([213372, 5538660, 571666, 6102110], grid.bbox, 1)
306
+
307
+ def test_with_min_res(self):
308
+ conf = {'grids': {'grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55], 'min_res': 0.0390625}}}
309
+ conf = ProxyConfiguration(conf)
310
+ grid = conf.grids['grid'].tile_grid()
311
+ assert_almost_equal_bbox([5, 50, 10, 55], grid.bbox)
312
+ assert grid.resolution(0) == 0.0390625
313
+ assert grid.resolution(1) == 0.01953125
314
+
315
+ def test_with_max_res(self):
316
+ conf = {'grids': {'grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55], 'max_res': 0.0048828125}}}
317
+ conf = ProxyConfiguration(conf)
318
+ grid = conf.grids['grid'].tile_grid()
319
+ assert_almost_equal_bbox([5, 50, 10, 55], grid.bbox)
320
+ assert grid.resolution(0) == 0.01953125
321
+ assert grid.resolution(1) == 0.01953125/2
322
+
323
+
324
+ class TestWMSSourceConfiguration(object):
325
+ def test_simple_grid(self):
326
+ conf_dict = {
327
+ 'grids': {
328
+ 'grid': {'srs': 'EPSG:4326', 'bbox': [5, 50, 10, 55]},
329
+ },
330
+ 'sources': {
331
+ 'osm': {
332
+ 'type': 'wms',
333
+ 'req': {
334
+ 'url': 'http://localhost/service?',
335
+ 'layers': 'base',
336
+ },
337
+ },
338
+ },
339
+ 'caches': {
340
+ 'osm': {
341
+ 'sources': ['osm'],
342
+ 'grids': ['grid'],
343
+ }
344
+ }
345
+ }
346
+
347
+ conf = ProxyConfiguration(conf_dict)
348
+
349
+ caches = conf.caches['osm'].caches()
350
+ assert len(caches) == 1
351
+ grid, extent, manager = caches[0]
352
+
353
+ assert grid.srs == SRS(4326)
354
+ assert grid.bbox == (5.0, 50.0, 10.0, 55.0)
355
+
356
+ assert isinstance(manager, TileManager)
357
+
358
+ def check_source_layers(self, conf_dict, layers):
359
+ conf = ProxyConfiguration(conf_dict)
360
+ caches = conf.caches['osm'].caches()
361
+ assert len(caches) == 1
362
+ grid, extent, manager = caches[0]
363
+ source_layers = manager.sources[0].client.request_template.params.layers
364
+ assert source_layers == layers
365
+
366
+ def test_tagged_source(self):
367
+ conf_dict = {
368
+ 'sources': {
369
+ 'osm': {
370
+ 'type': 'wms',
371
+ 'req': {
372
+ 'url': 'http://localhost/service?',
373
+ },
374
+ },
375
+ },
376
+ 'caches': {
377
+ 'osm': {
378
+ 'sources': ['osm:base,roads'],
379
+ 'grids': ['GLOBAL_MERCATOR'],
380
+ }
381
+ }
382
+ }
383
+ self.check_source_layers(conf_dict, ['base', 'roads'])
384
+
385
+ def test_tagged_source_with_layers(self):
386
+ conf_dict = {
387
+ 'sources': {
388
+ 'osm': {
389
+ 'type': 'wms',
390
+ 'req': {
391
+ 'url': 'http://localhost/service?',
392
+ 'layers': 'base,roads,poi'
393
+ },
394
+ },
395
+ },
396
+ 'caches': {
397
+ 'osm': {
398
+ 'sources': ['osm:base,roads'],
399
+ 'grids': ['GLOBAL_MERCATOR'],
400
+ }
401
+ }
402
+ }
403
+ self.check_source_layers(conf_dict, ['base', 'roads'])
404
+
405
+ def test_tagged_source_with_layers_missing(self):
406
+ conf_dict = {
407
+ 'sources': {
408
+ 'osm': {
409
+ 'type': 'wms',
410
+ 'req': {
411
+ 'url': 'http://localhost/service?',
412
+ 'layers': 'base,poi'
413
+ },
414
+ },
415
+ },
416
+ 'caches': {
417
+ 'osm': {
418
+ 'sources': ['osm:base,roads'],
419
+ 'grids': ['GLOBAL_MERCATOR'],
420
+ }
421
+ }
422
+ }
423
+ conf = ProxyConfiguration(conf_dict)
424
+ try:
425
+ conf.caches['osm'].caches()
426
+ except ConfigurationError as ex:
427
+ assert 'base,roads' in ex.args[0]
428
+ assert ('base,poi' in ex.args[0] or 'poi,base' in ex.args[0])
429
+ else:
430
+ assert False, 'expected ConfigurationError'
431
+
432
+ def test_tagged_source_on_non_wms_source(self):
433
+ conf_dict = {
434
+ 'sources': {
435
+ 'osm': {
436
+ 'type': 'tile',
437
+ 'url': 'http://example.org/'
438
+ },
439
+ },
440
+ 'caches': {
441
+ 'osm': {
442
+ 'sources': ['osm:base,roads'],
443
+ 'grids': ['GLOBAL_MERCATOR'],
444
+ }
445
+ }
446
+ }
447
+ conf = ProxyConfiguration(conf_dict)
448
+ try:
449
+ conf.caches['osm'].caches()
450
+ except ConfigurationError as ex:
451
+ assert 'osm:base,roads' in ex.args[0]
452
+ else:
453
+ assert False, 'expected ConfigurationError'
454
+
455
+ def test_layer_tagged_source(self):
456
+ conf_dict = {
457
+ 'layers': [
458
+ {
459
+ 'name': 'osm',
460
+ 'title': 'OSM',
461
+ 'sources': ['osm:base,roads']
462
+ }
463
+ ],
464
+ 'sources': {
465
+ 'osm': {
466
+ 'type': 'wms',
467
+ 'req': {
468
+ 'url': 'http://localhost/service?',
469
+ },
470
+ },
471
+ },
472
+ }
473
+ conf = ProxyConfiguration(conf_dict)
474
+ wms_layer = conf.layers['osm'].wms_layer()
475
+ layers = wms_layer.map_layers[0].client.request_template.params.layers
476
+ assert layers == ['base', 'roads']
477
+
478
+ def test_tagged_source_encoding(self):
479
+ conf_dict = {
480
+ 'layers': [
481
+ {
482
+ 'name': 'osm',
483
+ 'title': 'OSM',
484
+ 'sources': [u'osm:☃']
485
+ }
486
+ ],
487
+ 'sources': {
488
+ 'osm': {
489
+ 'type': 'wms',
490
+ 'req': {
491
+ 'url': 'http://localhost/service?',
492
+ },
493
+ },
494
+ },
495
+ 'caches': {
496
+ 'osm': {
497
+ 'sources': [u'osm:☃'],
498
+ 'grids': ['GLOBAL_MERCATOR'],
499
+ }
500
+ }
501
+ }
502
+ # from source
503
+ conf = ProxyConfiguration(conf_dict)
504
+ wms_layer = conf.layers['osm'].wms_layer()
505
+ layers = wms_layer.map_layers[0].client.request_template.params.layers
506
+ assert layers == [u'☃']
507
+ # from cache
508
+ self.check_source_layers(conf_dict, [u'☃'])
509
+
510
+ def test_https_source_insecure(self):
511
+ conf_dict = {
512
+ 'sources': {
513
+ 'osm': {
514
+ 'type': 'wms',
515
+ 'http': {'ssl_no_cert_checks': True},
516
+ 'req': {
517
+ 'url': 'https://foo:bar@localhost/service?',
518
+ 'layers': 'base',
519
+ },
520
+ },
521
+ },
522
+ }
523
+
524
+ conf = ProxyConfiguration(conf_dict)
525
+ try:
526
+ conf.sources['osm'].source({'format': 'image/png'})
527
+ except ImportError:
528
+ raise SkipTest('no ssl support')
529
+
530
+
531
+ class TestBandMergeConfig(object):
532
+
533
+ def test_invalid_band(self):
534
+ conf_dict = {
535
+ 'caches': {
536
+ 'osm': {
537
+ 'sources': {'f': [{'source': 'foo', 'band': 1}]},
538
+ 'grids': ['GLOBAL_WEBMERCATOR'],
539
+ }
540
+ }
541
+ }
542
+ errors, informal_only = validate_options(conf_dict)
543
+ assert len(errors) == 1
544
+ assert "unknown 'f' in caches" in errors[0]
545
+
546
+ def test_no_band_cache(self):
547
+ conf_dict = {
548
+ 'caches': {
549
+ 'osm': {
550
+ 'sources': {'l': [{'source': 'foo'}]},
551
+ 'grids': ['GLOBAL_WEBMERCATOR'],
552
+ }
553
+ }
554
+ }
555
+ errors, informal_only = validate_options(conf_dict)
556
+ assert len(errors) == 1
557
+ assert "missing 'band', not in caches" in errors[0], errors
558
+
559
+
560
+ def load_services(conf_file):
561
+ conf = load_configuration(conf_file)
562
+ return conf.configured_services()
563
+
564
+
565
+ class TestConfLoading(object):
566
+ yaml_string = b"""
567
+ services:
568
+ wms:
569
+
570
+ layers:
571
+ - name: osm
572
+ title: OSM
573
+ sources: [osm]
574
+
575
+ sources:
576
+ osm:
577
+ type: wms
578
+ supported_srs: ['EPSG:31467']
579
+ req:
580
+ url: http://foo
581
+ layers: base
582
+ """
583
+
584
+ def test_loading(self):
585
+ with TempFile() as tf:
586
+ with open(tf, 'wb') as f:
587
+ f.write(self.yaml_string)
588
+ services = load_services(tf)
589
+ assert 'service' in services[0].names
590
+
591
+ def test_loading_broken_yaml(self):
592
+ with TempFile() as tf:
593
+ with open(tf, 'wb') as f:
594
+ f.write(b'\tbroken:foo')
595
+ try:
596
+ load_services(tf)
597
+ except ConfigurationError:
598
+ pass
599
+ else:
600
+ assert False, 'expected configuration error'
601
+
602
+ def test_loading_extra_service(self):
603
+ """ Test registration of extra service """
604
+
605
+ my_yaml_string = b"""
606
+ services:
607
+ my_extra_service:
608
+ foo: bar
609
+
610
+ layers:
611
+ - name: osm
612
+ title: OSM
613
+ sources: [osm]
614
+
615
+ sources:
616
+ osm:
617
+ type: wms
618
+ supported_srs: ['EPSG:31467']
619
+ req:
620
+ url: http://foo
621
+ layers: base
622
+ """
623
+ from mapproxy.config.loader import plugin_services, register_service_configuration
624
+ from mapproxy.service.base import Server
625
+
626
+ class MyExtraServiceServer(Server):
627
+ names = ('my_extra_service',)
628
+
629
+ def __init__(self):
630
+ pass
631
+
632
+ def my_extra_service_method(serviceConfiguration, conf):
633
+ return MyExtraServiceServer()
634
+
635
+ try:
636
+ with TempFile() as tf:
637
+ with open(tf, 'wb') as f:
638
+ f.write(my_yaml_string)
639
+
640
+ register_service_configuration('my_extra_service', my_extra_service_method,
641
+ 'my_extra_service', {'foo': str()})
642
+ conf = load_configuration(tf, ignore_warnings=False)
643
+ services = conf.configured_services()
644
+ assert 'my_extra_service' in services[0].names
645
+
646
+ finally:
647
+ plugin_services.clear()
648
+
649
+ def test_loading_extra_source(self):
650
+ """ Test registration of extra source """
651
+
652
+ my_yaml_string = b"""
653
+ services:
654
+ wms:
655
+
656
+ layers:
657
+ - name: osm
658
+ title: OSM
659
+ sources: [osm]
660
+
661
+ sources:
662
+ osm:
663
+ type: my_extra_source
664
+ foo: bar
665
+ """
666
+ from mapproxy.config.loader import source_configuration_types, register_source_configuration
667
+ from mapproxy.config.loader import SourceConfiguration
668
+
669
+ class my_source_configuration(SourceConfiguration):
670
+ source_type = ('my_extra_source',)
671
+
672
+ def source(self, params=None):
673
+ class MySource(object):
674
+ def __init__(self):
675
+ self.extent = None
676
+ return MySource()
677
+
678
+ source_configuration_types_before = copy.copy(source_configuration_types)
679
+ try:
680
+ with TempFile() as tf:
681
+ with open(tf, 'wb') as f:
682
+ f.write(my_yaml_string)
683
+
684
+ register_source_configuration('my_extra_source', my_source_configuration,
685
+ 'my_extra_source', {'foo': str()})
686
+ conf = load_configuration(tf, ignore_warnings=False)
687
+
688
+ assert conf.sources['osm'].source_type == ('my_extra_source',)
689
+
690
+ finally:
691
+ source_configuration_types = source_configuration_types_before
692
+
693
+
694
+ class TestConfImport(object):
695
+
696
+ yaml_string = """
697
+ services:
698
+ wms:
699
+ # ======= overwritten max_output_pixels:
700
+ max_output_pixels: [4000, 4000]
701
+
702
+ layers:
703
+ - name: Zones_A
704
+ title: Zones_A
705
+ # ======= overwritten sources and layers:
706
+ sources: []
707
+ layers:
708
+ - name: layerA1
709
+ title: layer A 1
710
+ sources: [osm_cache]
711
+ - name: layerA2
712
+ title: layer A 2
713
+ sources: [osm_cache]
714
+ # ======= overwritten add Zones_B:
715
+ - name: Zones_B
716
+ title: Zones_B
717
+ sources: [cache-Zones_B]
718
+ - name: osm
719
+ # ======= overwritten sources:
720
+ sources: [overwritten_source]
721
+
722
+ caches:
723
+ cache-Zones_B:
724
+ sources: ['src_mymap:Zones_B']
725
+ grids: [webmercator]
726
+ cache:
727
+ type: file
728
+ directory_layout: mp
729
+
730
+ sources:
731
+ overwritten_source:
732
+ type: wms
733
+ req:
734
+ url: http://localhost/qgis/overwritten_source?
735
+ transparent: true
736
+ layers: osm
737
+
738
+ globals:
739
+ http:
740
+ client_timeout: 1
741
+ # ======= overwritten headers:
742
+ headers:
743
+ baz: quux
744
+
745
+ grids:
746
+ webmercator:
747
+ base: GLOBAL_WEBMERCATOR
748
+ srs: EPSG:3857
749
+ # ======= overwritten tile size:
750
+ tile_size: [1024, 1024]
751
+ """
752
+
753
+ yaml_parent = """
754
+ layers:
755
+ - name: Zones_A
756
+ title: Zones_A
757
+ sources: [cache-Zones_A]
758
+ - name: osm
759
+ # ======= overwritten title:
760
+ title: overwritten
761
+
762
+ sources:
763
+ src_mymap:
764
+ type: wms
765
+ req:
766
+ url: http://localhost/qgis/mymap?
767
+ transparent: true
768
+
769
+ caches:
770
+ cache-Zones_A:
771
+ sources: ['src_mymap:Zones_A']
772
+ grids: [webmercator]
773
+ cache:
774
+ type: file
775
+ directory_layout: mp
776
+
777
+ grids:
778
+ grid_alaska_4326:
779
+ # ======= overwritten bbox:
780
+ bbox: [-180, 60, -100, 70]
781
+
782
+ globals:
783
+ http:
784
+ client_timeout: 2
785
+ # ======= overwritten headers:
786
+ headers:
787
+ foo: bar
788
+ bar: qux
789
+ baz: qax
790
+ """
791
+
792
+ yaml_grand_parent = """
793
+ services:
794
+ demo:
795
+ tms:
796
+ use_grid_names: true
797
+ origin: 'nw'
798
+ kml:
799
+ use_grid_names: true
800
+ wmts:
801
+ wms:
802
+ image_formats: ['image/jpeg', 'image/png']
803
+ srs: [ 'EPSG:3857' ]
804
+ max_output_pixels: [2000, 2000]
805
+
806
+ layers:
807
+ - name: osm
808
+ title: Omniscale OSM WMS - osm.omniscale.net
809
+ sources: [osm_cache]
810
+
811
+ caches:
812
+ osm_cache:
813
+ grids: [webmercator]
814
+ sources: [osm_wms]
815
+
816
+ sources:
817
+ osm_wms:
818
+ type: wms
819
+ req:
820
+ url: https://maps.omniscale.net/v2/demo/style.default/service?
821
+ layers: osm
822
+
823
+ grids:
824
+ webmercator:
825
+ base: GLOBAL_WEBMERCATOR
826
+ srs: EPSG:3857
827
+ bbox_srs: EPSG:3857
828
+ tile_size: [512, 512]
829
+
830
+ grid_alaska_4326:
831
+ srs: EPSG:4326
832
+ origin: sw
833
+ bbox: [-167, 53, -141, 67]
834
+ bbox_srs: 'EPSG:4326'
835
+
836
+ globals:
837
+ http:
838
+ client_timeout: 3
839
+ method: GET
840
+ headers:
841
+ bar: baz
842
+ """
843
+
844
+ def test_loading(self):
845
+ with TempFile() as gp:
846
+ open(gp, 'wb').write(self.yaml_grand_parent.encode('utf-8'))
847
+ self.yaml_parent = """
848
+ base:
849
+ - %s
850
+ %s
851
+ """ % (gp, self.yaml_parent)
852
+
853
+ with TempFile() as p:
854
+ open(p, 'wb').write(self.yaml_parent.encode("utf-8"))
855
+
856
+ self.yaml_string = """
857
+ base: [%s]
858
+ %s
859
+ """ % (p, self.yaml_string)
860
+
861
+ with TempFile() as cfg:
862
+ open(cfg, 'wb').write(self.yaml_string.encode("utf-8"))
863
+
864
+ config = load_configuration(cfg)
865
+
866
+ http = config.globals.get_value('http')
867
+ assert http['client_timeout'] == 1
868
+ assert http['headers']['bar'] == 'qux'
869
+ assert http['headers']['foo'] == 'bar'
870
+ assert http['headers']['baz'] == 'quux'
871
+ assert http['method'] == 'GET'
872
+
873
+ grid_webmercator = config.grids['webmercator']
874
+ assert grid_webmercator is not None
875
+ assert grid_webmercator.tile_grid().tile_size == (1024, 1024)
876
+ assert grid_webmercator.conf['srs'] == 'EPSG:3857'
877
+ assert grid_webmercator.conf['bbox_srs'] == 'EPSG:3857'
878
+
879
+ grid_alaska = config.grids['grid_alaska_4326']
880
+ assert grid_alaska is not None
881
+ assert grid_alaska.conf['bbox'] == [-180.0, 60.0, -100.0, 70.0]
882
+ assert grid_alaska.conf['srs'] == 'EPSG:4326'
883
+ assert grid_alaska.conf['bbox_srs'] == 'EPSG:4326'
884
+ assert grid_alaska.conf['origin'] == 'sw'
885
+
886
+ wms = config.services.conf['wms']
887
+ assert wms is not None
888
+ assert wms['max_output_pixels'] == [4000, 4000]
889
+ assert wms['image_formats'] == ['image/jpeg', 'image/png']
890
+
891
+ layers = config.layers
892
+ assert layers['osm'].conf['title'] == 'overwritten'
893
+ assert layers['osm'].conf['sources'] == ['overwritten_source']
894
+ assert layers['Zones_A'].conf['sources'] == []
895
+ assert layers['layerA1'].conf['sources'] == ['osm_cache']
896
+ assert layers['layerA2'].conf['sources'] == ['osm_cache']
897
+ assert layers['Zones_B'].conf['sources'] == ['cache-Zones_B']
898
+
899
+ config_files = config.config_files()
900
+ assert set(config_files.keys()) == set([gp, p, cfg])
901
+ assert abs(config_files[gp] - time.time()) < 10
902
+ assert abs(config_files[p] - time.time()) < 10
903
+ assert abs(config_files[cfg] - time.time()) < 10
904
+
905
+
906
+ class TestConfMerger(object):
907
+ def test_empty_base(self):
908
+ a = {'a': 1, 'b': [12, 13]}
909
+ b = {}
910
+ m = merge_dict(a, b)
911
+ assert a == m
912
+
913
+ def test_empty_conf(self):
914
+ a = {}
915
+ b = {'a': 1, 'b': [12, 13]}
916
+ m = merge_dict(a, b)
917
+ assert b == m
918
+
919
+ def test_differ(self):
920
+ a = {'a': 12}
921
+ b = {'b': 42}
922
+ m = merge_dict(a, b)
923
+ assert {'a': 12, 'b': 42} == m
924
+
925
+ def test_recursive(self):
926
+ a = {'a': {'aa': 12, 'a': {'aaa': 100}}}
927
+ b = {'a': {'aa': 11, 'ab': 13, 'a': {'aaa': 101, 'aab': 101}}}
928
+ m = merge_dict(a, b)
929
+ assert {'a': {'aa': 12, 'ab': 13, 'a': {'aaa': 100, 'aab': 101}}} == m
930
+
931
+
932
+ class TestLoadConfiguration(object):
933
+ def test_with_warnings(object):
934
+ with TempFile() as f:
935
+ open(f, 'wb').write(b"""
936
+ services:
937
+ unknown:
938
+ """)
939
+ load_configuration(f) # defaults to ignore_warnings=True
940
+
941
+ with pytest.raises(ConfigurationError):
942
+ load_configuration(f, ignore_warnings=False)
943
+
944
+ def test_load_default_cache_coverage(object):
945
+ with TempFile() as f:
946
+ open(f, 'wb').write(b"""
947
+ services:
948
+ my_extra_service:
949
+ foo: bar
950
+
951
+ layers:
952
+ - name: temp
953
+ title: temp
954
+ sources: [temp]
955
+
956
+ caches:
957
+ temp:
958
+ grids: [grid]
959
+ sources: []
960
+ cache:
961
+ type: geopackage
962
+
963
+ grids:
964
+ grid:
965
+ srs: 'EPSG:4326'
966
+ bbox: [-180, -90, 180, 90]
967
+ """)
968
+ config = load_configuration(f) # defaults to ignore_warnings=True
969
+ cache = config.caches['temp']
970
+ assert cache.coverage() is None
971
+ assert cache.caches()[0][1] == MapExtent((-180, -90, 180, 90), SRS(4326))
972
+
973
+ def test_load_cache_coverage(object):
974
+ with TempFile() as f:
975
+ open(f, 'wb').write(b"""
976
+ services:
977
+ my_extra_service:
978
+ foo: bar
979
+
980
+ layers:
981
+ - name: temp
982
+ title: temp
983
+ sources: [temp]
984
+
985
+ parts:
986
+ coverages:
987
+ test_coverage: &test_coverage
988
+ bbox: [-50, -50, 50, 50]
989
+ srs: EPSG:4326
990
+
991
+ caches:
992
+ temp:
993
+ sources: []
994
+ cache:
995
+ type: geopackage
996
+ coverage: *test_coverage
997
+ """)
998
+ config = load_configuration(f) # defaults to ignore_warnings=True
999
+ assert config.caches['temp'].coverage() == coverage([-50, -50, 50, 50], SRS(4326))
1000
+
1001
+
1002
+ class TestImageOptions(object):
1003
+ def test_default_format(self):
1004
+ conf_dict = {
1005
+ }
1006
+ conf = ProxyConfiguration(conf_dict)
1007
+ image_opts = conf.globals.image_options.image_opts({}, 'image/png')
1008
+ assert image_opts.format == 'image/png'
1009
+ assert image_opts.mode is None
1010
+ assert image_opts.colors == 256
1011
+ assert image_opts.transparent is None
1012
+ assert image_opts.resampling == 'bicubic'
1013
+
1014
+ def test_default_format_paletted_false(self):
1015
+ conf_dict = {'globals': {'image': {'paletted': False}}}
1016
+ conf = ProxyConfiguration(conf_dict)
1017
+ image_opts = conf.globals.image_options.image_opts({}, 'image/png')
1018
+ assert image_opts.format == 'image/png'
1019
+ assert image_opts.mode is None
1020
+ assert image_opts.colors is None
1021
+ assert image_opts.transparent is None
1022
+ assert image_opts.resampling == 'bicubic'
1023
+
1024
+ def test_update_default_format(self):
1025
+ conf_dict = {'globals': {'image': {'formats': {
1026
+ 'image/png': {'colors': 16, 'resampling_method': 'nearest',
1027
+ 'encoding_options': {'quantizer': 'mediancut'}}
1028
+ }}}}
1029
+ conf = ProxyConfiguration(conf_dict)
1030
+ image_opts = conf.globals.image_options.image_opts({}, 'image/png')
1031
+ assert image_opts.format == 'image/png'
1032
+ assert image_opts.mode is None
1033
+ assert image_opts.colors == 16
1034
+ assert image_opts.transparent is None
1035
+ assert image_opts.resampling == 'nearest'
1036
+ assert image_opts.encoding_options['quantizer'] == 'mediancut'
1037
+
1038
+ def test_custom_format(self):
1039
+ conf_dict = {'globals': {'image': {'resampling_method': 'bilinear',
1040
+ 'formats': {
1041
+ 'image/foo': {'mode': 'RGBA', 'colors': 42}
1042
+ }
1043
+ }}}
1044
+ conf = ProxyConfiguration(conf_dict)
1045
+ image_opts = conf.globals.image_options.image_opts({}, 'image/foo')
1046
+ assert image_opts.format == 'image/foo'
1047
+ assert image_opts.mode == 'RGBA'
1048
+ assert image_opts.colors == 42
1049
+ assert image_opts.transparent is None
1050
+ assert image_opts.resampling == 'bilinear'
1051
+
1052
+ def test_format_grid(self):
1053
+ conf_dict = {
1054
+ 'globals': {
1055
+ 'image': {
1056
+ 'resampling_method': 'bilinear',
1057
+ }
1058
+ },
1059
+ 'caches': {
1060
+ 'test': {
1061
+ 'sources': [],
1062
+ 'grids': ['GLOBAL_MERCATOR'],
1063
+ 'format': 'image/png',
1064
+ }
1065
+ }
1066
+ }
1067
+ conf = ProxyConfiguration(conf_dict)
1068
+ image_opts = conf.caches['test'].image_opts()
1069
+ assert image_opts.format == 'image/png'
1070
+ assert image_opts.mode is None
1071
+ assert image_opts.colors == 256
1072
+ assert image_opts.transparent is None
1073
+ assert image_opts.resampling == 'bilinear'
1074
+
1075
+ def test_custom_format_grid(self):
1076
+ conf_dict = {
1077
+ 'globals': {
1078
+ 'image': {
1079
+ 'resampling_method': 'bilinear',
1080
+ 'formats': {
1081
+ 'png8': {'mode': 'P', 'colors': 256},
1082
+ 'image/png': {'mode': 'RGBA', 'transparent': True}
1083
+ },
1084
+ }
1085
+ },
1086
+ 'caches': {
1087
+ 'test': {
1088
+ 'sources': [],
1089
+ 'grids': ['GLOBAL_MERCATOR'],
1090
+ 'format': 'png8',
1091
+ 'image': {
1092
+ 'colors': 16,
1093
+ }
1094
+ },
1095
+ 'test2': {
1096
+ 'sources': [],
1097
+ 'grids': ['GLOBAL_MERCATOR'],
1098
+ 'format': 'image/png',
1099
+ 'image': {
1100
+ 'colors': 8,
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ conf = ProxyConfiguration(conf_dict)
1106
+ image_opts = conf.caches['test'].image_opts()
1107
+ assert image_opts.format == 'image/png'
1108
+ assert image_opts.mode == 'P'
1109
+ assert image_opts.colors == 16
1110
+ assert image_opts.transparent is None
1111
+ assert image_opts.resampling == 'bilinear'
1112
+
1113
+ image_opts = conf.caches['test2'].image_opts()
1114
+ assert image_opts.format == 'image/png'
1115
+ assert image_opts.mode == 'RGBA'
1116
+ assert image_opts.colors == 8
1117
+ assert image_opts.transparent is True
1118
+ assert image_opts.resampling == 'bilinear'
1119
+
1120
+ def test_custom_format_source(self):
1121
+ conf_dict = {
1122
+ 'globals': {
1123
+ 'image': {
1124
+ 'resampling_method': 'bilinear',
1125
+ 'formats': {
1126
+ 'png8': {'mode': 'P', 'colors': 256, 'format': 'image/png'},
1127
+ 'image/png': {'mode': 'RGBA', 'transparent': True}
1128
+ },
1129
+ }
1130
+ },
1131
+ 'caches': {
1132
+ 'test': {
1133
+ 'sources': ['test_source'],
1134
+ 'grids': ['GLOBAL_MERCATOR'],
1135
+ 'format': 'png8',
1136
+ 'image': {
1137
+ 'colors': 16,
1138
+ }
1139
+ },
1140
+ },
1141
+ 'sources': {
1142
+ 'test_source': {
1143
+ 'type': 'wms',
1144
+ 'req': {
1145
+ 'url': 'http://example.org/',
1146
+ 'layers': 'foo',
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ conf = ProxyConfiguration(conf_dict)
1152
+ _grid, _extent, tile_mgr = conf.caches['test'].caches()[0]
1153
+ image_opts = tile_mgr.image_opts
1154
+ assert image_opts.format == 'image/png'
1155
+ assert image_opts.mode == 'P'
1156
+ assert image_opts.colors == 16
1157
+ assert image_opts.transparent is None
1158
+ assert image_opts.resampling == 'bilinear'
1159
+
1160
+ image_opts = tile_mgr.sources[0].image_opts
1161
+ assert image_opts.format == 'image/png'
1162
+ assert image_opts.mode == 'P'
1163
+ assert image_opts.colors == 256
1164
+ assert image_opts.transparent is None
1165
+ assert image_opts.resampling == 'bilinear'
1166
+
1167
+ conf_dict['caches']['test']['request_format'] = 'image/tiff'
1168
+ conf = ProxyConfiguration(conf_dict)
1169
+ _grid, _extent, tile_mgr = conf.caches['test'].caches()[0]
1170
+ image_opts = tile_mgr.image_opts
1171
+ assert image_opts.format == 'image/png'
1172
+ assert image_opts.mode == 'P'
1173
+ assert image_opts.colors == 16
1174
+ assert image_opts.transparent is None
1175
+ assert image_opts.resampling == 'bilinear'
1176
+
1177
+ image_opts = tile_mgr.sources[0].image_opts
1178
+ assert image_opts.format == 'image/tiff'
1179
+ assert image_opts.mode is None
1180
+ assert image_opts.colors is None
1181
+ assert image_opts.transparent is None
1182
+ assert image_opts.resampling == 'bilinear'
1183
+
1184
+ def test_encoding_options_errors(self):
1185
+ conf_dict = {
1186
+ 'globals': {
1187
+ 'image': {
1188
+ 'formats': {
1189
+ 'image/jpeg': {
1190
+ 'encoding_options': {
1191
+ 'foo': 'baz',
1192
+ }
1193
+ }
1194
+ },
1195
+ }
1196
+ },
1197
+ }
1198
+
1199
+ try:
1200
+ conf = ProxyConfiguration(conf_dict)
1201
+ except ConfigurationError:
1202
+ pass
1203
+ else:
1204
+ raise Exception('expected ConfigurationError')
1205
+
1206
+ conf_dict['globals']['image']['formats']['image/jpeg']['encoding_options'] = {
1207
+ 'quantizer': 'foo'
1208
+ }
1209
+ try:
1210
+ conf = ProxyConfiguration(conf_dict)
1211
+ except ConfigurationError:
1212
+ pass
1213
+ else:
1214
+ raise Exception('expected ConfigurationError')
1215
+
1216
+ conf_dict['globals']['image']['formats']['image/jpeg']['encoding_options'] = {}
1217
+ conf = ProxyConfiguration(conf_dict)
1218
+ try:
1219
+ conf.globals.image_options.image_opts({'encoding_options': {'quantizer': 'foo'}}, 'image/jpeg')
1220
+ except ConfigurationError:
1221
+ pass
1222
+ else:
1223
+ raise Exception('expected ConfigurationError')
1224
+
1225
+ conf_dict['globals']['image']['formats']['image/jpeg']['encoding_options'] = {
1226
+ 'quantizer': 'fastoctree'
1227
+ }
1228
+ conf = ProxyConfiguration(conf_dict)
1229
+
1230
+ conf.globals.image_options.image_opts({}, 'image/jpeg')
1231
+
1232
+
1233
+ class TestCoverageValidation(object):
1234
+ def test_union(self):
1235
+ conf = {
1236
+ 'coverages': {
1237
+ 'covname': {
1238
+ 'union': [
1239
+ {'bbox': [0, 0, 10, 10], 'srs': 'EPSG:4326'},
1240
+ {'bbox': [10, 0, 20, 10], 'srs': 'EPSG:4326', 'unknown': True},
1241
+ ],
1242
+ },
1243
+ },
1244
+ }
1245
+
1246
+ errors, informal_only = validate_seed_conf(conf)
1247
+ assert informal_only
1248
+ assert len(errors) == 1
1249
+ assert errors[0] == "unknown 'unknown' in coverages.covname.union[1]"
1250
+
1251
+
1252
+ class TestLoadCoverage(object):
1253
+ def test_load_empty_geojson(self):
1254
+ with TempFile() as tf:
1255
+ with open(tf, 'wb') as f:
1256
+ f.write(b'{"type": "FeatureCollection", "features": []}')
1257
+ conf = {'datasource': tf, 'srs': 'EPSG:4326'}
1258
+ with pytest.raises(EmptyGeometryError):
1259
+ load_coverage(conf)
1260
+
1261
+ def test_load_empty_geojson_ogr(self):
1262
+ with TempFile() as tf:
1263
+ with open(tf, 'wb') as f:
1264
+ f.write(b'{"type": "FeatureCollection", "features": []}')
1265
+ conf = {'datasource': tf, 'where': '0 != 1', 'srs': 'EPSG:4326'}
1266
+ with pytest.raises(EmptyGeometryError):
1267
+ load_coverage(conf)