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,793 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Service requests (parsing, handling, etc).
18
+ """
19
+ import codecs
20
+ import re
21
+ from mapproxy.request.wms import exception
22
+ from mapproxy.exception import RequestError
23
+ from mapproxy.srs import SRS, make_lin_transf
24
+ from mapproxy.request.base import RequestParams, BaseRequest, split_mime_type
25
+ from mapproxy.compat import string_type, iteritems
26
+
27
+ import logging
28
+ log = logging.getLogger(__name__)
29
+
30
+ class WMSMapRequestParams(RequestParams):
31
+ """
32
+ This class represents key-value parameters for WMS map requests.
33
+
34
+ All values can be accessed as a property.
35
+ Some properties return processed values. ``size`` returns a tuple of the width
36
+ and height, ``layers`` returns an iterator of all layers, etc.
37
+
38
+ """
39
+ def _get_layers(self):
40
+ """
41
+ List with all layer names.
42
+ """
43
+ return sum((layers.split(',') for layers in self.params.get_all('layers')), [])
44
+ def _set_layers(self, layers):
45
+ if isinstance(layers, (list, tuple)):
46
+ layers = ','.join(layers)
47
+ self.params['layers'] = layers
48
+ layers = property(_get_layers, _set_layers)
49
+ del _get_layers
50
+ del _set_layers
51
+
52
+ def _get_bbox(self):
53
+ """
54
+ ``bbox`` as a tuple (minx, miny, maxx, maxy).
55
+ """
56
+ if 'bbox' not in self.params or self.params['bbox'] is None:
57
+ return None
58
+ points = map(float, self.params['bbox'].split(','))
59
+ return tuple(points)
60
+
61
+ def _set_bbox(self, value):
62
+ if value is not None and not isinstance(value, string_type):
63
+ value = ','.join(str(x) for x in value)
64
+ self['bbox'] = value
65
+ bbox = property(_get_bbox, _set_bbox)
66
+ del _get_bbox
67
+ del _set_bbox
68
+
69
+ def _get_size(self):
70
+ """
71
+ Size of the request in pixel as a tuple (width, height),
72
+ or None if one is missing.
73
+ """
74
+ if 'height' not in self or 'width' not in self:
75
+ return None
76
+ width = int(float(self.params['width'])) # allow float sizes (100.0), but truncate decimals
77
+ height = int(float(self.params['height']))
78
+ return (width, height)
79
+ def _set_size(self, value):
80
+ self['width'] = str(value[0])
81
+ self['height'] = str(value[1])
82
+ size = property(_get_size, _set_size)
83
+ del _get_size
84
+ del _set_size
85
+
86
+ def _get_srs(self):
87
+ return self.params.get('srs', None)
88
+ def _set_srs(self, srs):
89
+ if hasattr(srs, 'srs_code'):
90
+ self.params['srs'] = srs.srs_code
91
+ else:
92
+ self.params['srs'] = srs
93
+
94
+ srs = property(_get_srs, _set_srs)
95
+ del _get_srs
96
+ del _set_srs
97
+
98
+ def _get_transparent(self):
99
+ """
100
+ ``True`` if transparent is set to true, otherwise ``False``.
101
+ """
102
+ if self.get('transparent', 'false').lower() == 'true':
103
+ return True
104
+ return False
105
+ def _set_transparent(self, transparent):
106
+ self.params['transparent'] = str(transparent).lower()
107
+ transparent = property(_get_transparent, _set_transparent)
108
+ del _get_transparent
109
+ del _set_transparent
110
+
111
+ @property
112
+ def bgcolor(self):
113
+ """
114
+ The background color in PIL format (#rrggbb). Defaults to '#ffffff'.
115
+ """
116
+ color = self.get('bgcolor', '0xffffff')
117
+ return '#'+color[2:]
118
+
119
+ def _get_format(self):
120
+ """
121
+ The requested format as string (w/o any 'image/', 'text/', etc prefixes)
122
+ """
123
+ _mime_class, format, options = split_mime_type(self.get('format', default=''))
124
+ return format
125
+
126
+ def _set_format(self, format):
127
+ if '/' not in format:
128
+ format = 'image/' + format
129
+ self['format'] = format
130
+
131
+ format = property(_get_format, _set_format)
132
+ del _get_format
133
+ del _set_format
134
+
135
+ @property
136
+ def format_mime_type(self):
137
+ return self.get('format')
138
+
139
+ def __repr__(self):
140
+ return '%s(param=%r)' % (self.__class__.__name__, self.params)
141
+
142
+
143
+ class WMSRequest(BaseRequest):
144
+ request_params = RequestParams
145
+ request_handler_name = None
146
+ fixed_params = {}
147
+ expected_param = []
148
+ non_strict_params = set()
149
+ #pylint: disable-msg=E1102
150
+ xml_exception_handler = None
151
+
152
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
153
+ self.non_strict = non_strict
154
+ BaseRequest.__init__(self, param=param, url=url, validate=validate, **kw)
155
+ self.adapt_to_111()
156
+
157
+ def adapt_to_111(self):
158
+ pass
159
+
160
+ def adapt_params_to_version(self):
161
+ params = self.params.copy()
162
+ for key, value in iteritems(self.fixed_params):
163
+ params[key] = value
164
+ if 'styles' not in params:
165
+ params['styles'] = ''
166
+ return params
167
+
168
+ @property
169
+ def query_string(self):
170
+ return self.adapt_params_to_version().query_string
171
+
172
+ class WMSMapRequest(WMSRequest):
173
+ """
174
+ Base class for all WMS GetMap requests.
175
+
176
+ :ivar requests: the ``RequestParams`` class for this request
177
+ :ivar request_handler_name: the name of the server handler
178
+ :ivar fixed_params: parameters that are fixed for a request
179
+ :ivar expected_param: required parameters, used for validating
180
+ """
181
+ request_params = WMSMapRequestParams
182
+ request_handler_name = 'map'
183
+ fixed_params = {'request': 'GetMap', 'service': 'WMS'}
184
+ expected_param = ['version', 'request', 'layers', 'styles', 'srs', 'bbox',
185
+ 'width', 'height', 'format']
186
+ #pylint: disable-msg=E1102
187
+ xml_exception_handler = None
188
+ prevent_image_exception = False
189
+ dimension_params = ['time', 'elevation']
190
+ dimension_prefix = 'dim_'
191
+
192
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
193
+ self.dimensions = self._get_dimensions(param)
194
+ WMSRequest.__init__(self, param=param, url=url, validate=validate,
195
+ non_strict=non_strict, **kw)
196
+
197
+ def _get_dimensions(self, param):
198
+ if param:
199
+ regex = "(?i)%s%s" % (("^%s|" % self.dimension_prefix if self.dimension_prefix else ""),
200
+ "^(%s)$" % "|".join(self.dimension_params))
201
+ keys = []
202
+ if isinstance(param, RequestParams):
203
+ keys = list(map (lambda k: k[0], param.iteritems()))
204
+ else:
205
+ keys = list(param.keys())
206
+ if len(keys) > 0:
207
+ return dict(map(lambda k: (k, param.get(k)), filter (lambda k: re.search(regex, k), keys)))
208
+ else:
209
+ return None
210
+ else:
211
+ return None
212
+
213
+ def validate(self):
214
+ self.validate_param()
215
+ self.validate_bbox()
216
+ self.validate_styles()
217
+
218
+ def validate_param(self):
219
+ missing_param = []
220
+ for param in self.expected_param:
221
+ if self.non_strict and param in self.non_strict_params:
222
+ continue
223
+ if param not in self.params:
224
+ missing_param.append(param)
225
+
226
+ if missing_param:
227
+ if 'format' in missing_param:
228
+ self.params['format'] = 'image/png'
229
+ raise RequestError('missing parameters ' + str(missing_param),
230
+ request=self)
231
+
232
+ def validate_bbox(self):
233
+ x0, y0, x1, y1 = self.params.bbox
234
+ if x0 >= x1 or y0 >= y1:
235
+ raise RequestError('invalid bbox ' + self.params.get('bbox', None),
236
+ request=self)
237
+
238
+ def validate_format(self, image_formats):
239
+ format = self.params['format']
240
+ if format not in image_formats:
241
+ format = self.params['format']
242
+ self.params['format'] = 'image/png'
243
+ raise RequestError('unsupported image format: ' + format,
244
+ code='InvalidFormat', request=self)
245
+ def validate_srs(self, srs):
246
+ if self.params['srs'].upper() not in srs:
247
+ raise RequestError('unsupported srs: ' + self.params['srs'],
248
+ code='InvalidSRS', request=self)
249
+ def validate_styles(self):
250
+ if 'styles' in self.params:
251
+ styles = self.params['styles']
252
+ if not set(styles.split(',')).issubset(set(['default', '', 'inspire_common:DEFAULT'])):
253
+ raise RequestError('unsupported styles: ' + self.params['styles'],
254
+ code='StyleNotDefined', request=self)
255
+
256
+
257
+ @property
258
+ def exception_handler(self):
259
+ if self.prevent_image_exception:
260
+ return self.xml_exception_handler()
261
+ if 'exceptions' in self.params:
262
+ if 'image' in self.params['exceptions'].lower():
263
+ return exception.WMSImageExceptionHandler()
264
+ elif 'blank' in self.params['exceptions'].lower():
265
+ return exception.WMSBlankExceptionHandler()
266
+ return self.xml_exception_handler()
267
+
268
+ def copy(self):
269
+ return self.__class__(param=self.params.copy(), url=self.url)
270
+
271
+
272
+ class Version(object):
273
+ _versions = {}
274
+ def __new__(cls, version):
275
+ if version in cls._versions:
276
+ return cls._versions[version]
277
+ version_obj = object.__new__(cls)
278
+ version_obj.__init__(version)
279
+ cls._versions[version] = version_obj
280
+ return version_obj
281
+ def __init__(self, version):
282
+ self.parts = tuple(int(x) for x in version.split('.'))
283
+
284
+ def __lt__(self, other):
285
+ if not isinstance(other, Version):
286
+ return NotImplemented
287
+ return self.parts < other.parts
288
+
289
+ def __ge__(self, other):
290
+ if not isinstance(other, Version):
291
+ return NotImplemented
292
+ return self.parts >= other.parts
293
+
294
+ def __repr__(self):
295
+ return "Version('%s')" % ('.'.join(str(part) for part in self.parts),)
296
+
297
+ class WMS100MapRequest(WMSMapRequest):
298
+ version = Version('1.0.0')
299
+ xml_exception_handler = exception.WMS100ExceptionHandler
300
+ fixed_params = {'request': 'map', 'wmtver': '1.0.0'}
301
+ expected_param = ['wmtver', 'request', 'layers', 'styles', 'srs', 'bbox',
302
+ 'width', 'height', 'format']
303
+ dimension_params = []
304
+ dimension_prefix = ''
305
+ def adapt_to_111(self):
306
+ del self.params['wmtver']
307
+ self.params['version'] = '1.0.0'
308
+ self.params['request'] = 'GetMap'
309
+
310
+ def adapt_params_to_version(self):
311
+ params = WMSMapRequest.adapt_params_to_version(self)
312
+ del params['version']
313
+ del params['service']
314
+
315
+ image_format = params['format']
316
+ if '/' in image_format:
317
+ params['format'] = image_format.split('/', 1)[1].upper()
318
+ return params
319
+
320
+ def validate_format(self, image_formats):
321
+ format = self.params['format']
322
+ image_formats100 = [f.split('/', 1)[1].upper() for f in image_formats]
323
+
324
+ if format in image_formats100:
325
+ format = 'image/' + format.lower()
326
+ self.params['format'] = format
327
+
328
+ if format not in image_formats:
329
+ format = self.params['format']
330
+ self.params['format'] = 'image/png'
331
+ raise RequestError('unsupported image format: ' + format,
332
+ code='InvalidFormat', request=self)
333
+
334
+ class WMS110MapRequest(WMSMapRequest):
335
+ version = Version('1.1.0')
336
+ fixed_params = {'request': 'GetMap', 'version': '1.1.0', 'service': 'WMS'}
337
+ xml_exception_handler = exception.WMS110ExceptionHandler
338
+
339
+ def adapt_to_111(self):
340
+ del self.params['wmtver']
341
+
342
+ class WMS111MapRequest(WMSMapRequest):
343
+ version = Version('1.1.1')
344
+ fixed_params = {'request': 'GetMap', 'version': '1.1.1', 'service': 'WMS'}
345
+ xml_exception_handler = exception.WMS111ExceptionHandler
346
+
347
+ def adapt_to_111(self):
348
+ del self.params['wmtver']
349
+
350
+ def switch_bbox_epsg_axis_order(bbox, srs):
351
+ if bbox is not None and srs is not None:
352
+ try:
353
+ if SRS(srs).is_axis_order_ne:
354
+ return bbox[1], bbox[0], bbox[3], bbox[2]
355
+ except RuntimeError:
356
+ log.warning('unknown SRS %s' % srs)
357
+ return bbox
358
+
359
+ def _switch_bbox(self):
360
+ self.bbox = switch_bbox_epsg_axis_order(self.bbox, self.srs)
361
+
362
+ class WMS130MapRequestParams(WMSMapRequestParams):
363
+ """
364
+ RequestParams for WMS 1.3.0 GetMap requests. Handles bbox axis-order.
365
+ """
366
+ switch_bbox = _switch_bbox
367
+
368
+
369
+ class WMS130MapRequest(WMSMapRequest):
370
+ version = Version('1.3.0')
371
+ request_params = WMS130MapRequestParams
372
+ xml_exception_handler = exception.WMS130ExceptionHandler
373
+ fixed_params = {'request': 'GetMap', 'version': '1.3.0', 'service': 'WMS'}
374
+ expected_param = ['version', 'request', 'layers', 'styles', 'crs', 'bbox',
375
+ 'width', 'height', 'format']
376
+ def adapt_to_111(self):
377
+ del self.params['wmtver']
378
+ if 'crs' in self.params:
379
+ self.params['srs'] = self.params['crs']
380
+ del self.params['crs']
381
+ self.params.switch_bbox()
382
+
383
+ def adapt_params_to_version(self):
384
+ params = WMSMapRequest.adapt_params_to_version(self)
385
+ params.switch_bbox()
386
+ if 'srs' in params:
387
+ params['crs'] = params['srs']
388
+ del params['srs']
389
+ return params
390
+
391
+ def validate_srs(self, srs):
392
+ # its called crs in 1.3.0 and we validate before adapt_to_111
393
+ if self.params['srs'].upper() not in srs:
394
+ raise RequestError('unsupported crs: ' + self.params['srs'],
395
+ code='InvalidCRS', request=self)
396
+
397
+ def copy_with_request_params(self, req):
398
+ new_req = WMSMapRequest.copy_with_request_params(self, req)
399
+ new_req.params.switch_bbox()
400
+ return new_req
401
+
402
+ class WMSLegendGraphicRequestParams(WMSMapRequestParams):
403
+ """
404
+ RequestParams for WMS GetLegendGraphic requests.
405
+ """
406
+ def _set_layer(self, value):
407
+ self.params['layer'] = value
408
+
409
+ def _get_layer(self):
410
+ """
411
+ Layer for which to produce legend graphic.
412
+ """
413
+ return self.params.get('layer')
414
+ layer = property(_get_layer, _set_layer)
415
+ del _set_layer
416
+ del _get_layer
417
+
418
+ @property
419
+ def sld_version(self):
420
+ """
421
+ Specification version for SLD-specification
422
+ """
423
+ return self.params.get('sld_version')
424
+
425
+
426
+ def _set_scale(self, value):
427
+ self.params['scale'] = value
428
+
429
+ def _get_scale(self):
430
+ if self.params.get('scale') is not None:
431
+ return float(self['scale'])
432
+ return None
433
+
434
+ scale = property(_get_scale,_set_scale)
435
+ del _set_scale
436
+ del _get_scale
437
+
438
+ class WMSFeatureInfoRequestParams(WMSMapRequestParams):
439
+ """
440
+ RequestParams for WMS GetFeatureInfo requests.
441
+ """
442
+ @property
443
+ def query_layers(self):
444
+ """
445
+ List with all query_layers.
446
+ """
447
+ return sum((layers.split(',') for layers in self.params.get_all('query_layers')), [])
448
+
449
+ def _get_pos(self):
450
+ """x, y query image coordinates (in pixel)"""
451
+ if '.' in self['x'] or '.' in self['y']:
452
+ return float(self['x']), float(self['y'])
453
+ return int(self['x']), int(self['y'])
454
+
455
+ def _set_pos(self, value):
456
+ self['x'] = str(value[0])
457
+ self['y'] = str(value[1])
458
+ pos = property(_get_pos, _set_pos)
459
+ del _get_pos
460
+ del _set_pos
461
+
462
+ @property
463
+ def pos_coords(self):
464
+ """x, y query coordinates (in request SRS)"""
465
+ width, height = self.size
466
+ bbox = self.bbox
467
+ return make_lin_transf((0, 0, width, height), bbox)(self.pos)
468
+
469
+ class WMS130FeatureInfoRequestParams(WMSFeatureInfoRequestParams):
470
+ switch_bbox = _switch_bbox
471
+
472
+ class WMSLegendGraphicRequest(WMSMapRequest):
473
+ request_params = WMSLegendGraphicRequestParams
474
+ request_handler_name = 'legendgraphic'
475
+ non_strict_params = set(['sld_version', 'scale'])
476
+ fixed_params = {'request': 'GetLegendGraphic', 'service': 'WMS', 'sld_version': '1.1.0'}
477
+ expected_param = ['version', 'request', 'layer', 'format', 'sld_version']
478
+
479
+ def validate(self):
480
+ self.validate_param()
481
+ self.validate_sld_version()
482
+
483
+ def validate_sld_version(self):
484
+ if self.params.get('sld_version', '1.1.0') != '1.1.0':
485
+ raise RequestError('invalid sld_version ' + self.params.get('sld_version'),
486
+ request=self)
487
+
488
+
489
+ class WMS111LegendGraphicRequest(WMSLegendGraphicRequest):
490
+ version = Version('1.1.1')
491
+ fixed_params = WMSLegendGraphicRequest.fixed_params.copy()
492
+ fixed_params['version'] = '1.1.1'
493
+ xml_exception_handler = exception.WMS111ExceptionHandler
494
+
495
+ class WMS130LegendGraphicRequest(WMSLegendGraphicRequest):
496
+ version = Version('1.3.0')
497
+ fixed_params = WMSLegendGraphicRequest.fixed_params.copy()
498
+ fixed_params['version'] = '1.3.0'
499
+ xml_exception_handler = exception.WMS130ExceptionHandler
500
+
501
+ class WMSFeatureInfoRequest(WMSMapRequest):
502
+ non_strict_params = set(['format', 'styles'])
503
+
504
+ def validate_format(self, image_formats):
505
+ if self.non_strict: return
506
+ WMSMapRequest.validate_format(self, image_formats)
507
+
508
+ class WMS111FeatureInfoRequest(WMSFeatureInfoRequest):
509
+ version = Version('1.1.1')
510
+ request_params = WMSFeatureInfoRequestParams
511
+ xml_exception_handler = exception.WMS111ExceptionHandler
512
+ request_handler_name = 'featureinfo'
513
+ fixed_params = WMS111MapRequest.fixed_params.copy()
514
+ fixed_params['request'] = 'GetFeatureInfo'
515
+ expected_param = WMSMapRequest.expected_param[:] + ['query_layers', 'x', 'y']
516
+
517
+ class WMS110FeatureInfoRequest(WMSFeatureInfoRequest):
518
+ version = Version('1.1.0')
519
+ request_params = WMSFeatureInfoRequestParams
520
+ xml_exception_handler = exception.WMS110ExceptionHandler
521
+ request_handler_name = 'featureinfo'
522
+ fixed_params = WMS110MapRequest.fixed_params.copy()
523
+ fixed_params['request'] = 'GetFeatureInfo'
524
+ expected_param = WMSMapRequest.expected_param[:] + ['query_layers', 'x', 'y']
525
+
526
+ class WMS100FeatureInfoRequest(WMSFeatureInfoRequest):
527
+ version = Version('1.0.0')
528
+ request_params = WMSFeatureInfoRequestParams
529
+ xml_exception_handler = exception.WMS100ExceptionHandler
530
+ request_handler_name = 'featureinfo'
531
+ fixed_params = WMS100MapRequest.fixed_params.copy()
532
+ fixed_params['request'] = 'feature_info'
533
+ expected_param = WMS100MapRequest.expected_param[:] + ['query_layers', 'x', 'y']
534
+
535
+ def adapt_to_111(self):
536
+ del self.params['wmtver']
537
+
538
+ def adapt_params_to_version(self):
539
+ params = WMSMapRequest.adapt_params_to_version(self)
540
+ del params['version']
541
+ return params
542
+
543
+ class WMS130FeatureInfoRequest(WMS130MapRequest):
544
+ # XXX: this class inherits from WMS130MapRequest to reuse
545
+ # the axis order stuff
546
+ version = Version('1.3.0')
547
+ request_params = WMS130FeatureInfoRequestParams
548
+ xml_exception_handler = exception.WMS130ExceptionHandler
549
+ request_handler_name = 'featureinfo'
550
+ fixed_params = WMS130MapRequest.fixed_params.copy()
551
+ fixed_params['request'] = 'GetFeatureInfo'
552
+ expected_param = WMS130MapRequest.expected_param[:] + ['query_layers', 'i', 'j']
553
+ non_strict_params = set(['format', 'styles'])
554
+
555
+ def adapt_to_111(self):
556
+ WMS130MapRequest.adapt_to_111(self)
557
+ # only set x,y when present,
558
+ # avoids empty values for request templates
559
+ if 'i' in self.params:
560
+ self.params['x'] = self.params['i']
561
+ if 'j' in self.params:
562
+ self.params['y'] = self.params['j']
563
+ del self.params['i']
564
+ del self.params['j']
565
+
566
+ def adapt_params_to_version(self):
567
+ params = WMS130MapRequest.adapt_params_to_version(self)
568
+ params['i'] = self.params['x']
569
+ params['j'] = self.params['y']
570
+ del params['x']
571
+ del params['y']
572
+ return params
573
+
574
+ def validate_format(self, image_formats):
575
+ if self.non_strict: return
576
+ WMSMapRequest.validate_format(self, image_formats)
577
+
578
+ class WMSCapabilitiesRequest(WMSRequest):
579
+ request_handler_name = 'capabilities'
580
+ exception_handler = None
581
+ mime_type = 'text/xml'
582
+ fixed_params = {}
583
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
584
+ WMSRequest.__init__(self, param=param, url=url, validate=validate, **kw)
585
+
586
+ def adapt_to_111(self):
587
+ pass
588
+
589
+ def validate(self):
590
+ pass
591
+
592
+
593
+ class WMS100CapabilitiesRequest(WMSCapabilitiesRequest):
594
+ version = Version('1.0.0')
595
+ capabilities_template = 'wms100capabilities.xml'
596
+ fixed_params = {'request': 'capabilities', 'wmtver': '1.0.0'}
597
+
598
+ @property
599
+ def exception_handler(self):
600
+ return exception.WMS100ExceptionHandler()
601
+
602
+
603
+ class WMS110CapabilitiesRequest(WMSCapabilitiesRequest):
604
+ version = Version('1.1.0')
605
+ capabilities_template = 'wms110capabilities.xml'
606
+ mime_type = 'application/vnd.ogc.wms_xml'
607
+ fixed_params = {'request': 'GetCapabilities', 'version': '1.1.0', 'service': 'WMS'}
608
+
609
+ @property
610
+ def exception_handler(self):
611
+ return exception.WMS110ExceptionHandler()
612
+
613
+ class WMS111CapabilitiesRequest(WMSCapabilitiesRequest):
614
+ version = Version('1.1.1')
615
+ capabilities_template = 'wms111capabilities.xml'
616
+ mime_type = 'application/vnd.ogc.wms_xml'
617
+ fixed_params = {'request': 'GetCapabilities', 'version': '1.1.1', 'service': 'WMS'}
618
+
619
+ @property
620
+ def exception_handler(self):
621
+ return exception.WMS111ExceptionHandler()
622
+
623
+
624
+ class WMS130CapabilitiesRequest(WMSCapabilitiesRequest):
625
+ version = Version('1.3.0')
626
+ capabilities_template = 'wms130capabilities.xml'
627
+ fixed_params = {'request': 'GetCapabilities', 'version': '1.3.0', 'service': 'WMS'}
628
+
629
+ @property
630
+ def exception_handler(self):
631
+ return exception.WMS130ExceptionHandler()
632
+
633
+ request_mapping = {Version('1.0.0'): {'featureinfo': WMS100FeatureInfoRequest,
634
+ 'map': WMS100MapRequest,
635
+ 'capabilities': WMS100CapabilitiesRequest},
636
+ Version('1.1.0'): {'featureinfo': WMS110FeatureInfoRequest,
637
+ 'map': WMS110MapRequest,
638
+ 'capabilities': WMS110CapabilitiesRequest},
639
+ Version('1.1.1'): {'featureinfo': WMS111FeatureInfoRequest,
640
+ 'map': WMS111MapRequest,
641
+ 'capabilities': WMS111CapabilitiesRequest,
642
+ 'legendgraphic': WMS111LegendGraphicRequest},
643
+ Version('1.3.0'): {'featureinfo': WMS130FeatureInfoRequest,
644
+ 'map': WMS130MapRequest,
645
+ 'capabilities': WMS130CapabilitiesRequest,
646
+ 'legendgraphic': WMS130LegendGraphicRequest},
647
+ }
648
+
649
+
650
+
651
+ def _parse_version(req):
652
+ if 'version' in req.args:
653
+ return Version(req.args['version'])
654
+ if 'wmtver' in req.args:
655
+ return Version(req.args['wmtver'])
656
+
657
+ return None
658
+
659
+ def _parse_request_type(req):
660
+ if 'request' in req.args:
661
+ request_type = req.args['request'].lower()
662
+ if request_type in ('getmap', 'map'):
663
+ return 'map'
664
+ elif request_type in ('getfeatureinfo', 'feature_info'):
665
+ return 'featureinfo'
666
+ elif request_type in ('getcapabilities', 'capabilities'):
667
+ return 'capabilities'
668
+ elif request_type in ('getlegendgraphic',):
669
+ return 'legendgraphic'
670
+ else:
671
+ return request_type
672
+ else:
673
+ return None
674
+
675
+ def negotiate_version(version, supported_versions=None):
676
+ """
677
+ >>> negotiate_version(Version('0.9.0'))
678
+ Version('1.0.0')
679
+ >>> negotiate_version(Version('2.0.0'))
680
+ Version('1.3.0')
681
+ >>> negotiate_version(Version('1.1.1'))
682
+ Version('1.1.1')
683
+ >>> negotiate_version(Version('1.1.0'))
684
+ Version('1.1.0')
685
+ >>> negotiate_version(Version('1.1.0'), [Version('1.0.0')])
686
+ Version('1.0.0')
687
+ >>> negotiate_version(Version('1.3.0'), sorted([Version('1.1.0'), Version('1.1.1')]))
688
+ Version('1.1.1')
689
+ """
690
+ if not supported_versions:
691
+ supported_versions = list(request_mapping.keys())
692
+ supported_versions.sort()
693
+
694
+ if version < supported_versions[0]:
695
+ return supported_versions[0] # smallest version we support
696
+
697
+ if version > supported_versions[-1]:
698
+ return supported_versions[-1] # highest version we support
699
+
700
+ while True:
701
+ next_highest_version = supported_versions.pop()
702
+ if version >= next_highest_version:
703
+ return next_highest_version
704
+
705
+ def wms_request(req, validate=True, strict=True, versions=None):
706
+ version = _parse_version(req)
707
+ req_type = _parse_request_type(req)
708
+
709
+ if versions is None:
710
+ versions = sorted([
711
+ Version(v) for v in ('1.0.0', '1.1.0', '1.1.1', '1.3.0')])
712
+
713
+ if version is None:
714
+ # If no version number is specified in the request,
715
+ # the server shall respond with the highest version.
716
+ version = max(versions)
717
+
718
+ if version not in versions:
719
+ version_requests = None
720
+ else:
721
+ version_requests = request_mapping.get(version, None)
722
+
723
+ if version_requests is None:
724
+ negotiated_version = negotiate_version(version, supported_versions=versions)
725
+ version_requests = request_mapping[negotiated_version]
726
+ req_class = version_requests.get(req_type, None)
727
+ if req_class is None:
728
+ # use map request to get an exception handler for the requested version
729
+ dummy_req = version_requests['map'](param=req.args, url=req.base_url,
730
+ validate=False)
731
+ raise RequestError("unknown WMS request type '%s'" % req_type, request=dummy_req)
732
+ return req_class(param=req.args, url=req.base_url, validate=True,
733
+ non_strict=not strict, http=req)
734
+
735
+
736
+ def create_request(req_data, param, req_type='map', version='1.1.1', abspath=None):
737
+ url = req_data['url']
738
+ req_data = req_data.copy()
739
+ del req_data['url']
740
+ if 'request_format' in param:
741
+ req_data['format'] = param['request_format']
742
+ elif 'format' in param:
743
+ req_data['format'] = param['format']
744
+
745
+ if 'info_format' in param:
746
+ req_data['info_format'] = param['info_format']
747
+
748
+ if 'transparent' in req_data:
749
+ # we don't want a boolean
750
+ req_data['transparent'] = str(req_data['transparent'])
751
+
752
+ if req_data.get('sld', '').startswith('file://'):
753
+ sld_path = req_data['sld'][len('file://'):]
754
+ if abspath:
755
+ sld_path = abspath(sld_path)
756
+ with codecs.open(sld_path, 'r', 'utf-8') as f:
757
+ req_data['sld_body'] = f.read()
758
+ del req_data['sld']
759
+
760
+ return request_mapping[Version(version)][req_type](url=url, param=req_data)
761
+
762
+
763
+ info_formats = {
764
+ Version('1.3.0'): (('text', 'text/plain'),
765
+ ('html', 'text/html'),
766
+ ('xml', 'text/xml'),
767
+ ('json', 'application/json'),
768
+ ),
769
+ None: (('text', 'text/plain'),
770
+ ('html', 'text/html'),
771
+ ('xml', 'application/vnd.ogc.gml'),
772
+ ('json', 'application/json'),
773
+ )
774
+ }
775
+
776
+
777
+ def infotype_from_mimetype(version, mime_type):
778
+ if version in info_formats:
779
+ formats = info_formats[version]
780
+ else:
781
+ formats = info_formats[None] # default
782
+ for t, m in formats:
783
+ if m == mime_type: return t
784
+
785
+ def mimetype_from_infotype(version, info_type):
786
+ if version in info_formats:
787
+ formats = info_formats[version]
788
+ else:
789
+ formats = info_formats[None] # default
790
+ for t, m in formats:
791
+ if t == info_type: return m
792
+ return 'text/plain'
793
+