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,274 @@
1
+ # -:- encoding: utf8 -:-
2
+ # Copyright (c) 2011, Oliver Tonnhofer <olt@omniscale.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+
22
+ from __future__ import absolute_import
23
+
24
+ import unittest
25
+
26
+ from ..validator import validate, ValidationError, SpecError
27
+ from ..spec import required, one_of, number, recursive, type_spec, anything
28
+ from mapproxy.compat import string_type
29
+
30
+ def raises(exception):
31
+ def wrapper(f):
32
+ def _wrapper(self):
33
+ try:
34
+ f(self)
35
+ except exception:
36
+ pass
37
+ else:
38
+ raise AssertionError('expected exception %s', exception)
39
+ return wrapper
40
+
41
+ class TestSimpleDict(unittest.TestCase):
42
+ def test_validate_simple_dict(self):
43
+ spec = {'hello': 1, 'world': True}
44
+ validate(spec, {'hello': 34, 'world': False})
45
+
46
+ @raises(ValidationError)
47
+ def test_invalid_key(self):
48
+ spec = {'world': True}
49
+ validate(spec, {'world_foo': False})
50
+
51
+ def test_empty_data(self):
52
+ spec = {'world': 1}
53
+ validate(spec, {})
54
+
55
+ @raises(ValidationError)
56
+ def test_invalid_value(self):
57
+ spec = {'world': 1}
58
+ validate(spec, {'world_foo': False})
59
+
60
+ @raises(ValidationError)
61
+ def test_missing_required_key(self):
62
+ spec = {required('world'): 1}
63
+ validate(spec, {})
64
+
65
+ def test_valid_one_of(self):
66
+ spec = {'hello': one_of(1, bool())}
67
+ validate(spec, {'hello': 129})
68
+ validate(spec, {'hello': True})
69
+
70
+ @raises(ValidationError)
71
+ def test_invalid_one_of(self):
72
+ spec = {'hello': one_of(1, False)}
73
+ validate(spec, {'hello': []})
74
+
75
+ def test_instances_and_types(self):
76
+ spec = {'str()': str(), 'string_type': string_type, 'int': int, 'int()': int()}
77
+ validate(spec, {'str()': 'str', 'string_type': u'☃', 'int': 1, 'int()': 1})
78
+
79
+
80
+ class TestLists(unittest.TestCase):
81
+ def test_list(self):
82
+ spec = [1]
83
+ validate(spec, [1, 2, 3, 4, -9])
84
+
85
+ def test_empty_list(self):
86
+ spec = [1]
87
+ validate(spec, [])
88
+
89
+ @raises(ValidationError)
90
+ def test_invalid_item(self):
91
+ spec = [1]
92
+ validate(spec, [1, 'hello'])
93
+
94
+ class TestNumber(unittest.TestCase):
95
+ def check_valid(self, spec, data):
96
+ validate(spec, data)
97
+
98
+ def test_numbers(self):
99
+ spec = number()
100
+ for i in (0, 1, 23e999, int(10e20), 23.1, -0.0000000001):
101
+ self.check_valid(spec, i)
102
+
103
+ class TestNested(unittest.TestCase):
104
+ def check_valid(self, spec, data):
105
+ validate(spec, data)
106
+
107
+ def check_invalid(self, spec, data):
108
+ try:
109
+ validate(spec, data)
110
+ except ValidationError:
111
+ pass
112
+ else:
113
+ assert False, "expected ValidationError"
114
+
115
+ def test_dict(self):
116
+ spec = {
117
+ 'globals': {
118
+ 'image': {
119
+ 'format': {
120
+ 'png': {
121
+ 'mode': 'RGB',
122
+ }
123
+ },
124
+ },
125
+ 'cache': {
126
+ 'base_dir': '/path/to/foo'
127
+ }
128
+ }
129
+ }
130
+
131
+ self.check_valid(spec, {'globals': {'image': {'format': {'png': {'mode': 'P'}}}}})
132
+ self.check_valid(spec, {'globals': {'image': {'format': {'png': {'mode': 'P'}}},
133
+ 'cache': {'base_dir': '/somewhere'}}})
134
+ self.check_invalid(spec, {'globals': {'image': {'foo': {'png': {'mode': 'P'}}}}})
135
+ self.check_invalid(spec, {'globals': {'image': {'png': {'png': {'mode': 1}}}}})
136
+
137
+
138
+ def test_errors_in_unicode_keys(self):
139
+ # should not raise UnicodeEncodeError
140
+ spec = {
141
+ anything(): str(),
142
+ }
143
+ self.check_invalid(spec, {u'globalü': 12})
144
+
145
+ class TestRecursive(unittest.TestCase):
146
+ def test(self):
147
+ spec = recursive({'hello': str(), 'more': recursive()})
148
+ validate(spec, {'hello': 'world', 'more': {'hello': 'foo', 'more': {'more': {}}}})
149
+
150
+ def test_multiple(self):
151
+ spec = {'a': recursive({'hello': str(), 'more': recursive()}), 'b': recursive({'foo': recursive()})}
152
+ validate(spec, {'b': {'foo': {'foo': {}}}})
153
+ validate(spec, {'a': {'hello': 'world', 'more': {'hello': 'foo', 'more': {'more': {}}}}})
154
+ validate(spec, {'b': {'foo': {'foo': {}}},
155
+ 'a': {'hello': 'world', 'more': {'hello': 'foo', 'more': {'more': {}}}}})
156
+ @raises(SpecError)
157
+ def test_without_spec(self):
158
+ spec = {'a': recursive()}
159
+ validate(spec, {'a': {'a': {}}})
160
+
161
+ class TestTypeSpec(unittest.TestCase):
162
+ def test(self):
163
+ spec = type_spec('type', {'foo': {'alpha': str()}, 'bar': {'one': 1, 'two': str()}})
164
+ validate(spec, {'type': 'foo', 'alpha': 'yes'})
165
+ validate(spec, {'type': 'bar', 'one': 2})
166
+
167
+ def test_missing_type(self):
168
+ spec = type_spec('type', {'foo': {'alpha': str()}, 'bar': {'one': 1, 'two': str()}})
169
+ try:
170
+ validate(spec, {'alpha': 'yes'})
171
+ except ValidationError as ex:
172
+ assert "'type' not in ." in ex.errors[0]
173
+ else:
174
+ assert False
175
+
176
+ def test_unknown_type(self):
177
+ spec = type_spec('type', {'foo': {'alpha': str()}, 'bar': {'one': 1, 'two': str()}})
178
+ try:
179
+ validate(spec, {'type': 'baz', 'alpha': 'yes'})
180
+ except ValidationError as ex:
181
+ assert "unknown type value 'baz' in ." in ex.errors[0], ex
182
+ else:
183
+ assert False
184
+
185
+ def test_no_type_dict(self):
186
+ spec = {'dict': type_spec('type', {'foo': {'alpha': str()}, 'bar': {'one': 1, 'two': str()}})}
187
+ try:
188
+ validate(spec, {'dict': None})
189
+ except ValidationError as ex:
190
+ assert "dict is empty" in ex.errors[0], ex
191
+ else:
192
+ assert False
193
+
194
+
195
+ class TestErrors(unittest.TestCase):
196
+ def test_invalid_types(self):
197
+ spec = {'str': str, 'str()': str(), 'string_type': string_type, '1': 1, 'int': int}
198
+ try:
199
+ validate(spec, {'str': 1, 'str()': 1, 'string_type': 1, '1': 'a', 'int': 'int'})
200
+ except ValidationError as ex:
201
+ ex.errors.sort()
202
+ assert ex.errors[0] == "'a' in 1 not of type int"
203
+ assert ex.errors[1] == "'int' in int not of type int"
204
+ assert ex.errors[2] == '1 in str not of type str'
205
+ assert ex.errors[3] == '1 in str() not of type str'
206
+ assert ex.errors[4] in (
207
+ '1 in string_type not of type basestring', #PY2
208
+ '1 in string_type not of type str') #PY3
209
+ else:
210
+ assert False
211
+
212
+ def test_invalid_key(self):
213
+ spec = {'world': {'europe': {}}}
214
+ try:
215
+ validate(spec, {'world': {'europe': {'germany': 1}}})
216
+ except ValidationError as ex:
217
+ assert 'world.europe' in str(ex)
218
+ else:
219
+ assert False
220
+
221
+ def test_invalid_list_item(self):
222
+ spec = {'numbers': [number()]}
223
+ try:
224
+ validate(spec, {'numbers': [1, 2, 3, 'foo']})
225
+ except ValidationError as ex:
226
+ assert 'numbers[3] not of type number' in str(ex), str(ex)
227
+ else:
228
+ assert False
229
+
230
+ def test_multiple_invalid_list_items(self):
231
+ spec = {'numbers': [number()]}
232
+ try:
233
+ validate(spec, {'numbers': [1, True, 3, 'foo']})
234
+ except ValidationError as ex:
235
+ assert '2 validation errors' in str(ex), str(ex)
236
+ assert 'numbers[1] not of type number' in ex.errors[0]
237
+ assert 'numbers[3] not of type number' in ex.errors[1]
238
+ else:
239
+ assert False
240
+
241
+ def test_error_in_non_string_key(self):
242
+ spec = {1: bool()}
243
+ try:
244
+ validate(spec, {1: 'not a bool'})
245
+ except ValidationError as ex:
246
+ assert "'not a bool' in 1 not of type bool" in ex.errors[0]
247
+ else:
248
+ assert False
249
+
250
+ def test_error_in_non_string_key_with_anything_key_spec(self):
251
+ spec = {anything(): bool()}
252
+ try:
253
+ validate(spec, {1: 'not a bool'})
254
+ except ValidationError as ex:
255
+ assert "'not a bool' in 1 not of type bool" in ex.errors[0]
256
+ else:
257
+ assert False
258
+
259
+ def test_one_of_with_custom_types():
260
+ # test for fixed validation of one_of specs with values that are
261
+ # not lists or dicts (e.g. recursive)
262
+ spec = one_of([str], recursive({required('foo'): string_type}))
263
+ validate(spec, ['foo', 'bar'])
264
+ validate(spec, {'foo': 'bar'})
265
+ try:
266
+ validate(spec, {'nofoo': 'bar'})
267
+ except ValidationError as ex:
268
+ assert "missing 'foo'" in ex.errors[0]
269
+ else:
270
+ assert False
271
+
272
+ if __name__ == '__main__':
273
+ unittest.main()
274
+
@@ -0,0 +1,189 @@
1
+ # Copyright (c) 2011, Oliver Tonnhofer <olt@omniscale.de>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+
22
+ import re
23
+ from contextlib import contextmanager
24
+
25
+ from .spec import required, one_of, anything, recursive
26
+ from mapproxy.compat import iteritems, iterkeys, text_type
27
+
28
+ class Context(object):
29
+ def __init__(self):
30
+ self.recurse_spec = None
31
+ self.obj_pos = []
32
+
33
+ def push(self, spec):
34
+ self.obj_pos.append(spec)
35
+
36
+ def pop(self):
37
+ return self.obj_pos.pop()
38
+
39
+ @contextmanager
40
+ def pos(self, spec):
41
+ self.push(spec)
42
+ yield
43
+ self.pop()
44
+
45
+ @property
46
+ def current_pos(self):
47
+ return ''.join(self.obj_pos).lstrip('.') or '.'
48
+
49
+ def validate(spec, data):
50
+ """
51
+ Validate `data` against `spec`.
52
+ """
53
+ return Validator(spec).validate(data)
54
+
55
+ class ValidationError(TypeError):
56
+ def __init__(self, msg, errors=None, informal_only=False):
57
+ TypeError.__init__(self, msg)
58
+ self.informal_only = informal_only
59
+ self.errors = errors or []
60
+
61
+ class SpecError(TypeError):
62
+ pass
63
+
64
+ class Validator(object):
65
+ def __init__(self, spec, fail_fast=False):
66
+ """
67
+ :params fail_fast: True if it should raise on the first error
68
+ """
69
+ self.context = Context()
70
+ self.complete_spec = spec
71
+ self.raise_first_error = fail_fast
72
+ self.errors = False
73
+ self.messages = []
74
+
75
+ def validate(self, data):
76
+ self._validate_part(self.complete_spec, data)
77
+
78
+ if self.messages:
79
+ if len(self.messages) == 1:
80
+ raise ValidationError(self.messages[0], self.messages, informal_only=not self.errors)
81
+ else:
82
+ raise ValidationError('found %d validation errors.' % len(self.messages), self.messages,
83
+ informal_only=not self.errors)
84
+
85
+ def _validate_part(self, spec, data):
86
+ if hasattr(spec, 'subspec'):
87
+ try:
88
+ spec = spec.subspec(data, self.context)
89
+ except ValueError as ex:
90
+ return self._handle_error(str(ex))
91
+
92
+ if isinstance(spec, recursive):
93
+ if spec.spec:
94
+ self.context.recurse_spec = spec.spec
95
+ self._validate_part(spec.spec, data)
96
+ self.context.recurse_spec = None
97
+ return
98
+ else:
99
+ spec = self.context.recurse_spec
100
+ if spec is None:
101
+ raise SpecError('found recursive() outside recursive spec')
102
+
103
+ if isinstance(spec, anything):
104
+ return
105
+
106
+ if data is None:
107
+ data = {}
108
+
109
+ if isinstance(spec, one_of):
110
+ # check if at least one spec type matches
111
+ for subspec in spec.specs:
112
+ if type_matches(subspec, data):
113
+ self._validate_part(subspec, data)
114
+ return
115
+ else:
116
+ return self._handle_error("%r in %s not of any type %s" %
117
+ (data, self.context.current_pos, ', '.join(map(type_str, spec.specs))))
118
+ elif not type_matches(spec, data):
119
+ return self._handle_error("%r in %s not of type %s" %
120
+ (data, self.context.current_pos, type_str(spec)))
121
+
122
+ # recurse in dicts and lists
123
+ if isinstance(spec, dict):
124
+ self._validate_dict(spec, data)
125
+ elif isinstance(spec, list):
126
+ self._validate_list(spec, data)
127
+
128
+ def _validate_dict(self, spec, data):
129
+ accept_any_key = False
130
+ any_key_spec = None
131
+ for k in iterkeys(spec):
132
+ if isinstance(k, required):
133
+ if k not in data:
134
+ self._handle_error("missing '%s', not in %s" %
135
+ (k, self.context.current_pos))
136
+ if isinstance(k, anything):
137
+ accept_any_key = True
138
+ any_key_spec = spec[k]
139
+
140
+ for k, v in iteritems(data):
141
+ if accept_any_key:
142
+ with self.context.pos('.' + text_type(k)):
143
+ self._validate_part(any_key_spec, v)
144
+
145
+ else:
146
+ if k not in spec:
147
+ self._handle_error("unknown '%s' in %s" %
148
+ (k, self.context.current_pos), info_only=True)
149
+ continue
150
+ with self.context.pos('.' + text_type(k)):
151
+ self._validate_part(spec[k], v)
152
+
153
+ def _validate_list(self, spec, data):
154
+ if not len(spec) == 1:
155
+ raise SpecError('lists support only one type, got: %s' % spec)
156
+ for i, v in enumerate(data):
157
+ with self.context.pos('[%d]' % i):
158
+ self._validate_part(spec[0], v)
159
+
160
+ def _handle_error(self, msg, info_only=False):
161
+ if not info_only:
162
+ self.errors = True
163
+ if self.raise_first_error and not info_only:
164
+ raise ValidationError(msg)
165
+ self.messages.append(msg)
166
+
167
+ def type_str(spec):
168
+ if not isinstance(spec, type):
169
+ spec = type(spec)
170
+
171
+ match = re.match(r"<type '(\w+)'>", str(spec))
172
+ if match:
173
+ return match.group(1)
174
+
175
+ match = re.match(r"<class '([\w._]+)'>", str(spec))
176
+ if match:
177
+ return match.group(1).split('.')[-1]
178
+
179
+ return str(type)
180
+
181
+ def type_matches(spec, data):
182
+ if hasattr(spec, 'compare_type'):
183
+ return spec.compare_type(data)
184
+ if isinstance(spec, type):
185
+ spec_type = spec
186
+ else:
187
+ spec_type = type(spec)
188
+ return isinstance(data, spec_type)
189
+
@@ -0,0 +1,196 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ This module implements context-local objects.
4
+
5
+ This is a partial version of werkzeug/local.py containing only Local and
6
+ StackLocal.
7
+
8
+ Last update: 2011-03-15 9ada59c958b2edbb9739fb55a6b32ef4a97dac07
9
+
10
+ :copyright: (c) 2010 by the Werkzeug Team, see AUTHORS for more details.
11
+ :license: BSD, see LICENSE for more details.
12
+ """
13
+ try:
14
+ from greenlet import getcurrent as get_current_greenlet
15
+ except ImportError: # pragma: no cover
16
+ try:
17
+ from py.magic import greenlet
18
+ get_current_greenlet = greenlet.getcurrent
19
+ del greenlet
20
+ except Exception:
21
+ # catch all, py.* fails with so many different errors.
22
+ get_current_greenlet = int
23
+ try:
24
+ from _thread import get_ident as get_current_thread, allocate_lock
25
+ except ImportError: # pragma: no cover
26
+ try:
27
+ from thread import get_ident as get_current_thread, allocate_lock
28
+ except ImportError: # pragma: no cover
29
+ from dummy_thread import get_ident as get_current_thread, allocate_lock
30
+
31
+
32
+ # get the best ident function. if greenlets are not installed we can
33
+ # safely just use the builtin thread function and save a python methodcall
34
+ # and the cost of calculating a hash.
35
+ if get_current_greenlet is int: # pragma: no cover
36
+ get_ident = get_current_thread
37
+ else:
38
+ get_ident = lambda: (get_current_thread(), get_current_greenlet())
39
+
40
+
41
+ def release_local(local):
42
+ """Releases the contents of the local for the current context.
43
+ This makes it possible to use locals without a manager.
44
+
45
+ Example::
46
+
47
+ >>> loc = Local()
48
+ >>> loc.foo = 42
49
+ >>> release_local(loc)
50
+ >>> hasattr(loc, 'foo')
51
+ False
52
+
53
+ With this function one can release :class:`Local` objects as well
54
+ as :class:`StackLocal` objects. However it is not possible to
55
+ release data held by proxies that way, one always has to retain
56
+ a reference to the underlying local object in order to be able
57
+ to release it.
58
+
59
+ .. versionadded:: 0.6.1
60
+ """
61
+ local.__release_local__()
62
+
63
+
64
+ class Local(object):
65
+ __slots__ = ('__storage__', '__lock__', '__ident_func__')
66
+
67
+ def __init__(self):
68
+ object.__setattr__(self, '__storage__', {})
69
+ object.__setattr__(self, '__lock__', allocate_lock())
70
+ object.__setattr__(self, '__ident_func__', get_ident)
71
+
72
+ def __iter__(self):
73
+ return self.__storage__.iteritems()
74
+
75
+ def __call__(self, proxy):
76
+ """Create a proxy for a name."""
77
+ return LocalProxy(self, proxy)
78
+
79
+ def __release_local__(self):
80
+ self.__storage__.pop(self.__ident_func__(), None)
81
+
82
+ def __getattr__(self, name):
83
+ try:
84
+ return self.__storage__[self.__ident_func__()][name]
85
+ except KeyError:
86
+ raise AttributeError(name)
87
+
88
+ def __setattr__(self, name, value):
89
+ ident = self.__ident_func__()
90
+ self.__lock__.acquire()
91
+ try:
92
+ storage = self.__storage__
93
+ if ident in storage:
94
+ storage[ident][name] = value
95
+ else:
96
+ storage[ident] = {name: value}
97
+ finally:
98
+ self.__lock__.release()
99
+
100
+ def __delattr__(self, name):
101
+ try:
102
+ del self.__storage__[self.__ident_func__()][name]
103
+ except KeyError:
104
+ raise AttributeError(name)
105
+
106
+
107
+ class LocalStack(object):
108
+ """This class works similar to a :class:`Local` but keeps a stack
109
+ of objects instead. This is best explained with an example::
110
+
111
+ >>> ls = LocalStack()
112
+ >>> ls.push(42)
113
+ [42]
114
+ >>> ls.top
115
+ 42
116
+ >>> ls.push(23)
117
+ [42, 23]
118
+ >>> ls.top
119
+ 23
120
+ >>> ls.pop()
121
+ 23
122
+ >>> ls.top
123
+ 42
124
+
125
+ They can be force released by using a :class:`LocalManager` or with
126
+ the :func:`release_local` function but the correct way is to pop the
127
+ item from the stack after using. When the stack is empty it will
128
+ no longer be bound to the current context (and as such released).
129
+
130
+ By calling the stack without arguments it returns a proxy that resolves to
131
+ the topmost item on the stack.
132
+
133
+ .. versionadded:: 0.6.1
134
+ """
135
+
136
+ def __init__(self):
137
+ self._local = Local()
138
+ self._lock = allocate_lock()
139
+
140
+ def __release_local__(self):
141
+ self._local.__release_local__()
142
+
143
+ def _get__ident_func__(self):
144
+ return self._local.__ident_func__
145
+ def _set__ident_func__(self, value):
146
+ object.__setattr__(self._local, '__ident_func__', value)
147
+ __ident_func__ = property(_get__ident_func__, _set__ident_func__)
148
+ del _get__ident_func__, _set__ident_func__
149
+
150
+ def __call__(self):
151
+ def _lookup():
152
+ rv = self.top
153
+ if rv is None:
154
+ raise RuntimeError('object unbound')
155
+ return rv
156
+ return LocalProxy(_lookup)
157
+
158
+ def push(self, obj):
159
+ """Pushes a new item to the stack"""
160
+ self._lock.acquire()
161
+ try:
162
+ rv = getattr(self._local, 'stack', None)
163
+ if rv is None:
164
+ self._local.stack = rv = []
165
+ rv.append(obj)
166
+ return rv
167
+ finally:
168
+ self._lock.release()
169
+
170
+ def pop(self):
171
+ """Removes the topmost item from the stack, will return the
172
+ old value or `None` if the stack was already empty.
173
+ """
174
+ self._lock.acquire()
175
+ try:
176
+ stack = getattr(self._local, 'stack', None)
177
+ if stack is None:
178
+ return None
179
+ elif len(stack) == 1:
180
+ release_local(self._local)
181
+ return stack[-1]
182
+ else:
183
+ return stack.pop()
184
+ finally:
185
+ self._lock.release()
186
+
187
+ @property
188
+ def top(self):
189
+ """The topmost item on the stack. If the stack is empty,
190
+ `None` is returned.
191
+ """
192
+ try:
193
+ return self._local.stack[-1]
194
+ except (AttributeError, IndexError):
195
+ return None
196
+