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,107 @@
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 exception handling (WMS exceptions, XML, in_image, etc.).
18
+ """
19
+ from mapproxy.exception import ExceptionHandler, XMLExceptionHandler
20
+ from mapproxy.response import Response
21
+ from mapproxy.image.message import message_image
22
+ from mapproxy.image.opts import ImageOptions
23
+ import mapproxy.service
24
+ from mapproxy.template import template_loader
25
+ get_template = template_loader(mapproxy.service.__package__, 'templates')
26
+
27
+
28
+ class WMSXMLExceptionHandler(XMLExceptionHandler):
29
+ template_func = get_template
30
+
31
+
32
+ class WMS100ExceptionHandler(WMSXMLExceptionHandler):
33
+ """
34
+ Exception handler for OGC WMS 1.0.0 ServiceExceptionReports
35
+ """
36
+ template_file = 'wms100exception.xml'
37
+ content_type = 'text/xml'
38
+
39
+
40
+ class WMS110ExceptionHandler(WMSXMLExceptionHandler):
41
+ """
42
+ Exception handler for OGC WMS 1.1.0 ServiceExceptionReports
43
+ """
44
+ template_file = 'wms110exception.xml'
45
+ mimetype = 'application/vnd.ogc.se_xml'
46
+
47
+
48
+ class WMS111ExceptionHandler(WMSXMLExceptionHandler):
49
+ """
50
+ Exception handler for OGC WMS 1.1.1 ServiceExceptionReports
51
+ """
52
+ template_file = 'wms111exception.xml'
53
+ mimetype = 'application/vnd.ogc.se_xml'
54
+
55
+
56
+ class WMS130ExceptionHandler(WMSXMLExceptionHandler):
57
+ """
58
+ Exception handler for OGC WMS 1.3.0 ServiceExceptionReports
59
+ """
60
+ template_file = 'wms130exception.xml'
61
+ mimetype = 'text/xml'
62
+
63
+
64
+ class WMSImageExceptionHandler(ExceptionHandler):
65
+ """
66
+ Exception handler for image exceptions.
67
+ """
68
+
69
+ def render(self, request_error):
70
+ request = request_error.request
71
+ params = request.params
72
+ format = params.format
73
+ size = params.size
74
+ if size is None:
75
+ size = (256, 256)
76
+ transparent = ('transparent' in params
77
+ and params['transparent'].lower() == 'true')
78
+ bgcolor = WMSImageExceptionHandler._bgcolor(request.params)
79
+ image_opts = ImageOptions(format=format, bgcolor=bgcolor, transparent=transparent)
80
+ result = message_image(request_error.msg, size=size, image_opts=image_opts)
81
+ return Response(result.as_buffer(), content_type=params.format_mime_type)
82
+
83
+ @staticmethod
84
+ def _bgcolor(params):
85
+ """
86
+ >>> WMSImageExceptionHandler._bgcolor({'bgcolor': '0Xf0ea42'})
87
+ '#f0ea42'
88
+ >>> WMSImageExceptionHandler._bgcolor({})
89
+ '#ffffff'
90
+ """
91
+ if 'bgcolor' in params:
92
+ color = params['bgcolor']
93
+ if color.lower().startswith('0x'):
94
+ color = '#' + color[2:]
95
+ else:
96
+ color = '#ffffff'
97
+ return color
98
+
99
+
100
+ class WMSBlankExceptionHandler(WMSImageExceptionHandler):
101
+ """
102
+ Exception handler for blank image exceptions.
103
+ """
104
+
105
+ def render(self, request_error):
106
+ request_error.msg = ''
107
+ return WMSImageExceptionHandler.render(self, request_error)
@@ -0,0 +1,442 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2011 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ Service requests (parsing, handling, etc).
18
+ """
19
+ import re
20
+
21
+ from mapproxy.exception import RequestError
22
+ from mapproxy.request.base import RequestParams, BaseRequest, split_mime_type
23
+ from mapproxy.request.tile import TileRequest
24
+ from mapproxy.exception import XMLExceptionHandler
25
+ from mapproxy.template import template_loader
26
+
27
+ import mapproxy.service
28
+ get_template = template_loader(mapproxy.service.__package__, 'templates')
29
+
30
+
31
+ class WMTS100ExceptionHandler(XMLExceptionHandler):
32
+ template_func = get_template
33
+ template_file = 'wmts100exception.xml'
34
+ content_type = 'text/xml'
35
+
36
+ status_codes = {
37
+ None: 500,
38
+ 'TileOutOfRange': 400,
39
+ 'MissingParameterValue': 400,
40
+ 'InvalidParameterValue': 400,
41
+ 'OperationNotSupported': 501
42
+ }
43
+
44
+
45
+ class WMTSTileRequestParams(RequestParams):
46
+ """
47
+ This class represents key-value parameters for WMTS map requests.
48
+
49
+ All values can be accessed as a property.
50
+ Some properties return processed values. ``size`` returns a tuple of the width
51
+ and height, ``layers`` returns an iterator of all layers, etc.
52
+
53
+ """
54
+ @property
55
+ def layer(self):
56
+ """
57
+ List with all layer names.
58
+ """
59
+ return self['layer']
60
+
61
+ def _get_coord(self):
62
+ x = int(self['tilecol'])
63
+ y = int(self['tilerow'])
64
+ z = self['tilematrix']
65
+ return x, y, z
66
+
67
+ def _set_coord(self, value):
68
+ x, y, z = value
69
+ self['tilecol'] = x
70
+ self['tilerow'] = y
71
+ self['tilematrix'] = z
72
+ coord = property(_get_coord, _set_coord)
73
+ del _get_coord
74
+ del _set_coord
75
+
76
+ def _get_format(self):
77
+ """
78
+ The requested format as string (w/o any 'image/', 'text/', etc prefixes)
79
+ """
80
+ _mime_class, format, options = split_mime_type(self.get('format', default=''))
81
+ return format
82
+
83
+ def _set_format(self, format):
84
+ if '/' not in format:
85
+ format = 'image/' + format
86
+ self['format'] = format
87
+
88
+ format = property(_get_format, _set_format)
89
+ del _get_format
90
+ del _set_format
91
+
92
+ @property
93
+ def format_mime_type(self):
94
+ return self.get('format')
95
+
96
+ @property
97
+ def dimensions(self):
98
+ expected_param = set(['version', 'request', 'layer', 'style', 'tilematrixset',
99
+ 'tilematrix', 'tilerow', 'tilecol', 'format', 'service'])
100
+ dimensions = {}
101
+ for key, value in self.iteritems():
102
+ if key not in expected_param:
103
+ dimensions[key.lower()] = value
104
+ return dimensions
105
+
106
+ def __repr__(self):
107
+ return '%s(param=%r)' % (self.__class__.__name__, self.params)
108
+
109
+
110
+ class WMTSRequest(BaseRequest):
111
+ request_params = WMTSTileRequestParams
112
+ request_handler_name = None
113
+ fixed_params = {}
114
+ expected_param = []
115
+ non_strict_params = set()
116
+ xml_exception_handler = None
117
+
118
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
119
+ self.non_strict = non_strict
120
+ BaseRequest.__init__(self, param=param, url=url, validate=validate, **kw)
121
+
122
+ def validate(self):
123
+ pass
124
+
125
+ @property
126
+ def query_string(self):
127
+ return self.params.query_string
128
+
129
+
130
+ class WMTS100TileRequest(WMTSRequest):
131
+ """
132
+ Base class for all WMTS GetTile requests.
133
+
134
+ :ivar requests: the ``RequestParams`` class for this request
135
+ :ivar request_handler_name: the name of the server handler
136
+ :ivar fixed_params: parameters that are fixed for a request
137
+ :ivar expected_param: required parameters, used for validating
138
+ """
139
+ request_params = WMTSTileRequestParams
140
+ request_handler_name = 'tile'
141
+ fixed_params = {'request': 'GetTile', 'version': '1.0.0', 'service': 'WMTS'}
142
+ xml_exception_handler = WMTS100ExceptionHandler
143
+ expected_param = ['version', 'request', 'layer', 'style', 'tilematrixset',
144
+ 'tilematrix', 'tilerow', 'tilecol', 'format']
145
+
146
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
147
+ WMTSRequest.__init__(self, param=param, url=url, validate=validate,
148
+ non_strict=non_strict, **kw)
149
+
150
+ def make_request(self):
151
+ self.layer = self.params.layer
152
+ self.tilematrixset = self.params.tilematrixset
153
+ self.format = self.params.format # TODO
154
+ self.tile = (int(self.params.coord[0]), int(self.params.coord[1]), int(self.params.coord[2]))
155
+ self.origin = 'nw'
156
+ self.dimensions = self.params.dimensions
157
+
158
+ def validate(self):
159
+ missing_param = []
160
+ for param in self.expected_param:
161
+ if self.non_strict and param in self.non_strict_params:
162
+ continue
163
+ if param not in self.params:
164
+ missing_param.append(param)
165
+
166
+ if missing_param:
167
+ if 'format' in missing_param:
168
+ self.params['format'] = 'image/png'
169
+ raise RequestError('missing parameters ' + str(missing_param),
170
+ request=self)
171
+
172
+ self.validate_styles()
173
+
174
+ def validate_styles(self):
175
+ if 'styles' in self.params:
176
+ styles = self.params['styles']
177
+ if styles.replace(',', '').strip() != '':
178
+ raise RequestError('unsupported styles: ' + self.params['styles'],
179
+ code='StyleNotDefined', request=self)
180
+
181
+ @property
182
+ def exception_handler(self):
183
+ return self.xml_exception_handler()
184
+
185
+ def copy(self):
186
+ return self.__class__(param=self.params.copy(), url=self.url)
187
+
188
+
189
+ class WMTSFeatureInfoRequestParams(WMTSTileRequestParams):
190
+ """
191
+ RequestParams for WMTS GetFeatureInfo requests.
192
+ """
193
+
194
+ def _get_pos(self):
195
+ """x, y query image coordinates (in pixel)"""
196
+ return int(self['i']), int(self['j'])
197
+
198
+ def _set_pos(self, value):
199
+ self['i'] = str(int(round(value[0])))
200
+ self['j'] = str(int(round(value[1])))
201
+ pos = property(_get_pos, _set_pos)
202
+ del _get_pos
203
+ del _set_pos
204
+
205
+
206
+ class WMTS100FeatureInfoRequest(WMTS100TileRequest):
207
+ request_params = WMTSFeatureInfoRequestParams
208
+ request_handler_name = 'featureinfo'
209
+ fixed_params = WMTS100TileRequest.fixed_params.copy()
210
+ fixed_params['request'] = 'GetFeatureInfo'
211
+ expected_param = WMTS100TileRequest.expected_param[:] + ['infoformat', 'i', 'j']
212
+ non_strict_params = set(['format', 'styles'])
213
+
214
+ def make_request(self):
215
+ WMTS100TileRequest.make_request(self)
216
+ self.infoformat = self.params.infoformat
217
+ self.pos = self.params.pos
218
+
219
+
220
+ class WMTS100CapabilitiesRequest(WMTSRequest):
221
+ request_handler_name = 'capabilities'
222
+ capabilities_template = 'wmts100capabilities.xml'
223
+ exception_handler = None
224
+ mime_type = 'text/xml'
225
+ fixed_params = {}
226
+
227
+ def __init__(self, param=None, url='', validate=False, non_strict=False, **kw):
228
+ WMTSRequest.__init__(self, param=param, url=url, validate=validate, **kw)
229
+
230
+
231
+ request_mapping = {'featureinfo': WMTS100FeatureInfoRequest,
232
+ 'tile': WMTS100TileRequest,
233
+ 'capabilities': WMTS100CapabilitiesRequest
234
+ }
235
+
236
+
237
+ def _parse_request_type(req):
238
+ if 'request' in req.args:
239
+ request_type = req.args['request'].lower()
240
+ if request_type.startswith('get'):
241
+ request_type = request_type[3:]
242
+ if request_type in ('tile', 'featureinfo', 'capabilities'):
243
+ return request_type
244
+
245
+ return None
246
+
247
+
248
+ def wmts_request(req, validate=True):
249
+ req_type = _parse_request_type(req)
250
+
251
+ req_class = request_mapping.get(req_type, None)
252
+ if req_class is None:
253
+ # use map request to get an exception handler for the requested version
254
+ dummy_req = request_mapping['tile'](param=req.args, url=req.base_url,
255
+ validate=False)
256
+ raise RequestError("unknown WMTS request type '%s'" % req_type, request=dummy_req)
257
+ return req_class(param=req.args, url=req.base_url, validate=True, http=req)
258
+
259
+
260
+ def create_request(req_data, param, req_type='tile'):
261
+ url = req_data['url']
262
+ req_data = req_data.copy()
263
+ del req_data['url']
264
+ if 'request_format' in param:
265
+ req_data['format'] = param['request_format']
266
+ elif 'format' in param:
267
+ req_data['format'] = param['format']
268
+ # req_data['bbox'] = param['bbox']
269
+ # if isinstance(req_data['bbox'], types.ListType):
270
+ # req_data['bbox'] = ','.join(str(x) for x in req_data['bbox'])
271
+ # req_data['srs'] = param['srs']
272
+
273
+ return request_mapping[req_type](url=url, param=req_data)
274
+
275
+
276
+ class InvalidWMTSTemplate(Exception):
277
+ pass
278
+
279
+
280
+ class URLTemplateConverter(object):
281
+ var_re = re.compile(r'(?:\\{)?\\{(\w+)\\}(?:\\})?')
282
+ # TODO {{}} format is deprecated, change to this in 1.6
283
+ # var_re = re.compile(r'\\{(\w+)\\}')
284
+
285
+ variables = {
286
+ 'TileMatrixSet': r'[\w_.:-]+',
287
+ 'TileMatrix': r'\d+',
288
+ 'TileRow': r'-?\d+',
289
+ 'TileCol': r'-?\d+',
290
+ 'I': r'\d+',
291
+ 'J': r'\d+',
292
+ 'Style': r'[\w_.:-]+',
293
+ 'Layer': r'[\w_.:-]+',
294
+ 'Format': r'\w+',
295
+ 'InfoFormat': r'\w+',
296
+ }
297
+
298
+ required = set(['TileCol', 'TileRow', 'TileMatrix', 'TileMatrixSet', 'Layer'])
299
+
300
+ def __init__(self, template):
301
+ self.template = template
302
+ self.found = set()
303
+ self.dimensions = []
304
+ self._regexp = None
305
+ self.regexp()
306
+
307
+ def substitute_var(self, match):
308
+ var = match.group(1)
309
+ if var in self.variables:
310
+ var_type_re = self.variables[var]
311
+ else:
312
+ self.dimensions.append(var)
313
+ var = var.lower()
314
+ var_type_re = r'[\w_.,:-]+'
315
+ self.found.add(var)
316
+ return r'(?P<%s>%s)' % (var, var_type_re)
317
+
318
+ def regexp(self):
319
+ if self._regexp:
320
+ return self._regexp
321
+ converted_re = self.var_re.sub(self.substitute_var, re.escape(self.template))
322
+ wmts_re = re.compile(r'/wmts' + converted_re)
323
+ if not self.found.issuperset(self.required):
324
+ raise InvalidWMTSTemplate('missing required variables in WMTS restful template: %s' %
325
+ self.required.difference(self.found))
326
+ self._regexp = wmts_re
327
+ return wmts_re
328
+
329
+
330
+ class FeatureInfoURLTemplateConverter(URLTemplateConverter):
331
+ required = set(['TileCol', 'TileRow', 'TileMatrix', 'TileMatrixSet', 'Layer', 'I', 'J'])
332
+
333
+
334
+ class WMTS100RestTileRequest(TileRequest):
335
+ """
336
+ Class for RESTful WMTS requests.
337
+ """
338
+ xml_exception_handler = WMTS100ExceptionHandler
339
+ request_handler_name = 'tile'
340
+ origin = 'nw'
341
+
342
+ def __init__(self, request, req_vars, url_converter=None):
343
+ self.http = request
344
+ self.url = request.base_url
345
+ self.dimensions = {}
346
+ self.req_vars = req_vars
347
+ self.url_converter = url_converter
348
+
349
+ def make_request(self):
350
+ """
351
+ Initialize tile request. Sets ``tile`` and ``layer`` and ``format``.
352
+ :raise RequestError: if the format does not match the URL template``
353
+ """
354
+ req_vars = self.req_vars
355
+ self.layer = req_vars['Layer']
356
+ self.tile = int(req_vars['TileCol']), int(req_vars['TileRow']), int(req_vars['TileMatrix'])
357
+ self.format = req_vars.get('Format')
358
+ self.tilematrixset = req_vars['TileMatrixSet']
359
+ if self.url_converter and self.url_converter.dimensions:
360
+ for dim in self.url_converter.dimensions:
361
+ self.dimensions[dim.lower()] = req_vars[dim.lower()]
362
+
363
+ @property
364
+ def exception_handler(self):
365
+ return self.xml_exception_handler()
366
+
367
+
368
+ class WMTS100RestFeatureInfoRequest(TileRequest):
369
+ """
370
+ Class for RESTful WMTS FeatureInfo requests.
371
+ """
372
+ xml_exception_handler = WMTS100ExceptionHandler
373
+ request_handler_name = 'featureinfo'
374
+
375
+ def __init__(self, request, req_vars, url_converter=None):
376
+ self.http = request
377
+ self.url = request.base_url
378
+ self.dimensions = {}
379
+ self.req_vars = req_vars
380
+ self.url_converter = url_converter
381
+
382
+ def make_request(self):
383
+ """
384
+ Initialize tile request. Sets ``tile`` and ``layer`` and ``format``.
385
+ :raise RequestError: if the format does not match the URL template``
386
+ """
387
+ req_vars = self.req_vars
388
+ self.layer = req_vars['Layer']
389
+ self.tile = int(req_vars['TileCol']), int(req_vars['TileRow']), int(req_vars['TileMatrix'])
390
+ self.pos = int(req_vars['I']), int(req_vars['J'])
391
+ self.format = req_vars.get('Format')
392
+ self.infoformat = req_vars.get('InfoFormat')
393
+ self.tilematrixset = req_vars['TileMatrixSet']
394
+ if self.url_converter and self.url_converter.dimensions:
395
+ for dim in self.url_converter.dimensions:
396
+ self.dimensions[dim.lower()] = req_vars[dim.lower()]
397
+
398
+ @property
399
+ def exception_handler(self):
400
+ return self.xml_exception_handler()
401
+
402
+
403
+ RESTFUL_CAPABILITIES_PATH = '/1.0.0/WMTSCapabilities.xml'
404
+
405
+
406
+ class WMTS100RestCapabilitiesRequest(object):
407
+ """
408
+ Class for RESTful WMTS capabilities requests.
409
+ """
410
+ xml_exception_handler = WMTS100ExceptionHandler
411
+ request_handler_name = 'capabilities'
412
+ capabilities_template = 'wmts100capabilities.xml'
413
+
414
+ def __init__(self, request):
415
+ self.http = request
416
+ self.url = request.base_url[:-len(RESTFUL_CAPABILITIES_PATH)]
417
+
418
+ @property
419
+ def exception_handler(self):
420
+ return self.xml_exception_handler()
421
+
422
+
423
+ def make_wmts_rest_request_parser(url_converter, fi_url_converter):
424
+ tile_req_re = url_converter.regexp()
425
+ fi_req_re = fi_url_converter.regexp()
426
+
427
+ def wmts_request(req):
428
+ if req.path.endswith(RESTFUL_CAPABILITIES_PATH):
429
+ return WMTS100RestCapabilitiesRequest(req)
430
+
431
+ match = tile_req_re.search(req.path)
432
+ if not match:
433
+ match = fi_req_re.search(req.path)
434
+ if not match:
435
+ raise RequestError('invalid request (%s)' % (req.path))
436
+
437
+ req_vars = match.groupdict()
438
+ return WMTS100RestFeatureInfoRequest(req, req_vars, fi_url_converter)
439
+ req_vars = match.groupdict()
440
+ return WMTS100RestTileRequest(req, req_vars, url_converter)
441
+
442
+ return wmts_request