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,476 @@
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
+ from mapproxy.compat import PY2, iteritems, text_type
20
+ from mapproxy.compat.modules import parse_qsl, urlparse, quote
21
+ from mapproxy.util.py import cached_property
22
+
23
+ class NoCaseMultiDict(dict):
24
+ """
25
+ This is a dictionary that allows case insensitive access to values.
26
+
27
+ >>> d = NoCaseMultiDict([('A', 'b'), ('a', 'c'), ('B', 'f'), ('c', 'x'), ('c', 'y'), ('c', 'z')])
28
+ >>> d['a']
29
+ 'b'
30
+ >>> d.get_all('a')
31
+ ['b', 'c']
32
+ >>> 'a' in d and 'b' in d
33
+ True
34
+ """
35
+ def _gen_dict(self, mapping=()):
36
+ """A `NoCaseMultiDict` can be constructed from an iterable of
37
+ ``(key, value)`` tuples or a dict.
38
+ """
39
+ tmp = {}
40
+ if isinstance(mapping, NoCaseMultiDict):
41
+ for key, value in mapping.iteritems(): #pylint: disable-msg=E1103
42
+ tmp.setdefault(key.lower(), (key, []))[1].extend(value)
43
+ else:
44
+ if isinstance(mapping, dict):
45
+ itr = iteritems(mapping)
46
+ else:
47
+ itr = iter(mapping)
48
+ for key, value in itr:
49
+ tmp.setdefault(key.lower(), (key, []))[1].append(value)
50
+ return tmp
51
+
52
+ def __init__(self, mapping=()):
53
+ """A `NoCaseMultiDict` can be constructed from an iterable of
54
+ ``(key, value)`` tuples or a dict.
55
+ """
56
+ dict.__init__(self, self._gen_dict(mapping))
57
+
58
+ def update(self, mapping=(), append=False):
59
+ """A `NoCaseMultiDict` can be updated from an iterable of
60
+ ``(key, value)`` tuples or a dict.
61
+ """
62
+ for _, (key, values) in iteritems(self._gen_dict(mapping)):
63
+ self.set(key, values, append=append, unpack=True)
64
+
65
+ def __getitem__(self, key):
66
+ """
67
+ Return the first data value for this key.
68
+
69
+ :raise KeyError: if the key does not exist
70
+ """
71
+ if key in self:
72
+ return dict.__getitem__(self, key.lower())[1][0]
73
+ raise KeyError(key)
74
+
75
+ def __setitem__(self, key, value):
76
+ dict.setdefault(self, key.lower(), (key, []))[1][:] = [value]
77
+
78
+ def __delitem__(self, key):
79
+ dict.__delitem__(self, key.lower())
80
+
81
+ def __contains__(self, key):
82
+ return dict.__contains__(self, key.lower())
83
+
84
+ def __getstate__(self):
85
+ data = []
86
+ for key, values in self.iteritems():
87
+ for v in values:
88
+ data.append((key, v))
89
+ return data
90
+
91
+ def __setstate__(self, data):
92
+ self.__init__(data)
93
+
94
+ def get(self, key, default=None, type_func=None):
95
+ """Return the default value if the requested data doesn't exist.
96
+ If `type_func` is provided and is a callable it should convert the value,
97
+ return it or raise a `ValueError` if that is not possible. In this
98
+ case the function will return the default as if the value was not
99
+ found.
100
+
101
+ Example:
102
+
103
+ >>> d = NoCaseMultiDict(dict(foo='42', bar='blub'))
104
+ >>> d.get('foo', type_func=int)
105
+ 42
106
+ >>> d.get('bar', -1, type_func=int)
107
+ -1
108
+ """
109
+ try:
110
+ rv = self[key]
111
+ if type_func is not None:
112
+ rv = type_func(rv)
113
+ except (KeyError, ValueError):
114
+ rv = default
115
+ return rv
116
+
117
+ def get_all(self, key):
118
+ """
119
+ Return all values for the key as a list. Returns an empty list, if
120
+ the key doesn't exist.
121
+ """
122
+ if key in self:
123
+ return dict.__getitem__(self, key.lower())[1]
124
+ else:
125
+ return []
126
+
127
+ def set(self, key, value, append=False, unpack=False):
128
+ """
129
+ Set a `value` for the `key`. If `append` is ``True`` the value will be added
130
+ to other values for this `key`.
131
+
132
+ If `unpack` is True, `value` will be unpacked and each item will be added.
133
+ """
134
+ if key in self:
135
+ if not append:
136
+ dict.__getitem__(self, key.lower())[1][:] = []
137
+ else:
138
+ dict.__setitem__(self, key.lower(), (key, []))
139
+ if unpack:
140
+ for v in value:
141
+ dict.__getitem__(self, key.lower())[1].append(v)
142
+ else:
143
+ dict.__getitem__(self, key.lower())[1].append(value)
144
+
145
+ def iteritems(self):
146
+ """
147
+ Iterates over all keys and values.
148
+ """
149
+ if PY2:
150
+ for _, (key, values) in dict.iteritems(self):
151
+ yield key, values
152
+ else:
153
+ for _, (key, values) in dict.items(self):
154
+ yield key, values
155
+
156
+ def copy(self):
157
+ """
158
+ Returns a copy of this object.
159
+ """
160
+ return self.__class__(self)
161
+
162
+ def __repr__(self):
163
+ tmp = []
164
+ for key, values in self.iteritems():
165
+ tmp.append((key, values))
166
+ return '%s(%r)' % (self.__class__.__name__, tmp)
167
+
168
+
169
+ def url_decode(qs, charset='utf-8', decode_keys=False, include_empty=True,
170
+ errors='ignore'):
171
+ """
172
+ Parse query string `qs` and return a `NoCaseMultiDict`.
173
+ """
174
+ tmp = []
175
+ for key, value in parse_qsl(qs, include_empty):
176
+ if PY2:
177
+ if decode_keys:
178
+ key = key.decode(charset, errors)
179
+ tmp.append((key, value.decode(charset, errors)))
180
+ else:
181
+ if not isinstance(key, text_type):
182
+ key = key.decode(charset, errors)
183
+ if not isinstance(value, text_type):
184
+ value = value.decode(charset, errors)
185
+ tmp.append((key, value))
186
+ return NoCaseMultiDict(tmp)
187
+
188
+ class Request(object):
189
+ charset = 'utf8'
190
+
191
+ def __init__(self, environ):
192
+ self.environ = environ
193
+ self.environ['mapproxy.request'] = self
194
+
195
+ script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
196
+ if script_name:
197
+ del environ['HTTP_X_SCRIPT_NAME']
198
+ environ['SCRIPT_NAME'] = script_name
199
+ path_info = environ['PATH_INFO']
200
+ if path_info.startswith(script_name):
201
+ environ['PATH_INFO'] = path_info[len(script_name):]
202
+
203
+ @cached_property
204
+ def args(self):
205
+ if self.environ.get('QUERY_STRING'):
206
+ return url_decode(self.environ['QUERY_STRING'], self.charset)
207
+ else:
208
+ return {}
209
+
210
+ @property
211
+ def path(self):
212
+ path = self.environ.get('PATH_INFO', '')
213
+ if PY2:
214
+ return path
215
+ if path and isinstance(path, bytes):
216
+ path = path.decode('utf-8')
217
+ return path
218
+
219
+ def pop_path(self):
220
+ path = self.path.lstrip('/')
221
+ if '/' in path:
222
+ result, rest = path.split('/', 1)
223
+ self.environ['PATH_INFO'] = '/' + rest
224
+ else:
225
+ self.environ['PATH_INFO'] = ''
226
+ result = path
227
+ if result:
228
+ self.environ['SCRIPT_NAME'] = self.environ['SCRIPT_NAME'] + '/' + result
229
+ return result
230
+
231
+ @cached_property
232
+ def host(self):
233
+ if 'HTTP_X_FORWARDED_HOST' in self.environ:
234
+ # might be a list, return first host only
235
+ host = self.environ['HTTP_X_FORWARDED_HOST']
236
+ host = host.split(',', 1)[0].strip()
237
+ return host
238
+ elif 'HTTP_HOST' in self.environ:
239
+ host = self.environ['HTTP_HOST']
240
+ if ':' in host:
241
+ port = host.split(':')[1]
242
+ if ((self.url_scheme, port) in (('https', '443'), ('http', '80'))):
243
+ host = host.split(':')[0]
244
+ return host
245
+ result = self.environ['SERVER_NAME']
246
+ if ((self.url_scheme, self.environ['SERVER_PORT'])
247
+ not in (('https', '443'), ('http', '80'))):
248
+ result += ':' + self.environ['SERVER_PORT']
249
+ return result
250
+
251
+ @cached_property
252
+ def url_scheme(self):
253
+ scheme = self.environ.get('HTTP_X_FORWARDED_PROTO')
254
+ if not scheme:
255
+ scheme = self.environ['wsgi.url_scheme']
256
+ return scheme
257
+
258
+ @cached_property
259
+ def host_url(self):
260
+ return '%s://%s/' % (self.url_scheme, self.host)
261
+
262
+ @cached_property
263
+ def server_url(self):
264
+ return 'http://%s:%s/' % (
265
+ self.environ['SERVER_NAME'],
266
+ self.environ['SERVER_PORT']
267
+ )
268
+
269
+ @property
270
+ def script_url(self):
271
+ "Full script URL without trailing /"
272
+ return (self.host_url.rstrip('/') +
273
+ quote(self.environ.get('SCRIPT_NAME', '/').rstrip('/'))
274
+ )
275
+
276
+ @property
277
+ def server_script_url(self):
278
+ "Internal script URL"
279
+ return self.script_url.replace(
280
+ self.host_url.rstrip('/'),
281
+ self.server_url.rstrip('/')
282
+ )
283
+
284
+ @property
285
+ def base_url(self):
286
+ return (self.host_url.rstrip('/')
287
+ + quote(self.environ.get('SCRIPT_NAME', '').rstrip('/'))
288
+ + quote(self.environ.get('PATH_INFO', ''))
289
+ )
290
+
291
+ class RequestParams(object):
292
+ """
293
+ This class represents key-value request parameters. It allows case-insensitive
294
+ access to all keys. Multiple values for a single key will be concatenated
295
+ (eg. to ``layers=foo&layers=bar`` becomes ``layers: foo,bar``).
296
+
297
+ All values can be accessed as a property.
298
+
299
+ :param param: A dict or ``NoCaseMultiDict``.
300
+ """
301
+ params = None
302
+ def __init__(self, param=None):
303
+ self.delimiter = ','
304
+
305
+ if param is None:
306
+ self.params = NoCaseMultiDict()
307
+ else:
308
+ self.params = NoCaseMultiDict(param)
309
+
310
+ def __str__(self):
311
+ return self.query_string
312
+
313
+ def get(self, key, default=None, type_func=None):
314
+ """
315
+ Returns the value for `key` or the `default`. `type_func` is called on the
316
+ value to alter the value (e.g. use ``type_func=int`` to get ints).
317
+ """
318
+ return self.params.get(key, default, type_func)
319
+
320
+ def set(self, key, value, append=False, unpack=False):
321
+ """
322
+ Set a `value` for the `key`. If `append` is ``True`` the value will be added
323
+ to other values for this `key`.
324
+
325
+ If `unpack` is True, `value` will be unpacked and each item will be added.
326
+ """
327
+ self.params.set(key, value, append=append, unpack=unpack)
328
+
329
+ def update(self, mapping=(), append=False):
330
+ """
331
+ Update internal request parameters from an iterable of ``(key, value)``
332
+ tuples or a dict.
333
+
334
+ If `append` is ``True`` the value will be added to other values for
335
+ this `key`.
336
+ """
337
+ self.params.update(mapping, append=append)
338
+
339
+ def __getattr__(self, name):
340
+ if name in self:
341
+ return self[name]
342
+ else:
343
+ raise AttributeError("'%s' object has no attribute '%s" %
344
+ (self.__class__.__name__, name))
345
+
346
+ def __getitem__(self, key):
347
+ return self.delimiter.join(map(text_type, self.params.get_all(key)))
348
+
349
+ def __setitem__(self, key, value):
350
+ """
351
+ Set `value` for the `key`. Does not append values (see ``MapRequest.set``).
352
+ """
353
+ self.set(key, value)
354
+
355
+ def __delitem__(self, key):
356
+ if key in self:
357
+ del self.params[key]
358
+
359
+
360
+ def iteritems(self):
361
+ for key, values in self.params.iteritems():
362
+ yield key, self.delimiter.join((text_type(x) for x in values))
363
+
364
+ def __contains__(self, key):
365
+ return self.params and key in self.params
366
+
367
+ def copy(self):
368
+ return self.__class__(self.params)
369
+
370
+ @property
371
+ def query_string(self):
372
+ """
373
+ The map request as a query string (the order is not guaranteed).
374
+
375
+ >>> qs = RequestParams(dict(foo='egg', bar='ham%eggs', baz=100)).query_string
376
+ >>> sorted(qs.split('&'))
377
+ ['bar=ham%25eggs', 'baz=100', 'foo=egg']
378
+ """
379
+ kv_pairs = []
380
+ for key, values in self.params.iteritems():
381
+ value = ','.join(text_type(v) for v in values)
382
+ kv_pairs.append(key + '=' + quote(value.encode('utf-8'), safe=','))
383
+ return '&'.join(kv_pairs)
384
+
385
+ def with_defaults(self, defaults):
386
+ """
387
+ Return this MapRequest with all values from `defaults` overwritten.
388
+ """
389
+ new = self.copy()
390
+ for key, value in defaults.params.iteritems():
391
+ if value != [None]:
392
+ new.set(key, value, unpack=True)
393
+ return new
394
+
395
+ class BaseRequest(object):
396
+ """
397
+ This class represents a request with a URL and key-value parameters.
398
+
399
+ :param param: A dict, `NoCaseMultiDict` or ``RequestParams``.
400
+ :param url: The service URL for the request.
401
+ :param validate: True if the request should be validated after initialization.
402
+ """
403
+ request_params = RequestParams
404
+
405
+ def __init__(self, param=None, url='', validate=False, http=None, dimensions=None):
406
+ self.delimiter = ','
407
+ self.http = http
408
+
409
+ if param is None:
410
+ self.params = self.request_params(NoCaseMultiDict())
411
+ else:
412
+ if isinstance(param, RequestParams):
413
+ self.params = self.request_params(param.params)
414
+ else:
415
+ self.params = self.request_params(NoCaseMultiDict(param))
416
+ self.url = url
417
+ if validate:
418
+ self.validate()
419
+
420
+ def __str__(self):
421
+ return self.complete_url
422
+
423
+ def validate(self):
424
+ pass
425
+
426
+ @property
427
+ def raw_params(self):
428
+ params = {}
429
+ for key, value in iteritems(self.params):
430
+ params[key] = value
431
+ return params
432
+
433
+
434
+ @property
435
+ def query_string(self):
436
+ return self.params.query_string
437
+
438
+ @property
439
+ def complete_url(self):
440
+ """
441
+ The complete MapRequest as URL.
442
+ """
443
+ if not self.url:
444
+ return self.query_string
445
+ delimiter = '?'
446
+ if '?' in self.url:
447
+ delimiter = '&'
448
+ if self.url[-1] == '?':
449
+ delimiter = ''
450
+ return self.url + delimiter + self.query_string
451
+
452
+ def copy_with_request_params(self, req):
453
+ """
454
+ Return a copy of this request ond overwrite all param values from `req`.
455
+ Use this method for templates
456
+ (``req_template.copy_with_request_params(actual_values)``).
457
+ """
458
+ new_params = req.params.with_defaults(self.params)
459
+ return self.__class__(param=new_params, url=self.url)
460
+
461
+ def __repr__(self):
462
+ return '%s(param=%r, url=%r)' % (self.__class__.__name__, self.params, self.url)
463
+
464
+ def split_mime_type(mime_type):
465
+ """
466
+ >>> split_mime_type('text/xml; charset=utf-8')
467
+ ('text', 'xml', 'charset=utf-8')
468
+ """
469
+ options = None
470
+ mime_class = None
471
+ if '/' in mime_type:
472
+ mime_class, mime_type = mime_type.split('/', 1)
473
+ if ';' in mime_type:
474
+ mime_type, options = [part.strip() for part in mime_type.split(';', 2)]
475
+ return mime_class, mime_type, options
476
+
@@ -0,0 +1,128 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010 Omniscale <http://omniscale.de>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import re
17
+
18
+ from mapproxy.exception import (
19
+ RequestError,
20
+ XMLExceptionHandler,
21
+ PlainExceptionHandler, )
22
+
23
+ import mapproxy.service
24
+ from mapproxy.template import template_loader
25
+ get_template = template_loader(mapproxy.service.__name__, 'templates')
26
+
27
+ class TileRequest(object):
28
+ """
29
+ Class for tile requests.
30
+ """
31
+ request_handler_name = 'map'
32
+ tile_req_re = re.compile(r'''^(?P<begin>/[^/]+)/
33
+ ((?P<version>1\.0\.0)/)?
34
+ (?P<layer>[^/]+)/
35
+ ((?P<layer_spec>[^/]+)/)?
36
+ (?P<z>-?\d+)/
37
+ (?P<x>-?\d+)/
38
+ (?P<y>-?\d+)\.(?P<format>\w+)''', re.VERBOSE)
39
+ use_profiles = False
40
+ req_prefix = '/tiles'
41
+ origin = None
42
+ dimensions = {}
43
+
44
+ def __init__(self, request):
45
+ self.tile = None
46
+ self.format = None
47
+ self.http = request
48
+ self._init_request()
49
+ self.origin = self.http.args.get('origin')
50
+ if self.origin not in ('sw', 'nw', None):
51
+ self.origin = None
52
+
53
+ def _init_request(self):
54
+ """
55
+ Initialize tile request. Sets ``tile`` and ``layer``.
56
+ :raise RequestError: if the format is not ``/layer/z/x/y.format``
57
+ """
58
+ match = self.tile_req_re.search(self.http.path)
59
+ if not match or match.group('begin') != self.req_prefix:
60
+ raise RequestError('invalid request (%s)' % (self.http.path), request=self)
61
+
62
+ self.layer = match.group('layer')
63
+ self.dimensions = {}
64
+ if match.group('layer_spec') is not None:
65
+ self.dimensions['_layer_spec'] = match.group('layer_spec')
66
+ if not self.tile:
67
+ self.tile = tuple([int(match.group(v)) for v in ['x', 'y', 'z']])
68
+ if not self.format:
69
+ self.format = match.group('format')
70
+
71
+ @property
72
+ def exception_handler(self):
73
+ return PlainExceptionHandler()
74
+
75
+
76
+ class TMSRequest(TileRequest):
77
+ """
78
+ Class for TMS 1.0.0 requests.
79
+ """
80
+ request_handler_name = 'map'
81
+ req_prefix = '/tms'
82
+ capabilities_re = re.compile(r'''
83
+ ^.*/1\.0\.0/?
84
+ (/(?P<layer>[^/]+))?
85
+ (/(?P<layer_spec>[^/]+))?
86
+ $''', re.VERBOSE)
87
+ root_request_re = re.compile(r'/tms/?$')
88
+ use_profiles = True
89
+ origin = 'sw'
90
+
91
+ def __init__(self, request):
92
+ self.tile = None
93
+ self.format = None
94
+ self.http = request
95
+ cap_match = self.capabilities_re.match(request.path)
96
+ root_match = self.root_request_re.match(request.path)
97
+ if cap_match:
98
+ if cap_match.group('layer') is not None:
99
+ self.layer = cap_match.group('layer')
100
+ self.dimensions = {}
101
+ if cap_match.group('layer_spec') is not None:
102
+ self.dimensions['_layer_spec'] = cap_match.group('layer_spec')
103
+ self.request_handler_name = 'tms_capabilities'
104
+ elif root_match:
105
+ self.request_handler_name = 'tms_root_resource'
106
+ else:
107
+ self._init_request()
108
+
109
+ @property
110
+ def exception_handler(self):
111
+ return TMSExceptionHandler()
112
+
113
+ def tile_request(req):
114
+ if req.path.startswith('/tms'):
115
+ return TMSRequest(req)
116
+ else:
117
+ return TileRequest(req)
118
+
119
+ class TMSExceptionHandler(XMLExceptionHandler):
120
+ template_file = 'tms_exception.xml'
121
+ template_func = get_template
122
+ mimetype = 'text/xml'
123
+ status_code = 404
124
+
125
+ def render(self, request_error):
126
+ if request_error.internal:
127
+ self.status_code = 500
128
+ return XMLExceptionHandler.render(self, request_error)