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,79 @@
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
+ from mapproxy.client.http import HTTPClient
17
+ from mapproxy.client.wms import WMSInfoClient
18
+ from mapproxy.srs import SRS
19
+ from mapproxy.featureinfo import create_featureinfo_doc
20
+
21
+ class ArcGISClient(object):
22
+ def __init__(self, request_template, http_client=None):
23
+ self.request_template = request_template
24
+ self.http_client = http_client
25
+
26
+ def retrieve(self, query, format):
27
+ url = self._query_url(query, format)
28
+ resp = self.http_client.open(url)
29
+ return resp
30
+
31
+ def _query_url(self, query, format):
32
+ req = self.request_template.copy()
33
+ req.params.format = format
34
+ req.params.bbox = query.bbox
35
+ req.params.size = query.size
36
+ req.params.bboxSR = query.srs
37
+ req.params.imageSR = query.srs
38
+ req.params.transparent = query.transparent
39
+
40
+ return req.complete_url
41
+
42
+ def combined_client(self, other, query):
43
+ return
44
+
45
+ class ArcGISInfoClient(WMSInfoClient):
46
+ def __init__(self, request_template, supported_srs=None, http_client=None,
47
+ return_geometries=False,
48
+ tolerance=5,
49
+ ):
50
+ self.request_template = request_template
51
+ self.http_client = http_client or HTTPClient()
52
+ if not supported_srs and self.request_template.params.srs is not None:
53
+ supported_srs = [SRS(self.request_template.params.srs)]
54
+ self.supported_srs = supported_srs or []
55
+ self.return_geometries = return_geometries
56
+ self.tolerance = tolerance
57
+
58
+ def get_info(self, query):
59
+ if self.supported_srs and query.srs not in self.supported_srs:
60
+ query = self._get_transformed_query(query)
61
+ resp = self._retrieve(query)
62
+ # always use query.info_format and not content-type from response (even esri example server aleays return text/plain)
63
+ return create_featureinfo_doc(resp.read(), query.info_format)
64
+
65
+ def _query_url(self, query):
66
+ req = self.request_template.copy()
67
+ req.params.bbox = query.bbox
68
+ req.params.size = query.size
69
+ req.params.pos = query.pos
70
+ req.params.srs = query.srs.srs_code
71
+ if query.info_format.startswith('text/html'):
72
+ req.params['f'] = 'html'
73
+ else:
74
+ req.params['f'] = 'json'
75
+
76
+ req.params['tolerance'] = self.tolerance
77
+ req.params['returnGeometry'] = str(self.return_geometries).lower()
78
+
79
+ return req.complete_url
mapproxy/client/cgi.py ADDED
@@ -0,0 +1,139 @@
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
+ HTTP client that directly calls CGI executable.
18
+ """
19
+
20
+ import errno
21
+ import os
22
+ import re
23
+ import subprocess
24
+ import time
25
+
26
+ from mapproxy.source import SourceError
27
+ from mapproxy.image import ImageSource
28
+ from mapproxy.client.http import HTTPClientError
29
+ from mapproxy.client.log import log_request
30
+ from mapproxy.compat.modules import urlparse
31
+ from mapproxy.compat import BytesIO
32
+
33
+
34
+ def split_cgi_response(data):
35
+ headers = []
36
+ prev_n = 0
37
+ while True:
38
+ next_n = data.find(b'\n', prev_n)
39
+ if next_n < 0:
40
+ break
41
+ next_line_begin = data[next_n+1:next_n+3]
42
+ headers.append(data[prev_n:next_n].rstrip(b'\r'))
43
+ if next_line_begin[0:1] == b'\n':
44
+ return headers_dict(headers), data[next_n+2:]
45
+ elif next_line_begin == b'\r\n':
46
+ return headers_dict(headers), data[next_n+3:]
47
+ prev_n = next_n+1
48
+ return {}, data
49
+
50
+ def headers_dict(header_lines):
51
+ headers = {}
52
+ for line in header_lines:
53
+ if b':' in line:
54
+ key, value = line.split(b':', 1)
55
+ value = value.strip()
56
+ else:
57
+ key = line
58
+ value = None
59
+ key = key.decode('latin-1')
60
+ key = key[0].upper() + key[1:].lower()
61
+ if value:
62
+ value = value.decode('latin-1')
63
+ headers[key] = value
64
+ return headers
65
+
66
+ class IOwithHeaders(object):
67
+ def __init__(self, io, headers):
68
+ self.io = io
69
+ self.headers = headers
70
+
71
+ def __getattr__(self, name):
72
+ return getattr(self.io, name)
73
+
74
+ class CGIClient(object):
75
+ def __init__(self, script, no_headers=False, working_directory=None):
76
+ self.script = script
77
+ self.working_directory = working_directory
78
+ self.no_headers = no_headers
79
+
80
+ def open(self, url, data=None):
81
+ assert data is None, 'POST requests not supported by CGIClient'
82
+
83
+ parsed_url = urlparse.urlparse(url)
84
+ environ = os.environ.copy()
85
+ environ.update({
86
+ 'QUERY_STRING': parsed_url.query,
87
+ 'REQUEST_METHOD': 'GET',
88
+ 'GATEWAY_INTERFACE': 'CGI/1.1',
89
+ 'SERVER_ADDR': '127.0.0.1',
90
+ 'SERVER_NAME': 'localhost',
91
+ 'SERVER_PROTOCOL': 'HTTP/1.0',
92
+ 'SERVER_SOFTWARE': 'MapProxy',
93
+ })
94
+
95
+ start_time = time.time()
96
+ try:
97
+ p = subprocess.Popen([self.script], env=environ,
98
+ stdout=subprocess.PIPE,
99
+ cwd=self.working_directory or os.path.dirname(self.script)
100
+ )
101
+ except OSError as ex:
102
+ if ex.errno == errno.ENOENT:
103
+ raise SourceError('CGI script not found (%s)' % (self.script,))
104
+ elif ex.errno == errno.EACCES:
105
+ raise SourceError('No permission for CGI script (%s)' % (self.script,))
106
+ else:
107
+ raise
108
+
109
+ stdout = p.communicate()[0]
110
+ ret = p.wait()
111
+ if ret != 0:
112
+ raise HTTPClientError('Error during CGI call (exit code: %d)'
113
+ % (ret, ))
114
+
115
+ if self.no_headers:
116
+ content = stdout
117
+ headers = dict()
118
+ else:
119
+ headers, content = split_cgi_response(stdout)
120
+
121
+ status_match = re.match(r'(\d\d\d) ', headers.get('Status', ''))
122
+ if status_match:
123
+ status_code = status_match.group(1)
124
+ else:
125
+ status_code = '-'
126
+ size = len(content)
127
+ content = IOwithHeaders(BytesIO(content), headers)
128
+
129
+ log_request('%s:%s' % (self.script, parsed_url.query),
130
+ status_code, size=size, method='CGI', duration=time.time()-start_time)
131
+ return content
132
+
133
+ def open_image(self, url, data=None):
134
+ resp = self.open(url, data=data)
135
+ if 'Content-type' in resp.headers:
136
+ if not resp.headers['Content-type'].lower().startswith('image'):
137
+ raise HTTPClientError('response is not an image: (%s)' % (resp.read()))
138
+ return ImageSource(resp)
139
+
@@ -0,0 +1,315 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010-2017 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
+ Tile retrieval (WMS, TMS, etc.).
18
+ """
19
+ import sys
20
+ import time
21
+ import warnings
22
+
23
+ from mapproxy.version import version
24
+ from mapproxy.image import ImageSource
25
+ from mapproxy.util.py import reraise_exception
26
+ from mapproxy.client.log import log_request
27
+ from mapproxy.compat import PY2
28
+ from mapproxy.compat.modules import urlparse
29
+
30
+ if PY2:
31
+ import urllib2
32
+ from urllib2 import URLError, HTTPError, HTTPCookieProcessor
33
+ import httplib
34
+ from cookielib import CookieJar
35
+ else:
36
+ from urllib import request as urllib2
37
+ from urllib.error import URLError, HTTPError
38
+ from urllib.request import HTTPCookieProcessor
39
+ from http import client as httplib
40
+ from http.cookiejar import CookieJar
41
+
42
+ import socket
43
+ import ssl
44
+
45
+ supports_ssl_default_context = False
46
+ if hasattr(ssl, 'create_default_context'):
47
+ # Python >=2.7.9 and >=3.4.0
48
+ supports_ssl_default_context = True
49
+
50
+ class HTTPClientError(Exception):
51
+ def __init__(self, arg, response_code=None, full_msg=None):
52
+ Exception.__init__(self, arg)
53
+ self.response_code = response_code
54
+ self.full_msg = full_msg
55
+
56
+
57
+ def build_https_handler(ssl_ca_certs, insecure):
58
+ if supports_ssl_default_context:
59
+ # python >=2.7.9 and >=3.4 supports ssl context in
60
+ # HTTPSHandler use this
61
+ if insecure:
62
+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
63
+ ctx.verify_mode = ssl.CERT_NONE
64
+ elif ssl_ca_certs:
65
+ ctx = ssl.create_default_context(cafile=ssl_ca_certs)
66
+ else:
67
+ ctx = ssl.create_default_context()
68
+ return urllib2.HTTPSHandler(context=ctx)
69
+ else:
70
+ if insecure:
71
+ return None
72
+ else:
73
+ connection_class = verified_https_connection_with_ca_certs(
74
+ ssl_ca_certs)
75
+ return VerifiedHTTPSHandler(connection_class=connection_class)
76
+
77
+
78
+ class VerifiedHTTPSConnection(httplib.HTTPSConnection):
79
+ def __init__(self, *args, **kw):
80
+ self._ca_certs = kw.pop('ca_certs', None)
81
+ httplib.HTTPSConnection.__init__(self, *args, **kw)
82
+
83
+ def connect(self):
84
+ # overrides the version in httplib so that we do
85
+ # certificate verification
86
+
87
+ if hasattr(socket, 'create_connection') and hasattr(self, 'source_address'):
88
+ sock = socket.create_connection((self.host, self.port),
89
+ self.timeout, self.source_address)
90
+ else:
91
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
92
+ sock.connect((self.host, self.port))
93
+
94
+ if hasattr(self, '_tunnel_host') and self._tunnel_host:
95
+ # for Python >= 2.6 with proxy support
96
+ self.sock = sock
97
+ self._tunnel()
98
+
99
+ # wrap the socket using verification with the root
100
+ # certs in self.ca_certs_path
101
+ self.sock = ssl.wrap_socket(sock,
102
+ self.key_file,
103
+ self.cert_file,
104
+ cert_reqs=ssl.CERT_REQUIRED,
105
+ ca_certs=self._ca_certs)
106
+
107
+
108
+ def verified_https_connection_with_ca_certs(ca_certs):
109
+ """
110
+ Creates VerifiedHTTPSConnection classes with given ca_certs file.
111
+ """
112
+ def wrapper(*args, **kw):
113
+ kw['ca_certs'] = ca_certs
114
+ return VerifiedHTTPSConnection(*args, **kw)
115
+ return wrapper
116
+
117
+
118
+ class VerifiedHTTPSHandler(urllib2.HTTPSHandler):
119
+ def __init__(self, connection_class=VerifiedHTTPSConnection):
120
+ self.specialized_conn_class = connection_class
121
+ urllib2.HTTPSHandler.__init__(self)
122
+
123
+ def https_open(self, req):
124
+ return self.do_open(self.specialized_conn_class, req)
125
+
126
+
127
+ class _URLOpenerCache(object):
128
+ """
129
+ Creates custom URLOpener with BasicAuth and HTTPS handler.
130
+
131
+ Caches and reuses opener if possible (i.e. if they share the same
132
+ ssl_ca_certs).
133
+ """
134
+ def __init__(self):
135
+ self._opener = {}
136
+
137
+ def __call__(self, ssl_ca_certs, url, username, password, insecure=False, manage_cookies=False):
138
+ cache_key = (ssl_ca_certs, insecure, manage_cookies)
139
+ if cache_key not in self._opener:
140
+ handlers = []
141
+ https_handler = build_https_handler(ssl_ca_certs, insecure)
142
+ if https_handler:
143
+ handlers.append(https_handler)
144
+ passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
145
+ authhandler = urllib2.HTTPBasicAuthHandler(passman)
146
+ handlers.append(authhandler)
147
+ authhandler = urllib2.HTTPDigestAuthHandler(passman)
148
+ handlers.append(authhandler)
149
+ if manage_cookies:
150
+ cj = CookieJar()
151
+ handlers.append(HTTPCookieProcessor(cj))
152
+
153
+ opener = urllib2.build_opener(*handlers)
154
+
155
+ opener.addheaders = [('User-agent', 'MapProxy-%s' % (version,))]
156
+
157
+ self._opener[cache_key] = (opener, passman)
158
+ else:
159
+ opener, passman = self._opener[cache_key]
160
+
161
+ if url is not None and username is not None and password is not None:
162
+ passman.add_password(None, url, username, password)
163
+
164
+ return opener
165
+
166
+ create_url_opener = _URLOpenerCache()
167
+
168
+ class HTTPClient(object):
169
+ def __init__(self, url=None, username=None, password=None, insecure=False,
170
+ ssl_ca_certs=None, timeout=None, headers=None, hide_error_details=False,
171
+ manage_cookies=False):
172
+ self._timeout = timeout
173
+ if url and url.startswith('https'):
174
+ if insecure:
175
+ ssl_ca_certs = None
176
+ elif ssl_ca_certs is None and not supports_ssl_default_context:
177
+ raise HTTPClientError('No ca_certs file set (http.ssl_ca_certs). '
178
+ 'Set file or disable verification with http.ssl_no_cert_checks option.')
179
+
180
+ self.opener = create_url_opener(ssl_ca_certs, url, username, password, insecure=insecure, manage_cookies=manage_cookies)
181
+ self.header_list = headers.items() if headers else []
182
+ self.hide_error_details = hide_error_details
183
+
184
+ def open(self, url, data=None, method=None):
185
+ code = None
186
+ result = None
187
+ try:
188
+ req = urllib2.Request(url, data=data)
189
+ except ValueError as e:
190
+ err = self.handle_url_exception(url, 'URL not correct', e.args[0])
191
+ reraise_exception(err, sys.exc_info())
192
+ for key, value in self.header_list:
193
+ req.add_header(key, value)
194
+ if method:
195
+ req.method=method
196
+ try:
197
+ start_time = time.time()
198
+ if self._timeout is not None:
199
+ result = self.opener.open(req, timeout=self._timeout)
200
+ else:
201
+ result = self.opener.open(req)
202
+ except HTTPError as e:
203
+ code = e.code
204
+ err = self.handle_url_exception(url, 'HTTP Error', str(code), response_code=code)
205
+ reraise_exception(err, sys.exc_info())
206
+ except URLError as e:
207
+ if isinstance(e.reason, ssl.SSLError):
208
+ err = self.handle_url_exception(url, 'Could not verify connection to URL', e.reason.args[1])
209
+ reraise_exception(err, sys.exc_info())
210
+ try:
211
+ reason = e.reason.args[1]
212
+ except (AttributeError, IndexError):
213
+ reason = e.reason
214
+ err = self.handle_url_exception(url, 'No response from URL', reason)
215
+ reraise_exception(err, sys.exc_info())
216
+ except ValueError as e:
217
+ err = self.handle_url_exception(url, 'URL not correct', e.args[0])
218
+ reraise_exception(err, sys.exc_info())
219
+ except Exception as e:
220
+ err = self.handle_url_exception(url, 'Internal HTTP error', repr(e))
221
+ reraise_exception(err, sys.exc_info())
222
+ else:
223
+ code = getattr(result, 'code', 200)
224
+ if code == 204:
225
+ raise HTTPClientError('HTTP Error "204 No Content"', response_code=204)
226
+ return result
227
+ finally:
228
+ log_request(url, code, result, duration=time.time()-start_time, method=req.get_method())
229
+
230
+ def open_image(self, url, data=None):
231
+ resp = self.open(url, data=data)
232
+ if 'content-type' in resp.headers:
233
+ if not resp.headers['content-type'].lower().startswith('image'):
234
+ raise HTTPClientError('response is not an image: (%s)' % (resp.read()))
235
+ return ImageSource(resp)
236
+
237
+ def handle_url_exception(self, url, message, reason, response_code=None):
238
+ full_msg = '%s "%s": %s' % (message, url, reason)
239
+ if self.hide_error_details:
240
+ return HTTPClientError(
241
+ '{} (see logs for URL and reason).'.format(message),
242
+ response_code=response_code,
243
+ full_msg=full_msg,
244
+ )
245
+ else:
246
+ return HTTPClientError(
247
+ full_msg,
248
+ response_code=response_code,
249
+ )
250
+
251
+ def auth_data_from_url(url):
252
+ """
253
+ >>> auth_data_from_url('invalid_url')
254
+ ('invalid_url', (None, None))
255
+ >>> auth_data_from_url('http://localhost/bar')
256
+ ('http://localhost/bar', (None, None))
257
+ >>> auth_data_from_url('http://bar@localhost/bar')
258
+ ('http://localhost/bar', ('bar', None))
259
+ >>> auth_data_from_url('http://bar:baz@localhost/bar')
260
+ ('http://localhost/bar', ('bar', 'baz'))
261
+ >>> auth_data_from_url('http://bar:b:az@@localhost/bar')
262
+ ('http://localhost/bar', ('bar', 'b:az@'))
263
+ >>> auth_data_from_url('http://bar foo; foo@bar:b:az@@localhost/bar')
264
+ ('http://localhost/bar', ('bar foo; foo@bar', 'b:az@'))
265
+ >>> auth_data_from_url('https://bar:foo#;%$@localhost/bar')
266
+ ('https://localhost/bar', ('bar', 'foo#;%$'))
267
+ >>> auth_data_from_url('http://localhost/bar@2x')
268
+ ('http://localhost/bar@2x', (None, None))
269
+ >>> auth_data_from_url('http://bar@localhost/bar@2x')
270
+ ('http://localhost/bar@2x', ('bar', None))
271
+ >>> auth_data_from_url('http://bar:baz@localhost/bar@2x')
272
+ ('http://localhost/bar@2x', ('bar', 'baz'))
273
+ >>> auth_data_from_url('https://bar@localhost/bar/0/0/0@2x.png')
274
+ ('https://localhost/bar/0/0/0@2x.png', ('bar', None))
275
+ >>> auth_data_from_url('http://bar:baz@localhost/bar@2x.png')
276
+ ('http://localhost/bar@2x.png', ('bar', 'baz'))
277
+ """
278
+ if not url or '://' not in url:
279
+ # be silent for invalid URLs
280
+ return url, (None, None)
281
+
282
+ schema, url = url.split('://', 1)
283
+ if '/' in url:
284
+ host, request = url.split('/', 1)
285
+ else:
286
+ host, request = url, ''
287
+
288
+ username = password = None
289
+ if '@' in host:
290
+ auth_data, host = host.rsplit('@', 1)
291
+ if ':' in auth_data:
292
+ username, password = auth_data.split(':', 1)
293
+ else:
294
+ username = auth_data
295
+ url = schema + "://" + host + "/" + request
296
+ return url, (username, password)
297
+
298
+
299
+ def open_url(url):
300
+ url, (username, password) = auth_data_from_url(url)
301
+ http_client = HTTPClient(url, username, password)
302
+ return http_client.open(url)
303
+
304
+ def retrieve_image(url, client=None):
305
+ """
306
+ Retrive an image from `url`.
307
+
308
+ :return: the image as a file object (with url .header and .info)
309
+ :raise HTTPClientError: if response content-type doesn't start with image
310
+ """
311
+ resp = open_url(url)
312
+ if not resp.headers['content-type'].startswith('image'):
313
+ raise HTTPClientError('response is not an image: (%s)' % (resp.read()))
314
+ return ImageSource(resp)
315
+
mapproxy/client/log.py ADDED
@@ -0,0 +1,33 @@
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
+ import logging
17
+ logger = logging.getLogger('mapproxy.source.request')
18
+
19
+ def log_request(url, status, result=None, size=None, method='GET', duration=None):
20
+ if not logger.isEnabledFor(logging.INFO):
21
+ return
22
+
23
+ if not size and result is not None:
24
+ size = result.headers.get('Content-length')
25
+ if size:
26
+ size = '%.1f' % (int(size)/1024.0, )
27
+ else:
28
+ size = '-'
29
+ if not status:
30
+ status = '-'
31
+ duration = '%d' % (duration*1000) if duration else '-'
32
+ logger.info('%s %s %s %s %s', method, url.replace(' ', ''), status, size, duration)
33
+