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,476 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2010-2013 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 glob
17
+ import multiprocessing
18
+ import os
19
+ import random
20
+ import shutil
21
+ import sys
22
+ import tempfile
23
+ import threading
24
+ import time
25
+
26
+ from mapproxy.util.lock import FileLock, SemLock, cleanup_lockdir, LockTimeout
27
+ from mapproxy.util.fs import (
28
+ _force_rename_dir,
29
+ swap_dir,
30
+ cleanup_directory,
31
+ write_atomic,
32
+ )
33
+ from mapproxy.util.py import reraise_exception
34
+ from mapproxy.util.times import timestamp_before
35
+ from mapproxy.test.helper import Mocker
36
+
37
+
38
+ is_win = sys.platform == "win32"
39
+
40
+
41
+ class TestFileLock(Mocker):
42
+
43
+ def setup_method(self):
44
+ Mocker.setup_method(self)
45
+ self.lock_dir = tempfile.mkdtemp()
46
+ self.lock_file = os.path.join(self.lock_dir, "lock.lck")
47
+
48
+ def teardown_method(self):
49
+ shutil.rmtree(self.lock_dir)
50
+ Mocker.teardown_method(self)
51
+
52
+ def test_file_lock_timeout(self):
53
+ lock = self._create_lock()
54
+ assert_locked(self.lock_file)
55
+ lock # prevent lint warnings
56
+
57
+ def test_file_lock(self):
58
+ # Test a lock that becomes free during a waiting lock() call.
59
+ class Lock(threading.Thread):
60
+
61
+ def __init__(self, lock_file):
62
+ threading.Thread.__init__(self)
63
+ self.lock_file = lock_file
64
+ self.lock = FileLock(self.lock_file)
65
+
66
+ def run(self):
67
+ self.lock.lock()
68
+ time.sleep(0.2)
69
+ self.lock.unlock()
70
+
71
+ lock_thread = Lock(self.lock_file)
72
+ start_time = time.time()
73
+ lock_thread.start()
74
+
75
+ # wait until thread got the locked
76
+ while not lock_thread.lock._locked:
77
+ time.sleep(0.001)
78
+
79
+ # one lock that times out
80
+ assert_locked(self.lock_file)
81
+
82
+ # one lock that will get it after some time
83
+ x = FileLock(self.lock_file, timeout=0.3, step=0.001)
84
+ x.lock()
85
+
86
+ locked_for = time.time() - start_time
87
+ assert locked_for - 0.2 <= 0.1, "locking took to long?! (rerun if not sure)"
88
+
89
+ # cleanup
90
+ x.unlock()
91
+ lock_thread.join()
92
+
93
+ def test_lock_cleanup(self):
94
+ old_lock_file = os.path.join(self.lock_dir, "lock_old.lck")
95
+ x = FileLock(old_lock_file)
96
+ x.lock()
97
+ x.unlock()
98
+ mtime = os.stat(old_lock_file).st_mtime
99
+ mtime -= 7 * 60
100
+ os.utime(old_lock_file, (mtime, mtime))
101
+
102
+ x = self._create_lock()
103
+ x.unlock()
104
+ assert os.path.exists(old_lock_file)
105
+ assert os.path.exists(self.lock_file)
106
+ cleanup_lockdir(self.lock_dir)
107
+
108
+ assert not os.path.exists(old_lock_file)
109
+ assert os.path.exists(self.lock_file)
110
+
111
+ def test_concurrent_access(self):
112
+ count_file = os.path.join(self.lock_dir, "count.txt")
113
+ with open(count_file, "wb") as f:
114
+ f.write(b"0")
115
+
116
+ def count_up():
117
+ with FileLock(self.lock_file, timeout=60):
118
+ with open(count_file, "r+b") as f:
119
+ counter = int(f.read().strip())
120
+ f.seek(0)
121
+ f.write(str(counter + 1).encode("utf-8"))
122
+
123
+ def do_it():
124
+ for x in range(20):
125
+ time.sleep(0.002)
126
+ count_up()
127
+
128
+ threads = [threading.Thread(target=do_it) for _ in range(20)]
129
+ [t.start() for t in threads]
130
+ [t.join() for t in threads]
131
+
132
+ with open(count_file, "r+b") as f:
133
+ counter = int(f.read().strip())
134
+
135
+ assert counter == 400, counter
136
+
137
+ def test_remove_on_unlock(self):
138
+ x = FileLock(self.lock_file, remove_on_unlock=True)
139
+ x.lock()
140
+ assert os.path.exists(self.lock_file)
141
+ x.unlock()
142
+ if is_win: # not removed on windows
143
+ assert os.path.exists(self.lock_file)
144
+ else:
145
+ assert not os.path.exists(self.lock_file)
146
+
147
+ if is_win:
148
+ # not possible to remove lock file when lock is held
149
+ pass
150
+ else:
151
+ x.lock()
152
+ assert os.path.exists(self.lock_file)
153
+ os.remove(self.lock_file)
154
+ assert not os.path.exists(self.lock_file)
155
+ # ignore removed lock
156
+ x.unlock()
157
+ assert not os.path.exists(self.lock_file)
158
+
159
+ def _create_lock(self):
160
+ lock = FileLock(self.lock_file)
161
+ lock.lock()
162
+ return lock
163
+
164
+
165
+ def assert_locked(lock_file, timeout=0.02, step=0.001):
166
+ assert os.path.exists(lock_file)
167
+ x = FileLock(lock_file, timeout=timeout, step=step)
168
+ try:
169
+ x.lock()
170
+ assert False, "file was not locked"
171
+ except LockTimeout:
172
+ pass
173
+
174
+
175
+ class TestSemLock(object):
176
+
177
+ def setup_method(self):
178
+ self.lock_dir = tempfile.mkdtemp()
179
+ self.lock_file = os.path.join(self.lock_dir, "lock.lck")
180
+
181
+ def teardown_method(self):
182
+ shutil.rmtree(self.lock_dir)
183
+
184
+ def count_lockfiles(self):
185
+ return len(glob.glob(self.lock_file + "*"))
186
+
187
+ def test_single(self):
188
+ locks = [SemLock(self.lock_file, 1, timeout=0.01) for _ in range(2)]
189
+ locks[0].lock()
190
+ try:
191
+ locks[1].lock()
192
+ except LockTimeout:
193
+ pass
194
+ else:
195
+ assert False, "expected LockTimeout"
196
+
197
+ def test_creating(self):
198
+ locks = [SemLock(self.lock_file, 2) for _ in range(3)]
199
+
200
+ assert self.count_lockfiles() == 0
201
+ locks[0].lock()
202
+ assert self.count_lockfiles() == 1
203
+ locks[1].lock()
204
+ assert self.count_lockfiles() == 2
205
+ assert os.path.exists(locks[0]._lock._path)
206
+ assert os.path.exists(locks[1]._lock._path)
207
+ locks[0].unlock()
208
+ locks[2].lock()
209
+ locks[2].unlock()
210
+ locks[1].unlock()
211
+
212
+ def test_timeout(self):
213
+ locks = [SemLock(self.lock_file, 2, timeout=0.1) for _ in range(3)]
214
+
215
+ assert self.count_lockfiles() == 0
216
+ locks[0].lock()
217
+ assert self.count_lockfiles() == 1
218
+ locks[1].lock()
219
+ assert self.count_lockfiles() == 2
220
+ try:
221
+ locks[2].lock()
222
+ except LockTimeout:
223
+ pass
224
+ else:
225
+ assert False, "expected LockTimeout"
226
+ locks[0].unlock()
227
+ locks[2].unlock()
228
+
229
+ def test_load(self):
230
+ locks = [SemLock(self.lock_file, 8, timeout=1) for _ in range(20)]
231
+
232
+ new_locks = random.sample([x for x in locks if not x._locked], 5)
233
+ for x in new_locks:
234
+ x.lock()
235
+
236
+ for _ in range(20):
237
+ old_locks = random.sample([x for x in locks if x._locked], 3)
238
+ for x in old_locks:
239
+ x.unlock()
240
+ assert len([x for x in locks if x._locked]) == 2
241
+ assert len([x for x in locks if not x._locked]) == 18
242
+
243
+ new_locks = random.sample([x for x in locks if not x._locked], 3)
244
+ for x in new_locks:
245
+ x.lock()
246
+
247
+ assert len([x for x in locks if x._locked]) == 5
248
+ assert len([x for x in locks if not x._locked]) == 15
249
+
250
+ assert self.count_lockfiles() == 8
251
+
252
+
253
+ class DirTest(object):
254
+
255
+ def setup_method(self):
256
+ self.tmpdir = tempfile.mkdtemp()
257
+
258
+ def teardown_method(self):
259
+ if os.path.exists(self.tmpdir):
260
+ shutil.rmtree(self.tmpdir)
261
+
262
+ def mkdir(self, name):
263
+ dirname = os.path.join(self.tmpdir, name)
264
+ os.mkdir(dirname)
265
+ self.mkfile(name, dirname=dirname)
266
+ return dirname
267
+
268
+ def mkfile(self, name, dirname=None):
269
+ if dirname is None:
270
+ dirname = self.mkdir(name)
271
+ filename = os.path.join(dirname, name + ".txt")
272
+ open(filename, "wb").close()
273
+ return filename
274
+
275
+
276
+ class TestForceRenameDir(DirTest):
277
+
278
+ def test_rename(self):
279
+ src_dir = self.mkdir("bar")
280
+ dst_dir = os.path.join(self.tmpdir, "baz")
281
+ _force_rename_dir(src_dir, dst_dir)
282
+ assert os.path.exists(dst_dir)
283
+ assert os.path.exists(os.path.join(dst_dir, "bar.txt"))
284
+ assert not os.path.exists(src_dir)
285
+
286
+ def test_rename_overwrite(self):
287
+ src_dir = self.mkdir("bar")
288
+ dst_dir = self.mkdir("baz")
289
+ _force_rename_dir(src_dir, dst_dir)
290
+ assert os.path.exists(dst_dir)
291
+ assert os.path.exists(os.path.join(dst_dir, "bar.txt"))
292
+ assert not os.path.exists(src_dir)
293
+
294
+
295
+ class TestSwapDir(DirTest):
296
+
297
+ def test_swap_dir(self):
298
+ src_dir = self.mkdir("bar")
299
+ dst_dir = os.path.join(self.tmpdir, "baz")
300
+
301
+ swap_dir(src_dir, dst_dir)
302
+ assert os.path.exists(dst_dir)
303
+ assert os.path.exists(os.path.join(dst_dir, "bar.txt"))
304
+ assert not os.path.exists(src_dir)
305
+
306
+ def test_swap_dir_w_old(self):
307
+ src_dir = self.mkdir("bar")
308
+ dst_dir = self.mkdir("baz")
309
+
310
+ swap_dir(src_dir, dst_dir)
311
+ assert os.path.exists(dst_dir)
312
+ assert os.path.exists(os.path.join(dst_dir, "bar.txt"))
313
+ assert not os.path.exists(src_dir)
314
+
315
+ def test_swap_dir_keep_old(self):
316
+ src_dir = self.mkdir("bar")
317
+ dst_dir = self.mkdir("baz")
318
+
319
+ swap_dir(src_dir, dst_dir, keep_old=True, backup_ext=".bak")
320
+ assert os.path.exists(dst_dir)
321
+ assert os.path.exists(os.path.join(dst_dir, "bar.txt"))
322
+ assert os.path.exists(dst_dir + ".bak")
323
+ assert os.path.exists(os.path.join(dst_dir + ".bak", "baz.txt"))
324
+
325
+
326
+ class TestCleanupDirectory(DirTest):
327
+
328
+ def test_no_remove(self):
329
+ dirs = [self.mkdir("dir" + str(n)) for n in range(10)]
330
+ for d in dirs:
331
+ assert os.path.exists(d), d
332
+ cleanup_directory(self.tmpdir, timestamp_before(minutes=1))
333
+ for d in dirs:
334
+ assert os.path.exists(d), d
335
+
336
+ def test_file_handler(self):
337
+ files = []
338
+ file_handler_calls = []
339
+
340
+ def file_handler(filename):
341
+ file_handler_calls.append(filename)
342
+
343
+ new_date = timestamp_before(weeks=1)
344
+ for n in range(10):
345
+ fname = "foo" + str(n)
346
+ filename = self.mkfile(fname)
347
+ os.utime(filename, (new_date, new_date))
348
+ files.append(filename)
349
+
350
+ for filename in files:
351
+ assert os.path.exists(filename), filename
352
+ cleanup_directory(self.tmpdir, timestamp_before(), file_handler=file_handler)
353
+ for filename in files:
354
+ assert os.path.exists(filename), filename
355
+
356
+ assert set(files) == set(file_handler_calls)
357
+
358
+ def test_no_directory(self):
359
+ cleanup_directory(os.path.join(self.tmpdir, "invalid"), timestamp_before())
360
+ # nothing should happen
361
+
362
+ def test_remove_all(self):
363
+ files = []
364
+ new_date = timestamp_before(weeks=1)
365
+ for n in range(10):
366
+ fname = "foo" + str(n)
367
+ filename = self.mkfile(fname)
368
+ os.utime(filename, (new_date, new_date))
369
+ files.append(filename)
370
+
371
+ for filename in files:
372
+ assert os.path.exists(filename), filename
373
+ cleanup_directory(self.tmpdir, timestamp_before())
374
+ for filename in files:
375
+ assert not os.path.exists(filename), filename
376
+ assert not os.path.exists(os.path.dirname(filename)), filename
377
+
378
+ def test_remove_empty_dirs(self):
379
+ os.makedirs(os.path.join(self.tmpdir, "foo", "bar", "baz"))
380
+ cleanup_directory(self.tmpdir, timestamp_before(minutes=-1))
381
+ assert not os.path.exists(os.path.join(self.tmpdir, "foo"))
382
+
383
+ def test_remove_some(self):
384
+ files = []
385
+ # create a few files, every other file is one week old
386
+ new_date = timestamp_before(weeks=1)
387
+ for n in range(10):
388
+ fname = "foo" + str(n)
389
+ filename = self.mkfile(fname)
390
+ if n % 2 == 0:
391
+ os.utime(filename, (new_date, new_date))
392
+ files.append(filename)
393
+
394
+ # check all files are present
395
+ for filename in files:
396
+ assert os.path.exists(filename), filename
397
+
398
+ # cleanup_directory for all files older then one minute
399
+ cleanup_directory(self.tmpdir, timestamp_before(minutes=1))
400
+
401
+ # check old files and dirs are removed
402
+ for filename in files[::2]:
403
+ assert not os.path.exists(filename), filename
404
+ assert not os.path.exists(os.path.dirname(filename)), filename
405
+
406
+ # check new files are still present
407
+ for filename in files[1::2]:
408
+ assert os.path.exists(filename), filename
409
+
410
+
411
+ def _write_atomic_data(i_filename):
412
+ (i, filename) = i_filename
413
+ data = str(i) + "\n" + "x" * 10000
414
+ write_atomic(filename, data.encode("utf-8"))
415
+ time.sleep(0.001)
416
+
417
+
418
+ class TestWriteAtomic(object):
419
+
420
+ def setup_method(self):
421
+ self.dirname = tempfile.mkdtemp()
422
+
423
+ def teardown_method(self):
424
+ if self.dirname:
425
+ shutil.rmtree(self.dirname)
426
+
427
+ def test_concurrent_write(self):
428
+ filename = os.path.join(self.dirname, "tmpfile")
429
+
430
+ num_writes = 800
431
+ concurrent_writes = 8
432
+
433
+ p = multiprocessing.Pool(concurrent_writes)
434
+ p.map(_write_atomic_data, ((i, filename) for i in range(num_writes)))
435
+ p.close()
436
+ p.join()
437
+
438
+ assert os.path.exists(filename)
439
+ last_i = int(open(filename).readline())
440
+ assert last_i > (num_writes / 2), (
441
+ "file should contain content from "
442
+ "later writes, got content from write %d" % (last_i + 1)
443
+ )
444
+ os.unlink(filename)
445
+ assert os.listdir(self.dirname) == []
446
+
447
+ def test_not_a_file(self):
448
+ # check that expected errors are not hidden
449
+ filename = os.path.join(self.dirname, "tmpfile")
450
+ os.mkdir(filename)
451
+
452
+ try:
453
+ write_atomic(filename, b"12345")
454
+ except (OSError, IOError):
455
+ pass
456
+ else:
457
+ assert False, "expected exception"
458
+
459
+
460
+ def test_reraise_exception():
461
+
462
+ def valueerror_raiser():
463
+ raise ValueError()
464
+
465
+ def reraiser():
466
+ try:
467
+ valueerror_raiser()
468
+ except ValueError:
469
+ reraise_exception(TypeError(), sys.exc_info())
470
+
471
+ try:
472
+ reraiser()
473
+ except TypeError as ex:
474
+ assert ex
475
+ else:
476
+ assert False, "expected exception"
@@ -0,0 +1,44 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2014 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.service.wms import limit_srs_extents
17
+ from mapproxy.layer import DefaultMapExtent, MapExtent
18
+ from mapproxy.srs import SRS
19
+
20
+
21
+ class TestLimitSRSExtents(object):
22
+
23
+ def test_defaults(self):
24
+ assert limit_srs_extents({}, ["EPSG:4326", "EPSG:3857"]) == {
25
+ "EPSG:4326": DefaultMapExtent(),
26
+ "EPSG:3857": DefaultMapExtent(),
27
+ }
28
+
29
+ def test_unsupported(self):
30
+ assert (
31
+ limit_srs_extents(
32
+ {"EPSG:9999": DefaultMapExtent()}, ["EPSG:4326", "EPSG:3857"]
33
+ )
34
+ == {}
35
+ )
36
+
37
+ def test_limited_unsupported(self):
38
+ assert limit_srs_extents(
39
+ {
40
+ "EPSG:9999": DefaultMapExtent(),
41
+ "EPSG:4326": MapExtent([0, 0, 10, 10], SRS(4326)),
42
+ },
43
+ ["EPSG:4326", "EPSG:3857"],
44
+ ) == {"EPSG:4326": MapExtent([0, 0, 10, 10], SRS(4326))}
@@ -0,0 +1,113 @@
1
+ # This file is part of the MapProxy project.
2
+ # Copyright (C) 2013 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 __future__ import division
17
+
18
+ from mapproxy.layer import MapQuery, InfoQuery
19
+ from mapproxy.srs import SRS
20
+ from mapproxy.service.wms import combined_layers
21
+ from mapproxy.source.wms import WMSSource
22
+ from mapproxy.client.wms import WMSClient
23
+ from mapproxy.request.wms import create_request
24
+
25
+
26
+ class TestCombinedLayers(object):
27
+ q = MapQuery((0, 0, 10000, 10000), (100, 100), SRS(3857))
28
+
29
+ def test_empty(self):
30
+ assert combined_layers([], self.q) == []
31
+
32
+ def test_same_source(self):
33
+ layers = [
34
+ WMSSource(
35
+ WMSClient(create_request({"url": "http://foo/", "layers": "a"}, {}))
36
+ ),
37
+ WMSSource(
38
+ WMSClient(create_request({"url": "http://foo/", "layers": "b"}, {}))
39
+ ),
40
+ ]
41
+ combined = combined_layers(layers, self.q)
42
+ assert len(combined) == 1
43
+ assert combined[0].client.request_template.params.layers == ["a", "b"]
44
+
45
+ def test_mixed_hosts(self):
46
+ layers = [
47
+ WMSSource(
48
+ WMSClient(create_request({"url": "http://foo/", "layers": "a"}, {}))
49
+ ),
50
+ WMSSource(
51
+ WMSClient(create_request({"url": "http://foo/", "layers": "b"}, {}))
52
+ ),
53
+ WMSSource(
54
+ WMSClient(create_request({"url": "http://bar/", "layers": "c"}, {}))
55
+ ),
56
+ WMSSource(
57
+ WMSClient(create_request({"url": "http://bar/", "layers": "d"}, {}))
58
+ ),
59
+ WMSSource(
60
+ WMSClient(create_request({"url": "http://foo/", "layers": "e"}, {}))
61
+ ),
62
+ WMSSource(
63
+ WMSClient(create_request({"url": "http://foo/", "layers": "f"}, {}))
64
+ ),
65
+ ]
66
+ combined = combined_layers(layers, self.q)
67
+ assert len(combined) == 3
68
+ assert combined[0].client.request_template.params.layers == ["a", "b"]
69
+ assert combined[1].client.request_template.params.layers == ["c", "d"]
70
+ assert combined[2].client.request_template.params.layers == ["e", "f"]
71
+
72
+ def test_mixed_params(self):
73
+ layers = [
74
+ WMSSource(
75
+ WMSClient(create_request({"url": "http://foo/", "layers": "a"}, {}))
76
+ ),
77
+ WMSSource(
78
+ WMSClient(create_request({"url": "http://foo/", "layers": "b"}, {}))
79
+ ),
80
+ WMSSource(
81
+ WMSClient(create_request({"url": "http://foo/", "layers": "c"}, {}))
82
+ ),
83
+ WMSSource(
84
+ WMSClient(create_request({"url": "http://foo/", "layers": "d"}, {}))
85
+ ),
86
+ WMSSource(
87
+ WMSClient(create_request({"url": "http://foo/", "layers": "e"}, {}))
88
+ ),
89
+ WMSSource(
90
+ WMSClient(create_request({"url": "http://foo/", "layers": "f"}, {}))
91
+ ),
92
+ ]
93
+
94
+ layers[0].supported_srs = ["EPSG:4326"]
95
+ layers[1].supported_srs = ["EPSG:4326"]
96
+
97
+ layers[2].supported_formats = ["image/png"]
98
+ layers[3].supported_formats = ["image/png"]
99
+
100
+ combined = combined_layers(layers, self.q)
101
+ assert len(combined) == 3
102
+ assert combined[0].client.request_template.params.layers == ["a", "b"]
103
+ assert combined[1].client.request_template.params.layers == ["c", "d"]
104
+ assert combined[2].client.request_template.params.layers == ["e", "f"]
105
+
106
+
107
+ class TestInfoQuery(object):
108
+
109
+ def test_coord(self):
110
+ query = InfoQuery(
111
+ (8, 50, 9, 51), (400, 1000), SRS(4326), (100, 600), "text/plain"
112
+ )
113
+ assert query.coord == (8.25, 50.4)
@@ -0,0 +1,68 @@
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 os
17
+ import tempfile
18
+
19
+ from mapproxy.util.yaml import load_yaml, load_yaml_file, YAMLError
20
+
21
+
22
+ class TestLoadYAMLFile(object):
23
+
24
+ def setup_method(self):
25
+ self.tmp_files = []
26
+
27
+ def teardown_method(self):
28
+ for f in self.tmp_files:
29
+ os.unlink(f)
30
+
31
+ def yaml_file(self, content):
32
+ fd, fname = tempfile.mkstemp()
33
+ f = os.fdopen(fd, "w")
34
+ f.write(content)
35
+ self.tmp_files.append(fname)
36
+ return fname
37
+
38
+ def test_load_yaml_file(self):
39
+ f = self.yaml_file("hello:\n - 1\n - 2")
40
+ doc = load_yaml_file(open(f))
41
+ assert doc == {"hello": [1, 2]}
42
+
43
+ def test_load_yaml_file_filename(self):
44
+ f = self.yaml_file("hello:\n - 1\n - 2")
45
+ assert isinstance(f, str)
46
+ doc = load_yaml_file(f)
47
+ assert doc == {"hello": [1, 2]}
48
+
49
+ def test_load_yaml(self):
50
+ doc = load_yaml("hello:\n - 1\n - 2")
51
+ assert doc == {"hello": [1, 2]}
52
+
53
+ def test_load_yaml_with_tabs(self):
54
+ try:
55
+ f = self.yaml_file("hello:\n\t- world")
56
+ load_yaml_file(f)
57
+ except YAMLError as ex:
58
+ assert "line 2" in str(ex)
59
+ else:
60
+ assert False, "expected YAMLError"
61
+
62
+ def test_load_yaml_string_error(self):
63
+ try:
64
+ load_yaml('only a string')
65
+ except YAMLError as ex:
66
+ assert "not a YAML dict" in str(ex)
67
+ else:
68
+ assert False, "expected YAMLError"